Refactor settings store

This commit is contained in:
jeffvli
2022-12-10 15:03:42 -08:00
parent bcc32deda1
commit 06d018883b
7 changed files with 53 additions and 34 deletions
@@ -3,7 +3,7 @@ import { Stack } from '@mantine/core';
import { Slider } from '/@/components/slider'; import { Slider } from '/@/components/slider';
import { Switch } from '/@/components/switch'; import { Switch } from '/@/components/switch';
import { Text } from '/@/components/text'; import { Text } from '/@/components/text';
import { useSettingsStore } from '/@/store/settings.store'; import { useSettingsStore, useSettingsStoreActions } from '/@/store/settings.store';
import type { TableType } from '/@/types'; import type { TableType } from '/@/types';
import { TableColumn } from '/@/types'; import { TableColumn } from '/@/types';
import { MultiSelect } from '/@/components/select'; import { MultiSelect } from '/@/components/select';
@@ -36,7 +36,7 @@ interface TableConfigDropdownProps {
} }
export const TableConfigDropdown = ({ type }: TableConfigDropdownProps) => { export const TableConfigDropdown = ({ type }: TableConfigDropdownProps) => {
const setSettings = useSettingsStore((state) => state.setSettings); const { setSettings } = useSettingsStoreActions();
const tableConfig = useSettingsStore((state) => state.tables); const tableConfig = useSettingsStore((state) => state.tables);
const handleAddOrRemoveColumns = (values: TableColumn[]) => { const handleAddOrRemoveColumns = (values: TableColumn[]) => {
@@ -15,7 +15,11 @@ import {
usePreviousSong, usePreviousSong,
useQueueControls, useQueueControls,
} from '/@/store'; } from '/@/store';
import { useSettingsStore } from '/@/store/settings.store'; import {
useSettingsStore,
useSettingsStoreActions,
useTableSettings,
} from '/@/store/settings.store';
import type { QueueSong, TableType } from '/@/types'; import type { QueueSong, TableType } from '/@/types';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { ErrorBoundary } from 'react-error-boundary'; import { ErrorBoundary } from 'react-error-boundary';
@@ -34,9 +38,9 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: any) => {
const { reorderQueue, setCurrentTrack } = useQueueControls(); const { reorderQueue, setCurrentTrack } = useQueueControls();
const currentSong = useCurrentSong(); const currentSong = useCurrentSong();
const previousSong = usePreviousSong(); const previousSong = usePreviousSong();
const setSettings = useSettingsStore((state) => state.setSettings); const { setSettings } = useSettingsStoreActions();
const { setAppStore } = useAppStoreActions(); const { setAppStore } = useAppStoreActions();
const tableConfig = useSettingsStore((state) => state.tables[type]); const tableConfig = useTableSettings(type);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
get grid() { get grid() {
@@ -3,7 +3,7 @@ import isElectron from 'is-electron';
import { Switch, Select } from '/@/components'; import { Switch, Select } from '/@/components';
import { SettingsOptions } from '/@/features/settings/components/settings-option'; import { SettingsOptions } from '/@/features/settings/components/settings-option';
import { THEME_DATA } from '/@/hooks'; import { THEME_DATA } from '/@/hooks';
import { useSettingsStore } from '/@/store/settings.store'; import { useGeneralSettings, useSettingsStoreActions } from '/@/store/settings.store';
import type { AppTheme } from '/@/themes/types'; import type { AppTheme } from '/@/themes/types';
const FONT_OPTIONS = [ const FONT_OPTIONS = [
@@ -29,8 +29,8 @@ const FONT_OPTIONS = [
]; ];
export const GeneralTab = () => { export const GeneralTab = () => {
const settings = useSettingsStore((state) => state.general); const settings = useGeneralSettings();
const update = useSettingsStore((state) => state.setSettings); const { setSettings } = useSettingsStoreActions();
const options = [ const options = [
{ {
@@ -63,7 +63,7 @@ export const GeneralTab = () => {
defaultValue={settings.fontContent} defaultValue={settings.fontContent}
onChange={(e) => { onChange={(e) => {
if (!e) return; if (!e) return;
update({ setSettings({
general: { general: {
...settings, ...settings,
fontContent: e, fontContent: e,
@@ -83,7 +83,7 @@ export const GeneralTab = () => {
defaultValue={settings.fontHeader} defaultValue={settings.fontHeader}
onChange={(e) => { onChange={(e) => {
if (!e) return; if (!e) return;
update({ setSettings({
general: { general: {
...settings, ...settings,
fontHeader: e, fontHeader: e,
@@ -104,7 +104,7 @@ export const GeneralTab = () => {
<Switch <Switch
defaultChecked={settings.followSystemTheme} defaultChecked={settings.followSystemTheme}
onChange={(e) => { onChange={(e) => {
update({ setSettings({
general: { general: {
...settings, ...settings,
followSystemTheme: e.currentTarget.checked, followSystemTheme: e.currentTarget.checked,
@@ -123,7 +123,7 @@ export const GeneralTab = () => {
data={THEME_DATA} data={THEME_DATA}
defaultValue={settings.theme} defaultValue={settings.theme}
onChange={(e) => { onChange={(e) => {
update({ setSettings({
general: { general: {
...settings, ...settings,
theme: e as AppTheme, theme: e as AppTheme,
@@ -142,7 +142,7 @@ export const GeneralTab = () => {
data={THEME_DATA} data={THEME_DATA}
defaultValue={settings.themeDark} defaultValue={settings.themeDark}
onChange={(e) => { onChange={(e) => {
update({ setSettings({
general: { general: {
...settings, ...settings,
themeDark: e as AppTheme, themeDark: e as AppTheme,
@@ -161,7 +161,7 @@ export const GeneralTab = () => {
data={THEME_DATA} data={THEME_DATA}
defaultValue={settings.themeLight} defaultValue={settings.themeLight}
onChange={(e) => { onChange={(e) => {
update({ setSettings({
general: { general: {
...settings, ...settings,
themeLight: e as AppTheme, themeLight: e as AppTheme,
@@ -17,7 +17,7 @@ import {
import { mpvPlayer } from '#preload'; import { mpvPlayer } from '#preload';
import { SettingsOptions } from '/@/features/settings/components/settings-option'; import { SettingsOptions } from '/@/features/settings/components/settings-option';
import { useCurrentStatus, usePlayerStore } from '/@/store'; import { useCurrentStatus, usePlayerStore } from '/@/store';
import { useSettingsStore } from '/@/store/settings.store'; import { useSettingsStore, useSettingsStoreActions } from '/@/store/settings.store';
import { Play, PlaybackStyle, PlaybackType, PlayerStatus, CrossfadeStyle } from '/@/types'; import { Play, PlaybackStyle, PlaybackType, PlayerStatus, CrossfadeStyle } from '/@/types';
import { localSettings } from '#preload'; import { localSettings } from '#preload';
@@ -28,7 +28,7 @@ const getAudioDevice = async () => {
export const PlaybackTab = () => { export const PlaybackTab = () => {
const settings = useSettingsStore((state) => state.player); const settings = useSettingsStore((state) => state.player);
const update = useSettingsStore((state) => state.setSettings); const { setSettings } = useSettingsStoreActions();
const status = useCurrentStatus(); const status = useCurrentStatus();
const [audioDevices, setAudioDevices] = useState<SelectItem[]>([]); const [audioDevices, setAudioDevices] = useState<SelectItem[]>([]);
const [mpvPath, setMpvPath] = useState(''); const [mpvPath, setMpvPath] = useState('');
@@ -81,7 +81,7 @@ export const PlaybackTab = () => {
defaultValue={settings.type} defaultValue={settings.type}
disabled={status === PlayerStatus.PLAYING} disabled={status === PlayerStatus.PLAYING}
onChange={(e) => { onChange={(e) => {
update({ player: { ...settings, type: e as PlaybackType } }); setSettings({ player: { ...settings, type: e as PlaybackType } });
if (isElectron() && e === PlaybackType.LOCAL) { if (isElectron() && e === PlaybackType.LOCAL) {
const queueData = usePlayerStore.getState().actions.getPlayerData(); const queueData = usePlayerStore.getState().actions.getPlayerData();
mpvPlayer.setQueue(queueData); mpvPlayer.setQueue(queueData);
@@ -152,7 +152,7 @@ export const PlaybackTab = () => {
data={audioDevices} data={audioDevices}
defaultValue={settings.audioDeviceId} defaultValue={settings.audioDeviceId}
disabled={settings.type !== PlaybackType.WEB} disabled={settings.type !== PlaybackType.WEB}
onChange={(e) => update({ player: { ...settings, audioDeviceId: e } })} onChange={(e) => setSettings({ player: { ...settings, audioDeviceId: e } })}
/> />
), ),
description: 'The audio device to use for playback (web player only)', description: 'The audio device to use for playback (web player only)',
@@ -168,7 +168,7 @@ export const PlaybackTab = () => {
]} ]}
defaultValue={settings.style} defaultValue={settings.style}
disabled={settings.type !== PlaybackType.WEB || status === PlayerStatus.PLAYING} disabled={settings.type !== PlaybackType.WEB || status === PlayerStatus.PLAYING}
onChange={(e) => update({ player: { ...settings, style: e as PlaybackStyle } })} onChange={(e) => setSettings({ player: { ...settings, style: e as PlaybackStyle } })}
/> />
), ),
description: 'Adjust the playback style (web player only)', description: 'Adjust the playback style (web player only)',
@@ -188,7 +188,7 @@ export const PlaybackTab = () => {
max={15} max={15}
min={0} min={0}
w={100} w={100}
onChangeEnd={(e) => update({ player: { ...settings, crossfadeDuration: e } })} onChangeEnd={(e) => setSettings({ player: { ...settings, crossfadeDuration: e } })}
/> />
), ),
description: 'Adjust the crossfade duration (web player only)', description: 'Adjust the crossfade duration (web player only)',
@@ -222,7 +222,7 @@ export const PlaybackTab = () => {
width={200} width={200}
onChange={(e) => { onChange={(e) => {
if (!e) return; if (!e) return;
update({ setSettings({
player: { ...settings, crossfadeStyle: e as CrossfadeStyle }, player: { ...settings, crossfadeStyle: e as CrossfadeStyle },
}); });
}} }}
@@ -240,7 +240,7 @@ export const PlaybackTab = () => {
defaultChecked={settings.globalMediaHotkeys} defaultChecked={settings.globalMediaHotkeys}
disabled={!isElectron()} disabled={!isElectron()}
onChange={(e) => { onChange={(e) => {
update({ setSettings({
player: { player: {
...settings, ...settings,
globalMediaHotkeys: e.currentTarget.checked, globalMediaHotkeys: e.currentTarget.checked,
@@ -274,7 +274,7 @@ export const PlaybackTab = () => {
]} ]}
defaultValue={settings.playButtonBehavior} defaultValue={settings.playButtonBehavior}
onChange={(e) => onChange={(e) =>
update({ setSettings({
player: { player: {
...settings, ...settings,
playButtonBehavior: e as Play, playButtonBehavior: e as Play,
@@ -293,7 +293,7 @@ export const PlaybackTab = () => {
aria-label="Toggle skip buttons" aria-label="Toggle skip buttons"
defaultChecked={settings.skipButtons?.enabled} defaultChecked={settings.skipButtons?.enabled}
onChange={(e) => onChange={(e) =>
update({ setSettings({
player: { player: {
...settings, ...settings,
skipButtons: { skipButtons: {
@@ -318,7 +318,7 @@ export const PlaybackTab = () => {
min={0} min={0}
width={75} width={75}
onBlur={(e) => onBlur={(e) =>
update({ setSettings({
player: { player: {
...settings, ...settings,
skipButtons: { skipButtons: {
@@ -338,7 +338,7 @@ export const PlaybackTab = () => {
min={0} min={0}
width={75} width={75}
onBlur={(e) => onBlur={(e) =>
update({ setSettings({
player: { player: {
...settings, ...settings,
skipButtons: { skipButtons: {
@@ -5,11 +5,11 @@ import { motion } from 'framer-motion';
import { Tabs } from '/@/components'; import { Tabs } from '/@/components';
import { GeneralTab } from '/@/features/settings/components/general-tab'; import { GeneralTab } from '/@/features/settings/components/general-tab';
import { PlaybackTab } from '/@/features/settings/components/playback-tab'; import { PlaybackTab } from '/@/features/settings/components/playback-tab';
import { useSettingsStore } from '/@/store/settings.store'; import { useSettingsStore, useSettingsStoreActions } from '/@/store/settings.store';
export const Settings = () => { export const Settings = () => {
const currentTab = useSettingsStore((state) => state.tab); const currentTab = useSettingsStore((state) => state.tab);
const update = useSettingsStore((state) => state.setSettings); const { setSettings } = useSettingsStoreActions();
const tabVariants: Variants = { const tabVariants: Variants = {
in: { in: {
@@ -42,7 +42,7 @@ export const Settings = () => {
}} }}
value={currentTab} value={currentTab}
variant="pills" variant="pills"
onTabChange={(e) => e && update({ tab: e })} onTabChange={(e) => e && setSettings({ tab: e })}
> >
<Tabs.List> <Tabs.List>
<Tabs.Tab value="general">General</Tabs.Tab> <Tabs.Tab value="general">General</Tabs.Tab>
@@ -18,7 +18,7 @@ import { useAppStoreActions } from '/@/store/app.store';
import { DrawerPlayQueue, SidebarPlayQueue } from '/@/features/now-playing'; import { DrawerPlayQueue, SidebarPlayQueue } from '/@/features/now-playing';
if (!isElectron()) { if (!isElectron()) {
useSettingsStore.getState().setSettings({ useSettingsStore.getState().actions.setSettings({
player: { player: {
...useSettingsStore.getState().player, ...useSettingsStore.getState().player,
type: PlaybackType.WEB, type: PlaybackType.WEB,
+19 -4
View File
@@ -5,6 +5,7 @@ import create from 'zustand';
import { devtools, persist } from 'zustand/middleware'; import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
import { AppTheme } from '/@/themes/types'; import { AppTheme } from '/@/themes/types';
import type { TableType } from '/@/types';
import { CrossfadeStyle, Play, PlaybackStyle, PlaybackType, TableColumn } from '/@/types'; import { CrossfadeStyle, Play, PlaybackStyle, PlaybackType, TableColumn } from '/@/types';
export type PersistedTableColumn = { export type PersistedTableColumn = {
@@ -56,13 +57,20 @@ export interface SettingsState {
} }
export interface SettingsSlice extends SettingsState { export interface SettingsSlice extends SettingsState {
setSettings: (data: Partial<SettingsState>) => void; actions: {
setSettings: (data: Partial<SettingsState>) => void;
};
} }
export const useSettingsStore = create<SettingsSlice>()( export const useSettingsStore = create<SettingsSlice>()(
persist( persist(
devtools( devtools(
immer((set, get) => ({ immer((set, get) => ({
actions: {
setSettings: (data) => {
set({ ...get(), ...data });
},
},
general: { general: {
followSystemTheme: false, followSystemTheme: false,
fontContent: 'Circular STD', fontContent: 'Circular STD',
@@ -90,9 +98,7 @@ export const useSettingsStore = create<SettingsSlice>()(
style: PlaybackStyle.GAPLESS, style: PlaybackStyle.GAPLESS,
type: PlaybackType.LOCAL, type: PlaybackType.LOCAL,
}, },
setSettings: (data) => {
set({ ...get(), ...data });
},
tab: 'general', tab: 'general',
tables: { tables: {
nowPlaying: { nowPlaying: {
@@ -177,3 +183,12 @@ export const useSettingsStore = create<SettingsSlice>()(
}, },
), ),
); );
export const useSettingsStoreActions = () => useSettingsStore((state) => state.actions);
export const usePlayerSettings = () => useSettingsStore((state) => state.player);
export const useTableSettings = (type: TableType) =>
useSettingsStore((state) => state.tables[type]);
export const useGeneralSettings = () => useSettingsStore((state) => state.general);