@@ -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: <span class="good">${ Str . spaced ( Xss . escape ( ki . fingerprints [ 0 ] ) ) } </span>` ;
511- const space = ` ` ;
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 => {
0 commit comments