Live video on the AT Protocol
at eli/fix-postgres-locking 124 lines 3.7 kB view raw
1import { createAppSlice } from "../../hooks/createSlice"; 2import WebStorage from "../../storage/storage"; 3 4const storage = new WebStorage(); 5export const SIDEBAR_STORAGE_KEY = "sidebarState"; 6 7export interface SidebarState { 8 isCollapsed: boolean; 9 // should only be used in fullscreen 10 isHidden: boolean; 11 targetWidth: number; 12 isLoaded: boolean; 13} 14 15const initialState: SidebarState = { 16 isCollapsed: false, 17 isHidden: false, 18 targetWidth: 250, 19 isLoaded: false, 20}; 21 22function verifySidebarState(state: any): SidebarState { 23 const verifiedState: SidebarState = { 24 isCollapsed: 25 typeof state.isCollapsed === "boolean" ? state.isCollapsed : false, 26 isHidden: typeof state.isHidden === "boolean" ? state.isHidden : false, 27 targetWidth: 28 typeof state.targetWidth === "number" ? state.targetWidth : 250, 29 isLoaded: false, 30 }; 31 32 if (!verifiedState.isHidden) { 33 if (verifiedState.targetWidth < 64) { 34 verifiedState.targetWidth = 64; 35 } 36 } else { 37 verifiedState.targetWidth = 0; 38 } 39 40 return verifiedState; 41} 42 43export const sidebarSlice = createAppSlice({ 44 name: "sidebar", 45 initialState, 46 reducers: (create) => ({ 47 setSidebarHidden: create.reducer((state) => { 48 state.isHidden = true; 49 state.targetWidth = 50 state.isCollapsed || state.isHidden ? (state.isHidden ? 0 : 64) : 250; 51 }), 52 setSidebarUnhidden: create.reducer((state) => { 53 state.isHidden = false; 54 state.targetWidth = 55 state.isCollapsed || state.isHidden ? (state.isHidden ? 0 : 64) : 250; 56 }), 57 toggleSidebar: create.reducer((state) => { 58 state.isCollapsed = !state.isCollapsed; 59 state.targetWidth = 60 state.isCollapsed || state.isHidden ? (state.isHidden ? 0 : 64) : 250; 61 }), 62 loadStateFromStorage: create.asyncThunk( 63 async () => { 64 const storedStateString = await storage.getItem(SIDEBAR_STORAGE_KEY); 65 if (storedStateString) { 66 let state = JSON.parse(storedStateString); 67 // should never be 'true' on load, component should ALWAYS request to hide sidebar when loaded 68 state.isHidden = false; 69 return verifySidebarState(state) as SidebarState; 70 } 71 return null; 72 }, 73 { 74 pending: (state) => { 75 // unlikely that this will hang for a noticeable duration 76 }, 77 fulfilled: (state, action) => { 78 if (action.payload) { 79 state.isCollapsed = action.payload.isCollapsed; 80 state.targetWidth = action.payload.targetWidth; 81 console.log( 82 "Sidebar state loaded from localStorage:", 83 action.payload, 84 ); 85 } else { 86 console.log( 87 "No sidebar state found in localStorage, using defaults.", 88 ); 89 } 90 state.isLoaded = true; 91 }, 92 rejected: (state, action) => { 93 state.isLoaded = true; 94 console.error( 95 "Failed to load sidebar state from storage, using defaults:", 96 action.error, 97 ); 98 // use defaults 99 state.isCollapsed = false; 100 state.targetWidth = 250; 101 }, 102 }, 103 ), 104 }), 105 selectors: { 106 selectIsSidebarCollapsed: (state) => state.isCollapsed, 107 selectSidebarTargetWidth: (state) => state.targetWidth, 108 selectIsSidebarLoaded: (state) => state.isLoaded, 109 selectIsSidebarHidden: (state) => state.isHidden, 110 }, 111}); 112 113export const { 114 toggleSidebar, 115 loadStateFromStorage, 116 setSidebarHidden, 117 setSidebarUnhidden, 118} = sidebarSlice.actions; 119export const { 120 selectIsSidebarCollapsed, 121 selectSidebarTargetWidth, 122 selectIsSidebarLoaded, 123 selectIsSidebarHidden, 124} = sidebarSlice.selectors;