Lint all files

This commit is contained in:
jeffvli 2023-07-01 19:10:05 -07:00
parent 22af76b4d6
commit 30e52ebb54
334 changed files with 76519 additions and 75932 deletions

View file

@ -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 };
});

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
};

View file

@ -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

View file

@ -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);

View file

@ -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);