Skip to content

Commit 711de1f

Browse files
#6114 Improved my keys section (#6121)
* feat: improve my keys screen * fix: flaky test * fix: compact my keys section * fix: pr review * fix: pr reviews * fix: pr review * fix: align
1 parent fe06686 commit 711de1f

File tree

3 files changed

+78
-12
lines changed

3 files changed

+78
-12
lines changed

extension/chrome/settings/index.ts

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -496,24 +496,67 @@ View.run(
496496
private addKeyRowsHtml = async (privateKeys: KeyInfoWithIdentity[]) => {
497497
let html = '';
498498
const canRemoveKey = !this.clientConfiguration?.usesKeyManager();
499+
500+
// 1. Parse and prepare data
501+
const rows = [];
499502
for (let i = 0; i < privateKeys.length; i++) {
500503
const ki = privateKeys[i];
501504
const prv = await KeyUtil.parse(ki.private);
502505
const created = new Date(prv.created);
503506
const date = Str.monthName(created.getMonth()) + ' ' + created.getDate() + ', ' + created.getFullYear();
507+
const isExpired = KeyUtil.expired(prv);
508+
rows.push({
509+
ki,
510+
prv,
511+
createdTime: prv.created,
512+
dateStr: date,
513+
isExpired,
514+
originalIndex: i,
515+
});
516+
}
517+
518+
// 2. Sort: newest to oldest
519+
rows.sort((a, b) => b.createdTime - a.createdTime);
520+
521+
// 3. Build HTML
522+
// Header row
523+
html += `
524+
<div class="row key-list-header">
525+
<div class="col-3">Email</div>
526+
<div class="col-2">Created</div>
527+
<div class="col-6">Fingerprint</div>
528+
<div class="col-1">Status</div>
529+
</div>
530+
`;
531+
532+
for (const row of rows) {
533+
const { ki, prv, dateStr, isExpired, originalIndex } = row;
534+
504535
let removeKeyBtn = '';
505536
if (canRemoveKey && privateKeys.length > 1) {
506-
removeKeyBtn = `(<a href="#" class="action_remove_key" data-test="action-remove-key-${i}" data-fingerprint=${ki.fingerprints[0]} data-type="${ki.family}" data-id="${ki.id}" data-longid="${ki.longid}">remove</a>)`;
537+
removeKeyBtn = `<a href="#" class="action_remove_key" style="margin-left: 5px;" data-test="action-remove-key-${originalIndex}" data-fingerprint=${ki.fingerprints[0]} data-type="${ki.family}" data-id="${ki.id}" data-longid="${ki.longid}">remove</a>`;
507538
}
539+
508540
const escapedEmail = Xss.escape(prv.emails[0] || '');
509-
const escapedLink = `<a href="#" data-test="action-show-key-${i}" class="action_show_key" page="modules/my_key.htm" addurltext="&fingerprint=${ki.id}">${escapedEmail}</a>`;
510-
const fpHtml = `fingerprint:&nbsp;<span class="good">${Str.spaced(Xss.escape(ki.fingerprints[0]))}</span>`;
511-
const space = `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`;
512-
html += `<div class="row key-content-row">`;
513-
html += ` <div class="col-12">${escapedLink} from ${Xss.escape(date)}${space}${fpHtml}${space}${KeyUtil.statusHtml(ki.id, prv)}${space}${removeKeyBtn}</div>`;
541+
const escapedLink = `<a href="#" data-test="action-show-key-${originalIndex}" class="action_show_key" page="modules/my_key.htm" addurltext="&fingerprint=${ki.id}">${escapedEmail}</a>`;
542+
const fpHtml = `<span class="good" style="font-family: monospace;">${Str.spaced(Xss.escape(ki.fingerprints[0]))}</span>`;
543+
544+
const rowClass = isExpired ? 'key-content-row expired' : 'key-content-row';
545+
const opacityStyle = isExpired ? 'opacity: 0.7;' : '';
546+
547+
html += `<div class="row ${rowClass}" style="${opacityStyle}">`;
548+
html += ` <div class="col-3" style="overflow: hidden; text-overflow: ellipsis;">${escapedLink}</div>`;
549+
html += ` <div class="col-2">${Xss.escape(dateStr)}</div>`;
550+
html += ` <div class="col-6">${fpHtml}</div>`;
551+
html += ` <div class="col-1 status-col">
552+
${KeyUtil.statusHtml(ki.id, prv)}
553+
${removeKeyBtn}
554+
</div>`;
514555
html += `</div>`;
515556
}
557+
516558
Xss.sanitizeAppend('.key_list', html);
559+
517560
$('.action_show_key').on(
518561
'click',
519562
this.setHandler(async target => {

extension/css/settings.css

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,7 @@ a.gray_link {
255255
#settings-row .my-keys-row {
256256
display: flex;
257257
justify-content: center;
258-
margin-top: 60px;
259-
margin-left: 0 !important;
258+
margin: 60px 0;
260259
text-indent: 0;
261260
}
262261

@@ -533,7 +532,7 @@ body#settings .settings-border .row {
533532
}
534533

535534
body#settings .settings-border .key-content-row {
536-
padding: 7px 0;
535+
padding: 4px 0;
537536
border-bottom: 1px solid #e6e6e6;
538537
}
539538

@@ -544,6 +543,10 @@ body#settings .settings-border .key_list {
544543
height: 219px;
545544
}
546545

546+
.key-content-row.expired {
547+
opacity: 0.7;
548+
}
549+
547550
#settings-row .box img.security-icon {
548551
width: 70px;
549552
}
@@ -583,6 +586,26 @@ body#settings .settings-border .key_list {
583586
top: 28px;
584587
}
585588

