summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-12-01 14:47:34 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-12-01 14:47:34 +0200
commitb18b380014222131572a186888e6aa035c9c06e1 (patch)
treed21e066681c67b094ddfa0c67e03b77c39f1780b /src/ui
parentd87edbfc4907b0985b107e1432f73104eb66d356 (diff)
Subscribing to new headings on a page
When "subscribed" and "headings" tags are used, the subscribed page is tracked for newly added headings (of any kind). This works for the weiph/pikkulogs out there.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c35
-rw-r--r--src/ui/sidebarwidget.c22
2 files changed, 43 insertions, 14 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index cca77c15..96440feb 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -171,6 +171,7 @@ struct Impl_DocumentWidget {
171 const iGmRun * firstVisibleRun; 171 const iGmRun * firstVisibleRun;
172 const iGmRun * lastVisibleRun; 172 const iGmRun * lastVisibleRun;
173 iClick click; 173 iClick click;
174 iString pendingGotoHeading;
174 float initNormScrollY; 175 float initNormScrollY;
175 iAnim scrollY; 176 iAnim scrollY;
176 iAnim sideOpacity; 177 iAnim sideOpacity;
@@ -230,6 +231,7 @@ void init_DocumentWidget(iDocumentWidget *d) {
230 init_PtrArray(&d->visiblePlayers); 231 init_PtrArray(&d->visiblePlayers);
231 d->grabbedPlayer = NULL; 232 d->grabbedPlayer = NULL;
232 d->playerTimer = 0; 233 d->playerTimer = 0;
234 init_String(&d->pendingGotoHeading);
233 init_Click(&d->click, d, SDL_BUTTON_LEFT); 235 init_Click(&d->click, d, SDL_BUTTON_LEFT);
234 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); 236 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget()));
235 d->menu = NULL; /* created when clicking */ 237 d->menu = NULL; /* created when clicking */
@@ -259,6 +261,7 @@ void deinit_DocumentWidget(iDocumentWidget *d) {
259 deinit_Array(&d->outline); 261 deinit_Array(&d->outline);
260 iRelease(d->media); 262 iRelease(d->media);
261 iRelease(d->request); 263 iRelease(d->request);
264 deinit_String(&d->pendingGotoHeading);
262 deinit_Block(&d->sourceContent); 265 deinit_Block(&d->sourceContent);
263 deinit_String(&d->sourceMime); 266 deinit_String(&d->sourceMime);
264 iRelease(d->doc); 267 iRelease(d->doc);
@@ -1070,6 +1073,16 @@ static void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY, iBool ce
1070 scroll_DocumentWidget_(d, 0); /* clamp it */ 1073 scroll_DocumentWidget_(d, 0); /* clamp it */
1071} 1074}
1072 1075
1076static void scrollToHeading_DocumentWidget_(iDocumentWidget *d, const char *heading) {
1077 iConstForEach(Array, h, headings_GmDocument(d->doc)) {
1078 const iGmHeading *head = h.value;
1079 if (startsWithCase_Rangecc(head->text, heading)) {
1080 postCommandf_App("document.goto loc:%p", head->text.start);
1081 break;
1082 }
1083 }
1084}
1085
1073static void scrollWideBlock_DocumentWidget_(iDocumentWidget *d, iInt2 mousePos, int delta, 1086static void scrollWideBlock_DocumentWidget_(iDocumentWidget *d, iInt2 mousePos, int delta,
1074 int duration) { 1087 int duration) {
1075 if (delta == 0) { 1088 if (delta == 0) {
@@ -1623,6 +1636,11 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1623 updateSideIconBuf_DocumentWidget_(d); 1636 updateSideIconBuf_DocumentWidget_(d);
1624 updateOutline_DocumentWidget_(d); 1637 updateOutline_DocumentWidget_(d);
1625 postCommandf_App("document.changed url:%s", cstr_String(d->mod.url)); 1638 postCommandf_App("document.changed url:%s", cstr_String(d->mod.url));
1639 /* Check for a pending goto. */
1640 if (!isEmpty_String(&d->pendingGotoHeading)) {
1641 scrollToHeading_DocumentWidget_(d, cstr_String(&d->pendingGotoHeading));
1642 clear_String(&d->pendingGotoHeading);
1643 }
1626 return iFalse; 1644 return iFalse;
1627 } 1645 }
1628 else if (equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.finished")) { 1646 else if (equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.finished")) {
@@ -1779,17 +1797,14 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1779 return iTrue; 1797 return iTrue;
1780 } 1798 }
1781 else if (equal_Command(cmd, "document.goto") && document_App() == d) { 1799 else if (equal_Command(cmd, "document.goto") && document_App() == d) {
1782 const iRangecc heading = range_Command(cmd, "heading"); 1800 const char *heading = suffixPtr_Command(cmd, "heading");
1783 if (heading.start) { 1801 if (heading) {
1784 const char *target = cstr_Rangecc(heading); 1802 if (isRequestOngoing_DocumentWidget(d)) {
1785 iConstForEach(Array, h, headings_GmDocument(d->doc)) { 1803 /* Scroll position set when request finishes. */
1786 const iGmHeading *head = h.value; 1804 setCStr_String(&d->pendingGotoHeading, heading);
1787 if (startsWithCase_Rangecc(head->text, target)) { 1805 return iTrue;
1788 /* TODO: A bit lazy here, the code is right down below. */
1789 postCommandf_App("document.goto loc:%p", head->text.start);
1790 break;
1791 }
1792 } 1806 }
1807 scrollToHeading_DocumentWidget_(d, heading);
1793 return iTrue; 1808 return iTrue;
1794 } 1809 }
1795 const char *loc = pointerLabel_Command(cmd, "loc"); 1810 const char *loc = pointerLabel_Command(cmd, "loc");
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 6bb6d7a1..5baa08f7 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -123,6 +123,9 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
123 iZap(on); 123 iZap(on);
124 iConstForEach(PtrArray, i, listEntries_Feeds()) { 124 iConstForEach(PtrArray, i, listEntries_Feeds()) {
125 const iFeedEntry *entry = i.ptr; 125 const iFeedEntry *entry = i.ptr;
126 if (isHidden_FeedEntry(entry)) {
127 continue; /* A hidden entry. */
128 }
126 /* For more items, one can always see "about:feeds". A large number of items 129 /* For more items, one can always see "about:feeds". A large number of items
127 is a bit difficult to navigate in the sidebar. */ 130 is a bit difficult to navigate in the sidebar. */
128 if (numItems_ListWidget(d->list) == 100) { 131 if (numItems_ListWidget(d->list) == 100) {
@@ -151,9 +154,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
151 if (equal_String(docUrl, &entry->url)) { 154 if (equal_String(docUrl, &entry->url)) {
152 item->listItem.isSelected = iTrue; /* currently being viewed */ 155 item->listItem.isSelected = iTrue; /* currently being viewed */
153 } 156 }
154 if (!containsUrl_Visited(visited_App(), &entry->url)) { 157 item->indent = isUnread_FeedEntry(entry);
155 item->indent = 1; /* unread */
156 }
157 set_String(&item->url, &entry->url); 158 set_String(&item->url, &entry->url);
158 set_String(&item->label, &entry->title); 159 set_String(&item->label, &entry->title);
159 const iBookmark *bm = get_Bookmarks(bookmarks_App(), entry->bookmarkId); 160 const iBookmark *bm = get_Bookmarks(bookmarks_App(), entry->bookmarkId);
@@ -498,7 +499,20 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, const iSidebarItem *it
498 } 499 }
499 case feeds_SidebarMode: 500 case feeds_SidebarMode:
500 if (!isEmpty_String(&item->url)) { 501 if (!isEmpty_String(&item->url)) {
501 postCommandf_App("open url:%s", cstr_String(&item->url)); 502 const size_t fragPos = indexOf_String(&item->url, '#');
503 if (fragPos != iInvalidPos) {
504 iString *head = collect_String(
505 newRange_String((iRangecc){ constBegin_String(&item->url) + fragPos + 1,
506 constEnd_String(&item->url) }));
507 postCommandf_App(
508 "open gotourlheading:%s url:%s",
509 cstr_String(head),
510 cstr_Rangecc((iRangecc){ constBegin_String(&item->url),
511 constBegin_String(&item->url) + fragPos }));
512 }
513 else {
514 postCommandf_App("open url:%s", cstr_String(&item->url));
515 }
502 } 516 }
503 break; 517 break;
504 case bookmarks_SidebarMode: 518 case bookmarks_SidebarMode: