import { create } from "zustand" import { persist, createJSONStorage } from "zustand/middleware" type EntryListViewMode = "compact" | "comfortable" | "expanded" type DisplayDensity = "compact" | "default" | "spacious" type FontSize = "small" | "default" | "large" type TimeDisplayFormat = "relative" | "absolute" type FocusedPanel = "sidebar" | "entryList" | "detailPanel" type SettingsTab = | "subscriptions" | "folders" | "muted-phrases" | "custom-feeds" | "import-export" | "appearance" | "account" | "billing" | "api" | "danger" interface UserInterfaceState { isSidebarCollapsed: boolean isCommandPaletteOpen: boolean isAddFeedDialogOpen: boolean isSearchOpen: boolean selectedEntryIdentifier: string | null focusedEntryIdentifier: string | null focusedPanel: FocusedPanel focusedSidebarIndex: number entryListViewMode: EntryListViewMode displayDensity: DisplayDensity activeSettingsTab: SettingsTab showFeedFavicons: boolean focusFollowsInteraction: boolean fontSize: FontSize timeDisplayFormat: TimeDisplayFormat showEntryImages: boolean showReadingTime: boolean isShortcutsDialogOpen: boolean expandedFolderIdentifiers: string[] navigableEntryIdentifiers: string[] resetSidebarLayout: (() => void) | null resetDetailLayout: (() => void) | null toggleSidebar: () => void setSidebarCollapsed: (isCollapsed: boolean) => void setCommandPaletteOpen: (isOpen: boolean) => void setAddFeedDialogOpen: (isOpen: boolean) => void setSearchOpen: (isOpen: boolean) => void setSelectedEntryIdentifier: (identifier: string | null) => void setFocusedEntryIdentifier: (identifier: string | null) => void setFocusedPanel: (panel: FocusedPanel) => void setFocusedSidebarIndex: (index: number) => void setEntryListViewMode: (mode: EntryListViewMode) => void setDisplayDensity: (density: DisplayDensity) => void setActiveSettingsTab: (tab: SettingsTab) => void setShowFeedFavicons: (show: boolean) => void setFocusFollowsInteraction: (enabled: boolean) => void setFontSize: (size: FontSize) => void setTimeDisplayFormat: (format: TimeDisplayFormat) => void setShowEntryImages: (show: boolean) => void setShowReadingTime: (show: boolean) => void setShortcutsDialogOpen: (isOpen: boolean) => void toggleShortcutsDialog: () => void toggleFolderExpansion: (folderIdentifier: string) => void setNavigableEntryIdentifiers: (identifiers: string[]) => void setResetSidebarLayout: (callback: (() => void) | null) => void setResetDetailLayout: (callback: (() => void) | null) => void } export const useUserInterfaceStore = create()( persist( (set) => ({ isSidebarCollapsed: false, isCommandPaletteOpen: false, isAddFeedDialogOpen: false, isSearchOpen: false, selectedEntryIdentifier: null, focusedEntryIdentifier: null, focusedPanel: "entryList", focusedSidebarIndex: 0, entryListViewMode: "comfortable", displayDensity: "default", activeSettingsTab: "subscriptions", showFeedFavicons: true, focusFollowsInteraction: false, fontSize: "default", timeDisplayFormat: "relative", showEntryImages: true, showReadingTime: true, isShortcutsDialogOpen: false, expandedFolderIdentifiers: [], navigableEntryIdentifiers: [], resetSidebarLayout: null, resetDetailLayout: null, toggleSidebar: () => set((state) => ({ isSidebarCollapsed: !state.isSidebarCollapsed })), setSidebarCollapsed: (isCollapsed) => set({ isSidebarCollapsed: isCollapsed }), setCommandPaletteOpen: (isOpen) => set({ isCommandPaletteOpen: isOpen }), setAddFeedDialogOpen: (isOpen) => set({ isAddFeedDialogOpen: isOpen }), setSearchOpen: (isOpen) => set({ isSearchOpen: isOpen }), setSelectedEntryIdentifier: (identifier) => set({ selectedEntryIdentifier: identifier }), setFocusedEntryIdentifier: (identifier) => set({ focusedEntryIdentifier: identifier }), setFocusedPanel: (panel) => set({ focusedPanel: panel }), setFocusedSidebarIndex: (index) => set({ focusedSidebarIndex: index }), setEntryListViewMode: (mode) => set({ entryListViewMode: mode }), setDisplayDensity: (density) => set({ displayDensity: density }), setActiveSettingsTab: (tab) => set({ activeSettingsTab: tab }), setShowFeedFavicons: (show) => set({ showFeedFavicons: show }), setFocusFollowsInteraction: (enabled) => set({ focusFollowsInteraction: enabled }), setFontSize: (size) => set({ fontSize: size }), setTimeDisplayFormat: (format) => set({ timeDisplayFormat: format }), setShowEntryImages: (show) => set({ showEntryImages: show }), setShowReadingTime: (show) => set({ showReadingTime: show }), setShortcutsDialogOpen: (isOpen) => set({ isShortcutsDialogOpen: isOpen }), toggleShortcutsDialog: () => set((state) => ({ isShortcutsDialogOpen: !state.isShortcutsDialogOpen, })), toggleFolderExpansion: (folderIdentifier) => set((state) => { const current = state.expandedFolderIdentifiers const isExpanded = current.includes(folderIdentifier) return { expandedFolderIdentifiers: isExpanded ? current.filter((id) => id !== folderIdentifier) : [...current, folderIdentifier], } }), setNavigableEntryIdentifiers: (identifiers) => set({ navigableEntryIdentifiers: identifiers }), setResetSidebarLayout: (callback) => set({ resetSidebarLayout: callback }), setResetDetailLayout: (callback) => set({ resetDetailLayout: callback }), }), { name: "asa-news-ui-preferences", storage: createJSONStorage(() => { if (typeof window === "undefined") { return { getItem: () => null, setItem: () => {}, removeItem: () => {}, } } return localStorage }), partialize: (state) => ({ entryListViewMode: state.entryListViewMode, displayDensity: state.displayDensity, showFeedFavicons: state.showFeedFavicons, focusFollowsInteraction: state.focusFollowsInteraction, expandedFolderIdentifiers: state.expandedFolderIdentifiers, fontSize: state.fontSize, timeDisplayFormat: state.timeDisplayFormat, showEntryImages: state.showEntryImages, showReadingTime: state.showReadingTime, }), } ) )