589+
.my-keys-row .key-list-header {
590+
font-weight: 600;
591+
padding: 5px 0;
592+
border-bottom: 2px solid #eee;
593+
}
594+
595+
.my-keys-row .key-content-row {
596+
padding: 5px 0;
597+
border-bottom: 1px solid #e6e6e6;
598+
align-items: center;
599+
}
600+
601+
.my-keys-row .key-content-row .status-col {
602+
display: flex;
603+
flex-flow: column wrap;
604+
justify-content: flex-start;
605+
align-items: start;
606+
gap: 2px;
607+
}
608+
586609
@media (width <= 991px) {
587610
.my-keys-row .settings-border {
588611
margin: 35px auto !important;
@@ -847,4 +870,4 @@ span.fc-badge {
847870
.fc-badge-light-gray {
848871
background-color: #bcbcbc;
849872
color: #444 !important;
850-
}
873+
}

test/source/tests/setup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,15 +2250,15 @@ AN8G3r5Htj8olot+jm9mIa5XLXWzMNUZgg==
22502250
const title = await settingsPage.read('@container-overlay-prompt-text');
22512251
expect(title).to.contain(
22522252
'Failed to store newly generated key on FlowCrypt Email Key Manager, ' +
2253-
'No key has been generated for [email protected] yet. Please ask your administrator.'
2253+
'No key has been generated for [email protected] yet. Please ask your administrator.'
22542254
);
22552255
await settingsPage.click('@action-show-overlay-details');
22562256
await settingsPage.waitAll('@container-overlay-details');
22572257
await Util.sleep(0.5);
22582258
const details = await settingsPage.read('@container-overlay-details');
22592259
expect(details).to.contain(
22602260
`405 when PUT-ing https://localhost:${t.context.urls?.port}/flowcrypt-email-key-manager/v1/keys/private string: ` +
2261-
'privateKey -> No key has been generated for [email protected] yet'
2261+
'privateKey -> No key has been generated for [email protected] yet'
22622262
);
22632263
expect(details).to.not.contain('PRIVATE KEY');
22642264
})

0 commit comments

Comments
 (0)