fix(awards): the RDA comparison list no longer jumps back to the top
Two faults, one behind the other. RDAPanel is nested inside SettingsModal so it can read its state, and it was written as <RDAPanel />. A nested function is a new component TYPE on every render: React cannot know it is the same panel, so it unmounted the tree and mounted a fresh one — and a fresh scroll container starts at the top. It is called now, like the other panels, which produces the same elements in place and never disturbs the scroll position. What it was reacting to should not have reached it either. The PSK Reporter and grid-cache poll ran every three seconds from wherever you were in Preferences, re-rendering the whole dialog for a count shown only on the cluster section. It now runs while that section is open, and the one-time loads it was sharing an effect with have stayed where they were rather than refetching on every click in the sidebar. The visible result: a hundred contacts to correct can be read from top to bottom.
This commit is contained in:
+4
-2
@@ -14,7 +14,8 @@
|
||||
"An editable list of satellites (Preferences → Lists → Satellites). The satellite-name field on the entry form offers them as a dropdown, alphabetically, and still accepts anything typed. SAT_NAME is compared character for character by the awards and by LoTW — AO-91 and AO91 are two different satellites to everything downstream — so a remembered spelling beats one retyped on every pass.",
|
||||
"Awards, RDA district comparison: the conflict list is taller and scrolls, a callsign in it opens the contact, and the compare and fill-districts buttons say they are working. The list was capped at about six visible rows out of two hundred, in a panel that would not scroll to the rest, and nothing in it could be acted on.",
|
||||
"Preferences no longer redraw with the main window. Being a child of the main view, the whole panel was rebuilt on every cluster spot and every CAT update — several times a second on a busy evening — which looked like a page refreshing constantly and made buttons miss their clicks, the element under the pointer being replaced between the press and the release.",
|
||||
"A launch that fails before the window exists now says why, on screen and in a startup log kept outside the data folder. Every fault before that point was invisible — no window, no folder, no file to read — and the causes are named: a missing or blocked WebView2 runtime, an 'Edge blocker' tool stopping the engine OpsLog draws its interface with, a folder Windows refuses to write to, a copy already running. WebView2 also gets its own profile folder on the local disk, retries without GPU acceleration after a launch that hung, and can use a fixed-version runtime dropped beside OpsLog where the installer cannot run."
|
||||
"A launch that fails before the window exists now says why, on screen and in a startup log kept outside the data folder. Every fault before that point was invisible — no window, no folder, no file to read — and the causes are named: a missing or blocked WebView2 runtime, an 'Edge blocker' tool stopping the engine OpsLog draws its interface with, a folder Windows refuses to write to, a copy already running. WebView2 also gets its own profile folder on the local disk, retries without GPU acceleration after a launch that hung, and can use a fixed-version runtime dropped beside OpsLog where the installer cannot run.",
|
||||
"Awards, RDA district comparison: the list stays where it was put. It was thrown back to the first row every three seconds, which made a long list of contacts to correct impossible to work through."
|
||||
],
|
||||
"fr": [
|
||||
"Console Elecraft : les mesures d'émission sont lues dès que la RADIO se déclare en émission, et plus seulement quand OpsLog l'a mise en émission. Passer en émission par le PTT de façade, une pédale ou le bouton du micro laissait le panneau croire à une réception — et comme les barres de puissance et de ROS ne sont lues qu'en émission, elles ne l'étaient jamais pour qui manipule à la main.",
|
||||
@@ -28,7 +29,8 @@
|
||||
"Une liste de satellites éditable (Préférences → Listes → Satellites). Le champ du nom de satellite dans la saisie les propose en liste déroulante, par ordre alphabétique, et accepte toujours ce qu'on tape. SAT_NAME est comparé caractère par caractère par les diplômes et par LoTW — AO-91 et AO91 sont deux satellites différents pour tout ce qui suit — donc une orthographe mémorisée vaut mieux qu'une ressaisie à chaque passage.",
|
||||
"Diplômes, comparaison des districts RDA : la liste des divergences est plus haute et défile, un indicatif y ouvre le contact, et les boutons comparer et remplir les districts disent qu'ils travaillent. Elle était limitée à six lignes visibles environ sur deux cents, dans un panneau qui ne défilait pas pour montrer le reste, et rien n'y était actionnable.",
|
||||
"Les préférences ne se redessinent plus au rythme de la fenêtre principale. Étant un enfant de la vue principale, tout le panneau était reconstruit à chaque spot du cluster et à chaque mise à jour CAT — plusieurs fois par seconde un soir chargé — ce qui donnait l'impression d'une page qui se rafraîchit sans arrêt et faisait rater les clics, l'élément sous le pointeur étant remplacé entre l'appui et le relâchement.",
|
||||
"Un lancement qui échoue avant l'apparition de la fenêtre dit désormais pourquoi, à l'écran et dans un journal de démarrage tenu hors du dossier data. Toute panne survenant avant ce point était invisible — pas de fenêtre, pas de dossier, aucun fichier à lire — et les causes sont nommées : un runtime WebView2 absent ou bloqué, un « bloqueur Edge » qui empêche le moteur avec lequel OpsLog dessine son interface, un dossier où Windows refuse d'écrire, une copie déjà lancée. WebView2 reçoit aussi son propre dossier de profil sur le disque local, réessaie sans accélération GPU après un lancement bloqué, et peut utiliser un runtime en version fixe déposé à côté d'OpsLog là où l'installateur ne peut pas s'exécuter."
|
||||
"Un lancement qui échoue avant l'apparition de la fenêtre dit désormais pourquoi, à l'écran et dans un journal de démarrage tenu hors du dossier data. Toute panne survenant avant ce point était invisible — pas de fenêtre, pas de dossier, aucun fichier à lire — et les causes sont nommées : un runtime WebView2 absent ou bloqué, un « bloqueur Edge » qui empêche le moteur avec lequel OpsLog dessine son interface, un dossier où Windows refuse d'écrire, une copie déjà lancée. WebView2 reçoit aussi son propre dossier de profil sur le disque local, réessaie sans accélération GPU après un lancement bloqué, et peut utiliser un runtime en version fixe déposé à côté d'OpsLog là où l'installateur ne peut pas s'exécuter.",
|
||||
"Diplômes, comparaison des districts RDA : la liste reste où on l'a laissée. Elle revenait à la première ligne toutes les trois secondes, ce qui rendait impraticable une longue liste de contacts à corriger."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2050,14 +2050,22 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
|
||||
try { const n = await GetSpotTTLMinutes(); setSpotTTL(n); setSpotTTLText(String(n)); } catch { /* defaults stand */ }
|
||||
try { const n = await GetSpotMax(); setSpotMaxText(String(n)); } catch { /* defaults stand */ }
|
||||
})();
|
||||
// Poll the feed while the panel is open: a live count is the only thing that
|
||||
// distinguishes "connected" from "connected and receiving nothing".
|
||||
}, []);
|
||||
// Poll the feed only while the section that SHOWS it is open.
|
||||
//
|
||||
// A live count is the one thing that separates "connected" from "connected
|
||||
// and receiving nothing", so it has to be polled — but it was polled from
|
||||
// everywhere, re-rendering the whole dialog every three seconds whichever
|
||||
// panel was in front. That is a heartbeat through every list and every form
|
||||
// in Preferences for a number nobody is looking at.
|
||||
useEffect(() => {
|
||||
if (selected !== 'cluster') return;
|
||||
const t = window.setInterval(async () => {
|
||||
try { setPskrStatus(await GetPSKReporterStatus()); } catch { /* ignore */ }
|
||||
try { setGridStat(await GetGridCacheStatus()); } catch { /* ignore */ }
|
||||
}, 3000);
|
||||
return () => window.clearInterval(t);
|
||||
}, []);
|
||||
}, [selected]);
|
||||
const [selfSpot, setSelfSpot] = useState({ enabled: false, minutes: SELF_SPOT_MIN_MIN });
|
||||
const [selfSpotText, setSelfSpotText] = useState(String(SELF_SPOT_MIN_MIN));
|
||||
const [clusterStatuses, setClusterStatuses] = useState<ClusterServerStatus[]>([]);
|
||||
@@ -7560,7 +7568,16 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
|
||||
uscounties: USCountiesPanel,
|
||||
databases: DatabasesPanel,
|
||||
autostart: () => <AutostartPanelComponent />,
|
||||
awards: () => (<div className="space-y-6"><AwardsSelectionPanel profile={activeProfile ?? undefined} /><RDAPanel /></div>),
|
||||
// RDAPanel is CALLED, not written as <RDAPanel />.
|
||||
//
|
||||
// It is nested inside this component, so as an element it would be a new
|
||||
// component TYPE on every render — React cannot know it is the same panel,
|
||||
// so it unmounts the old tree and mounts a fresh one. A fresh scroll
|
||||
// container starts at the top, which is what threw the district comparison
|
||||
// back to the first row every three seconds. Calling it produces the same
|
||||
// elements in place, and the scroll position is simply never disturbed.
|
||||
// (Safe because RDAPanel holds no hooks of its own — see PanelHost.)
|
||||
awards: () => (<div className="space-y-6"><AwardsSelectionPanel profile={activeProfile ?? undefined} />{RDAPanel()}</div>),
|
||||
cat: CATPanel,
|
||||
rotator: RotatorPanel,
|
||||
winkeyer: WinkeyerPanel,
|
||||
|
||||
Reference in New Issue
Block a user