mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
Refactor settings store
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user