diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/documentwidget.c | 130 | ||||
-rw-r--r-- | src/ui/text.c | 4 |
2 files changed, 99 insertions, 35 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 3f952411..432dd290 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -754,6 +754,16 @@ static void updateTheme_DocumentWidget_(iDocumentWidget *d) { | |||
754 | updateTimestampBuf_DocumentWidget_(d); | 754 | updateTimestampBuf_DocumentWidget_(d); |
755 | } | 755 | } |
756 | 756 | ||
757 | static enum iGmDocumentBanner bannerType_DocumentWidget_(const iDocumentWidget *d) { | ||
758 | if (d->certFlags & available_GmCertFlag) { | ||
759 | const int req = domainVerified_GmCertFlag | timeVerified_GmCertFlag | trusted_GmCertFlag; | ||
760 | if ((d->certFlags & req) != req) { | ||
761 | return certificateWarning_GmDocumentBanner; | ||
762 | } | ||
763 | } | ||
764 | return siteDomain_GmDocumentBanner; | ||
765 | } | ||
766 | |||
757 | static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode code, | 767 | static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode code, |
758 | const iString *meta) { | 768 | const iString *meta) { |
759 | iString *src = collectNewCStr_String("# "); | 769 | iString *src = collectNewCStr_String("# "); |
@@ -794,7 +804,7 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode | |||
794 | break; | 804 | break; |
795 | } | 805 | } |
796 | } | 806 | } |
797 | setSiteBannerEnabled_GmDocument(d->doc, useBanner); | 807 | setBanner_GmDocument(d->doc, useBanner ? bannerType_DocumentWidget_(d) : none_GmDocumentBanner); |
798 | setFormat_GmDocument(d->doc, gemini_GmDocumentFormat); | 808 | setFormat_GmDocument(d->doc, gemini_GmDocumentFormat); |
799 | setSource_DocumentWidget_(d, src); | 809 | setSource_DocumentWidget_(d, src); |
800 | updateTheme_DocumentWidget_(d); | 810 | updateTheme_DocumentWidget_(d); |
@@ -956,15 +966,18 @@ static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *r | |||
956 | return; | 966 | return; |
957 | } | 967 | } |
958 | setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iFalse); | 968 | setFlags_Widget(as_Widget(lock), disabled_WidgetFlag, iFalse); |
969 | const iBool isDarkMode = isDark_ColorTheme(colorTheme_App()); | ||
959 | if (~d->certFlags & domainVerified_GmCertFlag) { | 970 | if (~d->certFlags & domainVerified_GmCertFlag) { |
960 | updateTextCStr_LabelWidget(lock, red_ColorEscape closedLock_CStr); | 971 | updateTextCStr_LabelWidget(lock, red_ColorEscape openLock_CStr); |
961 | } | 972 | } |
962 | else if (d->certFlags & trusted_GmCertFlag) { | 973 | else if (d->certFlags & trusted_GmCertFlag) { |
963 | updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_CStr); | 974 | updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_CStr); |
964 | } | 975 | } |
965 | else { | 976 | else { |
966 | updateTextCStr_LabelWidget(lock, orange_ColorEscape closedLock_CStr); | 977 | updateTextCStr_LabelWidget(lock, isDarkMode ? orange_ColorEscape closedLock_CStr |
978 | : black_ColorEscape closedLock_CStr); | ||
967 | } | 979 | } |
980 | setBanner_GmDocument(d->doc, bannerType_DocumentWidget_(d)); | ||
968 | } | 981 | } |
969 | 982 | ||
970 | static void parseUser_DocumentWidget_(iDocumentWidget *d) { | 983 | static void parseUser_DocumentWidget_(iDocumentWidget *d) { |
@@ -1490,6 +1503,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1490 | } | 1503 | } |
1491 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { | 1504 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { |
1492 | updateTheme_DocumentWidget_(d); | 1505 | updateTheme_DocumentWidget_(d); |
1506 | updateTrust_DocumentWidget_(d, NULL); | ||
1493 | updateSideIconBuf_DocumentWidget_(d); | 1507 | updateSideIconBuf_DocumentWidget_(d); |
1494 | invalidate_DocumentWidget_(d); | 1508 | invalidate_DocumentWidget_(d); |
1495 | refresh_Widget(w); | 1509 | refresh_Widget(w); |
@@ -2507,6 +2521,83 @@ static void drawMark_DrawContext_(void *context, const iGmRun *run) { | |||
2507 | } | 2521 | } |
2508 | } | 2522 | } |
2509 | 2523 | ||
2524 | static void drawBannerRun_DrawContext_(iDrawContext *d, const iGmRun *run, iInt2 visPos) { | ||
2525 | const iGmDocument *doc = d->widget->doc; | ||
2526 | const iChar icon = siteIcon_GmDocument(doc); | ||
2527 | iString str; | ||
2528 | init_String(&str); | ||
2529 | iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2)); | ||
2530 | if (icon) { | ||
2531 | appendChar_String(&str, icon); | ||
2532 | const iRect iconRect = visualBounds_Text(run->font, range_String(&str)); | ||
2533 | drawRange_Text( | ||
2534 | run->font, | ||
2535 | addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2), | ||
2536 | tmBannerIcon_ColorId, | ||
2537 | range_String(&str)); | ||
2538 | bpos.x += right_Rect(iconRect) + 3 * gap_Text; | ||
2539 | } | ||
2540 | drawRange_Text(run->font, | ||
2541 | bpos, | ||
2542 | tmBannerTitle_ColorId, | ||
2543 | bannerText_DocumentWidget_(d->widget)); | ||
2544 | if (bannerType_GmDocument(doc) == certificateWarning_GmDocumentBanner) { | ||
2545 | const int domainHeight = lineHeight_Text(banner_FontId) * 2; | ||
2546 | iRect rect = { add_I2(visPos, init_I2(0, domainHeight)), | ||
2547 | addY_I2(run->visBounds.size, -domainHeight - lineHeight_Text(uiContent_FontId)) }; | ||
2548 | format_String(&str, "UNTRUSTED CERTIFICATE"); | ||
2549 | const int certFlags = d->widget->certFlags; | ||
2550 | if (certFlags & timeVerified_GmCertFlag && certFlags & domainVerified_GmCertFlag) { | ||
2551 | iUrl parts; | ||
2552 | init_Url(&parts, d->widget->mod.url); | ||
2553 | const iTime oldUntil = domainValidUntil_GmCerts(certs_App(), parts.host); | ||
2554 | iDate exp; | ||
2555 | init_Date(&exp, &oldUntil); | ||
2556 | iTime now; | ||
2557 | initCurrent_Time(&now); | ||
2558 | const int days = secondsSince_Time(&oldUntil, &now) / 3600 / 24; | ||
2559 | if (days <= 30) { | ||
2560 | appendFormat_String(&str, | ||
2561 | "\nThe received certificate may have been recently renewed \u2014 it is " | ||
2562 | "for the correct domain and has not expired. The currently trusted " | ||
2563 | "certificate will expire on %s, in %d days.", | ||
2564 | cstrCollect_String(format_Date(&exp, "%Y-%m-%d")), | ||
2565 | days); | ||
2566 | } | ||
2567 | else { | ||
2568 | appendFormat_String(&str, "\nThe received certificate is valid but different than " | ||
2569 | "the one we trust."); | ||
2570 | } | ||
2571 | } | ||
2572 | else if (certFlags & domainVerified_GmCertFlag) { | ||
2573 | appendFormat_String(&str, "\nThe received certificate has expired on %s.", | ||
2574 | cstrCollect_String(format_Date(&d->widget->certExpiry, "%Y-%m-%d"))); | ||
2575 | } | ||
2576 | if (certFlags & haveFingerprint_GmCertFlag) { | ||
2577 | |||
2578 | } | ||
2579 | const iInt2 dims = advanceWrapRange_Text( | ||
2580 | uiContent_FontId, width_Rect(rect) - 16 * gap_UI, range_String(&str)); | ||
2581 | fillRect_Paint(&d->paint, | ||
2582 | init_Rect(0, | ||
2583 | visPos.y + domainHeight, | ||
2584 | d->widgetBounds.size.x, | ||
2585 | dims.y + lineHeight_Text(uiContent_FontId) / 2), | ||
2586 | orange_ColorId); | ||
2587 | const int fg = black_ColorId; | ||
2588 | bpos = topLeft_Rect(rect); | ||
2589 | draw_Text(uiLabelLarge_FontId, bpos, fg, "\u26a0"); | ||
2590 | adjustEdges_Rect(&rect, 0, -8 * gap_UI, 0, 8 * gap_UI); | ||
2591 | drawWrapRange_Text(uiContent_FontId, | ||
2592 | addY_I2(topLeft_Rect(rect), (lineHeight_Text(uiLabelLarge_FontId) - | ||
2593 | lineHeight_Text(uiContent_FontId)) / 2), | ||
2594 | width_Rect(rect), | ||
2595 | fg, | ||
2596 | range_String(&str)); | ||
2597 | } | ||
2598 | deinit_String(&str); | ||
2599 | } | ||
2600 | |||
2510 | static void drawRun_DrawContext_(void *context, const iGmRun *run) { | 2601 | static void drawRun_DrawContext_(void *context, const iGmRun *run) { |
2511 | iDrawContext *d = context; | 2602 | iDrawContext *d = context; |
2512 | const iInt2 origin = d->viewPos; | 2603 | const iInt2 origin = d->viewPos; |
@@ -2540,41 +2631,14 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
2540 | } | 2631 | } |
2541 | } | 2632 | } |
2542 | if (run->flags & siteBanner_GmRunFlag) { | 2633 | if (run->flags & siteBanner_GmRunFlag) { |
2543 | /* Draw the site banner. */ | 2634 | /* Banner background. */ |
2544 | fillRect_Paint( | 2635 | fillRect_Paint( |
2545 | &d->paint, | 2636 | &d->paint, |
2546 | initCorners_Rect(topLeft_Rect(d->widgetBounds), | 2637 | initCorners_Rect(topLeft_Rect(d->widgetBounds), |
2547 | init_I2(right_Rect(bounds_Widget(constAs_Widget(d->widget))), | 2638 | init_I2(right_Rect(bounds_Widget(constAs_Widget(d->widget))), |
2548 | visPos.y + height_Rect(run->visBounds))), | 2639 | visPos.y + height_Rect(run->visBounds))), |
2549 | tmBannerBackground_ColorId); | 2640 | tmBannerBackground_ColorId); |
2550 | const iChar icon = siteIcon_GmDocument(doc); | 2641 | drawBannerRun_DrawContext_(d, run, visPos); |
2551 | iString bannerText; | ||
2552 | init_String(&bannerText); | ||
2553 | iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2)); | ||
2554 | if (icon) { | ||
2555 | // appendChar_String(&bannerText, 0x2b24); // icon); | ||
2556 | // const iRect iconRect = visualBounds_Text(hugeBold_FontId, range_String(&bannerText)); | ||
2557 | // drawRange_Text(hugeBold_FontId, /*run->font,*/ | ||
2558 | // addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2), | ||
2559 | // tmBannerIcon_ColorId, | ||
2560 | // range_String(&bannerText)); | ||
2561 | // clear_String(&bannerText); | ||
2562 | appendChar_String(&bannerText, icon); | ||
2563 | const iRect iconRect = visualBounds_Text(run->font, range_String(&bannerText)); | ||
2564 | drawRange_Text( | ||
2565 | run->font, | ||
2566 | addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2), | ||
2567 | tmBannerIcon_ColorId, | ||
2568 | range_String(&bannerText)); | ||
2569 | bpos.x += right_Rect(iconRect) + 3 * gap_Text; | ||
2570 | } | ||
2571 | drawRange_Text(run->font, | ||
2572 | bpos, | ||
2573 | tmBannerTitle_ColorId, | ||
2574 | bannerText_DocumentWidget_(d->widget)); | ||
2575 | // isEmpty_String(d->widget->titleUser) ? run->text | ||
2576 | // : range_String(d->widget->titleUser)); | ||
2577 | deinit_String(&bannerText); | ||
2578 | } | 2642 | } |
2579 | else { | 2643 | else { |
2580 | if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) { | 2644 | if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) { |
diff --git a/src/ui/text.c b/src/ui/text.c index 3a9b6983..a8be1778 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -919,10 +919,10 @@ iInt2 advanceWrapRange_Text(int fontId, int maxWidth, iRangecc text) { | |||
919 | int drawWrapRange_Text(int fontId, iInt2 pos, int maxWidth, int color, iRangecc text) { | 919 | int drawWrapRange_Text(int fontId, iInt2 pos, int maxWidth, int color, iRangecc text) { |
920 | const char *endp; | 920 | const char *endp; |
921 | while (!isEmpty_Range(&text)) { | 921 | while (!isEmpty_Range(&text)) { |
922 | tryAdvance_Text(fontId, text, maxWidth, &endp); | 922 | const iInt2 adv = tryAdvance_Text(fontId, text, maxWidth, &endp); |
923 | drawRange_Text(fontId, pos, color, (iRangecc){ text.start, endp }); | 923 | drawRange_Text(fontId, pos, color, (iRangecc){ text.start, endp }); |
924 | text.start = endp; | 924 | text.start = endp; |
925 | pos.y += lineHeight_Text(fontId); | 925 | pos.y += adv.y; |
926 | } | 926 | } |
927 | return pos.y; | 927 | return pos.y; |
928 | } | 928 | } |