perf(cluster): dim spots via cell class, not redrawRows (0.23.6 slowdown)

The "dim spots that represent nothing" feature drove the dimming with getRowStyle
and called api.redrawRows() on EVERY spotStatus update to re-apply it — a full
grid re-render on a firehose of status updates, which pegged the CPU on a busy
cluster (reported as PCs slowing down since 0.23.6). Move the dimming to a
defaultColDef cellClassRules ('opacity-40') that the existing light
refreshCells({force:true}) re-applies; drop redrawRows and getRowStyle.
This commit is contained in:
2026-08-06 00:55:49 +02:00
parent fbd323af26
commit 57a9bed145
2 changed files with 13 additions and 6 deletions
+4 -2
View File
@@ -4,11 +4,13 @@
"date": "",
"en": [
"QSO edit: added the QRZ ↗ button next to the callsign, like the main entry form — one click opens that station's qrz.com profile.",
"PowerGenius XL: the fan mode (Standard / Contest / Broadcast) changes on the amp again. A previous fix dropped the \"setup\" prefix the amp requires (\"setup fanmode=…\"), so the amp rejected the command and the mode snapped straight back. The correct command is restored."
"PowerGenius XL: the fan mode (Standard / Contest / Broadcast) changes on the amp again. A previous fix dropped the \"setup\" prefix the amp requires (\"setup fanmode=…\"), so the amp rejected the command and the mode snapped straight back. The correct command is restored.",
"Performance: fixed a slowdown introduced in 0.23.6. To dim the \"represents nothing\" spots, the DX Cluster grid was redrawing EVERY row on each spot-status update, which pegged the CPU on a busy cluster (some PCs became sluggish). The dimming now updates with a light per-cell refresh instead — same look, no more churn."
],
"fr": [
"Édition de QSO : ajout du bouton QRZ ↗ à côté de l'indicatif, comme dans le formulaire de saisie — un clic ouvre le profil qrz.com de la station.",
"PowerGenius XL : le mode ventilateur (Standard / Contest / Broadcast) change de nouveau sur l'ampli. Un correctif précédent avait retiré le préfixe « setup » exigé par l'ampli (« setup fanmode=… »), qui rejetait donc la commande et le mode revenait aussitôt en arrière. La bonne commande est rétablie."
"PowerGenius XL : le mode ventilateur (Standard / Contest / Broadcast) change de nouveau sur l'ampli. Un correctif précédent avait retiré le préfixe « setup » exigé par l'ampli (« setup fanmode=… »), qui rejetait donc la commande et le mode revenait aussitôt en arrière. La bonne commande est rétablie.",
"Performance : correction d'un ralentissement apparu en 0.23.6. Pour atténuer les spots « qui ne représentent rien », la grille du DX Cluster redessinait TOUTES les lignes à chaque mise à jour de statut, ce qui saturait le CPU sur un cluster actif (des PC devenaient lents). L'atténuation se met désormais à jour via un rafraîchissement léger par cellule — même rendu, sans le brassage."
]
},
{
+9 -4
View File
@@ -410,6 +410,11 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) {
const defaultColDef = useMemo<ColDef>(() => ({
sortable: true, resizable: true, filter: true, suppressMovable: false,
// Dim "represents nothing" spots at the CELL level, via a class that
// refreshCells re-applies. Doing it with a row STYLE needed redrawRows() on
// every status update, which re-rendered the whole grid continuously and
// pegged the CPU on a busy cluster (the 0.23.6 slowdown).
cellClassRules: { 'opacity-40': (p: any) => isDull(statusFor(p)) },
}), []);
// Pass spotStatus through AG Grid's context so cell renderers can look up
@@ -423,9 +428,10 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) {
// won't re-render those cells on its own — force a refresh so e.g. a worked call
// turns blue once its status loads.
useEffect(() => {
// redrawRows (not refreshCells) so getRowStyle re-runs too — the whole-row
// dimming of "represents nothing" spots depends on the status that lands here.
gridRef.current?.api?.redrawRows();
// Light refresh so status-dependent styling — the Call/Band/Mode colours AND
// the dimmed "represents nothing" class (cellClassRules above) — re-applies
// once a status lands, WITHOUT redrawing whole rows (which pegged the CPU).
gridRef.current?.api?.refreshCells({ force: true });
}, [spotStatus]);
// Restore AFTER the profile scope is known — this grid has no key= remount to
@@ -511,7 +517,6 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) {
onColumnVisible={saveColumnState}
onSortChanged={saveColumnState}
onRowClicked={handleRowClicked}
getRowStyle={(p: any) => (isDull(statusFor(p)) ? { opacity: 0.4 } : undefined)}
animateRows={false}
suppressCellFocus
getRowId={(p) => `${(p.data as any).received_at}-${(p.data as any).dx_call}-${(p.data as any).source_id}`}