diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-07 10:46:07 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-07 10:46:07 +0300 |
commit | 8ddbf90ecd69da7e24237081413f0620641708dc (patch) | |
tree | f890d6850917d50dae20317f3d284d702002a752 /src/ui | |
parent | 77d172e3db30cdbecc79024da091903cfa7f349b (diff) |
LookupWidget: Show results for visited URLs
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/lookupwidget.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c index c1c52708..74f394e6 100644 --- a/src/ui/lookupwidget.c +++ b/src/ui/lookupwidget.c | |||
@@ -27,6 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
27 | #include "util.h" | 27 | #include "util.h" |
28 | #include "command.h" | 28 | #include "command.h" |
29 | #include "bookmarks.h" | 29 | #include "bookmarks.h" |
30 | #include "visited.h" | ||
30 | #include "gmutil.h" | 31 | #include "gmutil.h" |
31 | #include "app.h" | 32 | #include "app.h" |
32 | 33 | ||
@@ -38,11 +39,13 @@ iDeclareType(LookupJob) | |||
38 | 39 | ||
39 | struct Impl_LookupJob { | 40 | struct Impl_LookupJob { |
40 | iRegExp *term; | 41 | iRegExp *term; |
42 | iTime now; | ||
41 | iPtrArray results; | 43 | iPtrArray results; |
42 | }; | 44 | }; |
43 | 45 | ||
44 | static void init_LookupJob(iLookupJob *d) { | 46 | static void init_LookupJob(iLookupJob *d) { |
45 | d->term = NULL; | 47 | d->term = NULL; |
48 | initCurrent_Time(&d->now); | ||
46 | init_PtrArray(&d->results); | 49 | init_PtrArray(&d->results); |
47 | } | 50 | } |
48 | 51 | ||
@@ -102,7 +105,7 @@ static void draw_LookupItem_(iLookupItem *d, iPaint *p, iRect rect, const iListW | |||
102 | const iInt2 size = measure_Text(d->font, cstr_String(&d->text)); | 105 | const iInt2 size = measure_Text(d->font, cstr_String(&d->text)); |
103 | iInt2 pos = init_I2(left_Rect(rect) + 3 * gap_UI, mid_Rect(rect).y - size.y / 2); | 106 | iInt2 pos = init_I2(left_Rect(rect) + 3 * gap_UI, mid_Rect(rect).y - size.y / 2); |
104 | if (d->listItem.isSeparator) { | 107 | if (d->listItem.isSeparator) { |
105 | pos.y = bottom_Rect(rect) - lineHeight_Text(d->font) - gap_UI; | 108 | pos.y = bottom_Rect(rect) - lineHeight_Text(d->font); |
106 | } | 109 | } |
107 | drawRange_Text(d->font, pos, fg, range_String(&d->text)); | 110 | drawRange_Text(d->font, pos, fg, range_String(&d->text)); |
108 | } | 111 | } |
@@ -147,18 +150,31 @@ static float bookmarkRelevance_LookupJob_(const iLookupJob *d, const iBookmark * | |||
147 | return h + iMax(p, t) + 2 * g; /* extra weight for tags */ | 150 | return h + iMax(p, t) + 2 * g; /* extra weight for tags */ |
148 | } | 151 | } |
149 | 152 | ||
153 | static float visitedRelevance_LookupJob_(const iLookupJob *d, const iVisitedUrl *vis) { | ||
154 | iUrl parts; | ||
155 | init_Url(&parts, &vis->url); | ||
156 | const float h = scoreMatch_(d->term, parts.host); | ||
157 | const float p = scoreMatch_(d->term, parts.path); | ||
158 | const double age = secondsSince_Time(&d->now, &vis->when) / 3600.0 / 24.0; /* days */ | ||
159 | return iMax(h, p) / (age + 1); /* extra weight for recency */ | ||
160 | } | ||
161 | |||
150 | static iBool matchBookmark_LookupJob_(void *context, const iBookmark *bm) { | 162 | static iBool matchBookmark_LookupJob_(void *context, const iBookmark *bm) { |
151 | return bookmarkRelevance_LookupJob_(context, bm) > 0; | 163 | return bookmarkRelevance_LookupJob_(context, bm) > 0; |
152 | } | 164 | } |
153 | 165 | ||
154 | static void searchBookmarks_LookupJob_(iLookupJob *d) { | 166 | static void searchBookmarks_LookupJob_(iLookupJob *d) { |
155 | /* Note: Called in a background thread. */ | 167 | /* Note: Called in a background thread. */ |
168 | /* TODO: Thread safety! What if a bookmark gets deleted while its being accessed here? */ | ||
156 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), NULL, matchBookmark_LookupJob_, d)) { | 169 | iConstForEach(PtrArray, i, list_Bookmarks(bookmarks_App(), NULL, matchBookmark_LookupJob_, d)) { |
157 | const iBookmark *bm = i.ptr; | 170 | const iBookmark *bm = i.ptr; |
158 | iLookupResult * res = new_LookupResult(); | 171 | iLookupResult * res = new_LookupResult(); |
159 | res->type = bookmark_LookupResultType; | 172 | res->type = bookmark_LookupResultType; |
160 | res->relevance = bookmarkRelevance_LookupJob_(d, bm); | 173 | res->relevance = bookmarkRelevance_LookupJob_(d, bm); |
161 | set_String(&res->label, &bm->title); | 174 | appendChar_String(&res->label, bm->icon); |
175 | appendChar_String(&res->label, ' '); | ||
176 | append_String(&res->label, &bm->title); | ||
177 | // set_String(&res->label, &bm->title); | ||
162 | // appendFormat_String(&res->label, " (%f)", res->relevance); | 178 | // appendFormat_String(&res->label, " (%f)", res->relevance); |
163 | set_String(&res->url, &bm->url); | 179 | set_String(&res->url, &bm->url); |
164 | res->when = bm->when; | 180 | res->when = bm->when; |
@@ -166,6 +182,24 @@ static void searchBookmarks_LookupJob_(iLookupJob *d) { | |||
166 | } | 182 | } |
167 | } | 183 | } |
168 | 184 | ||
185 | static void searchVisited_LookupJob_(iLookupJob *d) { | ||
186 | /* Note: Called in a background thread. */ | ||
187 | /* TODO: Thread safety! Visited URLs may be deleted while being accessed here. */ | ||
188 | iConstForEach(PtrArray, i, list_Visited(visited_App(), 0)) { | ||
189 | const iVisitedUrl *vis = i.ptr; | ||
190 | const float relevance = visitedRelevance_LookupJob_(d, vis); | ||
191 | if (relevance > 0) { | ||
192 | iLookupResult *res = new_LookupResult(); | ||
193 | res->type = history_LookupResultType; | ||
194 | res->relevance = relevance; | ||
195 | set_String(&res->label, &vis->url); | ||
196 | set_String(&res->url, &vis->url); | ||
197 | res->when = vis->when; | ||
198 | pushBack_PtrArray(&d->results, res); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | |||
169 | static iThreadResult worker_LookupWidget_(iThread *thread) { | 203 | static iThreadResult worker_LookupWidget_(iThread *thread) { |
170 | iLookupWidget *d = userData_Thread(thread); | 204 | iLookupWidget *d = userData_Thread(thread); |
171 | printf("[LookupWidget] worker is running\n"); fflush(stdout); | 205 | printf("[LookupWidget] worker is running\n"); fflush(stdout); |
@@ -193,7 +227,6 @@ static iThreadResult worker_LookupWidget_(iThread *thread) { | |||
193 | isFirst = iFalse; | 227 | isFirst = iFalse; |
194 | } | 228 | } |
195 | iAssert(!isEmpty_String(pattern)); | 229 | iAssert(!isEmpty_String(pattern)); |
196 | // printf("{%s}\n", cstr_String(pattern)); | ||
197 | job->term = new_RegExp(cstr_String(pattern), caseInsensitive_RegExpOption); | 230 | job->term = new_RegExp(cstr_String(pattern), caseInsensitive_RegExpOption); |
198 | delete_String(pattern); | 231 | delete_String(pattern); |
199 | } | 232 | } |
@@ -201,6 +234,7 @@ static iThreadResult worker_LookupWidget_(iThread *thread) { | |||
201 | unlock_Mutex(d->mtx); | 234 | unlock_Mutex(d->mtx); |
202 | /* Do the lookup. */ { | 235 | /* Do the lookup. */ { |
203 | searchBookmarks_LookupJob_(job); | 236 | searchBookmarks_LookupJob_(job); |
237 | searchVisited_LookupJob_(job); | ||
204 | } | 238 | } |
205 | /* Submit the result. */ | 239 | /* Submit the result. */ |
206 | lock_Mutex(d->mtx); | 240 | lock_Mutex(d->mtx); |
@@ -226,7 +260,7 @@ void init_LookupWidget(iLookupWidget *d) { | |||
226 | setId_Widget(w, "lookup"); | 260 | setId_Widget(w, "lookup"); |
227 | setFlags_Widget(w, focusable_WidgetFlag | resizeChildren_WidgetFlag, iTrue); | 261 | setFlags_Widget(w, focusable_WidgetFlag | resizeChildren_WidgetFlag, iTrue); |
228 | d->list = addChild_Widget(w, iClob(new_ListWidget())); | 262 | d->list = addChild_Widget(w, iClob(new_ListWidget())); |
229 | setItemHeight_ListWidget(d->list, lineHeight_Text(default_FontId) * 2); | 263 | setItemHeight_ListWidget(d->list, lineHeight_Text(uiContent_FontId) * 1.25f); |
230 | d->cursor = iInvalidPos; | 264 | d->cursor = iInvalidPos; |
231 | d->work = new_Thread(worker_LookupWidget_); | 265 | d->work = new_Thread(worker_LookupWidget_); |
232 | setUserData_Thread(d->work, d); | 266 | setUserData_Thread(d->work, d); |
@@ -321,23 +355,34 @@ static void presentResults_LookupWidget_(iLookupWidget *d) { | |||
321 | iLookupItem *item = new_LookupItem(NULL); | 355 | iLookupItem *item = new_LookupItem(NULL); |
322 | item->listItem.isSeparator = iTrue; | 356 | item->listItem.isSeparator = iTrue; |
323 | item->fg = uiHeading_ColorId; | 357 | item->fg = uiHeading_ColorId; |
324 | item->font = default_FontId; | 358 | item->font = uiLabel_FontId; |
325 | format_String(&item->text, "%s", cstr_LookupResultType(res->type)); | 359 | format_String(&item->text, "%s", cstr_LookupResultType(res->type)); |
326 | addItem_ListWidget(d->list, item); | 360 | addItem_ListWidget(d->list, item); |
327 | iRelease(item); | 361 | iRelease(item); |
328 | lastType = res->type; | 362 | lastType = res->type; |
329 | } | 363 | } |
330 | iLookupItem *item = new_LookupItem(res); | 364 | iLookupItem *item = new_LookupItem(res); |
365 | const char *url = cstr_String(&res->url); | ||
366 | if (startsWithCase_String(&res->url, "gemini://")) { | ||
367 | url += 9; | ||
368 | } | ||
331 | switch (res->type) { | 369 | switch (res->type) { |
332 | case bookmark_LookupResultType: { | 370 | case bookmark_LookupResultType: { |
333 | item->fg = uiTextStrong_ColorId; | 371 | item->fg = uiTextStrong_ColorId; |
334 | item->font = default_FontId; | 372 | item->font = uiLabel_FontId; |
335 | const char *url = cstr_String(&res->url); | 373 | format_String(&item->text, |
336 | if (startsWithCase_String(&res->url, "gemini://")) { | 374 | "%s %s\u2014 %s", |
337 | url += 9; | 375 | cstr_String(&res->label), |
338 | } | 376 | uiText_ColorEscape, |
339 | format_String(&item->text, "%s\n%s Open %s", cstr_String(&res->label), | 377 | url); |
340 | uiText_ColorEscape, url); | 378 | format_String(&item->command, "open url:%s", cstr_String(&res->url)); |
379 | break; | ||
380 | } | ||
381 | case history_LookupResultType: { | ||
382 | item->fg = uiText_ColorId; | ||
383 | item->font = uiContent_FontId; | ||
384 | format_String(&item->text, "%s \u2014 ", url); | ||
385 | append_String(&item->text, collect_String(format_Time(&res->when, "%b %d, %Y"))); | ||
341 | format_String(&item->command, "open url:%s", cstr_String(&res->url)); | 386 | format_String(&item->command, "open url:%s", cstr_String(&res->url)); |
342 | break; | 387 | break; |
343 | } | 388 | } |