zulip/store/index.js

86 lines
2.3 KiB
JavaScript

import { createStore } from 'zustand/vanilla'
import { persist, createJSONStorage } from 'zustand/middleware'
import { get, set, del } from 'idb-keyval'
// Create IndexedDB storage adapter with error handling
const storage = createJSONStorage(() => ({
getItem: async (name) => {
try {
const value = await get(name)
return value ?? null
} catch (error) {
console.error('IndexedDB getItem error:', error)
return null // Fallback to null if IndexedDB fails
}
},
setItem: async (name, value) => {
try {
await set(name, value)
} catch (error) {
console.error('IndexedDB setItem error:', error)
// Silently fail - app continues to work without persistence
}
},
removeItem: async (name) => {
try {
await del(name)
} catch (error) {
console.error('IndexedDB removeItem error:', error)
// Silently fail
}
},
}))
export const store = createStore(
persist(
(set, get) => ({
_hydrated: true, // Start as true - persistence happens in background
user: null,
items: [],
route: 'home',
error: null, // For error notifications
// Actions
setUser: (user) => set({ user }),
addItem: (item) => {
try {
if (!item || !item.name || !item.name.trim()) {
throw new Error('Item name is required')
}
set(s => ({ items: [...s.items, item], error: null }))
} catch (error) {
console.error('addItem error:', error)
set({ error: error.message })
setTimeout(() => set({ error: null }), 3000) // Clear after 3s
}
},
removeItem: (id) => {
try {
if (!id) {
throw new Error('Item ID is required')
}
set(s => ({ items: s.items.filter(i => i.id !== id), error: null }))
} catch (error) {
console.error('removeItem error:', error)
set({ error: error.message })
setTimeout(() => set({ error: null }), 3000)
}
},
navigate: (route) => set({ route }),
clearError: () => set({ error: null }),
}),
{
name: 'app-store',
storage,
partialize: (state) => ({
user: state.user,
items: state.items,
route: state.route,
}),
}
)
)