diff options
-rw-r--r-- | src/feeds.c | 7 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 23 | ||||
-rw-r--r-- | src/visited.c | 15 | ||||
-rw-r--r-- | src/visited.h | 2 |
4 files changed, 37 insertions, 10 deletions
diff --git a/src/feeds.c b/src/feeds.c index 211ee353..9468ba65 100644 --- a/src/feeds.c +++ b/src/feeds.c | |||
@@ -183,8 +183,13 @@ static iBool updateEntries_Feeds_(iFeeds *d, iPtrArray *incoming) { | |||
183 | iFeedEntry *existing = *(iFeedEntry **) at_SortedArray(&d->entries, pos); | 183 | iFeedEntry *existing = *(iFeedEntry **) at_SortedArray(&d->entries, pos); |
184 | /* Already known, but update it, maybe the time and label have changed. */ | 184 | /* Already known, but update it, maybe the time and label have changed. */ |
185 | iBool changed = iFalse; | 185 | iBool changed = iFalse; |
186 | iDate newDate; | ||
187 | iDate oldDate; | ||
188 | init_Date(&newDate, &entry->timestamp); | ||
189 | init_Date(&oldDate, &existing->timestamp); | ||
186 | if (!equalCase_String(&existing->title, &entry->title) || | 190 | if (!equalCase_String(&existing->title, &entry->title) || |
187 | cmp_Time(&existing->timestamp, &entry->timestamp)) { | 191 | (newDate.year != oldDate.year || newDate.month != oldDate.month || |
192 | newDate.day != oldDate.day)) { | ||
188 | changed = iTrue; | 193 | changed = iTrue; |
189 | } | 194 | } |
190 | set_String(&existing->title, &entry->title); | 195 | set_String(&existing->title, &entry->title); |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 2edd28a9..35c19f7c 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -115,12 +115,18 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
115 | switch (d->mode) { | 115 | switch (d->mode) { |
116 | case feeds_SidebarMode: { | 116 | case feeds_SidebarMode: { |
117 | const iString *docUrl = url_DocumentWidget(document_App()); | 117 | const iString *docUrl = url_DocumentWidget(document_App()); |
118 | iTime now; | ||
118 | iDate on; | 119 | iDate on; |
119 | initCurrent_Date(&on); | 120 | initCurrent_Time(&now); |
121 | init_Date(&on, &now); | ||
120 | const int thisYear = on.year; | 122 | const int thisYear = on.year; |
121 | iZap(on); | 123 | iZap(on); |
122 | iConstForEach(PtrArray, i, listEntries_Feeds()) { | 124 | iConstForEach(PtrArray, i, listEntries_Feeds()) { |
123 | const iFeedEntry *entry = i.ptr; | 125 | const iFeedEntry *entry = i.ptr; |
126 | /* Exclude entries that are too old for Visited to keep track of. */ | ||
127 | if (secondsSince_Time(&now, &entry->timestamp) > maxAge_Visited) { | ||
128 | break; /* the rest are even older */ | ||
129 | } | ||
124 | /* Insert date separators. */ { | 130 | /* Insert date separators. */ { |
125 | iDate entryDate; | 131 | iDate entryDate; |
126 | init_Date(&entryDate, &entry->timestamp); | 132 | init_Date(&entryDate, &entry->timestamp); |
@@ -158,13 +164,13 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
158 | as_Widget(d), | 164 | as_Widget(d), |
159 | (iMenuItem[]){ { "Open Entry in New Tab", 0, 0, "feed.entry.opentab" }, | 165 | (iMenuItem[]){ { "Open Entry in New Tab", 0, 0, "feed.entry.opentab" }, |
160 | { "Open Feed Page", 0, 0, "feed.entry.openfeed" }, | 166 | { "Open Feed Page", 0, 0, "feed.entry.openfeed" }, |
161 | { "---", 0, 0, NULL }, | ||
162 | { "Mark as Read", 0, 0, "feed.entry.toggleread" }, | 167 | { "Mark as Read", 0, 0, "feed.entry.toggleread" }, |
163 | { "Add Bookmark...", 0, 0, "feed.entry.bookmark" }, | 168 | { "Add Bookmark...", 0, 0, "feed.entry.bookmark" }, |
164 | { "Edit Feed...", 0, 0, "feed.entry.edit" }, | ||
165 | { "---", 0, 0, NULL }, | 169 | { "---", 0, 0, NULL }, |
170 | { "Edit Feed...", 0, 0, "feed.entry.edit" }, | ||
166 | { uiTextCaution_ColorEscape "Unsubscribe...", 0, 0, "feed.entry.unsubscribe" }, | 171 | { uiTextCaution_ColorEscape "Unsubscribe...", 0, 0, "feed.entry.unsubscribe" }, |
167 | { "---", 0, 0, NULL }, | 172 | { "---", 0, 0, NULL }, |
173 | { "Mark All as Read", SDLK_a, KMOD_SHIFT, "feeds.markallread" }, | ||
168 | { "Refresh Feeds", SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh" } }, | 174 | { "Refresh Feeds", SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh" } }, |
169 | 10); | 175 | 10); |
170 | break; | 176 | break; |
@@ -694,6 +700,17 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
694 | else if (equal_Command(cmd, "feeds.update.finished") && d->mode == feeds_SidebarMode) { | 700 | else if (equal_Command(cmd, "feeds.update.finished") && d->mode == feeds_SidebarMode) { |
695 | updateItems_SidebarWidget_(d); | 701 | updateItems_SidebarWidget_(d); |
696 | } | 702 | } |
703 | else if (equal_Command(cmd, "feeds.markallread") && d->mode == feeds_SidebarMode) { | ||
704 | iConstForEach(PtrArray, i, listEntries_Feeds()) { | ||
705 | const iFeedEntry *entry = i.ptr; | ||
706 | const iString *url = &entry->url; | ||
707 | if (!containsUrl_Visited(visited_App(), url)) { | ||
708 | visitUrl_Visited(visited_App(), url, transient_VisitedUrlFlag); | ||
709 | } | ||
710 | } | ||
711 | postCommand_App("visited.changed"); | ||
712 | return iTrue; | ||
713 | } | ||
697 | else if (startsWith_CStr(cmd, "feed.entry.") && d->mode == feeds_SidebarMode) { | 714 | else if (startsWith_CStr(cmd, "feed.entry.") && d->mode == feeds_SidebarMode) { |
698 | const iSidebarItem *item = d->contextItem; | 715 | const iSidebarItem *item = d->contextItem; |
699 | if (item) { | 716 | if (item) { |
diff --git a/src/visited.c b/src/visited.c index 5d8a5676..3e034399 100644 --- a/src/visited.c +++ b/src/visited.c | |||
@@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
29 | #include <the_Foundation/ptrarray.h> | 29 | #include <the_Foundation/ptrarray.h> |
30 | #include <the_Foundation/sortedarray.h> | 30 | #include <the_Foundation/sortedarray.h> |
31 | 31 | ||
32 | static const size_t maxAgeVisited_Visited_ = 2 * 3600 * 24 * 30; /* two months */ | 32 | const int maxAge_Visited = 2 * 3600 * 24 * 30; /* two months */ |
33 | 33 | ||
34 | void init_VisitedUrl(iVisitedUrl *d) { | 34 | void init_VisitedUrl(iVisitedUrl *d) { |
35 | initCurrent_Time(&d->when); | 35 | initCurrent_Time(&d->when); |
@@ -113,16 +113,16 @@ void load_Visited(iVisited *d, const char *dirPath) { | |||
113 | sscanf(line.start, "%04d-%02d-%02dT%02d:%02d:%02d ", &y, &m, &D, &H, &M, &S); | 113 | sscanf(line.start, "%04d-%02d-%02dT%02d:%02d:%02d ", &y, &m, &D, &H, &M, &S); |
114 | if (!y) break; | 114 | if (!y) break; |
115 | iVisitedUrl item; | 115 | iVisitedUrl item; |
116 | init_VisitedUrl(&item); | ||
116 | const char *urlStart = line.start + 20; | 117 | const char *urlStart = line.start + 20; |
117 | if (*urlStart == '0' && size_Range(&line) >= 25) { | 118 | if (*urlStart == '0' && size_Range(&line) >= 25) { |
118 | item.flags = strtoul(line.start + 20, NULL, 16); | 119 | item.flags = strtoul(line.start + 20, NULL, 16); |
119 | urlStart += 5; | 120 | urlStart += 5; |
120 | } | 121 | } |
121 | init_VisitedUrl(&item); | ||
122 | init_Time( | 122 | init_Time( |
123 | &item.when, | 123 | &item.when, |
124 | &(iDate){ .year = y, .month = m, .day = D, .hour = H, .minute = M, .second = S }); | 124 | &(iDate){ .year = y, .month = m, .day = D, .hour = H, .minute = M, .second = S }); |
125 | if (secondsSince_Time(&now, &item.when) > maxAgeVisited_Visited_) { | 125 | if (secondsSince_Time(&now, &item.when) > maxAge_Visited) { |
126 | continue; /* Too old. */ | 126 | continue; /* Too old. */ |
127 | } | 127 | } |
128 | initRange_String(&item.url, (iRangecc){ urlStart, line.end }); | 128 | initRange_String(&item.url, (iRangecc){ urlStart, line.end }); |
@@ -179,9 +179,12 @@ void visitUrl_Visited(iVisited *d, const iString *url, uint16_t visitFlags) { | |||
179 | void removeUrl_Visited(iVisited *d, const iString *url) { | 179 | void removeUrl_Visited(iVisited *d, const iString *url) { |
180 | iGuardMutex(d->mtx, { | 180 | iGuardMutex(d->mtx, { |
181 | size_t pos = find_Visited_(d, url); | 181 | size_t pos = find_Visited_(d, url); |
182 | if (pos != iInvalidPos) { | 182 | if (pos < size_SortedArray(&d->visited)) { |
183 | deinit_VisitedUrl(at_SortedArray(&d->visited, pos)); | 183 | iVisitedUrl *visUrl = at_SortedArray(&d->visited, pos); |
184 | remove_Array(&d->visited.values, pos); | 184 | if (equal_String(&visUrl->url, url)) { |
185 | deinit_VisitedUrl(visUrl); | ||
186 | remove_Array(&d->visited.values, pos); | ||
187 | } | ||
185 | } | 188 | } |
186 | }); | 189 | }); |
187 | } | 190 | } |
diff --git a/src/visited.h b/src/visited.h index 467bad40..fec0b4c3 100644 --- a/src/visited.h +++ b/src/visited.h | |||
@@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
31 | iDeclareType(VisitedUrl) | 31 | iDeclareType(VisitedUrl) |
32 | iDeclareTypeConstruction(VisitedUrl) | 32 | iDeclareTypeConstruction(VisitedUrl) |
33 | 33 | ||
34 | extern const int maxAge_Visited; /* seconds */ | ||
35 | |||
34 | struct Impl_VisitedUrl { | 36 | struct Impl_VisitedUrl { |
35 | iString url; | 37 | iString url; |
36 | iTime when; | 38 | iTime when; |