Reddit API | Unable To Update Existing Widget
Issue
The RedditAPIClient contains methods for adding, deleting and reordering sidebar Widgets. However, there is not a method for updating existing widgets, though the Widget Models appear to have create methods available (though marked with @internal).
Currently, to "update" a sidebar widget, you need to delete the existing widget, recreate the widget with changes, then potentially reorder the new widget (which is currently failing: see Issue 163). This results in 2 or 3 total API calls, instead of 1 to the existing Update Widget API.
Example Usage
import {Devvit, SettingScope, TextAreaWidget} from '@devvit/public-api';
Devvit.configure({
redditAPI: true,
redis: true
});
const SettingKey_SummaryWidgetName = 'summary-widget-name';
Devvit.addSettings([
{
type: 'string',
name: SettingKey_SummaryWidgetName,
label: 'The name of the summary widget',
defaultValue: 'Summary',
scope: SettingScope.App
}
]);
Devvit.addSchedulerJob({
name: 'update_community_status',
onRun: async (event, context) => {
if (!context.subredditName) return;
// Find existing summary widget
const widgetName = await context.settings.get(SettingKey_SummaryWidgetName) ?? 'Summary';
const widgets = await context.reddit.getWidgets(context.subredditName);
const summary = widgets
.find(w => w.name.toLowerCase() === widgetName.toString().toLowerCase() &&
w instanceof TextAreaWidget) as TextAreaWidget | undefined;
// If exists, update it
if (summary) {
// ********** CORE ENHANCEMENT **********
await context.reddit.updateWidget({
type: 'textarea',
subreddit: context.subredditName,
id: summary.id,
shortName: widgetName.toString(),
text: 'Time ' + new Date().toISOString(),
styles: {
backgroundColor: '',
headerColor: ''
}
});
// ********** CORE ENHANCEMENT **********
} else {
// Create new if needed
await context.reddit.addWidget({
type: 'textarea',
subreddit: context.subredditName,
shortName: widgetName.toString(),
text: 'Time ' + new Date().toISOString(),
styles: {
backgroundColor: '',
headerColor: ''
}
});
}
}
});
Devvit.addTrigger({
event: 'AppInstall',
onEvent: async (_, context) => {
try {
const jobId = await context.scheduler.runJob({
cron: '* * * * *',
name: 'update_community_status',
data: {},
});
await context.redis.set('jobId', jobId);
} catch (e) {
console.log('Error: Failed to schedule update_community_status job:', e);
throw e;
}
},
});
export default Devvit;
Temporary Workaround
This temporary workaround does appear to work, though "hacky" since it casts to any to get around the @internal marked method:
const taw = TextAreaWidget as any;
taw.update({
id: summary.id,
type: 'textarea',
subreddit: context.subredditName,
shortName: widgetName.toString(),
text: 'Update Time ' + new Date().toISOString(),
styles: {
backgroundColor: '',
headerColor: ''
}
});
Hey @Beach-Brews , we've added context.reddit.updateWidget in @next. Let us know if you run into issues!