optimize settings store

This commit is contained in:
jeffvli
2026-01-02 03:13:17 -08:00
parent 0cfc4119ba
commit a66c67e86d
72 changed files with 479 additions and 354 deletions
+137 -6
View File
@@ -1,4 +1,5 @@
import isElectron from 'is-electron';
import merge from 'lodash/merge';
import { generatePath } from 'react-router';
import { z } from 'zod';
import { devtools, persist } from 'zustand/middleware';
@@ -42,6 +43,17 @@ type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
const deepMergeIntoState = <T extends Record<string, any>>(
state: T,
updates: DeepPartial<T>,
): void => {
// Skip 'actions' property
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { actions, ...updatesWithoutActions } = updates as any;
merge(state, updatesWithoutActions);
};
const HomeItemSchema = z.enum([
'genres',
'mostPlayed',
@@ -767,7 +779,7 @@ export interface SettingsSlice extends z.infer<typeof SettingsStateSchema> {
setHomeItems: (item: SortableItem<HomeItem>[]) => void;
setList: (type: ItemListKey, data: DeepPartial<ItemListSettings>) => void;
setPlaybackFilters: (filters: PlayerFilter[]) => void;
setSettings: (data: Partial<SettingsState>) => void;
setSettings: (data: DeepPartial<SettingsState>) => void;
setSidebarItems: (items: SidebarItemType[]) => void;
setTable: (type: ItemListKey, data: DataTableProps) => void;
setTranscodingConfig: (config: TranscodingConfig) => void;
@@ -1642,7 +1654,7 @@ const getInitialState = (): SettingsState => {
export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
persist(
devtools(
immer((set, get) => ({
immer((set) => ({
actions: {
reset: () => {
const freshState = getInitialState();
@@ -1723,7 +1735,9 @@ export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
});
},
setSettings: (data) => {
set({ ...get(), ...data });
set((state) => {
deepMergeIntoState(state, data);
});
},
setSidebarItems: (items: SidebarItemType[]) => {
set((state) => {
@@ -1980,11 +1994,128 @@ export const useListSettings = (type: ItemListKey) =>
shallow,
) as ItemListSettings;
export const usePrimaryColor = () => useSettingsStore((store) => store.general.accent);
export const usePrimaryColor = () => useSettingsStore((store) => store.general.accent, shallow);
export const usePlayerbarSlider = () => useSettingsStore((store) => store.general.playerbarSlider);
export const usePlayerbarSlider = () =>
useSettingsStore((store) => store.general.playerbarSlider, shallow);
export const useGenreTarget = () => useSettingsStore((store) => store.general.genreTarget);
export const useGenreTarget = () => useSettingsStore((store) => store.general.genreTarget, shallow);
export const useLanguage = () => useSettingsStore((state) => state.general.language, shallow);
export const useAccent = () => useSettingsStore((state) => state.general.accent, shallow);
export const useNativeAspectRatio = () =>
useSettingsStore((state) => state.general.nativeAspectRatio, shallow);
export const useButtonSize = () => useSettingsStore((state) => state.general.buttonSize, shallow);
export const useSkipButtons = () => useSettingsStore((state) => state.general.skipButtons, shallow);
export const useImageRes = () => useSettingsStore((state) => state.general.imageRes, shallow);
export const useVolumeWidth = () => useSettingsStore((state) => state.general.volumeWidth, shallow);
export const useFollowCurrentSong = () =>
useSettingsStore((state) => state.general.followCurrentSong, shallow);
export const useThemeSettings = () =>
useSettingsStore(
(state) => ({
followSystemTheme: state.general.followSystemTheme,
theme: state.general.theme,
themeDark: state.general.themeDark,
themeLight: state.general.themeLight,
useThemeAccentColor: state.general.useThemeAccentColor,
}),
shallow,
);
export const useSideQueueType = () =>
useSettingsStore((state) => state.general.sideQueueType, shallow);
export const useVolumeWheelStep = () =>
useSettingsStore((state) => state.general.volumeWheelStep, shallow);
export const useSidebarPlaylistList = () =>
useSettingsStore((state) => state.general.sidebarPlaylistList, shallow);
export const useSidebarItems = () =>
useSettingsStore((state) => state.general.sidebarItems, shallow);
export const useSidebarCollapsedNavigation = () =>
useSettingsStore((state) => state.general.sidebarCollapsedNavigation, shallow);
export const usePlayerbarOpenDrawer = () =>
useSettingsStore((state) => state.general.playerbarOpenDrawer, shallow);
export const useShowRatings = () => useSettingsStore((state) => state.general.showRatings, shallow);
export const useArtistRadioCount = () =>
useSettingsStore((state) => state.general.artistRadioCount, shallow);
export const useArtistBackground = () =>
useSettingsStore(
(state) => ({
artistBackground: state.general.artistBackground,
artistBackgroundBlur: state.general.artistBackgroundBlur,
}),
shallow,
);
export const useAlbumBackground = () =>
useSettingsStore(
(state) => ({
albumBackground: state.general.albumBackground,
albumBackgroundBlur: state.general.albumBackgroundBlur,
}),
shallow,
);
export const useExternalLinks = () =>
useSettingsStore(
(state) => ({
externalLinks: state.general.externalLinks,
lastFM: state.general.lastFM,
musicBrainz: state.general.musicBrainz,
}),
shallow,
);
export const useHomeFeature = () => useSettingsStore((state) => state.general.homeFeature, shallow);
export const useHomeItems = () => useSettingsStore((state) => state.general.homeItems, shallow);
export const useArtistItems = () => useSettingsStore((state) => state.general.artistItems, shallow);
export const useArtistReleaseTypeItems = () =>
useSettingsStore((state) => state.general.artistReleaseTypeItems, shallow);
export const useZoomFactor = () => useSettingsStore((state) => state.general.zoomFactor, shallow);
export const usePathReplace = () =>
useSettingsStore(
(state) => ({
pathReplace: state.general.pathReplace,
pathReplaceWith: state.general.pathReplaceWith,
}),
shallow,
);
export const useLastfmApiKey = () =>
useSettingsStore((state) => state.general.lastfmApiKey, shallow);
export const useSidebarPanelOrder = () =>
useSettingsStore((state) => state.general.sidebarPanelOrder, shallow);
export const useCombinedLyricsAndVisualizer = () =>
useSettingsStore((state) => state.general.combinedLyricsAndVisualizer, shallow);
export const useShowLyricsInSidebar = () =>
useSettingsStore((state) => state.general.showLyricsInSidebar, shallow);
export const useShowVisualizerInSidebar = () =>
useSettingsStore((state) => state.general.showVisualizerInSidebar, shallow);
export const useAutoDJSettings = () => useSettingsStore((store) => store.autoDJ, shallow);