@@ -329,7 +329,7 @@ import { LogLevel, useUiStore } from "@/stores/ui";
329329import { HelpTip } from " dwc-plugin-runtime" ;
330330
331331import CaptureChart from " ./CaptureChart.vue" ;
332- import { CAPTURE_DIR , DOCS } from " ../model/constants" ;
332+ import { CAPTURE_DIR , DOCS , LS_STATE } from " ../model/constants" ;
333333import {
334334 buildCalibrationCommand , buildCaptureCommand , buildModeCommand , buildPidCommand ,
335335 CALIBRATION_MOVES , CAPTURE_VARIABLES , DEFAULT_MODE_D , ENCODER_TYPES , MODE_LABELS ,
@@ -357,30 +357,60 @@ const modeHelp: Record<LoopMode, string> = {
357357};
358358const stepTitles = [" 1. Driver" , " 2. Loop mode" , " 3. Calibrate" , " 4. Tune PID" , " 5. Test & save" ];
359359
360- const step = ref (1 );
361- const selectedDriver = ref <string | null >(null );
362- const currentMode = ref <LoopMode | null >(null );
363- const encoderType = ref <EncoderType >(2 );
364- const modeD = reactive ({ ... DEFAULT_MODE_D });
365- const pid = reactive <PidConfig >({ p: 100 , i: 0 , d: 0 , v: 0 , a: 0 , warn: null , err: null });
360+ // Persisted UI state — restored on mount so navigating away and back keeps your place.
361+ interface SavedState {
362+ step? : number ; wizardIndex? : number ; selectedDriver? : string | null ; currentMode? : LoopMode | null ;
363+ encoderType? : EncoderType ; modeD? : Partial <typeof DEFAULT_MODE_D >; pid? : Partial <PidConfig >;
364+ samples? : number ; sampleRate? : number ; moveMode? : " step" | " custom" ; customMove? : string ;
365+ recordKeys? : Array <string >; viewKeys? : Array <string >;
366+ }
367+ function loadState(): SavedState {
368+ try { return JSON .parse (localStorage .getItem (LS_STATE ) ?? " {}" ) as SavedState ; } catch { return {}; }
369+ }
370+ const saved = loadState ();
371+
372+ const step = ref (saved .step ?? 1 );
373+ const selectedDriver = ref <string | null >(saved .selectedDriver ?? null );
374+ const currentMode = ref <LoopMode | null >(saved .currentMode ?? null );
375+ const encoderType = ref <EncoderType >(saved .encoderType ?? 2 );
376+ const modeD = reactive ({ ... DEFAULT_MODE_D , ... (saved .modeD ?? {}) });
377+ const pid = reactive <PidConfig >({ p: 100 , i: 0 , d: 0 , v: 0 , a: 0 , warn: null , err: null , ... (saved .pid ?? {}) });
366378const applyingPid = ref (false );
367379
368- const samples = ref (2000 );
369- const sampleRate = ref (2000 );
370- const moveMode = ref <" step" | " custom" >(" step" );
371- const customMove = ref (" G91 G1 H2 X50 F6000 G90" );
372- const recordKeys = ref <Array <string >>([" measuredMotorSteps" , " targetMotorSteps" , " currentError" , " pidPTerm" ]);
380+ const samples = ref (saved . samples ?? 2000 );
381+ const sampleRate = ref (saved . sampleRate ?? 2000 );
382+ const moveMode = ref <" step" | " custom" >(saved . moveMode ?? " step" );
383+ const customMove = ref (saved . customMove ?? " G91 G1 H2 X50 F6000 G90" );
384+ const recordKeys = ref <Array <string >>(saved . recordKeys ?? [" measuredMotorSteps" , " targetMotorSteps" , " currentError" , " pidPTerm" ]);
373385const recording = ref (false );
374386
375387const capture = ref <ParsedCapture | null >(null );
376388const overlayCapture = ref <ParsedCapture | null >(null );
377389const rawText = ref <string >(" " );
378390const metrics = ref <StepMetrics | null >(null );
379- const viewKeys = ref <Array <string >>([" measuredMotorSteps" , " targetMotorSteps" , " currentError" ]);
391+ const viewKeys = ref <Array <string >>(saved . viewKeys ?? [" measuredMotorSteps" , " targetMotorSteps" , " currentError" ]);
380392
381- const wizardIndex = ref (0 );
393+ const wizardIndex = ref (saved . wizardIndex ?? 0 );
382394const recommendation = ref <Recommendation | null >(null );
383395
396+ // Save the lightweight selections (not the captured CSV) whenever they change, debounced.
397+ let saveTimer: ReturnType <typeof setTimeout > | undefined ;
398+ function persistState(): void {
399+ if (saveTimer ) { clearTimeout (saveTimer ); }
400+ saveTimer = setTimeout (() => {
401+ try {
402+ localStorage .setItem (LS_STATE , JSON .stringify ({
403+ step: step .value , wizardIndex: wizardIndex .value , selectedDriver: selectedDriver .value ,
404+ currentMode: currentMode .value , encoderType: encoderType .value , modeD: { ... modeD }, pid: { ... pid },
405+ samples: samples .value , sampleRate: sampleRate .value , moveMode: moveMode .value ,
406+ customMove: customMove .value , recordKeys: recordKeys .value , viewKeys: viewKeys .value ,
407+ } satisfies SavedState ));
408+ } catch { /* storage unavailable */ }
409+ }, 300 );
410+ }
411+ watch ([step , wizardIndex , selectedDriver , currentMode , encoderType , modeD , pid , samples , sampleRate , moveMode , customMove , recordKeys , viewKeys ],
412+ persistState , { deep: true });
413+
384414// --- Auto-tune ---
385415const autoRunning = ref (false );
386416const autoCancel = ref (false );
0 commit comments