From b1a919108e3c447bbcbb7c0110663713b7c9b83c Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 23 Feb 2021 14:33:12 +0200 Subject: Option to auto-reload a tab at a given interval IssueID #116 --- src/app.c | 11 +++++- src/ui/documentwidget.c | 90 ++++++++++++++++++++++++++++++++++++++----------- src/ui/sidebarwidget.c | 3 +- src/ui/util.c | 24 ++++++++++--- 4 files changed, 102 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/app.c b/src/app.c index 10557370..929cc8a2 100644 --- a/src/app.c +++ b/src/app.c @@ -126,6 +126,7 @@ struct Impl_App { iStringList *launchCommands; iBool isFinishedLaunching; iTime lastDropTime; /* for detecting drops of multiple items */ + int autoReloadTimer; /* Preferences: */ iBool commandEcho; /* --echo */ iBool forceSoftwareRender; /* --sw */ @@ -414,6 +415,12 @@ static uint32_t checkAsleep_App_(uint32_t interval, void *param) { } #endif +static uint32_t postAutoReloadCommand_App_(uint32_t interval, void *param) { + iUnused(param); + postCommand_App("document.autoreload"); + return interval; +} + static void init_App_(iApp *d, int argc, char **argv) { init_CommandLine(&d->args, argc, argv); /* Where was the app started from? We ask SDL first because the command line alone is @@ -512,7 +519,9 @@ static void init_App_(iApp *d, int argc, char **argv) { postCommand_App("open url:about:help"); } postCommand_App("window.unfreeze"); - d->isFinishedLaunching = iTrue; + d->autoReloadTimer = SDL_AddTimer(60 * 1000, postAutoReloadCommand_App_, NULL); + postCommand_App("document.autoreload"); + d->isFinishedLaunching = iTrue; /* Run any commands that were pending completion of launch. */ { iForEach(StringList, i, d->launchCommands) { postCommandString_App(i.value); diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index fbfb94f3..7bf0beca 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -67,14 +67,49 @@ iDeclareType(PersistentDocumentState) iDeclareTypeConstruction(PersistentDocumentState) iDeclareTypeSerialization(PersistentDocumentState) +enum iReloadInterval { + never_RelodPeriod, + minute_ReloadInterval, + fiveMinutes_ReloadInterval, + fifteenMinutes_ReloadInterval, + hour_ReloadInterval, + fourHours_ReloadInterval, + twicePerDay_ReloadInterval, + day_ReloadInterval, + max_ReloadInterval +}; + +static int seconds_ReloadInterval_(enum iReloadInterval d) { + static const int times[] = { 0, 1, 5, 15, 60, 4 * 60, 12 * 60, 24 * 60 }; + if (d < 0 || d >= max_ReloadInterval) return 0; + return times[d]; +} + +static const char *label_ReloadInterval_(enum iReloadInterval d) { + static const char *labels[] = { + "Never", + "1 minute", + "5 minutes", + "15 minutes", + "1 hour", + "4 hours", + "12 hours", + "Once per day" + }; + if (d < 0 || d >= max_ReloadInterval) return 0; + return labels[d]; +} + struct Impl_PersistentDocumentState { iHistory *history; iString * url; + enum iReloadInterval reloadInterval; }; void init_PersistentDocumentState(iPersistentDocumentState *d) { - d->history = new_History(); - d->url = new_String(); + d->history = new_History(); + d->url = new_String(); + d->reloadInterval = 0; } void deinit_PersistentDocumentState(iPersistentDocumentState *d) { @@ -84,7 +119,7 @@ void deinit_PersistentDocumentState(iPersistentDocumentState *d) { void serialize_PersistentDocumentState(const iPersistentDocumentState *d, iStream *outs) { serialize_String(d->url, outs); - write16_Stream(outs, 0 /*d->zoomPercent*/); + writeU16_Stream(outs, d->reloadInterval & 7); serialize_History(d->history, outs); } @@ -94,7 +129,8 @@ void deserialize_PersistentDocumentState(iPersistentDocumentState *d, iStream *i /* Oopsie, this should not have been written; invalid URL. */ clear_String(d->url); } - /*d->zoomPercent =*/ read16_Stream(ins); + const uint16_t params = readU16_Stream(ins); + d->reloadInterval = params & 7; deserialize_History(d->history, ins); } @@ -1868,7 +1904,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) } return iTrue; } - else if (equal_Command(cmd, "document.reload") && document_App() == d) { + else if (equal_Command(cmd, "document.reload") && document_Command(cmd) == d) { d->initNormScrollY = normScrollPos_DocumentWidget_(d); fetch_DocumentWidget_(d); return iTrue; @@ -2083,13 +2119,6 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) size_PtrArray(links), plural), 0, 0, "bookmark.links" } }, 2); - - // (const char *[]){ "Cancel", - // format_CStr(uiTextAction_ColorEscape "Add %d - // Bookmark%s", - // size_PtrArray(links), plural) }, - // (const char *[]){ "cancel", "bookmark.links" }, - // 2); } else { iConstForEach(PtrArray, j, links) { @@ -2112,16 +2141,38 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) else if (equalWidget_Command(cmd, w, "menu.closed")) { updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); } + else if (equal_Command(cmd, "document.autoreload")) { + if (d->mod.reloadInterval) { + if (isValid_Time(&d->sourceTime) && + elapsedSeconds_Time(&d->sourceTime) >= + seconds_ReloadInterval_(d->mod.reloadInterval)) { + postCommand_Widget(w, "document.reload"); + } + } + } + else if (equal_Command(cmd, "document.autoreload.menu") && document_App() == d) { + iWidget *dlg = makeQuestion_Widget(uiTextAction_ColorEscape "AUTO-RELOAD", + "Select the auto-reload interval for this tab.", + (iMenuItem[]){ { "Cancel", 0, 0, NULL } }, + 1); + for (int i = 0; i < max_ReloadInterval; ++i) { + insertChildAfterFlags_Widget( + dlg, + iClob(new_LabelWidget(label_ReloadInterval_(i), + format_CStr("document.autoreload.set arg:%d", i))), + i + 1, + resizeToParentWidth_WidgetFlag | + ((int) d->mod.reloadInterval == i ? selected_WidgetFlag : 0)); + } + arrange_Widget(dlg); + return iTrue; + } + else if (equal_Command(cmd, "document.autoreload.set") && document_App() == d) { + d->mod.reloadInterval = arg_Command(cmd); + } return iFalse; } -#if 0 -static int outlineHeight_DocumentWidget_(const iDocumentWidget *d) { - if (isEmpty_Array(&d->outline)) return 0; - return bottom_Rect(((const iOutlineItem *) constBack_Array(&d->outline))->rect); -} -#endif - static iRect playerRect_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) { const iRect docBounds = documentBounds_DocumentWidget_(d); return moved_Rect(run->bounds, addY_I2(topLeft_Rect(docBounds), -value_Anim(&d->scrollY))); @@ -2538,6 +2589,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e { "Go to Root", navigateRoot_KeyShortcut, "navigate.root" }, { "---", 0, 0, NULL }, { "Reload Page", reload_KeyShortcut, "navigate.reload" }, + { "Set Auto-Reload...", 0, 0, "document.autoreload.menu" }, { "---", 0, 0, NULL }, { "Bookmark Page...", SDLK_d, KMOD_PRIMARY, "bookmark.add" }, { "Subscribe to Page...", subscribeToPage_KeyModifier, "feeds.subscribe" }, diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 17640aaa..9ca09fe8 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c @@ -1356,7 +1356,8 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, iString str; init_String(&str); appendChar_String(&str, d->icon ? d->icon : 0x1f588); - const iRect iconArea = { addX_I2(pos, gap_UI), init_I2(1.9f * lineHeight_Text(font), itemHeight) }; + const iRect iconArea = { addX_I2(pos, gap_UI), + init_I2(1.75f * lineHeight_Text(font), itemHeight) }; drawCentered_Text(font, iconArea, iTrue, diff --git a/src/ui/util.c b/src/ui/util.c index f8151807..04edbfd9 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -382,10 +382,20 @@ iWidget *addAction_Widget(iWidget *parent, int key, int kmods, const char *comma /*-----------------------------------------------------------------------------------------------*/ static iBool isCommandIgnoredByMenus_(const char *cmd) { - return equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.player.update") || + /* TODO: Perhaps a common way of indicating which commands are notifications and should not + be reacted to by menus? */ + return equal_Command(cmd, "media.updated") || + equal_Command(cmd, "media.player.update") || startsWith_CStr(cmd, "feeds.update.") || - equal_Command(cmd, "document.request.updated") || + equal_Command(cmd, "bookmarks.request.started") || equal_Command(cmd, "bookmarks.request.finished") || + equal_Command(cmd, "document.autoreload") || + equal_Command(cmd, "document.reload") || + equal_Command(cmd, "document.request.started") || + equal_Command(cmd, "document.request.updated") || + equal_Command(cmd, "document.request.finished") || + equal_Command(cmd, "document.changed") || + equal_Command(cmd, "visited.changed") || (deviceType_App() == desktop_AppDeviceType && equal_Command(cmd, "window.resized")) || equal_Command(cmd, "window.reload.update") || equal_Command(cmd, "window.mouse.exited") || @@ -1028,10 +1038,13 @@ void updateValueInput_Widget(iWidget *d, const char *title, const char *prompt) static iBool messageHandler_(iWidget *msg, const char *cmd) { /* Almost any command dismisses the sheet. */ - if (!(equal_Command(cmd, "media.updated") || + if (!(equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.player.update") || equal_Command(cmd, "bookmarks.request.finished") || - equal_Command(cmd, "document.request.updated") || startsWith_CStr(cmd, "window."))) { + equal_Command(cmd, "document.autoreload") || + equal_Command(cmd, "document.reload") || + equal_Command(cmd, "document.request.updated") || + startsWith_CStr(cmd, "window."))) { destroy_Widget(msg); } return iFalse; @@ -1053,7 +1066,7 @@ iWidget *makeQuestion_Widget(const char *title, const char *msg, addChildFlags_Widget(dlg, iClob(new_LabelWidget(title, NULL)), frameless_WidgetFlag); addChildFlags_Widget(dlg, iClob(new_LabelWidget(msg, NULL)), frameless_WidgetFlag); addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); - iWidget *buttons = addChild_Widget(dlg, iClob(makeDialogButtons_(items, numItems))); + addChild_Widget(dlg, iClob(makeDialogButtons_(items, numItems))); addChild_Widget(get_Window()->root, iClob(dlg)); arrange_Widget(dlg); /* BUG: This extra arrange shouldn't be needed but the dialog won't be arranged correctly unless it's here. */ @@ -1307,6 +1320,7 @@ iWidget *makePreferences_Widget(void) { setFlags_Widget(as_Widget(bind), borderTop_WidgetFlag, iTrue); appendFramelessTabPage_(tabs, iClob(bind), "Keys", '6', KMOD_PRIMARY); } + addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); resizeToLargestPage_Widget(tabs); arrange_Widget(dlg); /* Set input field sizes. */ { -- cgit v1.2.3