Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 49 additions & 6 deletions extension/chrome/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,24 +496,67 @@ View.run(
private addKeyRowsHtml = async (privateKeys: KeyInfoWithIdentity[]) => {
let html = '';
const canRemoveKey = !this.clientConfiguration?.usesKeyManager();

// 1. Parse and prepare data
const rows = [];
for (let i = 0; i < privateKeys.length; i++) {
const ki = privateKeys[i];
const prv = await KeyUtil.parse(ki.private);
const created = new Date(prv.created);
const date = Str.monthName(created.getMonth()) + ' ' + created.getDate() + ', ' + created.getFullYear();
const isExpired = KeyUtil.expired(prv);
rows.push({
ki,
prv,
createdTime: prv.created,
dateStr: date,
isExpired,
originalIndex: i,
});
}

// 2. Sort: newest to oldest
rows.sort((a, b) => b.createdTime - a.createdTime);

// 3. Build HTML
// Header row
html += `
<div class="row key-list-header" style="font-weight: 600; padding: 10px 0; border-bottom: 2px solid #eee;">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use padding: 5px 0; like it was in the previous version, as with 10px padding rows become too high as before.
also what about moving all these newly added styles to css instead of putting them inline into html?

<div class="col-3">Email</div>
<div class="col-2">Created</div>
<div class="col-6">Fingerprint</div>
<div class="col-1">Status</div>
</div>
`;

for (const row of rows) {
const { ki, prv, dateStr, isExpired, originalIndex } = row;

let removeKeyBtn = '';
if (canRemoveKey && privateKeys.length > 1) {
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>)`;
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>`;
}

const escapedEmail = Xss.escape(prv.emails[0] || '');
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>`;
const fpHtml = `fingerprint:&nbsp;<span class="good">${Str.spaced(Xss.escape(ki.fingerprints[0]))}</span>`;
const space = `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`;
html += `<div class="row key-content-row">`;
html += ` <div class="col-12">${escapedLink} from ${Xss.escape(date)}${space}${fpHtml}${space}${KeyUtil.statusHtml(ki.id, prv)}${space}${removeKeyBtn}</div>`;
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>`;
const fpHtml = `<span class="good" style="font-family: monospace;">${Str.spaced(Xss.escape(ki.fingerprints[0]))}</span>`;

const rowClass = isExpired ? 'key-content-row expired' : 'key-content-row';
const opacityStyle = isExpired ? 'opacity: 0.7;' : '';

html += `<div class="row ${rowClass}" style="padding: 10px 0; border-bottom: 1px solid #e6e6e6; align-items: center; ${opacityStyle}">`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that the last row is cut off at the bottom and can't be scrolled, probably because of overflow with bottom bar, need to add some additional margin below keys table to fix it:

Image

html += ` <div class="col-3" style="overflow: hidden; text-overflow: ellipsis;">${escapedLink}</div>`;
html += ` <div class="col-2">${Xss.escape(dateStr)}</div>`;
html += ` <div class="col-6">${fpHtml}</div>`;
html += ` <div class="col-1" style="display: flex; justify-content: space-between; align-items: center;">
${KeyUtil.statusHtml(ki.id, prv)}
${removeKeyBtn}
</div>`;
html += `</div>`;
}

Xss.sanitizeAppend('.key_list', html);

$('.action_show_key').on(
'click',
this.setHandler(async target => {
Expand Down
8 changes: 6 additions & 2 deletions extension/css/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ body#settings .settings-border .row {
}

body#settings .settings-border .key-content-row {
padding: 7px 0;
padding: 4px 0;
border-bottom: 1px solid #e6e6e6;
}

Expand All @@ -544,6 +544,10 @@ body#settings .settings-border .key_list {
height: 219px;
}

.key-content-row.expired {
opacity: 0.7;
}

#settings-row .box img.security-icon {
width: 70px;
}
Expand Down Expand Up @@ -847,4 +851,4 @@ span.fc-badge {
.fc-badge-light-gray {
background-color: #bcbcbc;
color: #444 !important;
}
}
6 changes: 3 additions & 3 deletions test/source/tests/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ AN8G3r5Htj8olot+jm9mIa5XLXWzMNUZgg==
await addKeyPopup.waitAndType('@input-armored-key', updatedKey.privateKey);
await addKeyPopup.waitAndType('#input_passphrase', passphrase);
await addKeyPopup.waitAndClick('.action_add_private_key', { delay: 1 });
await Util.sleep(1);
await settingsPage.waitAll('@action-show-key-1');
await gmailPage.page.reload();
await Util.sleep(3);
await gmailPage.waitTillGone('@webmail-notification-notify_expiring_keys');
Expand Down Expand Up @@ -2250,15 +2250,15 @@ AN8G3r5Htj8olot+jm9mIa5XLXWzMNUZgg==
const title = await settingsPage.read('@container-overlay-prompt-text');
expect(title).to.contain(
'Failed to store newly generated key on FlowCrypt Email Key Manager, ' +
'No key has been generated for [email protected] yet. Please ask your administrator.'
'No key has been generated for [email protected] yet. Please ask your administrator.'
);
await settingsPage.click('@action-show-overlay-details');
await settingsPage.waitAll('@container-overlay-details');
await Util.sleep(0.5);
const details = await settingsPage.read('@container-overlay-details');
expect(details).to.contain(
`405 when PUT-ing https://localhost:${t.context.urls?.port}/flowcrypt-email-key-manager/v1/keys/private string: ` +
'privateKey -> No key has been generated for [email protected] yet'
'privateKey -> No key has been generated for [email protected] yet'
);
expect(details).to.not.contain('PRIVATE KEY');
})
Expand Down
Loading