Live video on the AT Protocol
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
22export const sidebarSlice = createAppSlice({
23 name: "sidebar",
24 initialState,
25 reducers: (create) => ({
26 setSidebarHidden: create.reducer((state) => {
27 state.isHidden = true;
28 state.targetWidth =
29 state.isCollapsed || state.isHidden ? (state.isHidden ? 0 : 64) : 250;
30 }),
31 setSidebarUnhidden: create.reducer((state) => {
32 state.isHidden = false;
33 state.targetWidth =
34 state.isCollapsed || state.isHidden ? (state.isHidden ? 0 : 64) : 250;
35 }),
36 toggleSidebar: create.reducer((state) => {
37 state.isCollapsed = !state.isCollapsed;
38 state.targetWidth =
39 state.isCollapsed || state.isHidden ? (state.isHidden ? 0 : 64) : 250;
40 }),
41 loadStateFromStorage: create.asyncThunk(
42 async () => {
43 const storedStateString = await storage.getItem(SIDEBAR_STORAGE_KEY);
44 if (storedStateString) {
45 return JSON.parse(storedStateString) as SidebarState;
46 }
47 return null;
48 },
49 {
50 pending: (state) => {
51 // unlikely that this will hang for a noticeable duration
52 },
53 fulfilled: (state, action) => {
54 if (action.payload) {
55 state.isCollapsed = action.payload.isCollapsed;
56 state.targetWidth = action.payload.targetWidth;
57 console.log(
58 "Sidebar state loaded from localStorage:",
59 action.payload,
60 );
61 } else {
62 console.log(
63 "No sidebar state found in localStorage, using defaults.",
64 );
65 }
66 state.isLoaded = true;
67 },
68 rejected: (state, action) => {
69 state.isLoaded = true;
70 console.error(
71 "Failed to load sidebar state from storage, using defaults:",
72 action.error,
73 );
74 // use defaults
75 state.isCollapsed = false;
76 state.targetWidth = 250;
77 },
78 },
79 ),
80 }),
81 selectors: {
82 selectIsSidebarCollapsed: (state) => state.isCollapsed,
83 selectSidebarTargetWidth: (state) => state.targetWidth,
84 selectIsSidebarLoaded: (state) => state.isLoaded,
85 selectIsSidebarHidden: (state) => state.isHidden,
86 },
87});
88
89export const {
90 toggleSidebar,
91 loadStateFromStorage,
92 setSidebarHidden,
93 setSidebarUnhidden,
94} = sidebarSlice.actions;
95export const {
96 selectIsSidebarCollapsed,
97 selectSidebarTargetWidth,
98 selectIsSidebarLoaded,
99 selectIsSidebarHidden,
100} = sidebarSlice.selectors;