@@ -332,15 +332,6 @@ const UI_THEME_PREFERENCE_KEY = "linksim-ui-theme-v1";
332332const UI_COLOR_THEME_KEY = "linksim-ui-color-theme-v1" ;
333333const BASEMAP_PROVIDER_KEY = "linksim-basemap-provider-v1" ;
334334const BASEMAP_STYLE_PRESET_KEY = "linksim-basemap-style-preset-v1" ;
335- const STORAGE_SNAPSHOT_LIMIT = 5 ;
336-
337- type StoredSnapshot < T > = {
338- savedAtIso : string ;
339- value : T ;
340- } ;
341-
342- const snapshotKeyFor = ( key : string ) : string => `${ key } -snapshots-v1` ;
343- const isSnapshotTrackedKey = ( key : string ) : boolean => key === SITE_LIBRARY_KEY || key === SIM_PRESETS_KEY ;
344335
345336const readStorage = < T , > ( key : string , fallback : T ) : T => {
346337 try {
@@ -362,77 +353,19 @@ const readStorageRawState = <T,>(key: string): { status: "ok" | "missing" | "inv
362353 }
363354} ;
364355
365- const readSnapshotHistory = < T , > ( key : string ) : StoredSnapshot < T > [ ] => {
366- const parsed = readStorage < StoredSnapshot < T > [ ] > ( snapshotKeyFor ( key ) , [ ] ) ;
367- return Array . isArray ( parsed ) ? parsed : [ ] ;
368- } ;
369-
370- const getLatestSnapshotValue = < T , > ( key : string ) : T | null => {
371- const history = readSnapshotHistory < T > ( key ) ;
372- for ( let i = history . length - 1 ; i >= 0 ; i -= 1 ) {
373- const item = history [ i ] ;
374- if ( item && typeof item === "object" && "value" in item ) {
375- return item . value ;
376- }
377- }
378- return null ;
379- } ;
380-
381- const appendSnapshot = ( key : string , value : unknown ) => {
382- if ( ! isSnapshotTrackedKey ( key ) ) return ;
383- const history = readSnapshotHistory < unknown > ( key ) ;
384- const next : StoredSnapshot < unknown > [ ] = [
385- ...history ,
386- {
387- savedAtIso : new Date ( ) . toISOString ( ) ,
388- value,
389- } ,
390- ] . slice ( - STORAGE_SNAPSHOT_LIMIT ) ;
391- localStorage . setItem ( snapshotKeyFor ( key ) , JSON . stringify ( next ) ) ;
392- } ;
393-
394- const writeStorage = ( key : string , value : unknown , options ?: { snapshot ?: boolean } ) : boolean => {
395- const tryWriteWithSnapshot = ( ) : boolean => {
396- try {
397- localStorage . setItem ( key , JSON . stringify ( value ) ) ;
398- if ( options ?. snapshot !== false ) appendSnapshot ( key , value ) ;
399- return true ;
400- } catch {
401- return false ;
402- }
403- } ;
404-
405- const clearAllSnapshots = ( ) : void => {
406- const keys = [ SITE_LIBRARY_KEY , SIM_PRESETS_KEY ] ;
407- for ( const k of keys ) {
408- try {
409- const snapshotKey = snapshotKeyFor ( k ) ;
410- const existing = localStorage . getItem ( snapshotKey ) ;
411- if ( existing ) {
412- localStorage . setItem ( snapshotKey , "[]" ) ;
413- console . log ( `[appStore] Cleared ALL snapshots for "${ k } " due to quota` ) ;
414- }
415- } catch {
416- // Best effort
417- }
418- }
419- } ;
420-
421- if ( tryWriteWithSnapshot ( ) ) {
356+ const writeStorage = ( key : string , value : unknown ) : boolean => {
357+ try {
358+ localStorage . setItem ( key , JSON . stringify ( value ) ) ;
422359 return true ;
360+ } catch ( error ) {
361+ console . error ( `[appStore] Failed to write to localStorage (${ key } ):` , error ) ;
362+ return false ;
423363 }
364+ } ;
424365
425- console . error ( `[appStore] localStorage QUOTA EXCEEDED for key "${ key } ". Clearing snapshots and retrying...` ) ;
426- clearAllSnapshots ( ) ;
366+ const getLatestSnapshotValue = < T , > ( _key : string ) : T | null => null ;
427367
428- if ( tryWriteWithSnapshot ( ) ) {
429- console . log ( `[appStore] Retry after clearing snapshots succeeded` ) ;
430- return true ;
431- }
432368
433- console . error ( `[appStore] localStorage QUOTA EXCEEDED (retry failed) for key "${ key } "` ) ;
434- return false ;
435- } ;
436369
437370const makeId = ( prefix : string ) : string =>
438371 `${ prefix } -${ Date . now ( ) . toString ( 36 ) } -${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 8 ) } ` ;
@@ -1132,22 +1065,22 @@ export const useAppStore = create<AppState>((set, get) => ({
11321065 } ,
11331066 setUiThemePreference : ( value ) => {
11341067 const normalized = normalizeUiThemePreference ( value ) ;
1135- writeStorage ( UI_THEME_PREFERENCE_KEY , normalized , { snapshot : false } ) ;
1068+ writeStorage ( UI_THEME_PREFERENCE_KEY , normalized ) ;
11361069 set ( { uiThemePreference : normalized } ) ;
11371070 } ,
11381071 setUiColorTheme : ( value ) => {
11391072 const normalized = normalizeUiColorTheme ( value ) ;
1140- writeStorage ( UI_COLOR_THEME_KEY , normalized , { snapshot : false } ) ;
1073+ writeStorage ( UI_COLOR_THEME_KEY , normalized ) ;
11411074 set ( { uiColorTheme : normalized } ) ;
11421075 } ,
11431076 setBasemapProvider : ( value ) => {
11441077 const normalized = normalizeBasemapProvider ( value ) ;
1145- writeStorage ( BASEMAP_PROVIDER_KEY , normalized , { snapshot : false } ) ;
1078+ writeStorage ( BASEMAP_PROVIDER_KEY , normalized ) ;
11461079 set ( { basemapProvider : normalized } ) ;
11471080 } ,
11481081 setBasemapStylePreset : ( value ) => {
11491082 const normalized = normalizeBasemapStylePreset ( value ) ;
1150- writeStorage ( BASEMAP_STYLE_PRESET_KEY , normalized , { snapshot : false } ) ;
1083+ writeStorage ( BASEMAP_STYLE_PRESET_KEY , normalized ) ;
11511084 set ( { basemapStylePreset : normalized } ) ;
11521085 } ,
11531086 selectScenario : ( id ) => {
@@ -1184,7 +1117,7 @@ export const useAppStore = create<AppState>((set, get) => ({
11841117 mapViewport : scenario . viewport ,
11851118 siteLibrary : libraryBacked . siteLibrary ,
11861119 } ) ;
1187- writeStorage ( LAST_SESSION_KEY , { selectedScenarioId : scenario . id , savedAtIso : new Date ( ) . toISOString ( ) } , { snapshot : false } ) ;
1120+ writeStorage ( LAST_SESSION_KEY , { selectedScenarioId : scenario . id , savedAtIso : new Date ( ) . toISOString ( ) } ) ;
11881121 get ( ) . recomputeCoverage ( ) ;
11891122 } ,
11901123 setSelectedLinkId : ( id ) =>
@@ -1887,7 +1820,7 @@ export const useAppStore = create<AppState>((set, get) => ({
18871820 if ( libraryBacked . addedCount > 0 ) {
18881821 writeStorage ( SITE_LIBRARY_KEY , libraryBacked . siteLibrary ) ;
18891822 }
1890- writeStorage ( LAST_SESSION_KEY , { selectedScenarioId : preset . id , savedAtIso : new Date ( ) . toISOString ( ) } , { snapshot : false } ) ;
1823+ writeStorage ( LAST_SESSION_KEY , { selectedScenarioId : preset . id , savedAtIso : new Date ( ) . toISOString ( ) } ) ;
18911824 get ( ) . recomputeCoverage ( ) ;
18921825 } ,
18931826 renameSimulationPreset : ( presetId , name ) => {
0 commit comments