feat(cluster): refresh spot statuses after a log — visibility-gated & debounced
A just-worked call/entity/POTA/prefix/slot kept its NEW badge because per-spot status is cached and never expires. Drop the cache on qso:logged so the grid re-evaluates. Kept cheap for old machines / big logbooks: only fires while the cluster is on screen (a log while hidden marks it dirty and refreshes once on next open), and debounced 2 s so a fast run coalesces instead of re-scanning the logbook per QSO.
This commit is contained in:
+4
-2
@@ -5,12 +5,14 @@
|
|||||||
"en": [
|
"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.",
|
"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."
|
"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.",
|
||||||
|
"DX Cluster: after you log a QSO, the spots update — a callsign, entity, POTA, prefix or band/mode slot you just worked stops showing its NEW badge, instead of staying \"new\" until a restart. Kept fast: it re-evaluates only while the cluster is actually on screen (nothing runs otherwise — a QSO logged while it's hidden refreshes once when you next open it), and it's debounced so a quick run doesn't re-scan on every QSO."
|
||||||
],
|
],
|
||||||
"fr": [
|
"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.",
|
"É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."
|
"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.",
|
||||||
|
"DX Cluster : après avoir loggué un QSO, les spots se mettent à jour — un indicatif, une entité, un POTA, un préfixe ou un slot bande/mode que vous venez de contacter cesse d'afficher son badge NEW, au lieu de rester « new » jusqu'au redémarrage. Reste rapide : la réévaluation n'a lieu que si le cluster est affiché (sinon rien ne tourne — un QSO loggué cluster caché se rafraîchit une fois à sa réouverture), et c'est débouncé pour ne pas re-scanner à chaque QSO en série."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1500,6 +1500,34 @@ export default function App() {
|
|||||||
// still need resolving without re-subscribing the cluster:spot listener.
|
// still need resolving without re-subscribing the cluster:spot listener.
|
||||||
const spotStatusRef = useRef(spotStatus);
|
const spotStatusRef = useRef(spotStatus);
|
||||||
useEffect(() => { spotStatusRef.current = spotStatus; }, [spotStatus]);
|
useEffect(() => { spotStatusRef.current = spotStatus; }, [spotStatus]);
|
||||||
|
// After a QSO is logged, the call/entity/POTA/prefix/slot just worked is no
|
||||||
|
// longer "new" — but each spot's status is cached and never expires, so the
|
||||||
|
// cluster kept showing the old NEW badge until a restart. Dropping the cache
|
||||||
|
// re-evaluates every visible spot against the fresh logbook (the poll refetches
|
||||||
|
// the now-unknown statuses). Kept CHEAP for old machines / big logbooks:
|
||||||
|
// • only when the cluster is actually on screen — otherwise it costs nothing;
|
||||||
|
// • a log made while it's hidden just marks it dirty and refetches ONCE the
|
||||||
|
// next time you open the cluster;
|
||||||
|
// • debounced, so a fast run coalesces instead of re-scanning per QSO.
|
||||||
|
const clusterVisibleRef = useRef(false);
|
||||||
|
const spotsDirtyRef = useRef(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const vis = mainPaneLeft === 'cluster' || mainPaneRight === 'cluster' || activeTab === 'cluster';
|
||||||
|
if (vis && !clusterVisibleRef.current && spotsDirtyRef.current) {
|
||||||
|
spotsDirtyRef.current = false;
|
||||||
|
setSpotStatus({});
|
||||||
|
}
|
||||||
|
clusterVisibleRef.current = vis;
|
||||||
|
}, [mainPaneLeft, mainPaneRight, activeTab]);
|
||||||
|
useEffect(() => {
|
||||||
|
let t: number | undefined;
|
||||||
|
const off = EventsOn('qso:logged', () => {
|
||||||
|
if (!clusterVisibleRef.current) { spotsDirtyRef.current = true; return; }
|
||||||
|
if (t) window.clearTimeout(t);
|
||||||
|
t = window.setTimeout(() => setSpotStatus({}), 2000);
|
||||||
|
});
|
||||||
|
return () => { off(); if (t) window.clearTimeout(t); };
|
||||||
|
}, []);
|
||||||
// Incoming spots are staged here for a few ms, their status resolved, then
|
// Incoming spots are staged here for a few ms, their status resolved, then
|
||||||
// committed to `spots` together — so a row paints with its NEW BAND/MODE badge
|
// committed to `spots` together — so a row paints with its NEW BAND/MODE badge
|
||||||
// already on, instead of flashing plain text then flipping to the pill.
|
// already on, instead of flashing plain text then flipping to the pill.
|
||||||
|
|||||||
Reference in New Issue
Block a user