fix(autocall): disarm the stored preference, not just the loop
Withdrawing auto-call added a runtime guard and removed every control. The stored preference was left alone, so 'enabled: true' still sits in localStorage on the machines that had it on -- and any build without the guard reads it and keys the transmitter for a feature that no longer has a switch anywhere in the interface. loadAutoCall now switches it off and writes it back the first time it reads it, so the disarming survives a downgrade or a reinstall. Also drops the dead auto-call state left behind in the settings modal. A withdrawn feature that keys a radio has to be disarmed where it is remembered, not only where it runs.
This commit is contained in:
@@ -80,7 +80,6 @@ import {
|
||||
} from '@/components/ui/select';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { writeUiPref } from '@/lib/uiPref';
|
||||
import { loadAutoCall, autoCallKey, type AutoCallSettings, type AutoCallCriteria } from '@/lib/autocall';
|
||||
import { getDateFormat, setDateFormat, type DateFormat } from '@/lib/dateFormat';
|
||||
import { useI18n, FlagGB, FlagFR, type Lang } from '@/lib/i18n';
|
||||
import { useTheme, CONCRETE_THEMES, type ThemeChoice } from '@/lib/theme';
|
||||
@@ -1933,7 +1932,6 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
// feed up or down — so the write has to go where those live.
|
||||
const [bandOpen, setBandOpen] = useState<any>({ enabled: false, bands: [], available: [] });
|
||||
// How a worked square is matched, and what counts as still wanted.
|
||||
const [autoCall, setAutoCall] = useState<AutoCallSettings>(loadAutoCall);
|
||||
const [gridScope, setGridScope] = useState<any>({ scope: 'mix_digi', hunt: 'new', scopes: [] });
|
||||
useEffect(() => { GetGridScopeSettings().then((g) => setGridScope(g as any)).catch(() => {}); }, []);
|
||||
const saveGridScope = async (next: any) => {
|
||||
|
||||
@@ -72,13 +72,26 @@ export function loadAutoCall(): AutoCallSettings {
|
||||
const raw = localStorage.getItem(AC_KEY);
|
||||
if (!raw) return { ...defaultAutoCall };
|
||||
const v = JSON.parse(raw);
|
||||
return {
|
||||
const out: AutoCallSettings = {
|
||||
...defaultAutoCall,
|
||||
...v,
|
||||
criteria: { ...emptyCriteria, ...(v?.criteria ?? {}) },
|
||||
watchCriteria: { ...emptyCriteria, ...(v?.watchCriteria ?? {}) },
|
||||
watch: Array.isArray(v?.watch) ? v.watch : [],
|
||||
};
|
||||
// DISARMED ON SIGHT, and written back disabled.
|
||||
//
|
||||
// The runtime guard in App.tsx stops this build from calling anyone, but it
|
||||
// leaves "enabled": true sitting in storage, where any build without the
|
||||
// guard — an older one an operator reinstalls, a machine that upgrades
|
||||
// later — reads it and keys the transmitter for a feature with no switch
|
||||
// left to turn off. A withdrawn feature that keys a radio has to be
|
||||
// disarmed where it is REMEMBERED, not only where it runs.
|
||||
if (out.enabled) {
|
||||
out.enabled = false;
|
||||
try { localStorage.setItem(AC_KEY, JSON.stringify(out)); } catch { /* private mode: the guard still holds */ }
|
||||
}
|
||||
return out;
|
||||
} catch { return { ...defaultAutoCall }; }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user