diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-06 14:40:08 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-06 14:40:08 +0300 |
commit | 90c944ac0ca82ece56d61bfa6274c31decc95358 (patch) | |
tree | a9554d81064f4346392aac04f872ca578a089f25 /src/ui/documentwidget.c | |
parent | 8c1bd54f5b09abc30eff7d65ead1dc1de1c32143 (diff) |
Fetch content from cache when navigating back
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 124 |
1 files changed, 73 insertions, 51 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 48383560..5cf0f6a6 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -251,9 +251,9 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
251 | render_GmDocument(d->doc, visRange, addVisibleLink_DocumentWidget_, d); | 251 | render_GmDocument(d->doc, visRange, addVisibleLink_DocumentWidget_, d); |
252 | updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); | 252 | updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); |
253 | /* Remember scroll positions of recently visited pages. */ { | 253 | /* Remember scroll positions of recently visited pages. */ { |
254 | iHistoryItem *it = item_History(history_App()); | 254 | iRecentUrl *recent = mostRecentUrl_History(history_App()); |
255 | if (it) { | 255 | if (recent) { |
256 | it->scrollY = d->scrollY / gap_UI; | 256 | recent->scrollY = d->scrollY / gap_UI; |
257 | } | 257 | } |
258 | } | 258 | } |
259 | } | 259 | } |
@@ -318,16 +318,16 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode | |||
318 | d->state = ready_DocumentState; | 318 | d->state = ready_DocumentState; |
319 | } | 319 | } |
320 | 320 | ||
321 | static void updateSource_DocumentWidget_(iDocumentWidget *d) { | 321 | static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response) { |
322 | if (d->state == ready_DocumentState) { | 322 | if (d->state == ready_DocumentState) { |
323 | return; | 323 | return; |
324 | } | 324 | } |
325 | /* TODO: Do this in the background. However, that requires a text metrics calculator | 325 | /* TODO: Do this in the background. However, that requires a text metrics calculator |
326 | that does not try to cache the glyph bitmaps. */ | 326 | that does not try to cache the glyph bitmaps. */ |
327 | const enum iGmStatusCode statusCode = status_GmRequest(d->request); | 327 | const enum iGmStatusCode statusCode = response->statusCode; |
328 | if (category_GmStatusCode(statusCode) != categoryInput_GmStatusCode) { | 328 | if (category_GmStatusCode(statusCode) != categoryInput_GmStatusCode) { |
329 | iString str; | 329 | iString str; |
330 | /* Theming. */ { | 330 | /* Update theme. */ { |
331 | if (isEmpty_String(d->titleUser)) { | 331 | if (isEmpty_String(d->titleUser)) { |
332 | setThemeSeed_GmDocument(d->doc, | 332 | setThemeSeed_GmDocument(d->doc, |
333 | collect_Block(newRange_Block(urlHost_String(d->url)))); | 333 | collect_Block(newRange_Block(urlHost_String(d->url)))); |
@@ -336,10 +336,10 @@ static void updateSource_DocumentWidget_(iDocumentWidget *d) { | |||
336 | setThemeSeed_GmDocument(d->doc, &d->titleUser->chars); | 336 | setThemeSeed_GmDocument(d->doc, &d->titleUser->chars); |
337 | } | 337 | } |
338 | } | 338 | } |
339 | initBlock_String(&str, body_GmRequest(d->request)); | 339 | initBlock_String(&str, &response->body); |
340 | if (category_GmStatusCode(statusCode) == categorySuccess_GmStatusCode) { | 340 | if (category_GmStatusCode(statusCode) == categorySuccess_GmStatusCode) { |
341 | /* Check the MIME type. */ | 341 | /* Check the MIME type. */ |
342 | const iString *mime = meta_GmRequest(d->request); | 342 | const iString *mime = &response->meta; |
343 | if (startsWith_String(mime, "text/plain")) { | 343 | if (startsWith_String(mime, "text/plain")) { |
344 | setFormat_GmDocument(d->doc, plainText_GmDocumentFormat); | 344 | setFormat_GmDocument(d->doc, plainText_GmDocumentFormat); |
345 | } | 345 | } |
@@ -347,17 +347,17 @@ static void updateSource_DocumentWidget_(iDocumentWidget *d) { | |||
347 | setFormat_GmDocument(d->doc, gemini_GmDocumentFormat); | 347 | setFormat_GmDocument(d->doc, gemini_GmDocumentFormat); |
348 | } | 348 | } |
349 | else if (startsWith_String(mime, "image/")) { | 349 | else if (startsWith_String(mime, "image/")) { |
350 | if (isFinished_GmRequest(d->request)) { | 350 | if (!d->request || isFinished_GmRequest(d->request)) { |
351 | /* Make a simple document with an image. */ | 351 | /* Make a simple document with an image. */ |
352 | const char *imageTitle = "Image"; | 352 | const char *imageTitle = "Image"; |
353 | iUrl parts; | 353 | iUrl parts; |
354 | init_Url(&parts, url_GmRequest(d->request)); | 354 | init_Url(&parts, d->url); // url_GmRequest(d->request)); |
355 | if (!isEmpty_Range(&parts.path)) { | 355 | if (!isEmpty_Range(&parts.path)) { |
356 | imageTitle = baseName_Path(collect_String(newRange_String(parts.path))).start; | 356 | imageTitle = baseName_Path(collect_String(newRange_String(parts.path))).start; |
357 | } | 357 | } |
358 | format_String( | 358 | format_String( |
359 | &str, "=> %s %s\n", cstr_String(url_GmRequest(d->request)), imageTitle); | 359 | &str, "=> %s %s\n", cstr_String(d->url), imageTitle); |
360 | setImage_GmDocument(d->doc, 1, mime, body_GmRequest(d->request)); | 360 | setImage_GmDocument(d->doc, 1, mime, &response->body); |
361 | } | 361 | } |
362 | else { | 362 | else { |
363 | clear_String(&str); | 363 | clear_String(&str); |
@@ -392,25 +392,70 @@ static void fetch_DocumentWidget_(iDocumentWidget *d) { | |||
392 | submit_GmRequest(d->request); | 392 | submit_GmRequest(d->request); |
393 | } | 393 | } |
394 | 394 | ||
395 | void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { | 395 | static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response) { |
396 | #define openLock_CStr "\U0001f513" | ||
397 | #define closedLock_CStr "\U0001f512" | ||
398 | d->certFlags = response->certFlags; | ||
399 | d->certExpiry = response->certValidUntil; | ||
400 | iLabelWidget *lock = findWidget_App("navbar.lock"); | ||
401 | if (~d->certFlags & available_GmCertFlag) { | ||
402 | setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iTrue); | ||
403 | updateTextCStr_LabelWidget(lock, gray50_ColorEscape openLock_CStr); | ||
404 | return; | ||
405 | } | ||
406 | setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iFalse); | ||
407 | if (~d->certFlags & domainVerified_GmCertFlag) { | ||
408 | updateTextCStr_LabelWidget(lock, red_ColorEscape closedLock_CStr); | ||
409 | } | ||
410 | else if (d->certFlags & trusted_GmCertFlag) { | ||
411 | updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_CStr); | ||
412 | } | ||
413 | else { | ||
414 | updateTextCStr_LabelWidget(lock, orange_ColorEscape closedLock_CStr); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBool isFromCache) { | ||
396 | if (cmpStringSc_String(d->url, url, &iCaseInsensitive)) { | 419 | if (cmpStringSc_String(d->url, url, &iCaseInsensitive)) { |
397 | set_String(d->url, url); | 420 | set_String(d->url, url); |
398 | fetch_DocumentWidget_(d); | 421 | /* See if there a username in the URL. */ { |
399 | } | 422 | clear_String(d->titleUser); |
400 | /* See if there a username in the URL. */ { | 423 | iRegExp *userPats[2] = { new_RegExp("~([^/?]+)", 0), |
401 | clear_String(d->titleUser); | 424 | new_RegExp("/users/([^/?]+)", caseInsensitive_RegExpOption) }; |
402 | iRegExp *userPats[2] = { new_RegExp("~([^/?]+)", 0), | 425 | iRegExpMatch m; |
403 | new_RegExp("/users/([^/?]+)", caseInsensitive_RegExpOption) }; | 426 | iForIndices(i, userPats) { |
404 | iRegExpMatch m; | 427 | if (matchString_RegExp(userPats[i], d->url, &m)) { |
405 | iForIndices(i, userPats) { | 428 | setRange_String(d->titleUser, capturedRange_RegExpMatch(&m, 1)); |
406 | if (matchString_RegExp(userPats[i], d->url, &m)) { | 429 | } |
407 | setRange_String(d->titleUser, capturedRange_RegExpMatch(&m, 1)); | 430 | iRelease(userPats[i]); |
408 | } | 431 | } |
409 | iRelease(userPats[i]); | 432 | } |
433 | const iRecentUrl *recent = mostRecentUrl_History(history_App()); | ||
434 | if (isFromCache && recent && recent->cachedResponse) { | ||
435 | const iGmResponse *resp = recent->cachedResponse; | ||
436 | d->state = fetching_DocumentState; | ||
437 | /* Use the cached response data. */ | ||
438 | printf("cached response: %d [%s] %zu bytes\n{%s}\n", | ||
439 | resp->statusCode, | ||
440 | cstr_String(&resp->meta), | ||
441 | size_Block(&resp->body), | ||
442 | cstr_Block(&resp->body)); | ||
443 | d->scrollY = d->initialScrollY; | ||
444 | updateTrust_DocumentWidget_(d, resp); | ||
445 | updateDocument_DocumentWidget_(d, resp); | ||
446 | d->state = ready_DocumentState; | ||
447 | postCommandf_App("document.changed url:%s", cstr_String(d->url)); | ||
448 | } | ||
449 | else { | ||
450 | fetch_DocumentWidget_(d); | ||
410 | } | 451 | } |
411 | } | 452 | } |
412 | } | 453 | } |
413 | 454 | ||
455 | void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { | ||
456 | setUrlFromCache_DocumentWidget(d, url, iFalse); | ||
457 | } | ||
458 | |||
414 | void setInitialScroll_DocumentWidget (iDocumentWidget *d, int scrollY) { | 459 | void setInitialScroll_DocumentWidget (iDocumentWidget *d, int scrollY) { |
415 | d->initialScrollY = scrollY; | 460 | d->initialScrollY = scrollY; |
416 | } | 461 | } |
@@ -440,30 +485,6 @@ static void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY) { | |||
440 | scroll_DocumentWidget_(d, 0); /* clamp it */ | 485 | scroll_DocumentWidget_(d, 0); /* clamp it */ |
441 | } | 486 | } |
442 | 487 | ||
443 | static void updateTrust_DocumentWidget_(iDocumentWidget *d) { | ||
444 | iAssert(d->request); | ||
445 | #define openLock_CStr "\U0001f513" | ||
446 | #define closedLock_CStr "\U0001f512" | ||
447 | d->certFlags = certFlags_GmRequest(d->request); | ||
448 | d->certExpiry = certExpirationDate_GmRequest(d->request); | ||
449 | iLabelWidget *lock = findWidget_App("navbar.lock"); | ||
450 | if (~d->certFlags & available_GmCertFlag) { | ||
451 | setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iTrue); | ||
452 | updateTextCStr_LabelWidget(lock, gray50_ColorEscape openLock_CStr); | ||
453 | return; | ||
454 | } | ||
455 | setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iFalse); | ||
456 | if (~d->certFlags & domainVerified_GmCertFlag) { | ||
457 | updateTextCStr_LabelWidget(lock, red_ColorEscape closedLock_CStr); | ||
458 | } | ||
459 | else if (d->certFlags & trusted_GmCertFlag) { | ||
460 | updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_CStr); | ||
461 | } | ||
462 | else { | ||
463 | updateTextCStr_LabelWidget(lock, orange_ColorEscape closedLock_CStr); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | 488 | static void checkResponse_DocumentWidget_(iDocumentWidget *d) { |
468 | if (!d->request) { | 489 | if (!d->request) { |
469 | return; | 490 | return; |
@@ -474,7 +495,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
474 | } | 495 | } |
475 | if (d->state == fetching_DocumentState) { | 496 | if (d->state == fetching_DocumentState) { |
476 | d->state = receivedPartialResponse_DocumentState; | 497 | d->state = receivedPartialResponse_DocumentState; |
477 | updateTrust_DocumentWidget_(d); | 498 | updateTrust_DocumentWidget_(d, response_GmRequest(d->request)); |
478 | switch (category_GmStatusCode(statusCode)) { | 499 | switch (category_GmStatusCode(statusCode)) { |
479 | case categoryInput_GmStatusCode: { | 500 | case categoryInput_GmStatusCode: { |
480 | iUrl parts; | 501 | iUrl parts; |
@@ -498,7 +519,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
498 | case categorySuccess_GmStatusCode: | 519 | case categorySuccess_GmStatusCode: |
499 | d->scrollY = d->initialScrollY; | 520 | d->scrollY = d->initialScrollY; |
500 | reset_GmDocument(d->doc); /* new content incoming */ | 521 | reset_GmDocument(d->doc); /* new content incoming */ |
501 | updateSource_DocumentWidget_(d); | 522 | updateDocument_DocumentWidget_(d, response_GmRequest(d->request)); |
502 | break; | 523 | break; |
503 | case categoryRedirect_GmStatusCode: | 524 | case categoryRedirect_GmStatusCode: |
504 | if (isEmpty_String(meta_GmRequest(d->request))) { | 525 | if (isEmpty_String(meta_GmRequest(d->request))) { |
@@ -531,7 +552,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
531 | switch (category_GmStatusCode(statusCode)) { | 552 | switch (category_GmStatusCode(statusCode)) { |
532 | case categorySuccess_GmStatusCode: | 553 | case categorySuccess_GmStatusCode: |
533 | /* More content available. */ | 554 | /* More content available. */ |
534 | updateSource_DocumentWidget_(d); | 555 | updateDocument_DocumentWidget_(d, response_GmRequest(d->request)); |
535 | break; | 556 | break; |
536 | default: | 557 | default: |
537 | break; | 558 | break; |
@@ -739,6 +760,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
739 | pointerLabel_Command(command_UserEvent(ev), "request") == d->request) { | 760 | pointerLabel_Command(command_UserEvent(ev), "request") == d->request) { |
740 | checkResponse_DocumentWidget_(d); | 761 | checkResponse_DocumentWidget_(d); |
741 | d->state = ready_DocumentState; | 762 | d->state = ready_DocumentState; |
763 | setCachedResponse_History(history_App(), response_GmRequest(d->request)); | ||
742 | iReleasePtr(&d->request); | 764 | iReleasePtr(&d->request); |
743 | postCommandf_App("document.changed url:%s", cstr_String(d->url)); | 765 | postCommandf_App("document.changed url:%s", cstr_String(d->url)); |
744 | return iFalse; | 766 | return iFalse; |