summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gmcerts.c14
-rw-r--r--src/gmcerts.h5
-rw-r--r--src/ui/sidebarwidget.c186
3 files changed, 145 insertions, 60 deletions
diff --git a/src/gmcerts.c b/src/gmcerts.c
index 96013392..b24a6d9c 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -170,6 +170,10 @@ void clearUse_GmIdentity(iGmIdentity *d) {
170 clear_StringSet(d->useUrls); 170 clear_StringSet(d->useUrls);
171} 171}
172 172
173const iString *name_GmIdentity(const iGmIdentity *d) {
174 return collect_String(subject_TlsCertificate(d->cert));
175}
176
173iDefineTypeConstruction(GmIdentity) 177iDefineTypeConstruction(GmIdentity)
174 178
175/*-----------------------------------------------------------------------------------------------*/ 179/*-----------------------------------------------------------------------------------------------*/
@@ -481,3 +485,13 @@ const iPtrArray *identities_GmCerts(const iGmCerts *d) {
481 return &d->idents; 485 return &d->idents;
482} 486}
483 487
488void signIn_GmCerts(iGmCerts *d, iGmIdentity *identity, const iString *url) {
489 signOut_GmCerts(d, url);
490 setUse_GmIdentity(identity, url, iTrue);
491}
492
493void signOut_GmCerts(iGmCerts *d, const iString *url) {
494 iForEach(PtrArray, i, &d->idents) {
495 setUse_GmIdentity(i.ptr, url, iFalse);
496 }
497}
diff --git a/src/gmcerts.h b/src/gmcerts.h
index 4be23169..92a12a6a 100644
--- a/src/gmcerts.h
+++ b/src/gmcerts.h
@@ -50,6 +50,8 @@ iBool isUsedOn_GmIdentity (const iGmIdentity *, const iString *url);
50void setUse_GmIdentity (iGmIdentity *, const iString *url, iBool use); 50void setUse_GmIdentity (iGmIdentity *, const iString *url, iBool use);
51void clearUse_GmIdentity (iGmIdentity *); 51void clearUse_GmIdentity (iGmIdentity *);
52 52
53const iString *name_GmIdentity(const iGmIdentity *);
54
53/*----------------------------------------------------------------------------------------------*/ 55/*----------------------------------------------------------------------------------------------*/
54 56
55iDeclareType(GmCerts) 57iDeclareType(GmCerts)
@@ -81,3 +83,6 @@ iGmIdentity * identity_GmCerts (iGmCerts *, unsigned int id);
81const iGmIdentity * constIdentity_GmCerts (const iGmCerts *, unsigned int id); 83const iGmIdentity * constIdentity_GmCerts (const iGmCerts *, unsigned int id);
82const iGmIdentity * identityForUrl_GmCerts (const iGmCerts *, const iString *url); 84const iGmIdentity * identityForUrl_GmCerts (const iGmCerts *, const iString *url);
83const iPtrArray * identities_GmCerts (const iGmCerts *); 85const iPtrArray * identities_GmCerts (const iGmCerts *);
86
87void signIn_GmCerts (iGmCerts *, iGmIdentity *identity, const iString *url);
88void signOut_GmCerts (iGmCerts *, const iString *url);
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 325e8e2b..7d616469 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -49,6 +49,7 @@ struct Impl_SidebarItem {
49 iString meta; 49 iString meta;
50 iString url; 50 iString url;
51 iBool isSeparator; 51 iBool isSeparator;
52 iBool isSelected;
52}; 53};
53 54
54void init_SidebarItem(iSidebarItem *d) { 55void init_SidebarItem(iSidebarItem *d) {
@@ -59,6 +60,7 @@ void init_SidebarItem(iSidebarItem *d) {
59 init_String(&d->meta); 60 init_String(&d->meta);
60 init_String(&d->url); 61 init_String(&d->url);
61 d->isSeparator = iFalse; 62 d->isSeparator = iFalse;
63 d->isSelected = iFalse;
62} 64}
63 65
64void deinit_SidebarItem(iSidebarItem *d) { 66void deinit_SidebarItem(iSidebarItem *d) {
@@ -218,9 +220,9 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
218 break; 220 break;
219 } 221 }
220 case identities_SidebarMode: { 222 case identities_SidebarMode: {
223 const iString *tabUrl = url_DocumentWidget(document_App());
221 iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { 224 iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) {
222 const iGmIdentity *ident = i.ptr; 225 const iGmIdentity *ident = i.ptr;
223 /* icon, common name, used URLs, expiration, isTemp, free-form notes */
224 iSidebarItem item; 226 iSidebarItem item;
225 init_SidebarItem(&item); 227 init_SidebarItem(&item);
226 item.id = index_PtrArrayConstIterator(&i); 228 item.id = index_PtrArrayConstIterator(&i);
@@ -228,17 +230,26 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
228 set_String(&item.label, collect_String(subject_TlsCertificate(ident->cert))); 230 set_String(&item.label, collect_String(subject_TlsCertificate(ident->cert)));
229 iDate until; 231 iDate until;
230 validUntil_TlsCertificate(ident->cert, &until); 232 validUntil_TlsCertificate(ident->cert, &until);
231 set_String( 233 const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl);
234 format_String(
232 &item.meta, 235 &item.meta,
233 collectNewFormat_String( 236 "%s",
234 "%s \u2014 %s\n%s", 237 isActive ? "Using"
235 isUsed_GmIdentity(ident) 238 : isUsed_GmIdentity(ident)
236 ? format_CStr("Used on %zu URLs", size_StringSet(ident->useUrls)) 239 ? format_CStr("Used on %zu URLs", size_StringSet(ident->useUrls))
237 : "Not used", 240 : "Not used");
238 ident->flags & temporary_GmIdentityFlag 241 const char *expiry =
239 ? "Temporary" 242 ident->flags & temporary_GmIdentityFlag
240 : cstrCollect_String(format_Date(&until, "Expires %b %d, %Y")), 243 ? "Temporary"
241 cstr_String(&ident->notes))); 244 : cstrCollect_String(format_Date(&until, "Expires %b %d, %Y"));
245 if (isEmpty_String(&ident->notes)) {
246 appendFormat_String(&item.meta, "\n%s", expiry);
247 }
248 else {
249 appendFormat_String(
250 &item.meta, " \u2014 %s\n%s", expiry, cstr_String(&ident->notes));
251 }
252 item.isSelected = isActive;
242 pushBack_Array(&d->items, &item); 253 pushBack_Array(&d->items, &item);
243 } 254 }
244 const iMenuItem menuItems[] = { 255 const iMenuItem menuItems[] = {
@@ -287,7 +298,7 @@ void setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) {
287 for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) { 298 for (enum iSidebarMode i = 0; i < max_SidebarMode; i++) {
288 setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode); 299 setFlags_Widget(as_Widget(d->modeButtons[i]), selected_WidgetFlag, i == d->mode);
289 } 300 }
290 const float heights[max_SidebarMode] = { 1.333f, 1.333f, 3.0f, 1.2f }; 301 const float heights[max_SidebarMode] = { 1.333f, 1.333f, 3.5f, 1.2f };
291 d->itemHeight = heights[mode] * lineHeight_Text(uiContent_FontId); 302 d->itemHeight = heights[mode] * lineHeight_Text(uiContent_FontId);
292 invalidate_SidebarWidget_(d); 303 invalidate_SidebarWidget_(d);
293 /* Restore previous scroll position. */ 304 /* Restore previous scroll position. */
@@ -388,6 +399,51 @@ static size_t itemIndex_SidebarWidget_(const iSidebarWidget *d, iInt2 pos) {
388 return index; 399 return index;
389} 400}
390 401
402static const iSidebarItem *constHoverItem_SidebarWidget_(const iSidebarWidget *d) {
403 if (d->hoverItem < size_Array(&d->items)) {
404 return constAt_Array(&d->items, d->hoverItem);
405 }
406 return NULL;
407}
408
409static iSidebarItem *hoverItem_SidebarWidget_(iSidebarWidget *d) {
410 if (d->hoverItem < size_Array(&d->items)) {
411 return at_Array(&d->items, d->hoverItem);
412 }
413 return NULL;
414}
415
416static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) {
417 if (d->mode == identities_SidebarMode) {
418 const iSidebarItem *hoverItem = constHoverItem_SidebarWidget_(d);
419 if (hoverItem) {
420 return identity_GmCerts(certs_App(), hoverItem->id);
421 }
422 }
423 return NULL;
424}
425
426static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) {
427 return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d));
428}
429
430static void setHoverItem_SidebarWidget_(iSidebarWidget *d, size_t index) {
431 if (index < size_Array(&d->items)) {
432 if (constValue_Array(&d->items, index, iSidebarItem).isSeparator) {
433 index = iInvalidPos;
434 }
435 }
436 if (d->hoverItem != index) {
437 d->hoverItem = index;
438 invalidate_SidebarWidget_(d);
439 }
440}
441
442static void updateMouseHover_SidebarWidget_(iSidebarWidget *d) {
443 const iInt2 mouse = mouseCoord_Window(get_Window());
444 setHoverItem_SidebarWidget_(d, itemIndex_SidebarWidget_(d, mouse));
445}
446
391static void itemClicked_SidebarWidget_(iSidebarWidget *d, size_t index) { 447static void itemClicked_SidebarWidget_(iSidebarWidget *d, size_t index) {
392 const iSidebarItem *item = constAt_Array(&d->items, index); 448 const iSidebarItem *item = constAt_Array(&d->items, index);
393 switch (d->mode) { 449 switch (d->mode) {
@@ -405,6 +461,18 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, size_t index) {
405 break; 461 break;
406 } 462 }
407 case identities_SidebarMode: { 463 case identities_SidebarMode: {
464 iGmIdentity *ident = hoverIdentity_SidebarWidget_(d);
465 if (ident) {
466 const iString *tabUrl = url_DocumentWidget(document_App());
467 if (isUsedOn_GmIdentity(ident, tabUrl)) {
468 signOut_GmCerts(certs_App(), tabUrl);
469 }
470 else {
471 signIn_GmCerts(certs_App(), ident, tabUrl);
472 }
473 updateItems_SidebarWidget_(d);
474 updateMouseHover_SidebarWidget_(d);
475 }
408 break; 476 break;
409 } 477 }
410 default: 478 default:
@@ -427,20 +495,6 @@ static void checkModeButtonLayout_SidebarWidget_(iSidebarWidget *d) {
427 } 495 }
428} 496}
429 497
430static const iSidebarItem *constHoverItem_SidebarWidget_(const iSidebarWidget *d) {
431 if (d->hoverItem < size_Array(&d->items)) {
432 return constAt_Array(&d->items, d->hoverItem);
433 }
434 return NULL;
435}
436
437static iSidebarItem *hoverItem_SidebarWidget_(iSidebarWidget *d) {
438 if (d->hoverItem < size_Array(&d->items)) {
439 return at_Array(&d->items, d->hoverItem);
440 }
441 return NULL;
442}
443
444void setWidth_SidebarWidget(iSidebarWidget *d, int width) { 498void setWidth_SidebarWidget(iSidebarWidget *d, int width) {
445 iWidget *w = as_Widget(d); 499 iWidget *w = as_Widget(d);
446 width = iMax(30 * gap_UI, width); 500 width = iMax(30 * gap_UI, width);
@@ -478,27 +532,6 @@ iBool handleBookmarkEditorCommands_SidebarWidget_(iWidget *editor, const char *c
478 return iFalse; 532 return iFalse;
479} 533}
480 534
481static const iGmIdentity *constHoverIdentity_SidebarWidget_(const iSidebarWidget *d) {
482 if (d->mode == identities_SidebarMode) {
483 const iSidebarItem *hoverItem = constHoverItem_SidebarWidget_(d);
484 if (hoverItem) {
485 return identity_GmCerts(certs_App(), hoverItem->id);
486 }
487 }
488 return NULL;
489}
490
491static iGmIdentity *hoverIdentity_SidebarWidget_(const iSidebarWidget *d) {
492 return iConstCast(iGmIdentity *, constHoverIdentity_SidebarWidget_(d));
493}
494
495static void setHoverItem_SidebarWidget_(iSidebarWidget *d, size_t index) {
496 if (d->hoverItem != index) {
497 d->hoverItem = index;
498 invalidate_SidebarWidget_(d);
499 }
500}
501
502static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) { 535static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) {
503 iWidget *w = as_Widget(d); 536 iWidget *w = as_Widget(d);
504 /* Handle commands. */ 537 /* Handle commands. */
@@ -607,14 +640,17 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
607 updateItems_SidebarWidget_(d); 640 updateItems_SidebarWidget_(d);
608 } 641 }
609 else if (isCommand_Widget(w, ev, "ident.use")) { 642 else if (isCommand_Widget(w, ev, "ident.use")) {
610 iGmIdentity *ident = hoverIdentity_SidebarWidget_(d); 643 iGmIdentity * ident = hoverIdentity_SidebarWidget_(d);
644 const iString *tabUrl = url_DocumentWidget(document_App());
611 if (ident) { 645 if (ident) {
612 if (argLabel_Command(cmd, "clear")) { 646 if (argLabel_Command(cmd, "clear")) {
613 clearUse_GmIdentity(ident); 647 clearUse_GmIdentity(ident);
614 } 648 }
649 else if (arg_Command(cmd)) {
650 signIn_GmCerts(certs_App(), ident, tabUrl);
651 }
615 else { 652 else {
616 setUse_GmIdentity( 653 signOut_GmCerts(certs_App(), tabUrl);
617 ident, url_DocumentWidget(document_App()), arg_Command(cmd) != 0);
618 } 654 }
619 updateItems_SidebarWidget_(d); 655 updateItems_SidebarWidget_(d);
620 } 656 }
@@ -629,6 +665,23 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
629 return iTrue; 665 return iTrue;
630 } 666 }
631 else if (isCommand_Widget(w, ev, "ident.edit")) { 667 else if (isCommand_Widget(w, ev, "ident.edit")) {
668 const iGmIdentity *ident = constHoverIdentity_SidebarWidget_(d);
669 if (ident) {
670 makeValueInput_Widget(get_Window()->root,
671 &ident->notes,
672 uiHeading_ColorEscape "IDENTITY NOTES",
673 format_CStr("Notes about %s:", cstr_String(name_GmIdentity(ident))),
674 uiTextAction_ColorEscape "OK",
675 format_CStr("ident.setnotes ident:%p", ident));
676 }
677 return iTrue;
678 }
679 else if (equal_Command(cmd, "ident.setnotes")) {
680 iGmIdentity *ident = pointerLabel_Command(cmd, "ident");
681 if (ident) {
682 setCStr_String(&ident->notes, suffixPtr_Command(cmd, "value"));
683 updateItems_SidebarWidget_(d);
684 }
632 return iTrue; 685 return iTrue;
633 } 686 }
634 else if (isCommand_Widget(w, ev, "ident.pickicon")) { 687 else if (isCommand_Widget(w, ev, "ident.pickicon")) {
@@ -907,20 +960,33 @@ static void draw_SidebarWidget_(const iSidebarWidget *d) {
907 else if (d->mode == identities_SidebarMode) { 960 else if (d->mode == identities_SidebarMode) {
908 const int fg = isHover ? (isPressing ? uiTextPressed_ColorId 961 const int fg = isHover ? (isPressing ? uiTextPressed_ColorId
909 : uiTextFramelessHover_ColorId) 962 : uiTextFramelessHover_ColorId)
910 : uiText_ColorId; 963 : uiTextStrong_ColorId;
964 if (item->isSelected) {
965 drawRectThickness_Paint(&p,
966 adjusted_Rect(itemRect, zero_I2(), init_I2(-2, -1)),
967 gap_UI / 4,
968 isHover && isPressing ? uiTextPressed_ColorId
969 : uiIcon_ColorId);
970 }
911 iString icon; 971 iString icon;
912 initUnicodeN_String(&icon, &item->icon, 1); 972 initUnicodeN_String(&icon, &item->icon, 1);
913 drawRange_Text(font, add_I2(topLeft_Rect(itemRect), init_I2(3 * gap_UI, 0)), 973 iInt2 cPos = topLeft_Rect(itemRect);
914 iconColor, range_String(&icon)); 974 addv_I2(&cPos,
975 init_I2(3 * gap_UI,
976 (d->itemHeight - lineHeight_Text(default_FontId) * 2 -
977 lineHeight_Text(font)) / 2));
978 const int metaFg = isHover ? (isPressing ? uiTextPressed_ColorId
979 : uiTextFramelessHover_ColorId)
980 : uiText_ColorId;
981 drawRange_Text(
982 font, cPos, item->isSelected ? iconColor : metaFg, range_String(&icon));
915 deinit_String(&icon); 983 deinit_String(&icon);
916 drawRange_Text(font, add_I2(topLeft_Rect(itemRect), init_I2(10 * gap_UI, 0)), 984 drawRange_Text(font, add_I2(cPos, init_I2(7 * gap_UI, 0)),
917 fg, range_String(&item->label)); 985 fg, range_String(&item->label));
918 drawRange_Text( 986 drawRange_Text(
919 font, 987 default_FontId,
920 add_I2(topLeft_Rect(itemRect), init_I2(3 * gap_UI, lineHeight_Text(font))), 988 add_I2(cPos, init_I2(0, lineHeight_Text(font))),
921 isHover 989 metaFg,
922 ? (isPressing ? uiTextPressed_ColorId : uiTextFramelessHover_ColorId)
923 : uiAnnotation_ColorId,
924 range_String(&item->meta)); 990 range_String(&item->meta));
925 } 991 }
926 unsetClip_Paint(&p); 992 unsetClip_Paint(&p);