import { safeSetItem, safeGetItem } from "@react-buoy/shared-ui"; // Helper functions for persisting panel state using shared storage wrapper const setItem = async (key: string, value: string) => { await safeSetItem(key, value); }; const getItem = async (key: string): Promise => { return safeGetItem(key); }; export interface PanelDimensions { width: number; height: number; top: number; left: number; } export interface PanelState { dimensions: PanelDimensions | null; height: number | null; isFloating: boolean | null; } export interface ModalVisibilityState { isModalOpen: boolean; isDebugModalOpen: boolean; isEnvModalOpen?: boolean; isSentryModalOpen?: boolean; isStorageModalOpen?: boolean; isNetworkModalOpen?: boolean; selectedQueryKey?: string; // JSON stringified QueryKey selectedSection?: string; // For DevTools sections activeFilter?: string | null; // React Query filter state: "fresh", "stale", "fetching", "paused", "inactive" activeTab?: "queries" | "mutations"; selectedMutationId?: string; } // Storage operations /** * Persist the draggable panel dimensions so future sessions can restore the last window size. */ export const savePanelDimensions = async ( storagePrefix: string, dimensions: PanelDimensions, ) => { try { await setItem( `${storagePrefix}_panel_dimensions`, JSON.stringify(dimensions), ); } catch { // Silently fail - persistence is optional } }; /** Remember the last snap height of the panel for bottom-sheet style layouts. */ export const savePanelHeight = async ( storagePrefix: string, height: number, ) => { try { await setItem(`${storagePrefix}_panel_height`, height.toString()); } catch { // Silently fail - persistence is optional } }; /** * Persist whether the panel was in floating mode so we can reopen at the same presentation style. */ export const saveFloatingMode = async ( storagePrefix: string, isFloating: boolean, ) => { try { await setItem(`${storagePrefix}_is_floating_mode`, isFloating.toString()); } catch { // Silently fail - persistence is optional } }; /** * Retrieve persisted panel geometry and presentation mode. Returns null values when nothing was * previously stored so callers can fall back to defaults. */ export const loadPanelState = async ( storagePrefix: string, ): Promise => { try { const [dimensionsStr, heightStr, floatingModeStr] = await Promise.all([ getItem(`${storagePrefix}_panel_dimensions`), getItem(`${storagePrefix}_panel_height`), getItem(`${storagePrefix}_is_floating_mode`), ]); const dimensions = dimensionsStr ? JSON.parse(dimensionsStr) : null; const height = heightStr ? parseInt(heightStr, 10) : null; const isFloating = floatingModeStr ? floatingModeStr === "true" : null; return { dimensions, height, isFloating }; } catch { // Return defaults on error return { dimensions: null, height: null, isFloating: null }; } }; // Modal visibility state operations /** * Persist the comprehensive modal visibility state (open flags, selected query, etc.). Stored as a * single JSON blob keyed by the provided prefix. */ export const saveModalVisibilityState = async ( storagePrefix: string, state: ModalVisibilityState, ) => { try { const stateJson = JSON.stringify(state); // storagePrefix already contains the full key, don't append _modal_state const key = storagePrefix; await setItem(key, stateJson); } catch { // Silently fail - persistence is a nice-to-have feature } }; /** * Read previously persisted modal visibility state. Returns null when no entry is stored or the * payload cannot be parsed. */ export const loadModalVisibilityState = async ( storagePrefix: string, ): Promise => { try { // storagePrefix already contains the full key, don't append _modal_state const key = storagePrefix; const stateStr = await getItem(key); if (stateStr && stateStr !== "") { const parsed = JSON.parse(stateStr); return parsed; } return null; } catch { // Silently fail - persistence is a nice-to-have feature return null; } }; /** * Clear the cached modal visibility state. Useful when all modals close so we avoid reopening * unintentionally on the next session. */ export const clearModalVisibilityState = async (storagePrefix: string) => { try { // storagePrefix already contains the full key, don't append _modal_state const key = storagePrefix; await setItem(key, ""); } catch { // Silently fail - persistence is a nice-to-have feature } };