diff options
Diffstat (limited to 'src/ui/sidebarwidget.c')
-rw-r--r-- | src/ui/sidebarwidget.c | 335 |
1 files changed, 37 insertions, 298 deletions
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 9cfc507a..8440a597 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
25 | #include "app.h" | 25 | #include "app.h" |
26 | #include "defs.h" | 26 | #include "defs.h" |
27 | #include "bookmarks.h" | 27 | #include "bookmarks.h" |
28 | #include "certlistwidget.h" | ||
28 | #include "command.h" | 29 | #include "command.h" |
29 | #include "documentwidget.h" | 30 | #include "documentwidget.h" |
30 | #include "feeds.h" | 31 | #include "feeds.h" |
@@ -96,6 +97,7 @@ struct Impl_SidebarWidget { | |||
96 | iString cmdPrefix; | 97 | iString cmdPrefix; |
97 | iWidget * blank; | 98 | iWidget * blank; |
98 | iListWidget * list; | 99 | iListWidget * list; |
100 | iCertListWidget * certList; | ||
99 | iWidget * actions; /* below the list, area for buttons */ | 101 | iWidget * actions; /* below the list, area for buttons */ |
100 | int modeScroll[max_SidebarMode]; | 102 | int modeScroll[max_SidebarMode]; |
101 | iLabelWidget * modeButtons[max_SidebarMode]; | 103 | iLabelWidget * modeButtons[max_SidebarMode]; |
@@ -114,6 +116,10 @@ struct Impl_SidebarWidget { | |||
114 | 116 | ||
115 | iDefineObjectConstructionArgs(SidebarWidget, (enum iSidebarSide side), side) | 117 | iDefineObjectConstructionArgs(SidebarWidget, (enum iSidebarSide side), side) |
116 | 118 | ||
119 | iLocalDef iListWidget *list_SidebarWidget_(iSidebarWidget *d) { | ||
120 | return d->mode == identities_SidebarMode ? (iListWidget *) d->certList : d->list; | ||
121 | } | ||
122 | |||
117 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { | 123 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { |
118 | return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0; | 124 | return (flags_Widget(d->resizer) & pressed_WidgetFlag) != 0; |
119 | } | 125 | } |
@@ -195,65 +201,6 @@ static iLabelWidget *addActionButton_SidebarWidget_(iSidebarWidget *d, const cha | |||
195 | return btn; | 201 | return btn; |
196 | } | 202 | } |
197 | 203 | ||
198 | static iGmIdentity *menuIdentity_SidebarWidget_(const iSidebarWidget *d) { | ||
199 | if (d->mode == identities_SidebarMode) { | ||
200 | if (d->contextItem) { | ||
201 | return identity_GmCerts(certs_App(), d->contextItem->id); | ||
202 | } | ||
203 | } | ||
204 | return NULL; | ||
205 | } | ||
206 | |||
207 | static void updateContextMenu_SidebarWidget_(iSidebarWidget *d) { | ||
208 | if (d->mode != identities_SidebarMode) { | ||
209 | return; | ||
210 | } | ||
211 | iArray *items = collectNew_Array(sizeof(iMenuItem)); | ||
212 | pushBackN_Array(items, (iMenuItem[]){ | ||
213 | { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" }, | ||
214 | { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" }, | ||
215 | { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" }, | ||
216 | { "---", 0, 0, NULL }, | ||
217 | { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" }, | ||
218 | { "${ident.fingerprint}", 0, 0, "ident.fingerprint" }, | ||
219 | { export_Icon " ${ident.export}", 0, 0, "ident.export" }, | ||
220 | { "---", 0, 0, NULL }, | ||
221 | { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" }, | ||
222 | }, 9); | ||
223 | /* Used URLs. */ | ||
224 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
225 | if (ident) { | ||
226 | size_t insertPos = 3; | ||
227 | if (!isEmpty_StringSet(ident->useUrls)) { | ||
228 | insert_Array(items, insertPos++, &(iMenuItem){ "---", 0, 0, NULL }); | ||
229 | } | ||
230 | const iString *docUrl = url_DocumentWidget(document_App()); | ||
231 | iBool usedOnCurrentPage = iFalse; | ||
232 | iConstForEach(StringSet, i, ident->useUrls) { | ||
233 | const iString *url = i.value; | ||
234 | usedOnCurrentPage |= equalCase_String(docUrl, url); | ||
235 | iRangecc urlStr = range_String(url); | ||
236 | if (startsWith_Rangecc(urlStr, "gemini://")) { | ||
237 | urlStr.start += 9; /* omit the default scheme */ | ||
238 | } | ||
239 | if (endsWith_Rangecc(urlStr, "/")) { | ||
240 | urlStr.end--; /* looks cleaner */ | ||
241 | } | ||
242 | insert_Array(items, | ||
243 | insertPos++, | ||
244 | &(iMenuItem){ format_CStr(globe_Icon " %s", cstr_Rangecc(urlStr)), | ||
245 | 0, | ||
246 | 0, | ||
247 | format_CStr("!open url:%s", cstr_String(url)) }); | ||
248 | } | ||
249 | if (!usedOnCurrentPage) { | ||
250 | remove_Array(items, 1); | ||
251 | } | ||
252 | } | ||
253 | destroy_Widget(d->menu); | ||
254 | d->menu = makeMenu_Widget(as_Widget(d), data_Array(items), size_Array(items)); | ||
255 | } | ||
256 | |||
257 | static iBool isBookmarkFolded_SidebarWidget_(const iSidebarWidget *d, const iBookmark *bm) { | 204 | static iBool isBookmarkFolded_SidebarWidget_(const iSidebarWidget *d, const iBookmark *bm) { |
258 | while (bm->parentId) { | 205 | while (bm->parentId) { |
259 | if (contains_IntSet(d->closedFolders, bm->parentId)) { | 206 | if (contains_IntSet(d->closedFolders, bm->parentId)) { |
@@ -547,46 +494,7 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct | |||
547 | break; | 494 | break; |
548 | } | 495 | } |
549 | case identities_SidebarMode: { | 496 | case identities_SidebarMode: { |
550 | const iString *tabUrl = url_DocumentWidget(document_App()); | 497 | isEmpty = !updateItems_CertListWidget(d->certList); |
551 | const iRangecc tabHost = urlHost_String(tabUrl); | ||
552 | isEmpty = iTrue; | ||
553 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { | ||
554 | const iGmIdentity *ident = i.ptr; | ||
555 | iSidebarItem *item = new_SidebarItem(); | ||
556 | item->id = (uint32_t) index_PtrArrayConstIterator(&i); | ||
557 | item->icon = 0x1f464; /* person */ | ||
558 | set_String(&item->label, name_GmIdentity(ident)); | ||
559 | iDate until; | ||
560 | validUntil_TlsCertificate(ident->cert, &until); | ||
561 | const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl); | ||
562 | format_String(&item->meta, | ||
563 | "%s", | ||
564 | isActive ? cstr_Lang("ident.using") | ||
565 | : isUsed_GmIdentity(ident) | ||
566 | ? formatCStrs_Lang("ident.usedonurls.n", size_StringSet(ident->useUrls)) | ||
567 | : cstr_Lang("ident.notused")); | ||
568 | const char *expiry = | ||
569 | ident->flags & temporary_GmIdentityFlag | ||
570 | ? cstr_Lang("ident.temporary") | ||
571 | : cstrCollect_String(format_Date(&until, cstr_Lang("ident.expiry"))); | ||
572 | if (isEmpty_String(&ident->notes)) { | ||
573 | appendFormat_String(&item->meta, "\n%s", expiry); | ||
574 | } | ||
575 | else { | ||
576 | appendFormat_String(&item->meta, | ||
577 | " \u2014 %s\n%s%s", | ||
578 | expiry, | ||
579 | escape_Color(uiHeading_ColorId), | ||
580 | cstr_String(&ident->notes)); | ||
581 | } | ||
582 | item->listItem.isSelected = isActive; | ||
583 | if (isUsedOnDomain_GmIdentity(ident, tabHost)) { | ||
584 | item->indent = 1; /* will be highlighted */ | ||
585 | } | ||
586 | addItem_ListWidget(d->list, item); | ||
587 | iRelease(item); | ||
588 | isEmpty = iFalse; | ||
589 | } | ||
590 | /* Actions. */ | 498 | /* Actions. */ |
591 | if (!isEmpty) { | 499 | if (!isEmpty) { |
592 | addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); | 500 | addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); |
@@ -597,9 +505,11 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct | |||
597 | default: | 505 | default: |
598 | break; | 506 | break; |
599 | } | 507 | } |
600 | scrollOffset_ListWidget(d->list, 0); | 508 | setFlags_Widget(as_Widget(d->list), hidden_WidgetFlag, d->mode == identities_SidebarMode); |
601 | updateVisible_ListWidget(d->list); | 509 | setFlags_Widget(as_Widget(d->certList), hidden_WidgetFlag, d->mode != identities_SidebarMode); |
602 | invalidate_ListWidget(d->list); | 510 | scrollOffset_ListWidget(list_SidebarWidget_(d), 0); |
511 | updateVisible_ListWidget(list_SidebarWidget_(d)); | ||
512 | invalidate_ListWidget(list_SidebarWidget_(d)); | ||
603 | /* Content for a blank tab. */ | 513 | /* Content for a blank tab. */ |
604 | if (isEmpty) { | 514 | if (isEmpty) { |
605 | if (d->mode == feeds_SidebarMode) { | 515 | if (d->mode == feeds_SidebarMode) { |
@@ -649,7 +559,7 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct | |||
649 | #endif | 559 | #endif |
650 | arrange_Widget(d->actions); | 560 | arrange_Widget(d->actions); |
651 | arrange_Widget(as_Widget(d)); | 561 | arrange_Widget(as_Widget(d)); |
652 | updateMouseHover_ListWidget(d->list); | 562 | updateMouseHover_ListWidget(list_SidebarWidget_(d)); |
653 | } | 563 | } |
654 | 564 | ||
655 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { | 565 | static void updateItems_SidebarWidget_(iSidebarWidget *d) { |
@@ -668,10 +578,11 @@ static size_t findItem_SidebarWidget_(const iSidebarWidget *d, int id) { | |||
668 | } | 578 | } |
669 | 579 | ||
670 | static void updateItemHeight_SidebarWidget_(iSidebarWidget *d) { | 580 | static void updateItemHeight_SidebarWidget_(iSidebarWidget *d) { |
581 | const float heights[max_SidebarMode] = { 1.333f, 2.333f, 1.333f, 3.5f, 1.2f }; | ||
671 | if (d->list) { | 582 | if (d->list) { |
672 | const float heights[max_SidebarMode] = { 1.333f, 2.333f, 1.333f, 3.5f, 1.2f }; | ||
673 | setItemHeight_ListWidget(d->list, heights[d->mode] * lineHeight_Text(d->itemFonts[0])); | 583 | setItemHeight_ListWidget(d->list, heights[d->mode] * lineHeight_Text(d->itemFonts[0])); |
674 | } | 584 | } |
585 | updateItemHeight_CertListWidget(d->certList); | ||
675 | } | 586 | } |
676 | 587 | ||
677 | iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { | 588 | iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { |
@@ -679,18 +590,18 @@ iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) { | |||
679 | return iFalse; | 590 | return iFalse; |
680 | } | 591 | } |
681 | if (d->mode >= 0 && d->mode < max_SidebarMode) { | 592 | if (d->mode >= 0 && d->mode < max_SidebarMode) { |
682 | d->modeScroll[d->mode] = scrollPos_ListWidget(d->list); /* saved for later */ | 593 | d->modeScroll[d->mode] = scrollPos_ListWidget(list_SidebarWidget_(d)); /* saved for later */ |
683 | } | 594 | } |
684 | d->mode = mode; | 595 | d->mode = mode; |
685 | for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) { | 596 | for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) { |
686 | setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode); | 597 | setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode); |
687 | } | 598 | } |
688 | setBackgroundColor_Widget(as_Widget(d->list), | 599 | setBackgroundColor_Widget(as_Widget(list_SidebarWidget_(d)), |
689 | d->mode == documentOutline_SidebarMode ? tmBannerBackground_ColorId | 600 | d->mode == documentOutline_SidebarMode ? tmBannerBackground_ColorId |
690 | : uiBackgroundSidebar_ColorId); | 601 | : uiBackgroundSidebar_ColorId); |
691 | updateItemHeight_SidebarWidget_(d); | 602 | updateItemHeight_SidebarWidget_(d); |
692 | /* Restore previous scroll position. */ | 603 | /* Restore previous scroll position. */ |
693 | setScrollPos_ListWidget(d->list, d->modeScroll[mode]); | 604 | setScrollPos_ListWidget(list_SidebarWidget_(d), d->modeScroll[mode]); |
694 | return iTrue; | 605 | return iTrue; |
695 | } | 606 | } |
696 | 607 | ||
@@ -787,6 +698,7 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { | |||
787 | iZap(d->modeButtons); | 698 | iZap(d->modeButtons); |
788 | d->resizer = NULL; | 699 | d->resizer = NULL; |
789 | d->list = NULL; | 700 | d->list = NULL; |
701 | d->certList = NULL; | ||
790 | d->actions = NULL; | 702 | d->actions = NULL; |
791 | d->closedFolders = new_IntSet(); | 703 | d->closedFolders = new_IntSet(); |
792 | /* On a phone, the right sidebar is used exclusively for Identities. */ | 704 | /* On a phone, the right sidebar is used exclusively for Identities. */ |
@@ -829,10 +741,16 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) { | |||
829 | setFlags_Widget(content, resizeChildren_WidgetFlag, iTrue); | 741 | setFlags_Widget(content, resizeChildren_WidgetFlag, iTrue); |
830 | iWidget *listAndActions = makeVDiv_Widget(); | 742 | iWidget *listAndActions = makeVDiv_Widget(); |
831 | addChild_Widget(content, iClob(listAndActions)); | 743 | addChild_Widget(content, iClob(listAndActions)); |
832 | d->list = new_ListWidget(); | 744 | iWidget *listArea = new_Widget(); |
745 | setFlags_Widget(listArea, resizeChildren_WidgetFlag, iTrue); | ||
746 | d->list = new_ListWidget(); | ||
833 | setPadding_Widget(as_Widget(d->list), 0, gap_UI, 0, gap_UI); | 747 | setPadding_Widget(as_Widget(d->list), 0, gap_UI, 0, gap_UI); |
748 | addChild_Widget(listArea, iClob(d->list)); | ||
749 | d->certList = new_CertListWidget(); | ||
750 | setPadding_Widget(as_Widget(d->certList), 0, gap_UI, 0, gap_UI); | ||
751 | addChild_Widget(listArea, iClob(d->certList)); | ||
834 | addChildFlags_Widget(listAndActions, | 752 | addChildFlags_Widget(listAndActions, |
835 | iClob(d->list), | 753 | iClob(listArea), |
836 | expand_WidgetFlag); // | drawBackgroundToHorizontalSafeArea_WidgetFlag); | 754 | expand_WidgetFlag); // | drawBackgroundToHorizontalSafeArea_WidgetFlag); |
837 | setId_Widget(addChildPosFlags_Widget(listAndActions, | 755 | setId_Widget(addChildPosFlags_Widget(listAndActions, |
838 | iClob(d->actions = new_Widget()), | 756 | iClob(d->actions = new_Widget()), |
@@ -892,16 +810,16 @@ iBool setButtonFont_SidebarWidget(iSidebarWidget *d, int font) { | |||
892 | 810 | ||
893 | static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) { | 811 | static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) { |
894 | if (d->mode == identities_SidebarMode) { | 812 | if (d->mode == identities_SidebarMode) { |
895 | const iSidebarItem *hoverItem = constHoverItem_ListWidget(d->list); | 813 | return constHoverIdentity_CertListWidget(d->certList); |
896 | if (hoverItem) { | ||
897 | return identity_GmCerts(certs_App(), hoverItem->id); | ||
898 | } | ||
899 | } | 814 | } |
900 | return NULL; | 815 | return NULL; |
901 | } | 816 | } |
902 | 817 | ||
903 | static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) { | 818 | static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) { |
904 | return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d)); | 819 | if (d->mode == identities_SidebarMode) { |
820 | return hoverIdentity_CertListWidget(d->certList); | ||
821 | } | ||
822 | return NULL; | ||
905 | } | 823 | } |
906 | 824 | ||
907 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, size_t itemIndex) { | 825 | static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, size_t itemIndex) { |
@@ -944,23 +862,6 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, si | |||
944 | } | 862 | } |
945 | break; | 863 | break; |
946 | } | 864 | } |
947 | case identities_SidebarMode: { | ||
948 | d->contextItem = item; | ||
949 | if (d->contextIndex != iInvalidPos) { | ||
950 | invalidateItem_ListWidget(d->list, d->contextIndex); | ||
951 | } | ||
952 | d->contextIndex = itemIndex; | ||
953 | if (itemIndex < numItems_ListWidget(d->list)) { | ||
954 | updateContextMenu_SidebarWidget_(d); | ||
955 | arrange_Widget(d->menu); | ||
956 | openMenu_Widget(d->menu, | ||
957 | d->side == left_SidebarSide | ||
958 | ? topRight_Rect(itemRect_ListWidget(d->list, itemIndex)) | ||
959 | : addX_I2(topLeft_Rect(itemRect_ListWidget(d->list, itemIndex)), | ||
960 | -width_Widget(d->menu))); | ||
961 | } | ||
962 | break; | ||
963 | } | ||
964 | default: | 865 | default: |
965 | break; | 866 | break; |
966 | } | 867 | } |
@@ -1245,9 +1146,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1245 | } | 1146 | } |
1246 | } | 1147 | } |
1247 | } | 1148 | } |
1248 | else if (equal_Command(cmd, "idents.changed") && d->mode == identities_SidebarMode) { | ||
1249 | updateItems_SidebarWidget_(d); | ||
1250 | } | ||
1251 | else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) { | 1149 | else if (deviceType_App() == tablet_AppDeviceType && equal_Command(cmd, "toolbar.showident")) { |
1252 | postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode); | 1150 | postCommandf_App("sidebar.mode arg:%d toggle:1", identities_SidebarMode); |
1253 | return iTrue; | 1151 | return iTrue; |
@@ -1316,9 +1214,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1316 | } | 1214 | } |
1317 | return iTrue; | 1215 | return iTrue; |
1318 | } | 1216 | } |
1319 | // else if (isCommand_Widget(w, ev, "menu.closed")) { | ||
1320 | // invalidateItem_ListWidget(d->list, d->contextIndex); | ||
1321 | // } | ||
1322 | else if (isCommand_Widget(w, ev, "bookmark.open")) { | 1217 | else if (isCommand_Widget(w, ev, "bookmark.open")) { |
1323 | const iSidebarItem *item = d->contextItem; | 1218 | const iSidebarItem *item = d->contextItem; |
1324 | if (d->mode == bookmarks_SidebarMode && item) { | 1219 | if (d->mode == bookmarks_SidebarMode && item) { |
@@ -1548,103 +1443,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1548 | } | 1443 | } |
1549 | } | 1444 | } |
1550 | } | 1445 | } |
1551 | else if (isCommand_Widget(w, ev, "ident.use")) { | ||
1552 | iGmIdentity * ident = menuIdentity_SidebarWidget_(d); | ||
1553 | const iString *tabUrl = url_DocumentWidget(document_App()); | ||
1554 | if (ident) { | ||
1555 | if (argLabel_Command(cmd, "clear")) { | ||
1556 | clearUse_GmIdentity(ident); | ||
1557 | } | ||
1558 | else if (arg_Command(cmd)) { | ||
1559 | signIn_GmCerts(certs_App(), ident, tabUrl); | ||
1560 | postCommand_App("navigate.reload"); | ||
1561 | } | ||
1562 | else { | ||
1563 | signOut_GmCerts(certs_App(), tabUrl); | ||
1564 | postCommand_App("navigate.reload"); | ||
1565 | } | ||
1566 | saveIdentities_GmCerts(certs_App()); | ||
1567 | updateItems_SidebarWidget_(d); | ||
1568 | } | ||
1569 | return iTrue; | ||
1570 | } | ||
1571 | else if (isCommand_Widget(w, ev, "ident.edit")) { | ||
1572 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
1573 | if (ident) { | ||
1574 | makeValueInput_Widget(get_Root()->widget, | ||
1575 | &ident->notes, | ||
1576 | uiHeading_ColorEscape "${heading.ident.notes}", | ||
1577 | format_CStr(cstr_Lang("dlg.ident.notes"), cstr_String(name_GmIdentity(ident))), | ||
1578 | uiTextAction_ColorEscape "${dlg.default}", | ||
1579 | format_CStr("!ident.setnotes ident:%p ptr:%p", ident, d)); | ||
1580 | } | ||
1581 | return iTrue; | ||
1582 | } | ||
1583 | else if (isCommand_Widget(w, ev, "ident.fingerprint")) { | ||
1584 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
1585 | if (ident) { | ||
1586 | const iString *fps = collect_String( | ||
1587 | hexEncode_Block(collect_Block(fingerprint_TlsCertificate(ident->cert)))); | ||
1588 | SDL_SetClipboardText(cstr_String(fps)); | ||
1589 | } | ||
1590 | return iTrue; | ||
1591 | } | ||
1592 | else if (isCommand_Widget(w, ev, "ident.export")) { | ||
1593 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
1594 | if (ident) { | ||
1595 | iString *pem = collect_String(pem_TlsCertificate(ident->cert)); | ||
1596 | append_String(pem, collect_String(privateKeyPem_TlsCertificate(ident->cert))); | ||
1597 | iDocumentWidget *expTab = newTab_App(NULL, iTrue); | ||
1598 | setUrlAndSource_DocumentWidget( | ||
1599 | expTab, | ||
1600 | collectNewFormat_String("file:%s.pem", cstr_String(name_GmIdentity(ident))), | ||
1601 | collectNewCStr_String("text/plain"), | ||
1602 | utf8_String(pem)); | ||
1603 | } | ||
1604 | return iTrue; | ||
1605 | } | ||
1606 | else if (isCommand_Widget(w, ev, "ident.setnotes")) { | ||
1607 | iGmIdentity *ident = pointerLabel_Command(cmd, "ident"); | ||
1608 | if (ident) { | ||
1609 | setCStr_String(&ident->notes, suffixPtr_Command(cmd, "value")); | ||
1610 | updateItems_SidebarWidget_(d); | ||
1611 | } | ||
1612 | return iTrue; | ||
1613 | } | ||
1614 | else if (isCommand_Widget(w, ev, "ident.pickicon")) { | ||
1615 | return iTrue; | ||
1616 | } | ||
1617 | else if (isCommand_Widget(w, ev, "ident.reveal")) { | ||
1618 | const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); | ||
1619 | if (ident) { | ||
1620 | const iString *crtPath = certificatePath_GmCerts(certs_App(), ident); | ||
1621 | if (crtPath) { | ||
1622 | revealPath_App(crtPath); | ||
1623 | } | ||
1624 | } | ||
1625 | return iTrue; | ||
1626 | } | ||
1627 | else if (isCommand_Widget(w, ev, "ident.delete")) { | ||
1628 | iSidebarItem *item = d->contextItem; | ||
1629 | if (argLabel_Command(cmd, "confirm")) { | ||
1630 | makeQuestion_Widget( | ||
1631 | uiTextCaution_ColorEscape "${heading.ident.delete}", | ||
1632 | format_CStr(cstr_Lang("dlg.confirm.ident.delete"), | ||
1633 | uiTextAction_ColorEscape, | ||
1634 | cstr_String(&item->label), | ||
1635 | uiText_ColorEscape), | ||
1636 | (iMenuItem[]){ { "${cancel}", 0, 0, NULL }, | ||
1637 | { uiTextCaution_ColorEscape "${dlg.ident.delete}", | ||
1638 | 0, | ||
1639 | 0, | ||
1640 | format_CStr("!ident.delete confirm:0 ptr:%p", d) } }, | ||
1641 | 2); | ||
1642 | return iTrue; | ||
1643 | } | ||
1644 | deleteIdentity_GmCerts(certs_App(), menuIdentity_SidebarWidget_(d)); | ||
1645 | postCommand_App("idents.changed"); | ||
1646 | return iTrue; | ||
1647 | } | ||
1648 | else if (isCommand_Widget(w, ev, "history.delete")) { | 1446 | else if (isCommand_Widget(w, ev, "history.delete")) { |
1649 | if (d->contextItem && !isEmpty_String(&d->contextItem->url)) { | 1447 | if (d->contextItem && !isEmpty_String(&d->contextItem->url)) { |
1650 | removeUrl_Visited(visited_App(), &d->contextItem->url); | 1448 | removeUrl_Visited(visited_App(), &d->contextItem->url); |
@@ -1698,14 +1496,10 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1698 | /* Update cursor. */ | 1496 | /* Update cursor. */ |
1699 | else if (contains_Widget(w, mouse)) { | 1497 | else if (contains_Widget(w, mouse)) { |
1700 | const iSidebarItem *item = constHoverItem_ListWidget(d->list); | 1498 | const iSidebarItem *item = constHoverItem_ListWidget(d->list); |
1701 | if (item && d->mode != identities_SidebarMode) { | 1499 | setCursor_Window(get_Window(), |
1702 | setCursor_Window(get_Window(), | 1500 | item ? (item->listItem.isSeparator ? SDL_SYSTEM_CURSOR_ARROW |
1703 | item->listItem.isSeparator ? SDL_SYSTEM_CURSOR_ARROW | 1501 | : SDL_SYSTEM_CURSOR_HAND) |
1704 | : SDL_SYSTEM_CURSOR_HAND); | 1502 | : SDL_SYSTEM_CURSOR_ARROW); |
1705 | } | ||
1706 | else { | ||
1707 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); | ||
1708 | } | ||
1709 | } | 1503 | } |
1710 | if (d->contextIndex != iInvalidPos) { | 1504 | if (d->contextIndex != iInvalidPos) { |
1711 | invalidateItem_ListWidget(d->list, d->contextIndex); | 1505 | invalidateItem_ListWidget(d->list, d->contextIndex); |
@@ -1713,7 +1507,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1713 | } | 1507 | } |
1714 | } | 1508 | } |
1715 | /* Update context menu items. */ | 1509 | /* Update context menu items. */ |
1716 | if ((d->menu || d->mode == identities_SidebarMode) && ev->type == SDL_MOUSEBUTTONDOWN) { | 1510 | if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) { |
1717 | if (ev->button.button == SDL_BUTTON_RIGHT) { | 1511 | if (ev->button.button == SDL_BUTTON_RIGHT) { |
1718 | d->contextItem = NULL; | 1512 | d->contextItem = NULL; |
1719 | if (!isVisible_Widget(d->menu)) { | 1513 | if (!isVisible_Widget(d->menu)) { |
@@ -1726,7 +1520,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1726 | invalidateItem_ListWidget(d->list, d->contextIndex); | 1520 | invalidateItem_ListWidget(d->list, d->contextIndex); |
1727 | } | 1521 | } |
1728 | d->contextIndex = hoverItemIndex_ListWidget(d->list); | 1522 | d->contextIndex = hoverItemIndex_ListWidget(d->list); |
1729 | updateContextMenu_SidebarWidget_(d); | ||
1730 | /* TODO: Some callback-based mechanism would be nice for updating menus right | 1523 | /* TODO: Some callback-based mechanism would be nice for updating menus right |
1731 | before they open? At least move these to `updateContextMenu_ */ | 1524 | before they open? At least move these to `updateContextMenu_ */ |
1732 | if (d->mode == bookmarks_SidebarMode && d->contextItem) { | 1525 | if (d->mode == bookmarks_SidebarMode && d->contextItem) { |
@@ -1756,26 +1549,6 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
1756 | isRead ? circle_Icon " ${feeds.entry.markunread}" | 1549 | isRead ? circle_Icon " ${feeds.entry.markunread}" |
1757 | : circleWhite_Icon " ${feeds.entry.markread}"); | 1550 | : circleWhite_Icon " ${feeds.entry.markread}"); |
1758 | } | 1551 | } |
1759 | else if (d->mode == identities_SidebarMode) { | ||
1760 | const iGmIdentity *ident = constHoverIdentity_SidebarWidget_(d); | ||
1761 | const iString * docUrl = url_DocumentWidget(document_App()); | ||
1762 | iForEach(ObjectList, i, children_Widget(d->menu)) { | ||
1763 | if (isInstance_Object(i.object, &Class_LabelWidget)) { | ||
1764 | iLabelWidget *menuItem = i.object; | ||
1765 | const char * cmdItem = cstr_String(command_LabelWidget(menuItem)); | ||
1766 | if (equal_Command(cmdItem, "ident.use")) { | ||
1767 | const iBool cmdUse = arg_Command(cmdItem) != 0; | ||
1768 | const iBool cmdClear = argLabel_Command(cmdItem, "clear") != 0; | ||
1769 | setFlags_Widget( | ||
1770 | as_Widget(menuItem), | ||
1771 | disabled_WidgetFlag, | ||
1772 | (cmdClear && !isUsed_GmIdentity(ident)) || | ||
1773 | (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) || | ||
1774 | (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl))); | ||
1775 | } | ||
1776 | } | ||
1777 | } | ||
1778 | } | ||
1779 | } | 1552 | } |
1780 | } | 1553 | } |
1781 | } | 1554 | } |
@@ -2077,40 +1850,6 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
2077 | } | 1850 | } |
2078 | iEndCollect(); | 1851 | iEndCollect(); |
2079 | } | 1852 | } |
2080 | else if (sidebar->mode == identities_SidebarMode) { | ||
2081 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId) | ||
2082 | : uiTextStrong_ColorId; | ||
2083 | const iBool isUsedOnDomain = (d->indent != 0); | ||
2084 | iString icon; | ||
2085 | initUnicodeN_String(&icon, &d->icon, 1); | ||
2086 | iInt2 cPos = topLeft_Rect(itemRect); | ||
2087 | const int indent = 1.4f * lineHeight_Text(font); | ||
2088 | addv_I2(&cPos, | ||
2089 | init_I2(3 * gap_UI, | ||
2090 | (itemHeight - lineHeight_Text(uiLabel_FontId) * 2 - lineHeight_Text(font)) / | ||
2091 | 2)); | ||
2092 | const int metaFg = isHover ? permanent_ColorId | (isPressing ? uiTextPressed_ColorId | ||
2093 | : uiTextFramelessHover_ColorId) | ||
2094 | : uiTextDim_ColorId; | ||
2095 | if (!d->listItem.isSelected && !isUsedOnDomain) { | ||
2096 | drawOutline_Text(font, cPos, metaFg, none_ColorId, range_String(&icon)); | ||
2097 | } | ||
2098 | drawRange_Text(font, | ||
2099 | cPos, | ||
2100 | d->listItem.isSelected ? iconColor | ||
2101 | : isUsedOnDomain ? altIconColor | ||
2102 | : uiBackgroundSidebar_ColorId, | ||
2103 | range_String(&icon)); | ||
2104 | deinit_String(&icon); | ||
2105 | drawRange_Text(d->listItem.isSelected ? sidebar->itemFonts[1] : font, | ||
2106 | add_I2(cPos, init_I2(indent, 0)), | ||
2107 | fg, | ||
2108 | range_String(&d->label)); | ||
2109 | drawRange_Text(uiLabel_FontId, | ||
2110 | add_I2(cPos, init_I2(indent, lineHeight_Text(font))), | ||
2111 | metaFg, | ||
2112 | range_String(&d->meta)); | ||
2113 | } | ||
2114 | } | 1853 | } |
2115 | 1854 | ||
2116 | iBeginDefineSubclass(SidebarWidget, Widget) | 1855 | iBeginDefineSubclass(SidebarWidget, Widget) |