mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
274 lines
9.9 KiB
TypeScript
274 lines
9.9 KiB
TypeScript
import type { ItemListStateItem } from '/@/renderer/components/item-list/helpers/item-list-state';
|
|
import type { LibraryItem } from '/@/shared/types/domain-types';
|
|
|
|
import merge from 'lodash/merge';
|
|
import { devtools, persist } from 'zustand/middleware';
|
|
import { immer } from 'zustand/middleware/immer';
|
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
|
|
import { AlbumListSort, SortOrder } from '/@/shared/types/domain-types';
|
|
import { Platform } from '/@/shared/types/types';
|
|
|
|
export interface AppSlice extends AppState {
|
|
actions: {
|
|
setAlbumArtistDetailGroupingType: (groupingType: 'all' | 'primary') => void;
|
|
setAlbumArtistDetailSort: (sortBy: AlbumListSort, sortOrder: SortOrder) => void;
|
|
setAlbumArtistIdsMode: (mode: 'and' | 'or') => void;
|
|
setAlbumArtistSelectMode: (mode: 'multi' | 'single') => void;
|
|
setAppStore: (data: Partial<AppSlice>) => void;
|
|
setArtistIdsMode: (mode: 'and' | 'or') => void;
|
|
setArtistSelectMode: (mode: 'multi' | 'single') => void;
|
|
setGenreIdsMode: (mode: 'and' | 'or') => void;
|
|
setGenreSelectMode: (mode: 'multi' | 'single') => void;
|
|
setGlobalExpanded: (value: GlobalExpandedState | null) => void;
|
|
setPageSidebar: (key: string, value: boolean) => void;
|
|
setPrivateMode: (enabled: boolean) => void;
|
|
setShowTimeRemaining: (enabled: boolean) => void;
|
|
setSideBar: (options: Partial<SidebarProps>) => void;
|
|
setTitleBar: (options: Partial<TitlebarProps>) => void;
|
|
};
|
|
}
|
|
|
|
export interface AppState {
|
|
albumArtistDetailSort: {
|
|
groupingType: 'all' | 'primary';
|
|
sortBy: AlbumListSort;
|
|
sortOrder: SortOrder;
|
|
};
|
|
albumArtistIdsMode: 'and' | 'or';
|
|
albumArtistSelectMode: 'multi' | 'single';
|
|
artistIdsMode: 'and' | 'or';
|
|
artistSelectMode: 'multi' | 'single';
|
|
commandPalette: CommandPaletteProps;
|
|
genreIdsMode: 'and' | 'or';
|
|
genreSelectMode: 'multi' | 'single';
|
|
globalExpanded: GlobalExpandedState | null;
|
|
isReorderingQueue: boolean;
|
|
pageSidebar: Record<string, boolean>;
|
|
platform: Platform;
|
|
privateMode: boolean;
|
|
showTimeRemaining: boolean;
|
|
sidebar: SidebarProps;
|
|
titlebar: TitlebarProps;
|
|
}
|
|
|
|
export interface GlobalExpandedState {
|
|
item: ItemListStateItem;
|
|
itemType: LibraryItem;
|
|
}
|
|
|
|
type CommandPaletteProps = {
|
|
close: () => void;
|
|
open: () => void;
|
|
opened: boolean;
|
|
toggle: () => void;
|
|
};
|
|
|
|
type SidebarProps = {
|
|
collapsed: boolean;
|
|
expanded: string[];
|
|
image: boolean;
|
|
leftWidth: string;
|
|
rightExpanded: boolean;
|
|
rightWidth: string;
|
|
};
|
|
|
|
type TitlebarProps = {
|
|
backgroundColor: string;
|
|
outOfView: boolean;
|
|
};
|
|
|
|
export const useAppStore = createWithEqualityFn<AppSlice>()(
|
|
persist(
|
|
devtools(
|
|
immer((set, get) => ({
|
|
actions: {
|
|
setAlbumArtistDetailGroupingType: (groupingType) => {
|
|
set((state) => {
|
|
state.albumArtistDetailSort.groupingType = groupingType;
|
|
});
|
|
},
|
|
setAlbumArtistDetailSort: (sortBy, sortOrder) => {
|
|
set((state) => {
|
|
state.albumArtistDetailSort = {
|
|
...state.albumArtistDetailSort,
|
|
sortBy,
|
|
sortOrder,
|
|
};
|
|
});
|
|
},
|
|
setAlbumArtistIdsMode: (mode) => {
|
|
set((state) => {
|
|
state.albumArtistIdsMode = mode;
|
|
});
|
|
},
|
|
setAlbumArtistSelectMode: (mode) => {
|
|
set((state) => {
|
|
state.albumArtistSelectMode = mode;
|
|
});
|
|
},
|
|
setAppStore: (data) => {
|
|
set({ ...get(), ...data });
|
|
},
|
|
setArtistIdsMode: (mode) => {
|
|
set((state) => {
|
|
state.artistIdsMode = mode;
|
|
});
|
|
},
|
|
setArtistSelectMode: (mode) => {
|
|
set((state) => {
|
|
state.artistSelectMode = mode;
|
|
});
|
|
},
|
|
setGenreIdsMode: (mode) => {
|
|
set((state) => {
|
|
state.genreIdsMode = mode;
|
|
});
|
|
},
|
|
setGenreSelectMode: (mode) => {
|
|
set((state) => {
|
|
state.genreSelectMode = mode;
|
|
});
|
|
},
|
|
setGlobalExpanded: (value) => {
|
|
set((state) => {
|
|
state.globalExpanded = value;
|
|
});
|
|
},
|
|
setPageSidebar: (key, value) => {
|
|
set((state) => {
|
|
state.pageSidebar[key] = value;
|
|
});
|
|
},
|
|
setPrivateMode: (privateMode) => {
|
|
set((state) => {
|
|
state.privateMode = privateMode;
|
|
});
|
|
},
|
|
setShowTimeRemaining: (showTimeRemaining) => {
|
|
set((state) => {
|
|
state.showTimeRemaining = showTimeRemaining;
|
|
});
|
|
},
|
|
setSideBar: (options) => {
|
|
set((state) => {
|
|
state.sidebar = { ...state.sidebar, ...options };
|
|
});
|
|
},
|
|
setTitleBar: (options) => {
|
|
set((state) => {
|
|
state.titlebar = { ...state.titlebar, ...options };
|
|
});
|
|
},
|
|
},
|
|
albumArtistDetailSort: {
|
|
groupingType: 'primary',
|
|
sortBy: AlbumListSort.RELEASE_DATE,
|
|
sortOrder: SortOrder.DESC,
|
|
},
|
|
albumArtistIdsMode: 'and',
|
|
albumArtistSelectMode: 'multi',
|
|
artistIdsMode: 'and',
|
|
artistSelectMode: 'multi',
|
|
commandPalette: {
|
|
close: () => {
|
|
set((state) => {
|
|
state.commandPalette.opened = false;
|
|
});
|
|
},
|
|
open: () => {
|
|
set((state) => {
|
|
state.commandPalette.opened = true;
|
|
});
|
|
},
|
|
opened: false,
|
|
toggle: () => {
|
|
set((state) => {
|
|
state.commandPalette.opened = !state.commandPalette.opened;
|
|
});
|
|
},
|
|
},
|
|
genreIdsMode: 'and',
|
|
genreSelectMode: 'multi',
|
|
globalExpanded: null,
|
|
isReorderingQueue: false,
|
|
pageSidebar: {
|
|
album: true,
|
|
song: true,
|
|
},
|
|
platform: Platform.WINDOWS,
|
|
privateMode: false,
|
|
showTimeRemaining: false,
|
|
sidebar: {
|
|
collapsed: false,
|
|
expanded: [],
|
|
image: false,
|
|
leftWidth: '400px',
|
|
rightExpanded: false,
|
|
rightWidth: '600px',
|
|
},
|
|
titlebar: {
|
|
backgroundColor: '#000000',
|
|
outOfView: false,
|
|
},
|
|
})),
|
|
{ name: 'store_app' },
|
|
),
|
|
{
|
|
merge: (persistedState, currentState) => {
|
|
return merge(currentState, persistedState);
|
|
},
|
|
migrate: (persistedState, version) => {
|
|
if (version <= 2) {
|
|
return {} as AppState;
|
|
}
|
|
|
|
return persistedState;
|
|
},
|
|
name: 'store_app',
|
|
partialize: (state) => {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- ignore non-persisted state
|
|
const { globalExpanded: _, ...rest } = state;
|
|
return rest;
|
|
},
|
|
version: 4,
|
|
},
|
|
),
|
|
);
|
|
|
|
export const useAppStoreActions = () => useAppStore((state) => state.actions);
|
|
|
|
export const useSidebarStore = () => useAppStore((state) => state.sidebar);
|
|
|
|
export const useSidebarRightExpanded = () => useAppStore((state) => state.sidebar.rightExpanded);
|
|
|
|
export const useSetTitlebar = () => useAppStore((state) => state.actions.setTitleBar);
|
|
|
|
export const useTitlebarStore = () => useAppStore((state) => state.titlebar);
|
|
|
|
export const useCommandPalette = () => useAppStore((state) => state.commandPalette);
|
|
|
|
export const usePageSidebar = (key: string): [boolean, (value: boolean) => void] => {
|
|
const isOpen = useAppStore((state) => state.pageSidebar[key] ?? false);
|
|
const setPageSidebar = useAppStore((state) => state.actions.setPageSidebar);
|
|
|
|
const setIsOpen = (value: boolean) => {
|
|
setPageSidebar(key, value);
|
|
};
|
|
|
|
return [isOpen, setIsOpen];
|
|
};
|
|
|
|
export const useGlobalExpanded = () => useAppStore((state) => state.globalExpanded);
|
|
|
|
export const useSetGlobalExpanded = () => useAppStore((state) => state.actions.setGlobalExpanded);
|
|
|
|
export const useGlobalExpandedState = () => {
|
|
const globalExpanded = useGlobalExpanded();
|
|
const setGlobalExpanded = useSetGlobalExpanded();
|
|
|
|
const clearGlobalExpanded = () => setGlobalExpanded(null);
|
|
|
|
return { clearGlobalExpanded, globalExpanded, setGlobalExpanded };
|
|
};
|