mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-01 02:13:33 +00:00
Lint all files
This commit is contained in:
parent
22af76b4d6
commit
30e52ebb54
334 changed files with 76519 additions and 75932 deletions
|
|
@ -3,35 +3,35 @@ import { devtools } from 'zustand/middleware';
|
|||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
export interface AlbumArtistListDataState {
|
||||
itemData: any[];
|
||||
itemData: any[];
|
||||
}
|
||||
|
||||
export interface AlbumArtistListDataSlice extends AlbumArtistListDataState {
|
||||
actions: {
|
||||
setItemData: (data: any[]) => void;
|
||||
};
|
||||
actions: {
|
||||
setItemData: (data: any[]) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const useAlbumArtistListDataStore = create<AlbumArtistListDataSlice>()(
|
||||
devtools(
|
||||
immer((set) => ({
|
||||
actions: {
|
||||
setItemData: (data) => {
|
||||
set((state) => {
|
||||
state.itemData = data;
|
||||
});
|
||||
},
|
||||
},
|
||||
itemData: [],
|
||||
})),
|
||||
{ name: 'store_album_list_data' },
|
||||
),
|
||||
devtools(
|
||||
immer((set) => ({
|
||||
actions: {
|
||||
setItemData: (data) => {
|
||||
set((state) => {
|
||||
state.itemData = data;
|
||||
});
|
||||
},
|
||||
},
|
||||
itemData: [],
|
||||
})),
|
||||
{ name: 'store_album_list_data' },
|
||||
),
|
||||
);
|
||||
|
||||
export const useAlbumArtistListStoreActions = () =>
|
||||
useAlbumArtistListDataStore((state) => state.actions);
|
||||
useAlbumArtistListDataStore((state) => state.actions);
|
||||
|
||||
export const useAlbumArtistListItemData = () =>
|
||||
useAlbumArtistListDataStore((state) => {
|
||||
return { itemData: state.itemData, setItemData: state.actions.setItemData };
|
||||
});
|
||||
useAlbumArtistListDataStore((state) => {
|
||||
return { itemData: state.itemData, setItemData: state.actions.setItemData };
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,105 +7,108 @@ import { DataTableProps } from '/@/renderer/store/settings.store';
|
|||
import { ListDisplayType, TableColumn, TablePagination } from '/@/renderer/types';
|
||||
|
||||
type TableProps = {
|
||||
pagination: TablePagination;
|
||||
scrollOffset: number;
|
||||
pagination: TablePagination;
|
||||
scrollOffset: number;
|
||||
} & DataTableProps;
|
||||
|
||||
type ListProps<T> = {
|
||||
display: ListDisplayType;
|
||||
filter: T;
|
||||
grid: {
|
||||
scrollOffset: number;
|
||||
size: number;
|
||||
};
|
||||
table: TableProps;
|
||||
display: ListDisplayType;
|
||||
filter: T;
|
||||
grid: {
|
||||
scrollOffset: number;
|
||||
size: number;
|
||||
};
|
||||
table: TableProps;
|
||||
};
|
||||
|
||||
export type AlbumArtistListFilter = Omit<AlbumArtistListArgs['query'], 'startIndex' | 'limit'>;
|
||||
|
||||
export interface AlbumArtistState {
|
||||
list: ListProps<AlbumArtistListFilter>;
|
||||
list: ListProps<AlbumArtistListFilter>;
|
||||
}
|
||||
|
||||
export interface AlbumArtistSlice extends AlbumArtistState {
|
||||
actions: {
|
||||
setFilters: (data: Partial<AlbumArtistListFilter>) => AlbumArtistListFilter;
|
||||
setStore: (data: Partial<AlbumArtistSlice>) => void;
|
||||
setTable: (data: Partial<TableProps>) => void;
|
||||
setTablePagination: (data: Partial<TableProps['pagination']>) => void;
|
||||
};
|
||||
actions: {
|
||||
setFilters: (data: Partial<AlbumArtistListFilter>) => AlbumArtistListFilter;
|
||||
setStore: (data: Partial<AlbumArtistSlice>) => void;
|
||||
setTable: (data: Partial<TableProps>) => void;
|
||||
setTablePagination: (data: Partial<TableProps['pagination']>) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const useAlbumArtistStore = create<AlbumArtistSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setFilters: (data) => {
|
||||
set((state) => {
|
||||
state.list.filter = { ...state.list.filter, ...data };
|
||||
});
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setFilters: (data) => {
|
||||
set((state) => {
|
||||
state.list.filter = { ...state.list.filter, ...data };
|
||||
});
|
||||
|
||||
return get().list.filter;
|
||||
},
|
||||
setStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setTable: (data) => {
|
||||
set((state) => {
|
||||
state.list.table = { ...state.list.table, ...data };
|
||||
});
|
||||
},
|
||||
setTablePagination: (data) => {
|
||||
set((state) => {
|
||||
state.list.table.pagination = { ...state.list.table.pagination, ...data };
|
||||
});
|
||||
},
|
||||
},
|
||||
list: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
musicFolderId: undefined,
|
||||
sortBy: AlbumArtistListSort.NAME,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
grid: {
|
||||
scrollOffset: 0,
|
||||
size: 50,
|
||||
},
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
return get().list.filter;
|
||||
},
|
||||
setStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setTable: (data) => {
|
||||
set((state) => {
|
||||
state.list.table = { ...state.list.table, ...data };
|
||||
});
|
||||
},
|
||||
setTablePagination: (data) => {
|
||||
set((state) => {
|
||||
state.list.table.pagination = {
|
||||
...state.list.table.pagination,
|
||||
...data,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
list: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
musicFolderId: undefined,
|
||||
sortBy: AlbumArtistListSort.NAME,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
grid: {
|
||||
scrollOffset: 0,
|
||||
size: 50,
|
||||
},
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
})),
|
||||
{ name: 'store_album_artist' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
name: 'store_album_artist',
|
||||
version: 1,
|
||||
},
|
||||
})),
|
||||
{ name: 'store_album_artist' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_album_artist',
|
||||
version: 1,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const useAlbumArtistStoreActions = () => useAlbumArtistStore((state) => state.actions);
|
||||
|
|
@ -113,14 +116,14 @@ export const useAlbumArtistStoreActions = () => useAlbumArtistStore((state) => s
|
|||
export const useSetAlbumArtistStore = () => useAlbumArtistStore((state) => state.actions.setStore);
|
||||
|
||||
export const useSetAlbumArtistFilters = () =>
|
||||
useAlbumArtistStore((state) => state.actions.setFilters);
|
||||
useAlbumArtistStore((state) => state.actions.setFilters);
|
||||
|
||||
export const useAlbumArtistListStore = () => useAlbumArtistStore((state) => state.list);
|
||||
|
||||
export const useAlbumArtistTablePagination = () =>
|
||||
useAlbumArtistStore((state) => state.list.table.pagination);
|
||||
useAlbumArtistStore((state) => state.list.table.pagination);
|
||||
|
||||
export const useSetAlbumArtistTablePagination = () =>
|
||||
useAlbumArtistStore((state) => state.actions.setTablePagination);
|
||||
useAlbumArtistStore((state) => state.actions.setTablePagination);
|
||||
|
||||
export const useSetAlbumArtistTable = () => useAlbumArtistStore((state) => state.actions.setTable);
|
||||
|
|
|
|||
|
|
@ -3,45 +3,45 @@ import { devtools } from 'zustand/middleware';
|
|||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
export interface AlbumListDataState {
|
||||
itemData: any[];
|
||||
itemData: any[];
|
||||
}
|
||||
|
||||
export interface AlbumListDataSlice extends AlbumListDataState {
|
||||
actions: {
|
||||
setItemData: (data: any[]) => void;
|
||||
setItemDataById: (id: string, data: any) => void;
|
||||
};
|
||||
actions: {
|
||||
setItemData: (data: any[]) => void;
|
||||
setItemDataById: (id: string, data: any) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const useAlbumListDataStore = create<AlbumListDataSlice>()(
|
||||
devtools(
|
||||
immer((set) => ({
|
||||
actions: {
|
||||
setItemData: (data) => {
|
||||
set((state) => {
|
||||
state.itemData = data;
|
||||
});
|
||||
},
|
||||
setItemDataById: (id, data) => {
|
||||
set((state) => {
|
||||
const index = state.itemData.findIndex((item) => item?.id === id);
|
||||
if (index === -1) return;
|
||||
state.itemData[index] = { ...state.itemData[index], ...data };
|
||||
});
|
||||
},
|
||||
},
|
||||
itemData: [],
|
||||
})),
|
||||
{ name: 'store_album_list_data' },
|
||||
),
|
||||
devtools(
|
||||
immer((set) => ({
|
||||
actions: {
|
||||
setItemData: (data) => {
|
||||
set((state) => {
|
||||
state.itemData = data;
|
||||
});
|
||||
},
|
||||
setItemDataById: (id, data) => {
|
||||
set((state) => {
|
||||
const index = state.itemData.findIndex((item) => item?.id === id);
|
||||
if (index === -1) return;
|
||||
state.itemData[index] = { ...state.itemData[index], ...data };
|
||||
});
|
||||
},
|
||||
},
|
||||
itemData: [],
|
||||
})),
|
||||
{ name: 'store_album_list_data' },
|
||||
),
|
||||
);
|
||||
|
||||
export const useAlbumListStoreActions = () => useAlbumListDataStore((state) => state.actions);
|
||||
|
||||
export const useAlbumListItemData = () =>
|
||||
useAlbumListDataStore((state) => {
|
||||
return { itemData: state.itemData, setItemData: state.actions.setItemData };
|
||||
});
|
||||
useAlbumListDataStore((state) => {
|
||||
return { itemData: state.itemData, setItemData: state.actions.setItemData };
|
||||
});
|
||||
|
||||
export const useSetAlbumListItemDataById = () =>
|
||||
useAlbumListDataStore((state) => state.actions.setItemDataById);
|
||||
useAlbumListDataStore((state) => state.actions.setItemDataById);
|
||||
|
|
|
|||
|
|
@ -5,104 +5,104 @@ import { immer } from 'zustand/middleware/immer';
|
|||
import { Platform } from '/@/renderer/types';
|
||||
|
||||
type SidebarProps = {
|
||||
collapsed: boolean;
|
||||
expanded: string[];
|
||||
image: boolean;
|
||||
leftWidth: string;
|
||||
rightExpanded: boolean;
|
||||
rightWidth: string;
|
||||
collapsed: boolean;
|
||||
expanded: string[];
|
||||
image: boolean;
|
||||
leftWidth: string;
|
||||
rightExpanded: boolean;
|
||||
rightWidth: string;
|
||||
};
|
||||
|
||||
type TitlebarProps = {
|
||||
backgroundColor: string;
|
||||
outOfView: boolean;
|
||||
backgroundColor: string;
|
||||
outOfView: boolean;
|
||||
};
|
||||
|
||||
type CommandPaletteProps = {
|
||||
close: () => void;
|
||||
open: () => void;
|
||||
opened: boolean;
|
||||
toggle: () => void;
|
||||
close: () => void;
|
||||
open: () => void;
|
||||
opened: boolean;
|
||||
toggle: () => void;
|
||||
};
|
||||
|
||||
export interface AppState {
|
||||
commandPalette: CommandPaletteProps;
|
||||
isReorderingQueue: boolean;
|
||||
platform: Platform;
|
||||
sidebar: SidebarProps;
|
||||
titlebar: TitlebarProps;
|
||||
commandPalette: CommandPaletteProps;
|
||||
isReorderingQueue: boolean;
|
||||
platform: Platform;
|
||||
sidebar: SidebarProps;
|
||||
titlebar: TitlebarProps;
|
||||
}
|
||||
|
||||
export interface AppSlice extends AppState {
|
||||
actions: {
|
||||
setAppStore: (data: Partial<AppSlice>) => void;
|
||||
setSideBar: (options: Partial<SidebarProps>) => void;
|
||||
setTitleBar: (options: Partial<TitlebarProps>) => void;
|
||||
};
|
||||
actions: {
|
||||
setAppStore: (data: Partial<AppSlice>) => void;
|
||||
setSideBar: (options: Partial<SidebarProps>) => void;
|
||||
setTitleBar: (options: Partial<TitlebarProps>) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const useAppStore = create<AppSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setAppStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setSideBar: (options) => {
|
||||
set((state) => {
|
||||
state.sidebar = { ...state.sidebar, ...options };
|
||||
});
|
||||
},
|
||||
setTitleBar: (options) => {
|
||||
set((state) => {
|
||||
state.titlebar = { ...state.titlebar, ...options };
|
||||
});
|
||||
},
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setAppStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setSideBar: (options) => {
|
||||
set((state) => {
|
||||
state.sidebar = { ...state.sidebar, ...options };
|
||||
});
|
||||
},
|
||||
setTitleBar: (options) => {
|
||||
set((state) => {
|
||||
state.titlebar = { ...state.titlebar, ...options };
|
||||
});
|
||||
},
|
||||
},
|
||||
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;
|
||||
});
|
||||
},
|
||||
},
|
||||
isReorderingQueue: false,
|
||||
platform: Platform.WINDOWS,
|
||||
sidebar: {
|
||||
collapsed: false,
|
||||
expanded: [],
|
||||
image: false,
|
||||
leftWidth: '400px',
|
||||
rightExpanded: false,
|
||||
rightWidth: '400px',
|
||||
},
|
||||
titlebar: {
|
||||
backgroundColor: '#000000',
|
||||
outOfView: false,
|
||||
},
|
||||
})),
|
||||
{ name: 'store_app' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_app',
|
||||
version: 2,
|
||||
},
|
||||
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;
|
||||
});
|
||||
},
|
||||
},
|
||||
isReorderingQueue: false,
|
||||
platform: Platform.WINDOWS,
|
||||
sidebar: {
|
||||
collapsed: false,
|
||||
expanded: [],
|
||||
image: false,
|
||||
leftWidth: '400px',
|
||||
rightExpanded: false,
|
||||
rightWidth: '400px',
|
||||
},
|
||||
titlebar: {
|
||||
backgroundColor: '#000000',
|
||||
outOfView: false,
|
||||
},
|
||||
})),
|
||||
{ name: 'store_app' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_app',
|
||||
version: 2,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const useAppStoreActions = () => useAppStore((state) => state.actions);
|
||||
|
|
|
|||
|
|
@ -9,83 +9,83 @@ import { useListStore } from '/@/renderer/store/list.store';
|
|||
import { ServerListItem } from '/@/renderer/types';
|
||||
|
||||
export interface AuthState {
|
||||
currentServer: ServerListItem | null;
|
||||
deviceId: string;
|
||||
serverList: Record<string, ServerListItem>;
|
||||
currentServer: ServerListItem | null;
|
||||
deviceId: string;
|
||||
serverList: Record<string, ServerListItem>;
|
||||
}
|
||||
|
||||
export interface AuthSlice extends AuthState {
|
||||
actions: {
|
||||
addServer: (args: ServerListItem) => void;
|
||||
deleteServer: (id: string) => void;
|
||||
getServer: (id: string) => ServerListItem | null;
|
||||
setCurrentServer: (server: ServerListItem | null) => void;
|
||||
updateServer: (id: string, args: Partial<ServerListItem>) => void;
|
||||
};
|
||||
actions: {
|
||||
addServer: (args: ServerListItem) => void;
|
||||
deleteServer: (id: string) => void;
|
||||
getServer: (id: string) => ServerListItem | null;
|
||||
setCurrentServer: (server: ServerListItem | null) => void;
|
||||
updateServer: (id: string, args: Partial<ServerListItem>) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
addServer: (args) => {
|
||||
set((state) => {
|
||||
state.serverList[args.id] = args;
|
||||
});
|
||||
},
|
||||
deleteServer: (id) => {
|
||||
set((state) => {
|
||||
delete state.serverList[id];
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
addServer: (args) => {
|
||||
set((state) => {
|
||||
state.serverList[args.id] = args;
|
||||
});
|
||||
},
|
||||
deleteServer: (id) => {
|
||||
set((state) => {
|
||||
delete state.serverList[id];
|
||||
|
||||
if (state.currentServer?.id === id) {
|
||||
state.currentServer = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
getServer: (id) => {
|
||||
const server = get().serverList[id];
|
||||
if (server) return server;
|
||||
return null;
|
||||
},
|
||||
setCurrentServer: (server) => {
|
||||
set((state) => {
|
||||
state.currentServer = server;
|
||||
if (state.currentServer?.id === id) {
|
||||
state.currentServer = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
getServer: (id) => {
|
||||
const server = get().serverList[id];
|
||||
if (server) return server;
|
||||
return null;
|
||||
},
|
||||
setCurrentServer: (server) => {
|
||||
set((state) => {
|
||||
state.currentServer = server;
|
||||
|
||||
if (server) {
|
||||
// Reset list filters
|
||||
useListStore.getState()._actions.resetFilter();
|
||||
if (server) {
|
||||
// Reset list filters
|
||||
useListStore.getState()._actions.resetFilter();
|
||||
|
||||
// Reset persisted grid list stores
|
||||
useAlbumListDataStore.getState().actions.setItemData([]);
|
||||
useAlbumArtistListDataStore.getState().actions.setItemData([]);
|
||||
}
|
||||
});
|
||||
},
|
||||
updateServer: (id: string, args: Partial<ServerListItem>) => {
|
||||
set((state) => {
|
||||
const updatedServer = {
|
||||
...state.serverList[id],
|
||||
...args,
|
||||
};
|
||||
// Reset persisted grid list stores
|
||||
useAlbumListDataStore.getState().actions.setItemData([]);
|
||||
useAlbumArtistListDataStore.getState().actions.setItemData([]);
|
||||
}
|
||||
});
|
||||
},
|
||||
updateServer: (id: string, args: Partial<ServerListItem>) => {
|
||||
set((state) => {
|
||||
const updatedServer = {
|
||||
...state.serverList[id],
|
||||
...args,
|
||||
};
|
||||
|
||||
state.serverList[id] = updatedServer;
|
||||
state.currentServer = updatedServer;
|
||||
});
|
||||
},
|
||||
state.serverList[id] = updatedServer;
|
||||
state.currentServer = updatedServer;
|
||||
});
|
||||
},
|
||||
},
|
||||
currentServer: null,
|
||||
deviceId: nanoid(),
|
||||
serverList: {},
|
||||
})),
|
||||
{ name: 'store_authentication' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => merge(currentState, persistedState),
|
||||
name: 'store_authentication',
|
||||
version: 2,
|
||||
},
|
||||
currentServer: null,
|
||||
deviceId: nanoid(),
|
||||
serverList: {},
|
||||
})),
|
||||
{ name: 'store_authentication' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => merge(currentState, persistedState),
|
||||
name: 'store_authentication',
|
||||
version: 2,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const useCurrentServerId = () => useAuthStore((state) => state.currentServer)?.id || '';
|
||||
|
|
@ -97,9 +97,9 @@ export const useServerList = () => useAuthStore((state) => state.serverList);
|
|||
export const useAuthStoreActions = () => useAuthStore((state) => state.actions);
|
||||
|
||||
export const getServerById = (id?: string) => {
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return useAuthStore.getState().actions.getServer(id);
|
||||
return useAuthStore.getState().actions.getServer(id);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,46 +4,46 @@ import { devtools, persist } from 'zustand/middleware';
|
|||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
interface FullScreenPlayerState {
|
||||
activeTab: string | 'queue' | 'related' | 'lyrics';
|
||||
dynamicBackground?: boolean;
|
||||
expanded: boolean;
|
||||
useImageAspectRatio: boolean;
|
||||
activeTab: string | 'queue' | 'related' | 'lyrics';
|
||||
dynamicBackground?: boolean;
|
||||
expanded: boolean;
|
||||
useImageAspectRatio: boolean;
|
||||
}
|
||||
|
||||
export interface FullScreenPlayerSlice extends FullScreenPlayerState {
|
||||
actions: {
|
||||
setStore: (data: Partial<FullScreenPlayerSlice>) => void;
|
||||
};
|
||||
actions: {
|
||||
setStore: (data: Partial<FullScreenPlayerSlice>) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const useFullScreenPlayerStore = create<FullScreenPlayerSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
},
|
||||
activeTab: 'queue',
|
||||
dynamicBackground: true,
|
||||
expanded: false,
|
||||
useImageAspectRatio: false,
|
||||
})),
|
||||
{ name: 'store_full_screen_player' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_full_screen_player',
|
||||
version: 2,
|
||||
},
|
||||
activeTab: 'queue',
|
||||
dynamicBackground: true,
|
||||
expanded: false,
|
||||
useImageAspectRatio: false,
|
||||
})),
|
||||
{ name: 'store_full_screen_player' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_full_screen_player',
|
||||
version: 2,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const useFullScreenPlayerStoreActions = () =>
|
||||
useFullScreenPlayerStore((state) => state.actions);
|
||||
useFullScreenPlayerStore((state) => state.actions);
|
||||
|
||||
export const useSetFullScreenPlayerStore = () =>
|
||||
useFullScreenPlayerStore((state) => state.actions.setStore);
|
||||
useFullScreenPlayerStore((state) => state.actions.setStore);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -8,172 +8,175 @@ import { DataTableProps } from '/@/renderer/store/settings.store';
|
|||
import { ListDisplayType, TableColumn, TablePagination } from '/@/renderer/types';
|
||||
|
||||
type TableProps = {
|
||||
pagination: TablePagination;
|
||||
scrollOffset: number;
|
||||
pagination: TablePagination;
|
||||
scrollOffset: number;
|
||||
} & DataTableProps;
|
||||
|
||||
type ListProps<T> = {
|
||||
display: ListDisplayType;
|
||||
filter: T;
|
||||
table: TableProps;
|
||||
display: ListDisplayType;
|
||||
filter: T;
|
||||
table: TableProps;
|
||||
};
|
||||
|
||||
type DetailPaginationProps = TablePagination & {
|
||||
scrollOffset: number;
|
||||
scrollOffset: number;
|
||||
};
|
||||
|
||||
type DetailTableProps = DataTableProps & {
|
||||
id: {
|
||||
[key: string]: DetailPaginationProps & { filter: SongListFilter };
|
||||
};
|
||||
id: {
|
||||
[key: string]: DetailPaginationProps & { filter: SongListFilter };
|
||||
};
|
||||
};
|
||||
|
||||
type DetailProps = {
|
||||
display: ListDisplayType;
|
||||
table: DetailTableProps;
|
||||
display: ListDisplayType;
|
||||
table: DetailTableProps;
|
||||
};
|
||||
|
||||
export type PlaylistListFilter = Omit<PlaylistListArgs['query'], 'startIndex' | 'limit'>;
|
||||
|
||||
interface PlaylistState {
|
||||
detail: DetailProps;
|
||||
list: ListProps<PlaylistListFilter>;
|
||||
detail: DetailProps;
|
||||
list: ListProps<PlaylistListFilter>;
|
||||
}
|
||||
|
||||
export interface PlaylistSlice extends PlaylistState {
|
||||
actions: {
|
||||
setDetailFilters: (id: string, data: Partial<SongListFilter>) => SongListFilter;
|
||||
setDetailTable: (data: Partial<DetailTableProps>) => void;
|
||||
setDetailTablePagination: (id: string, data: Partial<DetailPaginationProps>) => void;
|
||||
setFilters: (data: Partial<PlaylistListFilter>) => PlaylistListFilter;
|
||||
setStore: (data: Partial<PlaylistSlice>) => void;
|
||||
setTable: (data: Partial<TableProps>) => void;
|
||||
setTablePagination: (args: { data: Partial<TablePagination> }) => void;
|
||||
};
|
||||
actions: {
|
||||
setDetailFilters: (id: string, data: Partial<SongListFilter>) => SongListFilter;
|
||||
setDetailTable: (data: Partial<DetailTableProps>) => void;
|
||||
setDetailTablePagination: (id: string, data: Partial<DetailPaginationProps>) => void;
|
||||
setFilters: (data: Partial<PlaylistListFilter>) => PlaylistListFilter;
|
||||
setStore: (data: Partial<PlaylistSlice>) => void;
|
||||
setTable: (data: Partial<TableProps>) => void;
|
||||
setTablePagination: (args: { data: Partial<TablePagination> }) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const usePlaylistStore = create<PlaylistSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setDetailFilters: (id, data) => {
|
||||
set((state) => {
|
||||
state.detail.table.id[id] = {
|
||||
...state.detail.table.id[id],
|
||||
filter: {
|
||||
...state.detail.table.id[id].filter,
|
||||
...data,
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
setDetailFilters: (id, data) => {
|
||||
set((state) => {
|
||||
state.detail.table.id[id] = {
|
||||
...state.detail.table.id[id],
|
||||
filter: {
|
||||
...state.detail.table.id[id].filter,
|
||||
...data,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return get().detail.table.id[id].filter;
|
||||
},
|
||||
setDetailTable: (data) => {
|
||||
set((state) => {
|
||||
state.detail.table = { ...state.detail.table, ...data };
|
||||
});
|
||||
},
|
||||
setDetailTablePagination: (id, data) => {
|
||||
set((state) => {
|
||||
state.detail.table.id[id] = {
|
||||
...state.detail.table.id[id],
|
||||
...data,
|
||||
};
|
||||
});
|
||||
},
|
||||
setFilters: (data) => {
|
||||
set((state) => {
|
||||
state.list.filter = { ...state.list.filter, ...data };
|
||||
});
|
||||
|
||||
return get().list.filter;
|
||||
},
|
||||
setStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setTable: (data) => {
|
||||
set((state) => {
|
||||
state.list.table = { ...state.list.table, ...data };
|
||||
});
|
||||
},
|
||||
setTablePagination: (args) => {
|
||||
set((state) => {
|
||||
state.list.table.pagination = {
|
||||
...state.list.table.pagination,
|
||||
...args.data,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return get().detail.table.id[id].filter;
|
||||
},
|
||||
setDetailTable: (data) => {
|
||||
set((state) => {
|
||||
state.detail.table = { ...state.detail.table, ...data };
|
||||
});
|
||||
},
|
||||
setDetailTablePagination: (id, data) => {
|
||||
set((state) => {
|
||||
state.detail.table.id[id] = {
|
||||
...state.detail.table.id[id],
|
||||
...data,
|
||||
};
|
||||
});
|
||||
},
|
||||
setFilters: (data) => {
|
||||
set((state) => {
|
||||
state.list.filter = { ...state.list.filter, ...data };
|
||||
});
|
||||
|
||||
return get().list.filter;
|
||||
},
|
||||
setStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setTable: (data) => {
|
||||
set((state) => {
|
||||
state.list.table = { ...state.list.table, ...data };
|
||||
});
|
||||
},
|
||||
setTablePagination: (args) => {
|
||||
set((state) => {
|
||||
state.list.table.pagination = { ...state.list.table.pagination, ...args.data };
|
||||
});
|
||||
},
|
||||
},
|
||||
detail: {
|
||||
display: ListDisplayType.TABLE,
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 500,
|
||||
},
|
||||
],
|
||||
id: {},
|
||||
rowHeight: 60,
|
||||
},
|
||||
},
|
||||
list: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
musicFolderId: undefined,
|
||||
sortBy: PlaylistListSort.NAME,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.SONG_COUNT,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
detail: {
|
||||
display: ListDisplayType.TABLE,
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 500,
|
||||
},
|
||||
],
|
||||
id: {},
|
||||
rowHeight: 60,
|
||||
},
|
||||
},
|
||||
list: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
musicFolderId: undefined,
|
||||
sortBy: PlaylistListSort.NAME,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.SONG_COUNT,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 40,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
})),
|
||||
{ name: 'store_playlist' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
rowHeight: 40,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
name: 'store_playlist',
|
||||
version: 1,
|
||||
},
|
||||
})),
|
||||
{ name: 'store_playlist' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_playlist',
|
||||
version: 1,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const usePlaylistStoreActions = () => usePlaylistStore((state) => state.actions);
|
||||
|
|
@ -183,29 +186,29 @@ export const useSetPlaylistStore = () => usePlaylistStore((state) => state.actio
|
|||
export const useSetPlaylistFilters = () => usePlaylistStore((state) => state.actions.setFilters);
|
||||
|
||||
export const usePlaylistFilters = () => {
|
||||
return usePlaylistStore((state) => [state.list.filter, state.actions.setFilters]);
|
||||
return usePlaylistStore((state) => [state.list.filter, state.actions.setFilters]);
|
||||
};
|
||||
|
||||
export const usePlaylistListStore = () => usePlaylistStore((state) => state.list);
|
||||
|
||||
export const usePlaylistTablePagination = () =>
|
||||
usePlaylistStore((state) => state.list.table.pagination);
|
||||
usePlaylistStore((state) => state.list.table.pagination);
|
||||
|
||||
export const useSetPlaylistTablePagination = () =>
|
||||
usePlaylistStore((state) => state.actions.setTablePagination);
|
||||
usePlaylistStore((state) => state.actions.setTablePagination);
|
||||
|
||||
export const useSetPlaylistTable = () => usePlaylistStore((state) => state.actions.setTable);
|
||||
|
||||
export const usePlaylistDetailStore = () => usePlaylistStore((state) => state.detail);
|
||||
|
||||
export const usePlaylistDetailTablePagination = (id: string) =>
|
||||
usePlaylistStore((state) => state.detail.table.id[id]);
|
||||
usePlaylistStore((state) => state.detail.table.id[id]);
|
||||
|
||||
export const useSetPlaylistDetailTablePagination = () =>
|
||||
usePlaylistStore((state) => state.actions.setDetailTablePagination);
|
||||
usePlaylistStore((state) => state.actions.setDetailTablePagination);
|
||||
|
||||
export const useSetPlaylistDetailTable = () =>
|
||||
usePlaylistStore((state) => state.actions.setDetailTable);
|
||||
usePlaylistStore((state) => state.actions.setDetailTable);
|
||||
|
||||
export const useSetPlaylistDetailFilters = () =>
|
||||
usePlaylistStore((state) => state.actions.setDetailFilters);
|
||||
usePlaylistStore((state) => state.actions.setDetailFilters);
|
||||
|
|
|
|||
|
|
@ -12,415 +12,418 @@ import { LibraryItem, LyricSource } from '/@/renderer/api/types';
|
|||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { AppTheme } from '/@/renderer/themes/types';
|
||||
import {
|
||||
TableColumn,
|
||||
CrossfadeStyle,
|
||||
Play,
|
||||
PlaybackStyle,
|
||||
PlaybackType,
|
||||
TableType,
|
||||
Platform,
|
||||
TableColumn,
|
||||
CrossfadeStyle,
|
||||
Play,
|
||||
PlaybackStyle,
|
||||
PlaybackType,
|
||||
TableType,
|
||||
Platform,
|
||||
} from '/@/renderer/types';
|
||||
|
||||
const utils = isElectron() ? window.electron.utils : null;
|
||||
|
||||
export type SidebarItemType = {
|
||||
disabled: boolean;
|
||||
id: string;
|
||||
label: string;
|
||||
route: AppRoute | string;
|
||||
disabled: boolean;
|
||||
id: string;
|
||||
label: string;
|
||||
route: AppRoute | string;
|
||||
};
|
||||
|
||||
export const sidebarItems = [
|
||||
{ disabled: true, id: 'Now Playing', label: 'Now Playing', route: AppRoute.NOW_PLAYING },
|
||||
{
|
||||
disabled: true,
|
||||
id: 'Search',
|
||||
label: 'Search',
|
||||
route: generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG }),
|
||||
},
|
||||
{ disabled: false, id: 'Home', label: 'Home', route: AppRoute.HOME },
|
||||
{ disabled: false, id: 'Albums', label: 'Albums', route: AppRoute.LIBRARY_ALBUMS },
|
||||
{ disabled: false, id: 'Tracks', label: 'Tracks', route: AppRoute.LIBRARY_SONGS },
|
||||
{
|
||||
disabled: false,
|
||||
id: 'Artists',
|
||||
label: 'Artists',
|
||||
route: AppRoute.LIBRARY_ALBUM_ARTISTS,
|
||||
},
|
||||
{ disabled: false, id: 'Genres', label: 'Genres', route: AppRoute.LIBRARY_GENRES },
|
||||
{ disabled: true, id: 'Folders', label: 'Folders', route: AppRoute.LIBRARY_FOLDERS },
|
||||
{ disabled: true, id: 'Playlists', label: 'Playlists', route: AppRoute.PLAYLISTS },
|
||||
{ disabled: true, id: 'Settings', label: 'Settings', route: AppRoute.SETTINGS },
|
||||
{ disabled: true, id: 'Now Playing', label: 'Now Playing', route: AppRoute.NOW_PLAYING },
|
||||
{
|
||||
disabled: true,
|
||||
id: 'Search',
|
||||
label: 'Search',
|
||||
route: generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG }),
|
||||
},
|
||||
{ disabled: false, id: 'Home', label: 'Home', route: AppRoute.HOME },
|
||||
{ disabled: false, id: 'Albums', label: 'Albums', route: AppRoute.LIBRARY_ALBUMS },
|
||||
{ disabled: false, id: 'Tracks', label: 'Tracks', route: AppRoute.LIBRARY_SONGS },
|
||||
{
|
||||
disabled: false,
|
||||
id: 'Artists',
|
||||
label: 'Artists',
|
||||
route: AppRoute.LIBRARY_ALBUM_ARTISTS,
|
||||
},
|
||||
{ disabled: false, id: 'Genres', label: 'Genres', route: AppRoute.LIBRARY_GENRES },
|
||||
{ disabled: true, id: 'Folders', label: 'Folders', route: AppRoute.LIBRARY_FOLDERS },
|
||||
{ disabled: true, id: 'Playlists', label: 'Playlists', route: AppRoute.PLAYLISTS },
|
||||
{ disabled: true, id: 'Settings', label: 'Settings', route: AppRoute.SETTINGS },
|
||||
];
|
||||
|
||||
export type PersistedTableColumn = {
|
||||
column: TableColumn;
|
||||
extraProps?: Partial<ColDef>;
|
||||
width: number;
|
||||
column: TableColumn;
|
||||
extraProps?: Partial<ColDef>;
|
||||
width: number;
|
||||
};
|
||||
|
||||
export type DataTableProps = {
|
||||
autoFit: boolean;
|
||||
columns: PersistedTableColumn[];
|
||||
followCurrentSong?: boolean;
|
||||
rowHeight: number;
|
||||
autoFit: boolean;
|
||||
columns: PersistedTableColumn[];
|
||||
followCurrentSong?: boolean;
|
||||
rowHeight: number;
|
||||
};
|
||||
|
||||
export type SideQueueType = 'sideQueue' | 'sideDrawerQueue';
|
||||
|
||||
type MpvSettings = {
|
||||
audioExclusiveMode: 'yes' | 'no';
|
||||
audioFormat?: 's16' | 's32' | 'float';
|
||||
audioSampleRateHz?: number;
|
||||
gaplessAudio: 'yes' | 'no' | 'weak';
|
||||
replayGainClip: boolean;
|
||||
replayGainFallbackDB?: number;
|
||||
replayGainMode: 'no' | 'track' | 'album';
|
||||
replayGainPreampDB?: number;
|
||||
audioExclusiveMode: 'yes' | 'no';
|
||||
audioFormat?: 's16' | 's32' | 'float';
|
||||
audioSampleRateHz?: number;
|
||||
gaplessAudio: 'yes' | 'no' | 'weak';
|
||||
replayGainClip: boolean;
|
||||
replayGainFallbackDB?: number;
|
||||
replayGainMode: 'no' | 'track' | 'album';
|
||||
replayGainPreampDB?: number;
|
||||
};
|
||||
|
||||
export enum BindingActions {
|
||||
GLOBAL_SEARCH = 'globalSearch',
|
||||
LOCAL_SEARCH = 'localSearch',
|
||||
MUTE = 'volumeMute',
|
||||
NEXT = 'next',
|
||||
PAUSE = 'pause',
|
||||
PLAY = 'play',
|
||||
PLAY_PAUSE = 'playPause',
|
||||
PREVIOUS = 'previous',
|
||||
SHUFFLE = 'toggleShuffle',
|
||||
SKIP_BACKWARD = 'skipBackward',
|
||||
SKIP_FORWARD = 'skipForward',
|
||||
STOP = 'stop',
|
||||
TOGGLE_FULLSCREEN_PLAYER = 'toggleFullscreenPlayer',
|
||||
TOGGLE_QUEUE = 'toggleQueue',
|
||||
TOGGLE_REPEAT = 'toggleRepeat',
|
||||
VOLUME_DOWN = 'volumeDown',
|
||||
VOLUME_UP = 'volumeUp',
|
||||
ZOOM_IN = 'zoomIn',
|
||||
ZOOM_OUT = 'zoomOut',
|
||||
GLOBAL_SEARCH = 'globalSearch',
|
||||
LOCAL_SEARCH = 'localSearch',
|
||||
MUTE = 'volumeMute',
|
||||
NEXT = 'next',
|
||||
PAUSE = 'pause',
|
||||
PLAY = 'play',
|
||||
PLAY_PAUSE = 'playPause',
|
||||
PREVIOUS = 'previous',
|
||||
SHUFFLE = 'toggleShuffle',
|
||||
SKIP_BACKWARD = 'skipBackward',
|
||||
SKIP_FORWARD = 'skipForward',
|
||||
STOP = 'stop',
|
||||
TOGGLE_FULLSCREEN_PLAYER = 'toggleFullscreenPlayer',
|
||||
TOGGLE_QUEUE = 'toggleQueue',
|
||||
TOGGLE_REPEAT = 'toggleRepeat',
|
||||
VOLUME_DOWN = 'volumeDown',
|
||||
VOLUME_UP = 'volumeUp',
|
||||
ZOOM_IN = 'zoomIn',
|
||||
ZOOM_OUT = 'zoomOut',
|
||||
}
|
||||
|
||||
export interface SettingsState {
|
||||
general: {
|
||||
followSystemTheme: boolean;
|
||||
fontContent: string;
|
||||
playButtonBehavior: Play;
|
||||
resume: boolean;
|
||||
showQueueDrawerButton: boolean;
|
||||
sideQueueType: SideQueueType;
|
||||
sidebarItems: SidebarItemType[];
|
||||
sidebarPlaylistList: boolean;
|
||||
skipButtons: {
|
||||
enabled: boolean;
|
||||
skipBackwardSeconds: number;
|
||||
skipForwardSeconds: number;
|
||||
general: {
|
||||
followSystemTheme: boolean;
|
||||
fontContent: string;
|
||||
playButtonBehavior: Play;
|
||||
resume: boolean;
|
||||
showQueueDrawerButton: boolean;
|
||||
sideQueueType: SideQueueType;
|
||||
sidebarItems: SidebarItemType[];
|
||||
sidebarPlaylistList: boolean;
|
||||
skipButtons: {
|
||||
enabled: boolean;
|
||||
skipBackwardSeconds: number;
|
||||
skipForwardSeconds: number;
|
||||
};
|
||||
theme: AppTheme;
|
||||
themeDark: AppTheme;
|
||||
themeLight: AppTheme;
|
||||
volumeWheelStep: number;
|
||||
zoomFactor: number;
|
||||
};
|
||||
theme: AppTheme;
|
||||
themeDark: AppTheme;
|
||||
themeLight: AppTheme;
|
||||
volumeWheelStep: number;
|
||||
zoomFactor: number;
|
||||
};
|
||||
hotkeys: {
|
||||
bindings: Record<BindingActions, { allowGlobal: boolean; hotkey: string; isGlobal: boolean }>;
|
||||
globalMediaHotkeys: boolean;
|
||||
};
|
||||
lyrics: {
|
||||
delayMs: number;
|
||||
fetch: boolean;
|
||||
follow: boolean;
|
||||
sources: LyricSource[];
|
||||
};
|
||||
playback: {
|
||||
audioDeviceId?: string | null;
|
||||
crossfadeDuration: number;
|
||||
crossfadeStyle: CrossfadeStyle;
|
||||
mpvExtraParameters: string[];
|
||||
mpvProperties: MpvSettings;
|
||||
muted: boolean;
|
||||
scrobble: {
|
||||
enabled: boolean;
|
||||
scrobbleAtDuration: number;
|
||||
scrobbleAtPercentage: number;
|
||||
hotkeys: {
|
||||
bindings: Record<
|
||||
BindingActions,
|
||||
{ allowGlobal: boolean; hotkey: string; isGlobal: boolean }
|
||||
>;
|
||||
globalMediaHotkeys: boolean;
|
||||
};
|
||||
lyrics: {
|
||||
delayMs: number;
|
||||
fetch: boolean;
|
||||
follow: boolean;
|
||||
sources: LyricSource[];
|
||||
};
|
||||
playback: {
|
||||
audioDeviceId?: string | null;
|
||||
crossfadeDuration: number;
|
||||
crossfadeStyle: CrossfadeStyle;
|
||||
mpvExtraParameters: string[];
|
||||
mpvProperties: MpvSettings;
|
||||
muted: boolean;
|
||||
scrobble: {
|
||||
enabled: boolean;
|
||||
scrobbleAtDuration: number;
|
||||
scrobbleAtPercentage: number;
|
||||
};
|
||||
style: PlaybackStyle;
|
||||
type: PlaybackType;
|
||||
};
|
||||
tab: 'general' | 'playback' | 'window' | 'hotkeys' | string;
|
||||
tables: {
|
||||
fullScreen: DataTableProps;
|
||||
nowPlaying: DataTableProps;
|
||||
sideDrawerQueue: DataTableProps;
|
||||
sideQueue: DataTableProps;
|
||||
songs: DataTableProps;
|
||||
};
|
||||
window: {
|
||||
disableAutoUpdate: boolean;
|
||||
exitToTray: boolean;
|
||||
minimizeToTray: boolean;
|
||||
windowBarStyle: Platform;
|
||||
};
|
||||
style: PlaybackStyle;
|
||||
type: PlaybackType;
|
||||
};
|
||||
tab: 'general' | 'playback' | 'window' | 'hotkeys' | string;
|
||||
tables: {
|
||||
fullScreen: DataTableProps;
|
||||
nowPlaying: DataTableProps;
|
||||
sideDrawerQueue: DataTableProps;
|
||||
sideQueue: DataTableProps;
|
||||
songs: DataTableProps;
|
||||
};
|
||||
window: {
|
||||
disableAutoUpdate: boolean;
|
||||
exitToTray: boolean;
|
||||
minimizeToTray: boolean;
|
||||
windowBarStyle: Platform;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SettingsSlice extends SettingsState {
|
||||
actions: {
|
||||
reset: () => void;
|
||||
setSettings: (data: Partial<SettingsState>) => void;
|
||||
setSidebarItems: (items: SidebarItemType[]) => void;
|
||||
};
|
||||
actions: {
|
||||
reset: () => void;
|
||||
setSettings: (data: Partial<SettingsState>) => void;
|
||||
setSidebarItems: (items: SidebarItemType[]) => void;
|
||||
};
|
||||
}
|
||||
|
||||
// Determines the default/initial windowBarStyle value based on the current platform.
|
||||
const getPlatformDefaultWindowBarStyle = (): Platform => {
|
||||
return isElectron() ? (utils.isMacOS() ? Platform.MACOS : Platform.WINDOWS) : Platform.WEB;
|
||||
return isElectron() ? (utils.isMacOS() ? Platform.MACOS : Platform.WINDOWS) : Platform.WEB;
|
||||
};
|
||||
|
||||
const platformDefaultWindowBarStyle: Platform = getPlatformDefaultWindowBarStyle();
|
||||
|
||||
const initialState: SettingsState = {
|
||||
general: {
|
||||
followSystemTheme: false,
|
||||
fontContent: 'Poppins',
|
||||
playButtonBehavior: Play.NOW,
|
||||
resume: false,
|
||||
showQueueDrawerButton: false,
|
||||
sideQueueType: 'sideQueue',
|
||||
sidebarItems,
|
||||
sidebarPlaylistList: true,
|
||||
skipButtons: {
|
||||
enabled: false,
|
||||
skipBackwardSeconds: 5,
|
||||
skipForwardSeconds: 10,
|
||||
general: {
|
||||
followSystemTheme: false,
|
||||
fontContent: 'Poppins',
|
||||
playButtonBehavior: Play.NOW,
|
||||
resume: false,
|
||||
showQueueDrawerButton: false,
|
||||
sideQueueType: 'sideQueue',
|
||||
sidebarItems,
|
||||
sidebarPlaylistList: true,
|
||||
skipButtons: {
|
||||
enabled: false,
|
||||
skipBackwardSeconds: 5,
|
||||
skipForwardSeconds: 10,
|
||||
},
|
||||
theme: AppTheme.DEFAULT_DARK,
|
||||
themeDark: AppTheme.DEFAULT_DARK,
|
||||
themeLight: AppTheme.DEFAULT_LIGHT,
|
||||
volumeWheelStep: 5,
|
||||
zoomFactor: 100,
|
||||
},
|
||||
theme: AppTheme.DEFAULT_DARK,
|
||||
themeDark: AppTheme.DEFAULT_DARK,
|
||||
themeLight: AppTheme.DEFAULT_LIGHT,
|
||||
volumeWheelStep: 5,
|
||||
zoomFactor: 100,
|
||||
},
|
||||
hotkeys: {
|
||||
bindings: {
|
||||
globalSearch: { allowGlobal: false, hotkey: 'mod+k', isGlobal: false },
|
||||
localSearch: { allowGlobal: false, hotkey: 'mod+f', isGlobal: false },
|
||||
next: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
pause: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
play: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
playPause: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
previous: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
skipBackward: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
skipForward: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
stop: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
toggleFullscreenPlayer: { allowGlobal: false, hotkey: '', isGlobal: false },
|
||||
toggleQueue: { allowGlobal: false, hotkey: '', isGlobal: false },
|
||||
toggleRepeat: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
toggleShuffle: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
volumeDown: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
volumeMute: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
volumeUp: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
zoomIn: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
zoomOut: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
hotkeys: {
|
||||
bindings: {
|
||||
globalSearch: { allowGlobal: false, hotkey: 'mod+k', isGlobal: false },
|
||||
localSearch: { allowGlobal: false, hotkey: 'mod+f', isGlobal: false },
|
||||
next: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
pause: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
play: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
playPause: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
previous: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
skipBackward: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
skipForward: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
stop: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
toggleFullscreenPlayer: { allowGlobal: false, hotkey: '', isGlobal: false },
|
||||
toggleQueue: { allowGlobal: false, hotkey: '', isGlobal: false },
|
||||
toggleRepeat: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
toggleShuffle: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
volumeDown: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
volumeMute: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
volumeUp: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
zoomIn: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
zoomOut: { allowGlobal: true, hotkey: '', isGlobal: false },
|
||||
},
|
||||
globalMediaHotkeys: true,
|
||||
},
|
||||
globalMediaHotkeys: true,
|
||||
},
|
||||
lyrics: {
|
||||
delayMs: 0,
|
||||
fetch: false,
|
||||
follow: true,
|
||||
sources: [],
|
||||
},
|
||||
playback: {
|
||||
audioDeviceId: undefined,
|
||||
crossfadeDuration: 5,
|
||||
crossfadeStyle: CrossfadeStyle.EQUALPOWER,
|
||||
mpvExtraParameters: [],
|
||||
mpvProperties: {
|
||||
audioExclusiveMode: 'no',
|
||||
audioFormat: undefined,
|
||||
audioSampleRateHz: 0,
|
||||
gaplessAudio: 'weak',
|
||||
replayGainClip: true,
|
||||
replayGainFallbackDB: undefined,
|
||||
replayGainMode: 'no',
|
||||
replayGainPreampDB: 0,
|
||||
lyrics: {
|
||||
delayMs: 0,
|
||||
fetch: false,
|
||||
follow: true,
|
||||
sources: [],
|
||||
},
|
||||
muted: false,
|
||||
scrobble: {
|
||||
enabled: true,
|
||||
scrobbleAtDuration: 240,
|
||||
scrobbleAtPercentage: 75,
|
||||
playback: {
|
||||
audioDeviceId: undefined,
|
||||
crossfadeDuration: 5,
|
||||
crossfadeStyle: CrossfadeStyle.EQUALPOWER,
|
||||
mpvExtraParameters: [],
|
||||
mpvProperties: {
|
||||
audioExclusiveMode: 'no',
|
||||
audioFormat: undefined,
|
||||
audioSampleRateHz: 0,
|
||||
gaplessAudio: 'weak',
|
||||
replayGainClip: true,
|
||||
replayGainFallbackDB: undefined,
|
||||
replayGainMode: 'no',
|
||||
replayGainPreampDB: 0,
|
||||
},
|
||||
muted: false,
|
||||
scrobble: {
|
||||
enabled: true,
|
||||
scrobbleAtDuration: 240,
|
||||
scrobbleAtPercentage: 75,
|
||||
},
|
||||
style: PlaybackStyle.GAPLESS,
|
||||
type: PlaybackType.LOCAL,
|
||||
},
|
||||
style: PlaybackStyle.GAPLESS,
|
||||
type: PlaybackType.LOCAL,
|
||||
},
|
||||
tab: 'general',
|
||||
tables: {
|
||||
fullScreen: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
tab: 'general',
|
||||
tables: {
|
||||
fullScreen: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.USER_FAVORITE,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 60,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
nowPlaying: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM_ARTIST,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.GENRE,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.YEAR,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 30,
|
||||
},
|
||||
{
|
||||
column: TableColumn.USER_FAVORITE,
|
||||
width: 100,
|
||||
sideDrawerQueue: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 60,
|
||||
},
|
||||
sideQueue: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 60,
|
||||
},
|
||||
songs: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ARTIST,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.YEAR,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
rowHeight: 60,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 60,
|
||||
},
|
||||
nowPlaying: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM_ARTIST,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.GENRE,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.YEAR,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 30,
|
||||
window: {
|
||||
disableAutoUpdate: false,
|
||||
exitToTray: false,
|
||||
minimizeToTray: false,
|
||||
windowBarStyle: platformDefaultWindowBarStyle,
|
||||
},
|
||||
sideDrawerQueue: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 60,
|
||||
},
|
||||
sideQueue: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
followCurrentSong: true,
|
||||
rowHeight: 60,
|
||||
},
|
||||
songs: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ARTIST,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.YEAR,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
rowHeight: 60,
|
||||
},
|
||||
},
|
||||
window: {
|
||||
disableAutoUpdate: false,
|
||||
exitToTray: false,
|
||||
minimizeToTray: false,
|
||||
windowBarStyle: platformDefaultWindowBarStyle,
|
||||
},
|
||||
};
|
||||
|
||||
export const useSettingsStore = create<SettingsSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
reset: () => {
|
||||
if (!isElectron()) {
|
||||
set({
|
||||
...initialState,
|
||||
playback: {
|
||||
...initialState.playback,
|
||||
type: PlaybackType.WEB,
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
actions: {
|
||||
reset: () => {
|
||||
if (!isElectron()) {
|
||||
set({
|
||||
...initialState,
|
||||
playback: {
|
||||
...initialState.playback,
|
||||
type: PlaybackType.WEB,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
set(initialState);
|
||||
}
|
||||
},
|
||||
setSettings: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setSidebarItems: (items: SidebarItemType[]) => {
|
||||
set((state) => {
|
||||
state.general.sidebarItems = items;
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
set(initialState);
|
||||
}
|
||||
},
|
||||
setSettings: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setSidebarItems: (items: SidebarItemType[]) => {
|
||||
set((state) => {
|
||||
state.general.sidebarItems = items;
|
||||
});
|
||||
},
|
||||
...initialState,
|
||||
})),
|
||||
{ name: 'store_settings' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_settings',
|
||||
version: 6,
|
||||
},
|
||||
...initialState,
|
||||
})),
|
||||
{ name: 'store_settings' },
|
||||
),
|
||||
{
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
name: 'store_settings',
|
||||
version: 6,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const useSettingsStoreActions = () => useSettingsStore((state) => state.actions);
|
||||
|
|
@ -428,20 +431,20 @@ export const useSettingsStoreActions = () => useSettingsStore((state) => state.a
|
|||
export const usePlaybackSettings = () => useSettingsStore((state) => state.playback, shallow);
|
||||
|
||||
export const useTableSettings = (type: TableType) =>
|
||||
useSettingsStore((state) => state.tables[type]);
|
||||
useSettingsStore((state) => state.tables[type]);
|
||||
|
||||
export const useGeneralSettings = () => useSettingsStore((state) => state.general, shallow);
|
||||
|
||||
export const usePlayerType = () => useSettingsStore((state) => state.playback.type, shallow);
|
||||
|
||||
export const usePlayButtonBehavior = () =>
|
||||
useSettingsStore((state) => state.general.playButtonBehavior, shallow);
|
||||
useSettingsStore((state) => state.general.playButtonBehavior, shallow);
|
||||
|
||||
export const useWindowSettings = () => useSettingsStore((state) => state.window, shallow);
|
||||
|
||||
export const useHotkeySettings = () => useSettingsStore((state) => state.hotkeys, shallow);
|
||||
|
||||
export const useMpvSettings = () =>
|
||||
useSettingsStore((state) => state.playback.mpvProperties, shallow);
|
||||
useSettingsStore((state) => state.playback.mpvProperties, shallow);
|
||||
|
||||
export const useLyricsSettings = () => useSettingsStore((state) => state.lyrics, shallow);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue