From b5a1f40f275de2ba2a42097272cfddabd099771b Mon Sep 17 00:00:00 2001 From: Arnaud Nelissen Date: Fri, 17 Apr 2026 11:07:58 +0200 Subject: [PATCH] Fix equipment profiles: allow selecting active setup and renaming default - All profiles (including the default AT71+ATR2600C) now show Edit and Use buttons - Active profile tracked in localStorage via astronome_active_profile - Default profile is seeded from localStorage on first load so it can be renamed - Delete button only shown when more than one profile exists Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/pages/Settings.tsx | 69 ++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx index c5e83b3..0e120d3 100644 --- a/frontend/src/pages/Settings.tsx +++ b/frontend/src/pages/Settings.tsx @@ -3,15 +3,14 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { api } from '../api'; import type { HorizonPoint } from '../api/types'; -// Current hardcoded setup constants (from config.rs) -const CURRENT_SETUP = { - name: 'AT71 + ATR2600C (current)', +const DEFAULT_PROFILE: EquipProfile = { + id: 'default', + name: 'AT71 + ATR2600C', focal_mm: 490, aperture_mm: 71, pixel_um: 3.76, res_x: 6248, res_y: 4176, - active: true, }; interface EquipProfile { @@ -24,9 +23,18 @@ interface EquipProfile { res_y: number; } +function loadProfiles(): EquipProfile[] { + try { + const stored = JSON.parse(localStorage.getItem('astronome_equip_profiles') ?? '[]') as EquipProfile[]; + // Ensure the default profile is always present + if (!stored.find(p => p.id === 'default')) { + return [DEFAULT_PROFILE, ...stored]; + } + return stored; + } catch { return [DEFAULT_PROFILE]; } +} + function calcProfile(p: { focal_mm: number; aperture_mm: number; pixel_um: number; res_x: number; res_y: number }) { - const plate_scale = (206.265 * p.pixel_um) / (p.focal_mm * 1000 / 1000); - // plate_scale in arcsec/px: (206265 * pixel_size_um / 1000) / focal_mm const ps = (206.265 * p.pixel_um / 1000) / p.focal_mm * 1000; const fov_w_deg = (ps * p.res_x) / 3600; const fov_h_deg = (ps * p.res_y) / 3600; @@ -39,11 +47,10 @@ function calcProfile(p: { focal_mm: number; aperture_mm: number; pixel_um: numbe } function EquipmentProfiles() { - const [profiles, setProfiles] = useState(() => { - try { - return JSON.parse(localStorage.getItem('astronome_equip_profiles') ?? '[]'); - } catch { return []; } - }); + const [profiles, setProfiles] = useState(loadProfiles); + const [activeId, setActiveId] = useState(() => + localStorage.getItem('astronome_active_profile') ?? 'default' + ); const [editing, setEditing] = useState(null); const [adding, setAdding] = useState(false); const [form, setForm] = useState({ name: '', focal_mm: 490, aperture_mm: 71, pixel_um: 3.76, res_x: 6248, res_y: 4176 }); @@ -52,6 +59,10 @@ function EquipmentProfiles() { localStorage.setItem('astronome_equip_profiles', JSON.stringify(profiles)); }, [profiles]); + useEffect(() => { + localStorage.setItem('astronome_active_profile', activeId); + }, [activeId]); + const saveProfile = () => { if (!form.name.trim()) return; if (editing) { @@ -65,7 +76,9 @@ function EquipmentProfiles() { }; const deleteProfile = (id: string) => { + if (profiles.length <= 1) return; setProfiles(ps => ps.filter(p => p.id !== id)); + if (activeId === id) setActiveId(profiles.find(p => p.id !== id)?.id ?? 'default'); }; const startEdit = (p: EquipProfile) => { @@ -74,9 +87,6 @@ function EquipmentProfiles() { setAdding(false); }; - const current = calcProfile(CURRENT_SETUP); - const allProfiles = [{ ...CURRENT_SETUP, id: '__current__' }, ...profiles]; - const fieldStyle: React.CSSProperties = { background: 'var(--bg-void)', border: '1px solid var(--border)', borderRadius: 3, color: 'var(--text-hi)', fontFamily: 'var(--font-mono)', fontSize: 12, @@ -90,19 +100,19 @@ function EquipmentProfiles() {
- {allProfiles.map(p => { + {profiles.map(p => { const calc = calcProfile(p); - const isCurrent = p.id === '__current__'; + const isActive = p.id === activeId; return (
-
-
-
+
+
+
{p.name} - {isCurrent && ACTIVE} + {isActive && ACTIVE}
{p.focal_mm}mm {calc.focal_ratio} · {p.aperture_mm}mm aperture · {p.pixel_um}μm px · {p.res_x}×{p.res_y} @@ -112,16 +122,21 @@ function EquipmentProfiles() { {' · '}FOV: {calc.fov_w}
- {!isCurrent && ( -
- + )} + + {profiles.length > 1 && ( -
- )} + )} +
);