diff --git a/changelog.json b/changelog.json index 4a23a56..d71f42e 100644 --- a/changelog.json +++ b/changelog.json @@ -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." ] }, { diff --git a/frontend/src/components/ClusterGrid.tsx b/frontend/src/components/ClusterGrid.tsx index 549db85..2a5995b 100644 --- a/frontend/src/components/ClusterGrid.tsx +++ b/frontend/src/components/ClusterGrid.tsx @@ -410,6 +410,11 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) { const defaultColDef = useMemo(() => ({ 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}`}