mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 20:40:15 +02:00
reset all stores, remove old ones
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
import { devtools } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
export interface AlbumArtistListDataSlice extends AlbumArtistListDataState {
|
||||
actions: {
|
||||
setItemData: (data: any[]) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AlbumArtistListDataState {
|
||||
itemData: any[];
|
||||
}
|
||||
|
||||
export const useAlbumArtistListDataStore = createWithEqualityFn<AlbumArtistListDataSlice>()(
|
||||
devtools(
|
||||
immer((set) => ({
|
||||
actions: {
|
||||
setItemData: (data) => {
|
||||
set((state) => {
|
||||
state.itemData = data;
|
||||
});
|
||||
},
|
||||
},
|
||||
itemData: [],
|
||||
})),
|
||||
{ name: 'store_album_list_data' },
|
||||
),
|
||||
);
|
||||
|
||||
export const useAlbumArtistListStoreActions = () =>
|
||||
useAlbumArtistListDataStore((state) => state.actions);
|
||||
|
||||
export const useAlbumArtistListItemData = () =>
|
||||
useAlbumArtistListDataStore((state) => {
|
||||
return { itemData: state.itemData, setItemData: state.actions.setItemData };
|
||||
});
|
||||
@@ -1,128 +0,0 @@
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
import { DataTableProps } from '/@/renderer/store/settings.store';
|
||||
import { mergeOverridingColumns } from '/@/renderer/store/utils';
|
||||
import { AlbumArtistListArgs, AlbumArtistListSort, SortOrder } from '/@/shared/types/domain-types';
|
||||
import { ListDisplayType, ListPagination, TableColumn } from '/@/shared/types/types';
|
||||
|
||||
export type AlbumArtistListFilter = Omit<AlbumArtistListArgs['query'], 'limit' | 'startIndex'>;
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AlbumArtistState {
|
||||
list: ListProps<AlbumArtistListFilter>;
|
||||
}
|
||||
|
||||
type ListProps<T> = {
|
||||
display: ListDisplayType;
|
||||
filter: T;
|
||||
grid: {
|
||||
scrollOffset: number;
|
||||
size: number;
|
||||
};
|
||||
table: TableProps;
|
||||
};
|
||||
|
||||
type TableProps = DataTableProps & {
|
||||
pagination: ListPagination;
|
||||
scrollOffset: number;
|
||||
};
|
||||
|
||||
export const useAlbumArtistStore = createWithEqualityFn<AlbumArtistSlice>()(
|
||||
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,
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
})),
|
||||
{ name: 'store_album_artist' },
|
||||
),
|
||||
{
|
||||
merge: mergeOverridingColumns,
|
||||
name: 'store_album_artist',
|
||||
version: 1,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const useAlbumArtistStoreActions = () => useAlbumArtistStore((state) => state.actions);
|
||||
|
||||
export const useSetAlbumArtistStore = () => useAlbumArtistStore((state) => state.actions.setStore);
|
||||
|
||||
export const useSetAlbumArtistFilters = () =>
|
||||
useAlbumArtistStore((state) => state.actions.setFilters);
|
||||
|
||||
export const useAlbumArtistListStore = () => useAlbumArtistStore((state) => state.list);
|
||||
|
||||
export const useAlbumArtistTablePagination = () =>
|
||||
useAlbumArtistStore((state) => state.list.table.pagination);
|
||||
|
||||
export const useSetAlbumArtistTablePagination = () =>
|
||||
useAlbumArtistStore((state) => state.actions.setTablePagination);
|
||||
|
||||
export const useSetAlbumArtistTable = () => useAlbumArtistStore((state) => state.actions.setTable);
|
||||
@@ -1,47 +0,0 @@
|
||||
import { devtools } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
export interface AlbumListDataSlice extends AlbumListDataState {
|
||||
actions: {
|
||||
setItemData: (data: any[]) => void;
|
||||
setItemDataById: (id: string, data: any) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AlbumListDataState {
|
||||
itemData: any[];
|
||||
}
|
||||
|
||||
export const useAlbumListDataStore = createWithEqualityFn<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' },
|
||||
),
|
||||
);
|
||||
|
||||
export const useAlbumListStoreActions = () => useAlbumListDataStore((state) => state.actions);
|
||||
|
||||
export const useAlbumListItemData = () =>
|
||||
useAlbumListDataStore((state) => {
|
||||
return { itemData: state.itemData, setItemData: state.actions.setItemData };
|
||||
});
|
||||
|
||||
export const useSetAlbumListItemDataById = () =>
|
||||
useAlbumListDataStore((state) => state.actions.setItemDataById);
|
||||
@@ -116,8 +116,15 @@ export const useAppStore = createWithEqualityFn<AppSlice>()(
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
migrate: (persistedState, version) => {
|
||||
if (version <= 2) {
|
||||
return {} as AppState;
|
||||
}
|
||||
|
||||
return persistedState;
|
||||
},
|
||||
name: 'store_app',
|
||||
version: 2,
|
||||
version: 3,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -5,9 +5,6 @@ import { immer } from 'zustand/middleware/immer';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
import { useAlbumArtistListDataStore } from '/@/renderer/store/album-artist-list-data.store';
|
||||
import { useAlbumListDataStore } from '/@/renderer/store/album-list-data.store';
|
||||
import { useListStore } from '/@/renderer/store/list.store';
|
||||
import { ServerListItem, ServerListItemWithCredential } from '/@/shared/types/domain-types';
|
||||
|
||||
export interface AuthSlice extends AuthState {
|
||||
@@ -54,15 +51,6 @@ export const useAuthStore = createWithEqualityFn<AuthSlice>()(
|
||||
setCurrentServer: (server) => {
|
||||
set((state) => {
|
||||
state.currentServer = server;
|
||||
|
||||
if (server) {
|
||||
// Reset list filters
|
||||
useListStore.getState()._actions.resetFilter();
|
||||
|
||||
// Reset persisted grid list stores
|
||||
useAlbumListDataStore.getState().actions.setItemData([]);
|
||||
useAlbumArtistListDataStore.getState().actions.setItemData([]);
|
||||
}
|
||||
});
|
||||
},
|
||||
setMusicFolderId: (musicFolderId: string[] | undefined) => {
|
||||
|
||||
@@ -42,8 +42,15 @@ export const useFullScreenPlayerStore = createWithEqualityFn<FullScreenPlayerSli
|
||||
merge: (persistedState, currentState) => {
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
migrate: (persistedState, version) => {
|
||||
if (version <= 2) {
|
||||
return {} as FullScreenPlayerState;
|
||||
}
|
||||
|
||||
return persistedState;
|
||||
},
|
||||
name: 'store_full_screen_player',
|
||||
version: 2,
|
||||
version: 3,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
export * from './album-artist-list-data.store';
|
||||
export * from './album-list-data.store';
|
||||
export * from './app.store';
|
||||
export * from './auth.store';
|
||||
export * from './full-screen-player.store';
|
||||
export * from './list.store';
|
||||
export * from './player.store';
|
||||
export * from './playlist.store';
|
||||
export * from './settings.store';
|
||||
export * from './timestamp.store';
|
||||
|
||||
@@ -1,723 +0,0 @@
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
import { ItemTableListColumnConfig } from '/@/renderer/components/item-list/types';
|
||||
import { ListDeterministicArgs } from '/@/renderer/store';
|
||||
import { DataTableProps } from '/@/renderer/store/settings.store';
|
||||
import { mergeOverridingColumns } from '/@/renderer/store/utils';
|
||||
import {
|
||||
AlbumArtistListArgs,
|
||||
AlbumArtistListSort,
|
||||
AlbumListArgs,
|
||||
AlbumListSort,
|
||||
ArtistListArgs,
|
||||
GenreListArgs,
|
||||
GenreListSort,
|
||||
LibraryItem,
|
||||
PlaylistListArgs,
|
||||
PlaylistListSort,
|
||||
SongListArgs,
|
||||
SongListSort,
|
||||
SortOrder,
|
||||
} from '/@/shared/types/domain-types';
|
||||
import { ListDisplayType, ListPagination, TableColumn } from '/@/shared/types/types';
|
||||
|
||||
export const generatePageKey = (page: string, id?: string) => {
|
||||
return id ? `${page}_${id}` : page;
|
||||
};
|
||||
|
||||
export type AlbumArtistListFilter = Omit<AlbumArtistListArgs['query'], 'limit' | 'startIndex'>;
|
||||
export type AlbumListFilter = Omit<AlbumListArgs['query'], 'limit' | 'startIndex'>;
|
||||
export type ArtistListFilter = Omit<ArtistListArgs['query'], 'limit' | 'startIndex'>;
|
||||
export type GenreListFilter = Omit<GenreListArgs['query'], 'limit' | 'startIndex'>;
|
||||
export type ListDeterministicArgs = { key: ListKey };
|
||||
export type ListGridProps = {
|
||||
itemGap?: number;
|
||||
itemSize?: number;
|
||||
itemsPerRow?: number;
|
||||
};
|
||||
|
||||
export type ListItemProps<TFilter = any> = {
|
||||
display: ListDisplayType;
|
||||
filter: TFilter;
|
||||
grid: ListGridProps;
|
||||
itemsPerPage: number;
|
||||
pagination: ListPagination;
|
||||
table: ListTableProps;
|
||||
};
|
||||
|
||||
export type ListKey = keyof ListState['item'] | string;
|
||||
|
||||
export interface ListSlice extends ListState {
|
||||
_actions: {
|
||||
getFilter: (args: {
|
||||
customFilters?: Record<any, any>;
|
||||
id?: string;
|
||||
itemType: LibraryItem;
|
||||
key?: string;
|
||||
}) => FilterType;
|
||||
resetFilter: () => void;
|
||||
setDisplayType: (args: ListDeterministicArgs & { data: ListDisplayType }) => void;
|
||||
setFilter: (
|
||||
args: ListDeterministicArgs & {
|
||||
customFilters?: Record<any, any>;
|
||||
data: Partial<FilterType>;
|
||||
itemType: LibraryItem;
|
||||
},
|
||||
) => FilterType;
|
||||
setGrid: (args: ListDeterministicArgs & { data: Partial<ListGridProps> }) => void;
|
||||
setStore: (data: Partial<ListSlice>) => void;
|
||||
setTable: (args: ListDeterministicArgs & { data: Partial<ListTableProps> }) => void;
|
||||
setTableColumns: (
|
||||
args: ListDeterministicArgs & { data: ItemTableListColumnConfig[] },
|
||||
) => void;
|
||||
setTablePagination: (
|
||||
args: ListDeterministicArgs & { data: Partial<ListPagination> },
|
||||
) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ListState {
|
||||
detail: {
|
||||
[key: string]: Omit<ListItemProps<any>, 'display'>;
|
||||
};
|
||||
item: {
|
||||
album: ListItemProps<AlbumListFilter>;
|
||||
albumArtist: ListItemProps<AlbumArtistListFilter>;
|
||||
albumArtistAlbum: ListItemProps<AlbumListFilter>;
|
||||
albumArtistSong: ListItemProps<SongListFilter>;
|
||||
albumDetail: ListItemProps<any>;
|
||||
genre: ListItemProps<GenreListFilter>;
|
||||
playlist: ListItemProps<PlaylistListFilter>;
|
||||
song: ListItemProps<SongListFilter>;
|
||||
};
|
||||
}
|
||||
|
||||
export type ListTableProps = DataTableProps;
|
||||
|
||||
export type PlaylistListFilter = Omit<PlaylistListArgs['query'], 'limit' | 'startIndex'>;
|
||||
|
||||
export type SongListFilter = Omit<SongListArgs['query'], 'limit' | 'startIndex'>;
|
||||
|
||||
type FilterType =
|
||||
| AlbumArtistListFilter
|
||||
| AlbumListFilter
|
||||
| ArtistListFilter
|
||||
| GenreListFilter
|
||||
| PlaylistListFilter
|
||||
| SongListFilter;
|
||||
|
||||
export const useListStore = createWithEqualityFn<ListSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
_actions: {
|
||||
getFilter: (args) => {
|
||||
const state = get();
|
||||
|
||||
if (args.id && args.key) {
|
||||
return {
|
||||
artistIds: [args.id],
|
||||
...state.item.song.filter,
|
||||
...state.detail[args.key]?.filter,
|
||||
_custom: {
|
||||
...state.detail[args.key]?.filter?._custom,
|
||||
jellyfin: {
|
||||
...state.detail[args.key]?.filter?._custom?.jellyfin,
|
||||
includeItemTypes:
|
||||
args?.itemType === LibraryItem.ALBUM
|
||||
? 'MusicAlbum'
|
||||
: 'Audio',
|
||||
},
|
||||
navidrome: {
|
||||
...state.detail[args.key]?.filter?._custom?.navidrome,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (args.key) {
|
||||
return state.item[args.key as keyof ListState['item']].filter;
|
||||
}
|
||||
|
||||
return state.item.song.filter;
|
||||
},
|
||||
resetFilter: () => {
|
||||
set((state) => {
|
||||
state.item.album.filter = {
|
||||
musicFolderId: undefined,
|
||||
sortBy: AlbumListSort.RECENTLY_ADDED,
|
||||
sortOrder: SortOrder.DESC,
|
||||
} as AlbumListFilter;
|
||||
|
||||
state.item.song.filter = {
|
||||
musicFolderId: undefined,
|
||||
sortBy: SongListSort.RECENTLY_ADDED,
|
||||
sortOrder: SortOrder.DESC,
|
||||
} as SongListFilter;
|
||||
});
|
||||
},
|
||||
setDisplayType: (args) => {
|
||||
set((state) => {
|
||||
const [page] = args.key.split('_');
|
||||
state.item[page as keyof ListState['item']].display = args.data;
|
||||
});
|
||||
},
|
||||
setFilter: (args) => {
|
||||
const [, id] = args.key.split('_');
|
||||
|
||||
set((state) => {
|
||||
if (id) {
|
||||
if (!state.detail[args.key]) {
|
||||
state.detail[args.key] = {
|
||||
filter: {} as FilterType,
|
||||
table: {
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
},
|
||||
} as ListTableProps,
|
||||
};
|
||||
}
|
||||
|
||||
state.detail[args.key].filter = {
|
||||
...state.detail[args.key as keyof ListState['item']].filter,
|
||||
...args.data,
|
||||
} as FilterType;
|
||||
} else {
|
||||
state.item[args.key as keyof ListState['item']].filter = {
|
||||
...state.item[args.key as keyof ListState['item']].filter,
|
||||
...args.data,
|
||||
} as FilterType;
|
||||
}
|
||||
});
|
||||
|
||||
const filter = get()._actions.getFilter({
|
||||
id,
|
||||
itemType: args.itemType,
|
||||
key: args.key,
|
||||
});
|
||||
|
||||
const mergedFilters = {
|
||||
...filter,
|
||||
...args.customFilters,
|
||||
_custom: {
|
||||
...filter._custom,
|
||||
...args.customFilters?._custom,
|
||||
jellyfin: {
|
||||
...filter._custom?.jellyfin,
|
||||
...args.customFilters?._custom?.jellyfin,
|
||||
},
|
||||
navidrome: {
|
||||
...filter._custom?.navidrome,
|
||||
...args.customFilters?._custom?.navidrome,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return mergedFilters;
|
||||
},
|
||||
setGrid: (args) => {
|
||||
const [page, id] = args.key.split('_');
|
||||
|
||||
set((state) => {
|
||||
if (id) {
|
||||
if (!state.detail[args.key]) {
|
||||
state.detail[args.key] = {
|
||||
filter: {} as FilterType,
|
||||
grid: {
|
||||
itemGap:
|
||||
state.item[page as keyof ListState['item']].grid
|
||||
?.itemGap || 10,
|
||||
itemSize:
|
||||
state.item[page as keyof ListState['item']].grid
|
||||
?.itemSize || 5,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
table: {
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
},
|
||||
} as ListTableProps,
|
||||
};
|
||||
}
|
||||
|
||||
if (state.detail[args.key as keyof ListState['item']].grid) {
|
||||
state.detail[args.key as keyof ListState['item']].grid = {
|
||||
...state.detail[args.key as keyof ListState['item']]?.grid,
|
||||
...args.data,
|
||||
};
|
||||
}
|
||||
} else if (state.item[page as keyof ListState['item']].grid) {
|
||||
state.item[page as keyof ListState['item']].grid = {
|
||||
...state.item[page as keyof ListState['item']]?.grid,
|
||||
...args.data,
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
setStore: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
},
|
||||
setTable: (args) => {
|
||||
set((state) => {
|
||||
const [page, id] = args.key.split('_');
|
||||
|
||||
if (id) {
|
||||
if (!state.detail[args.key]) {
|
||||
state.detail[args.key] = {
|
||||
filter: {
|
||||
...state.item[page as keyof ListState['item']].filter,
|
||||
} as FilterType,
|
||||
table: {
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
},
|
||||
scrollOffset: 0,
|
||||
} as ListTableProps,
|
||||
};
|
||||
}
|
||||
|
||||
if (state.detail[args.key as keyof ListState['item']].table) {
|
||||
state.detail[args.key as keyof ListState['item']].table = {
|
||||
...state.detail[args.key as keyof ListState['item']]?.table,
|
||||
...args.data,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
state.item[page as keyof ListState['item']].table = {
|
||||
...state.item[page as keyof ListState['item']].table,
|
||||
...args.data,
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
setTableColumns: (args) => {
|
||||
set((state) => {
|
||||
state.item[args.key as keyof ListState['item']].table.columns = [
|
||||
...state.item[args.key as keyof ListState['item']].table.columns,
|
||||
...args.data,
|
||||
];
|
||||
});
|
||||
},
|
||||
setTablePagination: (args) => {
|
||||
set((state) => {
|
||||
const [, id] = args.key.split('_');
|
||||
|
||||
if (id) {
|
||||
if (!state.detail[args.key]) {
|
||||
state.detail[args.key] = {
|
||||
filter: {} as FilterType,
|
||||
table: {
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
},
|
||||
} as ListTableProps,
|
||||
};
|
||||
}
|
||||
|
||||
state.detail[args.key as keyof ListState['item']].table.pagination =
|
||||
{
|
||||
...state.detail[args.key as keyof ListState['item']].table
|
||||
.pagination,
|
||||
...args.data,
|
||||
};
|
||||
} else {
|
||||
state.item[args.key as keyof ListState['item']].table.pagination = {
|
||||
...state.item[args.key as keyof ListState['item']].table
|
||||
.pagination,
|
||||
...args.data,
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
detail: {},
|
||||
item: {
|
||||
album: {
|
||||
display: ListDisplayType.GRID,
|
||||
filter: {
|
||||
sortBy: AlbumListSort.RECENTLY_ADDED,
|
||||
sortOrder: SortOrder.DESC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM_ARTIST,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
column: TableColumn.YEAR,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
albumArtist: {
|
||||
display: ListDisplayType.GRID,
|
||||
filter: {
|
||||
sortBy: AlbumArtistListSort.NAME,
|
||||
sortOrder: SortOrder.DESC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
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,
|
||||
},
|
||||
},
|
||||
albumArtistAlbum: {
|
||||
display: ListDisplayType.GRID,
|
||||
filter: {
|
||||
sortBy: AlbumListSort.RECENTLY_ADDED,
|
||||
sortOrder: SortOrder.DESC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM_ARTIST,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
column: TableColumn.YEAR,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
albumArtistSong: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
sortBy: SongListSort.RECENTLY_ADDED,
|
||||
sortOrder: SortOrder.DESC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
albumDetail: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
sortBy: SongListSort.ALBUM,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [],
|
||||
followCurrentSong: false,
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
artist: {
|
||||
display: ListDisplayType.GRID,
|
||||
filter: {
|
||||
role: '',
|
||||
sortBy: AlbumArtistListSort.NAME,
|
||||
sortOrder: SortOrder.DESC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
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,
|
||||
},
|
||||
},
|
||||
genre: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
sortBy: GenreListSort.NAME,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE,
|
||||
width: 500,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 30,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
playlist: {
|
||||
display: ListDisplayType.GRID,
|
||||
filter: {
|
||||
sortBy: PlaylistListSort.NAME,
|
||||
sortOrder: SortOrder.DESC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
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: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
song: {
|
||||
display: ListDisplayType.TABLE,
|
||||
filter: {
|
||||
sortBy: SongListSort.RECENTLY_ADDED,
|
||||
sortOrder: SortOrder.DESC,
|
||||
},
|
||||
grid: { itemGap: 10, itemSize: 200, scrollOffset: 0 },
|
||||
table: {
|
||||
autoFit: true,
|
||||
columns: [
|
||||
{
|
||||
column: TableColumn.ROW_INDEX,
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
column: TableColumn.TITLE_COMBINED,
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
column: TableColumn.ALBUM,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
column: TableColumn.DURATION,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 100,
|
||||
totalItems: 1,
|
||||
totalPages: 1,
|
||||
},
|
||||
rowHeight: 60,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
})),
|
||||
{ name: 'store_list' },
|
||||
),
|
||||
{
|
||||
merge: mergeOverridingColumns,
|
||||
name: 'store_list',
|
||||
partialize: (state) => {
|
||||
return Object.fromEntries(
|
||||
Object.entries(state).filter(([key]) => !['detail'].includes(key)),
|
||||
);
|
||||
},
|
||||
version: 2,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const useListStoreActions = () => useListStore((state) => state._actions);
|
||||
|
||||
export const useListStoreByKey = <TFilter>(args: {
|
||||
filter?: Partial<TFilter>;
|
||||
key: string;
|
||||
}): ListItemProps<TFilter> => {
|
||||
const key = args.key as keyof ListState['item'];
|
||||
return useListStore(
|
||||
(state) => ({
|
||||
...state.item[key],
|
||||
filter: {
|
||||
...state.item[key].filter,
|
||||
...args.filter,
|
||||
},
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
};
|
||||
|
||||
export const useListFilterByKey = <TFilter>(args: {
|
||||
filter?: any | Partial<TFilter>;
|
||||
key: string;
|
||||
}): TFilter => {
|
||||
const key = args.key as keyof ListState['item'];
|
||||
return useListStore(
|
||||
(state) => {
|
||||
return {
|
||||
...state.item[key].filter,
|
||||
...(args.filter && {
|
||||
...args.filter,
|
||||
_custom: {
|
||||
...state.item[key].filter._custom,
|
||||
...args.filter?._custom,
|
||||
jellyfin: {
|
||||
...state.item[key].filter._custom?.jellyfin,
|
||||
...args.filter?._custom?.jellyfin,
|
||||
},
|
||||
navidrome: {
|
||||
...state.item[key].filter._custom?.navidrome,
|
||||
...args.filter?._custom?.navidrome,
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
},
|
||||
|
||||
shallow,
|
||||
);
|
||||
};
|
||||
|
||||
export const useAlbumListFilter = (args: { id?: string; key?: string }) =>
|
||||
useListStore((state) => {
|
||||
return state._actions.getFilter({
|
||||
id: args.id,
|
||||
itemType: LibraryItem.ALBUM,
|
||||
key: args.key,
|
||||
}) as AlbumListFilter;
|
||||
}, shallow);
|
||||
|
||||
export const useListDetail = (key: string) => useListStore((state) => state.detail[key], shallow);
|
||||
@@ -1845,9 +1845,8 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
return merge(currentState, persistedState);
|
||||
},
|
||||
migrate: (persistedState, version) => {
|
||||
if (version === 1) {
|
||||
// Replace the old player store state with the new one
|
||||
persistedState = { ...initialState };
|
||||
if (version <= 3) {
|
||||
return {} as PlayerState;
|
||||
}
|
||||
|
||||
return persistedState;
|
||||
@@ -1913,7 +1912,7 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
return filteredState;
|
||||
},
|
||||
storage: createJSONStorage(() => idbStateStorage),
|
||||
version: 2,
|
||||
version: 3,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
import { PlaylistListFilter, SongListFilter } from '/@/renderer/store/list.store';
|
||||
import { DataTableProps } from '/@/renderer/store/settings.store';
|
||||
import { mergeOverridingColumns } from '/@/renderer/store/utils';
|
||||
import { PlaylistListSort, SortOrder } from '/@/shared/types/domain-types';
|
||||
import { ListDisplayType, ListPagination, TableColumn } from '/@/shared/types/types';
|
||||
|
||||
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;
|
||||
setGrid: (args: { data: Partial<ListGridProps> }) => void;
|
||||
setStore: (data: Partial<PlaylistSlice>) => void;
|
||||
setTable: (data: Partial<TableProps>) => void;
|
||||
setTablePagination: (args: { data: Partial<ListPagination> }) => void;
|
||||
};
|
||||
}
|
||||
|
||||
type DetailPaginationProps = ListPagination & {
|
||||
scrollOffset: number;
|
||||
};
|
||||
|
||||
type DetailProps = {
|
||||
display: ListDisplayType;
|
||||
table: DetailTableProps;
|
||||
};
|
||||
|
||||
type DetailTableProps = DataTableProps & {
|
||||
id: {
|
||||
[key: string]: DetailPaginationProps & { filter: SongListFilter };
|
||||
};
|
||||
};
|
||||
|
||||
type ListGridProps = {
|
||||
itemsPerRow?: number;
|
||||
scrollOffset?: number;
|
||||
};
|
||||
|
||||
type ListProps<T> = {
|
||||
display: ListDisplayType;
|
||||
filter: T;
|
||||
table: TableProps;
|
||||
};
|
||||
|
||||
interface PlaylistState {
|
||||
detail: DetailProps;
|
||||
grid: ListGridProps;
|
||||
list: ListProps<PlaylistListFilter>;
|
||||
}
|
||||
|
||||
type TableProps = DataTableProps & {
|
||||
pagination: ListPagination;
|
||||
scrollOffset: number;
|
||||
};
|
||||
|
||||
export const usePlaylistStore = createWithEqualityFn<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,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
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;
|
||||
},
|
||||
setGrid: (args) => {
|
||||
set((state) => {
|
||||
state.grid = {
|
||||
...state.grid,
|
||||
...args.data,
|
||||
};
|
||||
});
|
||||
},
|
||||
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,
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
itemsPerRow: 5,
|
||||
scrollOffset: 0,
|
||||
},
|
||||
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: mergeOverridingColumns,
|
||||
name: 'store_playlist',
|
||||
version: 1,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const usePlaylistStoreActions = () => usePlaylistStore((state) => state.actions);
|
||||
|
||||
export const useSetPlaylistStore = () => usePlaylistStore((state) => state.actions.setStore);
|
||||
|
||||
export const useSetPlaylistFilters = () => usePlaylistStore((state) => state.actions.setFilters);
|
||||
|
||||
export const usePlaylistFilters = () => {
|
||||
return usePlaylistStore((state) => [state.list.filter, state.actions.setFilters]);
|
||||
};
|
||||
|
||||
export const usePlaylistGridStore = () => usePlaylistStore((state) => state.grid);
|
||||
|
||||
export const usePlaylistListStore = () => usePlaylistStore((state) => state.list);
|
||||
|
||||
export const usePlaylistTablePagination = () =>
|
||||
usePlaylistStore((state) => state.list.table.pagination);
|
||||
|
||||
export const useSetPlaylistTablePagination = () =>
|
||||
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]);
|
||||
|
||||
export const useSetPlaylistDetailTablePagination = () =>
|
||||
usePlaylistStore((state) => state.actions.setDetailTablePagination);
|
||||
|
||||
export const useSetPlaylistDetailTable = () =>
|
||||
usePlaylistStore((state) => state.actions.setDetailTable);
|
||||
|
||||
export const useSetPlaylistDetailFilters = () =>
|
||||
usePlaylistStore((state) => state.actions.setDetailFilters);
|
||||
@@ -1308,10 +1308,14 @@ export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
|
||||
});
|
||||
}
|
||||
|
||||
if (version <= 11) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return persistedState;
|
||||
},
|
||||
name: 'store_settings',
|
||||
version: 11,
|
||||
version: 12,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user