@@ -26,19 +26,30 @@ const OverscanRows = 100;
2626
2727// ---- format helpers ----
2828
29+ function formatNumber4 ( n : number ) : string {
30+ if ( n < 10 ) return n . toFixed ( 2 ) ;
31+ if ( n < 100 ) return n . toFixed ( 1 ) ;
32+ return Math . floor ( n ) . toString ( ) . padStart ( 4 ) ;
33+ }
34+
2935function fmtMem ( bytes : number ) : string {
3036 if ( bytes == null ) return "" ;
31- if ( bytes < 1024 ) return bytes + " B" ;
32- if ( bytes < 1024 * 1024 ) return ( bytes / 1024 ) . toFixed ( 1 ) + " K" ;
33- if ( bytes < 1024 * 1024 * 1024 ) return ( bytes / 1024 / 1024 ) . toFixed ( 1 ) + " M" ;
34- return ( bytes / 1024 / 1024 / 1024 ) . toFixed ( 2 ) + " G" ;
37+ if ( bytes < 1024 ) return formatNumber4 ( bytes ) + " B" ;
38+ if ( bytes < 1024 * 1024 ) return formatNumber4 ( bytes / 1024 ) + " K" ;
39+ if ( bytes < 1024 * 1024 * 1024 ) return formatNumber4 ( bytes / 1024 / 1024 ) + " M" ;
40+ return formatNumber4 ( bytes / 1024 / 1024 / 1024 ) + " G" ;
3541}
3642
3743function fmtCpu ( cpu : number ) : string {
3844 if ( cpu == null ) return "" ;
3945 return cpu . toFixed ( 1 ) + "%" ;
4046}
4147
48+ function fmtLoad ( load : number ) : string {
49+ if ( load == null ) return " " ;
50+ return formatNumber4 ( load ) ;
51+ }
52+
4253// ---- model ----
4354
4455export class ProcessViewerViewModel implements ViewModel {
@@ -434,52 +445,62 @@ export const ProcessViewerView: React.FC<ViewComponentProps<ProcessViewerViewMod
434445 const paddingTop = startIdx * RowHeight ;
435446
436447 const summary = data ?. summary ;
437- const memUsedGb = summary ?. memused != null ? ( summary . memused / 1024 / 1024 / 1024 ) . toFixed ( 1 ) : null ;
438- const memTotalGb = summary ?. memtotal != null ? ( summary . memtotal / 1024 / 1024 / 1024 ) . toFixed ( 1 ) : null ;
448+ const memUsedFmt = summary ?. memused != null ? fmtMem ( summary . memused ) : null ;
449+ const memTotalFmt = summary ?. memtotal != null ? fmtMem ( summary . memtotal ) : null ;
439450 const cpuPct =
440451 summary ?. cpusum != null && summary ?. numcpu != null && summary . numcpu > 0
441- ? ( summary . cpusum / summary . numcpu ) . toFixed ( 1 ) . padStart ( 5 , " " )
452+ ? ( summary . cpusum / summary . numcpu ) . toFixed ( 1 ) . padStart ( 6 , " " )
442453 : null ;
443454
455+ const procCountValue =
456+ totalCount > 0
457+ ? filteredCount < totalCount
458+ ? `${ filteredCount } / ${ totalCount } `
459+ : String ( totalCount ) . padStart ( 5 , " " )
460+ : loading
461+ ? "…"
462+ : error
463+ ? "Err"
464+ : "" ;
465+
466+ const hasSummaryLoad = summary != null && summary . load1 != null ;
467+ const hasSummaryMem = summary != null && memUsedFmt != null ;
468+ const hasSummaryCpu = summary != null && cpuPct != null ;
469+
444470 return (
445471 < div className = "flex flex-col w-full h-full overflow-hidden" ref = { containerRef } >
446472 { /* status bar */ }
447- < div className = "flex shrink-0 items-center gap-4 px-2 py-1 text-xs text-secondary border-b border-white/10 bg-panel" >
448- < StatusIndicator model = { model } />
449- { summary != null && (
450- < >
451- { summary . load1 != null && (
452- < span >
453- Load:{ " " }
454- < span className = "font-mono" >
455- { summary . load1 . toFixed ( 2 ) } { summary . load5 . toFixed ( 2 ) } { " " }
456- { summary . load15 . toFixed ( 2 ) }
457- </ span >
473+ < div className = "shrink-0 text-xs text-secondary border-b border-white/10 bg-panel" >
474+ < div className = "flex items-center gap-4 px-2 pt-1 pb-0" >
475+ < StatusIndicator model = { model } />
476+ { hasSummaryLoad && < span className = "w-[120px] shrink-0" > Load</ span > }
477+ { hasSummaryMem && < span className = "w-[120px] shrink-0" > Mem</ span > }
478+ { hasSummaryCpu && (
479+ < Tooltip content = { `${ summary . numcpu } cores` } placement = "bottom" >
480+ < span className = "w-[70px] shrink-0 cursor-default" >
481+ CPU< span className = "font-mono text-[11px]" > x{ summary . numcpu } </ span >
458482 </ span >
459- ) }
460- { memUsedGb != null && (
461- < span >
462- Mem: < span className = "font-mono" > { memUsedGb } G / { memTotalGb } G</ span >
463- </ span >
464- ) }
465- { cpuPct != null && (
466- < span >
467- CPU: < span className = "font-mono whitespace-pre" > { cpuPct } % ({ summary . numcpu } cores)</ span >
468- </ span >
469- ) }
470- </ >
471- ) }
472- < span className = "ml-auto font-mono" >
473- { totalCount > 0
474- ? filteredCount < totalCount
475- ? `${ filteredCount } / ${ totalCount } processes`
476- : `${ totalCount } processes`
477- : loading
478- ? "Loading…"
479- : error
480- ? "Error"
481- : "" }
482- </ span >
483+ </ Tooltip >
484+ ) }
485+ < span className = "ml-auto" > Procs</ span >
486+ </ div >
487+ < div className = "flex items-center gap-4 px-2 pb-1 pt-0" >
488+ < div className = "w-4 shrink-0" />
489+ { hasSummaryLoad && (
490+ < span className = "font-mono text-[11px] w-[120px] shrink-0 whitespace-pre" >
491+ { fmtLoad ( summary . load1 ) } { fmtLoad ( summary . load5 ) } { fmtLoad ( summary . load15 ) }
492+ </ span >
493+ ) }
494+ { hasSummaryMem && (
495+ < span className = "font-mono text-[11px] w-[120px] shrink-0 whitespace-pre" >
496+ { memUsedFmt } / { memTotalFmt }
497+ </ span >
498+ ) }
499+ { hasSummaryCpu && (
500+ < span className = "font-mono text-[11px] w-[70px] shrink-0 whitespace-pre" > { cpuPct } %</ span >
501+ ) }
502+ < span className = "ml-auto font-mono text-[11px] whitespace-pre" > { procCountValue } </ span >
503+ </ div >
483504 </ div >
484505
485506 { /* error */ }
0 commit comments