summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-02-23 14:33:12 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-02-23 14:33:12 +0200
commitb1a919108e3c447bbcbb7c0110663713b7c9b83c (patch)
tree4f5964698bee8ce728f1084c6a94f2ce71687453 /src/ui
parent0fdf297a5750f736eddbdbfe73cdb86522cb302c (diff)
Option to auto-reload a tab at a given interval
IssueID #116
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c90
-rw-r--r--src/ui/sidebarwidget.c3
-rw-r--r--src/ui/util.c24
3 files changed, 92 insertions, 25 deletions
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)
67iDeclareTypeConstruction(PersistentDocumentState) 67iDeclareTypeConstruction(PersistentDocumentState)
68iDeclareTypeSerialization(PersistentDocumentState) 68iDeclareTypeSerialization(PersistentDocumentState)
69 69
70enum iReloadInterval {
71 never_RelodPeriod,
72 minute_ReloadInterval,
73 fiveMinutes_ReloadInterval,
74 fifteenMinutes_ReloadInterval,
75 hour_ReloadInterval,
76 fourHours_ReloadInterval,
77 twicePerDay_ReloadInterval,
78 day_ReloadInterval,
79 max_ReloadInterval
80};
81
82static int seconds_ReloadInterval_(enum iReloadInterval d) {
83 static const int times[] = { 0, 1, 5, 15, 60, 4 * 60, 12 * 60, 24 * 60 };
84 if (d < 0 || d >= max_ReloadInterval) return 0;
85 return times[d];
86}
87
88static const char *label_ReloadInterval_(enum iReloadInterval d) {
89 static const char *labels[] = {
90 "Never",
91 "1 minute",
92 "5 minutes",
93 "15 minutes",
94 "1 hour",
95 "4 hours",
96 "12 hours",
97 "Once per day"
98 };
99 if (d < 0 || d >= max_ReloadInterval) return 0;
100 return labels[d];
101}
102
70struct Impl_PersistentDocumentState { 103struct Impl_PersistentDocumentState {
71 iHistory *history; 104 iHistory *history;
72 iString * url; 105 iString * url;
106 enum iReloadInterval reloadInterval;
73}; 107};
74 108
75void init_PersistentDocumentState(iPersistentDocumentState *d) { 109void init_PersistentDocumentState(iPersistentDocumentState *d) {
76 d->history = new_History(); 110 d->history = new_History();
77 d->url = new_String(); 111 d->url = new_String();
112 d->reloadInterval = 0;
78} 113}
79 114
80void deinit_PersistentDocumentState(iPersistentDocumentState *d) { 115void deinit_PersistentDocumentState(iPersistentDocumentState *d) {
@@ -84,7 +119,7 @@ void deinit_PersistentDocumentState(iPersistentDocumentState *d) {
84 119
85void serialize_PersistentDocumentState(const iPersistentDocumentState *d, iStream *outs) { 120void serialize_PersistentDocumentState(const iPersistentDocumentState *d, iStream *outs) {
86 serialize_String(d->url, outs); 121 serialize_String(d->url, outs);
87 write16_Stream(outs, 0 /*d->zoomPercent*/); 122 writeU16_Stream(outs, d->reloadInterval & 7);
88 serialize_History(d->history, outs); 123 serialize_History(d->history, outs);
89} 124}
90 125
@@ -94,7 +129,8 @@ void deserialize_PersistentDocumentState(iPersistentDocumentState *d, iStream *i
94 /* Oopsie, this should not have been written; invalid URL. */ 129 /* Oopsie, this should not have been written; invalid URL. */
95 clear_String(d->url); 130 clear_String(d->url);
96 } 131 }
97 /*d->zoomPercent =*/ read16_Stream(ins); 132 const uint16_t params = readU16_Stream(ins);
133 d->reloadInterval = params & 7;
98 deserialize_History(d->history, ins); 134 deserialize_History(d->history, ins);
99} 135}
100 136
@@ -1868,7 +1904,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1868 } 1904 }
1869 return iTrue; 1905 return iTrue;
1870 } 1906 }
1871 else if (equal_Command(cmd, "document.reload") && document_App() == d) { 1907 else if (equal_Command(cmd, "document.reload") && document_Command(cmd) == d) {
1872 d->initNormScrollY = normScrollPos_DocumentWidget_(d); 1908 d->initNormScrollY = normScrollPos_DocumentWidget_(d);
1873 fetch_DocumentWidget_(d); 1909 fetch_DocumentWidget_(d);
1874 return iTrue; 1910 return iTrue;
@@ -2083,13 +2119,6 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2083 size_PtrArray(links), 2119 size_PtrArray(links),
2084 plural), 0, 0, "bookmark.links" } }, 2120 plural), 0, 0, "bookmark.links" } },
2085 2); 2121 2);
2086
2087 // (const char *[]){ "Cancel",
2088 // format_CStr(uiTextAction_ColorEscape "Add %d
2089 // Bookmark%s",
2090 // size_PtrArray(links), plural) },
2091 // (const char *[]){ "cancel", "bookmark.links" },
2092 // 2);
2093 } 2122 }
2094 else { 2123 else {
2095 iConstForEach(PtrArray, j, links) { 2124 iConstForEach(PtrArray, j, links) {
@@ -2112,16 +2141,38 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2112 else if (equalWidget_Command(cmd, w, "menu.closed")) { 2141 else if (equalWidget_Command(cmd, w, "menu.closed")) {
2113 updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); 2142 updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window()));
2114 } 2143 }
2144 else if (equal_Command(cmd, "document.autoreload")) {
2145 if (d->mod.reloadInterval) {
2146 if (isValid_Time(&d->sourceTime) &&
2147 elapsedSeconds_Time(&d->sourceTime) >=
2148 seconds_ReloadInterval_(d->mod.reloadInterval)) {
2149 postCommand_Widget(w, "document.reload");
2150 }
2151 }
2152 }
2153 else if (equal_Command(cmd, "document.autoreload.menu") && document_App() == d) {
2154 iWidget *dlg = makeQuestion_Widget(uiTextAction_ColorEscape "AUTO-RELOAD",
2155 "Select the auto-reload interval for this tab.",
2156 (iMenuItem[]){ { "Cancel", 0, 0, NULL } },
2157 1);
2158 for (int i = 0; i < max_ReloadInterval; ++i) {
2159 insertChildAfterFlags_Widget(
2160 dlg,
2161 iClob(new_LabelWidget(label_ReloadInterval_(i),
2162 format_CStr("document.autoreload.set arg:%d", i))),
2163 i + 1,
2164 resizeToParentWidth_WidgetFlag |
2165 ((int) d->mod.reloadInterval == i ? selected_WidgetFlag : 0));
2166 }
2167 arrange_Widget(dlg);
2168 return iTrue;
2169 }
2170 else if (equal_Command(cmd, "document.autoreload.set") && document_App() == d) {
2171 d->mod.reloadInterval = arg_Command(cmd);
2172 }
2115 return iFalse; 2173 return iFalse;
2116} 2174}
2117 2175
2118#if 0
2119static int outlineHeight_DocumentWidget_(const iDocumentWidget *d) {
2120 if (isEmpty_Array(&d->outline)) return 0;
2121 return bottom_Rect(((const iOutlineItem *) constBack_Array(&d->outline))->rect);
2122}
2123#endif
2124
2125static iRect playerRect_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) { 2176static iRect playerRect_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) {
2126 const iRect docBounds = documentBounds_DocumentWidget_(d); 2177 const iRect docBounds = documentBounds_DocumentWidget_(d);
2127 return moved_Rect(run->bounds, addY_I2(topLeft_Rect(docBounds), -value_Anim(&d->scrollY))); 2178 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
2538 { "Go to Root", navigateRoot_KeyShortcut, "navigate.root" }, 2589 { "Go to Root", navigateRoot_KeyShortcut, "navigate.root" },
2539 { "---", 0, 0, NULL }, 2590 { "---", 0, 0, NULL },
2540 { "Reload Page", reload_KeyShortcut, "navigate.reload" }, 2591 { "Reload Page", reload_KeyShortcut, "navigate.reload" },
2592 { "Set Auto-Reload...", 0, 0, "document.autoreload.menu" },
2541 { "---", 0, 0, NULL }, 2593 { "---", 0, 0, NULL },
2542 { "Bookmark Page...", SDLK_d, KMOD_PRIMARY, "bookmark.add" }, 2594 { "Bookmark Page...", SDLK_d, KMOD_PRIMARY, "bookmark.add" },
2543 { "Subscribe to Page...", subscribeToPage_KeyModifier, "feeds.subscribe" }, 2595 { "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,
1356 iString str; 1356 iString str;
1357 init_String(&str); 1357 init_String(&str);
1358 appendChar_String(&str, d->icon ? d->icon : 0x1f588); 1358 appendChar_String(&str, d->icon ? d->icon : 0x1f588);
1359 const iRect iconArea = { addX_I2(pos, gap_UI), init_I2(1.9f * lineHeight_Text(font), itemHeight) }; 1359 const iRect iconArea = { addX_I2(pos, gap_UI),
1360 init_I2(1.75f * lineHeight_Text(font), itemHeight) };
1360 drawCentered_Text(font, 1361 drawCentered_Text(font,
1361 iconArea, 1362 iconArea,
1362 iTrue, 1363 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
382/*-----------------------------------------------------------------------------------------------*/ 382/*-----------------------------------------------------------------------------------------------*/
383 383
384static iBool isCommandIgnoredByMenus_(const char *cmd) { 384static iBool isCommandIgnoredByMenus_(const char *cmd) {
385 return equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.player.update") || 385 /* TODO: Perhaps a common way of indicating which commands are notifications and should not
386 be reacted to by menus? */
387 return equal_Command(cmd, "media.updated") ||
388 equal_Command(cmd, "media.player.update") ||
386 startsWith_CStr(cmd, "feeds.update.") || 389 startsWith_CStr(cmd, "feeds.update.") ||
387 equal_Command(cmd, "document.request.updated") || 390 equal_Command(cmd, "bookmarks.request.started") ||
388 equal_Command(cmd, "bookmarks.request.finished") || 391 equal_Command(cmd, "bookmarks.request.finished") ||
392 equal_Command(cmd, "document.autoreload") ||
393 equal_Command(cmd, "document.reload") ||
394 equal_Command(cmd, "document.request.started") ||
395 equal_Command(cmd, "document.request.updated") ||
396 equal_Command(cmd, "document.request.finished") ||
397 equal_Command(cmd, "document.changed") ||
398 equal_Command(cmd, "visited.changed") ||
389 (deviceType_App() == desktop_AppDeviceType && equal_Command(cmd, "window.resized")) || 399 (deviceType_App() == desktop_AppDeviceType && equal_Command(cmd, "window.resized")) ||
390 equal_Command(cmd, "window.reload.update") || 400 equal_Command(cmd, "window.reload.update") ||
391 equal_Command(cmd, "window.mouse.exited") || 401 equal_Command(cmd, "window.mouse.exited") ||
@@ -1028,10 +1038,13 @@ void updateValueInput_Widget(iWidget *d, const char *title, const char *prompt)
1028 1038
1029static iBool messageHandler_(iWidget *msg, const char *cmd) { 1039static iBool messageHandler_(iWidget *msg, const char *cmd) {
1030 /* Almost any command dismisses the sheet. */ 1040 /* Almost any command dismisses the sheet. */
1031 if (!(equal_Command(cmd, "media.updated") || 1041 if (!(equal_Command(cmd, "media.updated") ||
1032 equal_Command(cmd, "media.player.update") || 1042 equal_Command(cmd, "media.player.update") ||
1033 equal_Command(cmd, "bookmarks.request.finished") || 1043 equal_Command(cmd, "bookmarks.request.finished") ||
1034 equal_Command(cmd, "document.request.updated") || startsWith_CStr(cmd, "window."))) { 1044 equal_Command(cmd, "document.autoreload") ||
1045 equal_Command(cmd, "document.reload") ||
1046 equal_Command(cmd, "document.request.updated") ||
1047 startsWith_CStr(cmd, "window."))) {
1035 destroy_Widget(msg); 1048 destroy_Widget(msg);
1036 } 1049 }
1037 return iFalse; 1050 return iFalse;
@@ -1053,7 +1066,7 @@ iWidget *makeQuestion_Widget(const char *title, const char *msg,
1053 addChildFlags_Widget(dlg, iClob(new_LabelWidget(title, NULL)), frameless_WidgetFlag); 1066 addChildFlags_Widget(dlg, iClob(new_LabelWidget(title, NULL)), frameless_WidgetFlag);
1054 addChildFlags_Widget(dlg, iClob(new_LabelWidget(msg, NULL)), frameless_WidgetFlag); 1067 addChildFlags_Widget(dlg, iClob(new_LabelWidget(msg, NULL)), frameless_WidgetFlag);
1055 addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); 1068 addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI)));
1056 iWidget *buttons = addChild_Widget(dlg, iClob(makeDialogButtons_(items, numItems))); 1069 addChild_Widget(dlg, iClob(makeDialogButtons_(items, numItems)));
1057 addChild_Widget(get_Window()->root, iClob(dlg)); 1070 addChild_Widget(get_Window()->root, iClob(dlg));
1058 arrange_Widget(dlg); /* BUG: This extra arrange shouldn't be needed but the dialog won't 1071 arrange_Widget(dlg); /* BUG: This extra arrange shouldn't be needed but the dialog won't
1059 be arranged correctly unless it's here. */ 1072 be arranged correctly unless it's here. */
@@ -1307,6 +1320,7 @@ iWidget *makePreferences_Widget(void) {
1307 setFlags_Widget(as_Widget(bind), borderTop_WidgetFlag, iTrue); 1320 setFlags_Widget(as_Widget(bind), borderTop_WidgetFlag, iTrue);
1308 appendFramelessTabPage_(tabs, iClob(bind), "Keys", '6', KMOD_PRIMARY); 1321 appendFramelessTabPage_(tabs, iClob(bind), "Keys", '6', KMOD_PRIMARY);
1309 } 1322 }
1323 addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI)));
1310 resizeToLargestPage_Widget(tabs); 1324 resizeToLargestPage_Widget(tabs);
1311 arrange_Widget(dlg); 1325 arrange_Widget(dlg);
1312 /* Set input field sizes. */ { 1326 /* Set input field sizes. */ {