mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-20 12:40:15 +02:00
massive UI/UX overhaul
This commit is contained in:
@@ -5,8 +5,10 @@ import {
|
||||
getAlbums,
|
||||
getAllTracks,
|
||||
getRecentlyPlayedTracks,
|
||||
getSetting,
|
||||
getTrackCount,
|
||||
markTrackPlayed,
|
||||
setSetting,
|
||||
} from '@/db/queries';
|
||||
import { ensureArtworkThumbnails } from '@/library/artwork';
|
||||
import { buildArtistList } from '@/library/artistGrouping';
|
||||
@@ -18,7 +20,9 @@ import {
|
||||
type ScanProgress,
|
||||
type ScanResult,
|
||||
} from '@/library/scanner';
|
||||
import type { TrackSort } from '@/lib/trackSort';
|
||||
import { ALBUM_SORT_LABELS, type AlbumSort } from '@/lib/albumSort';
|
||||
import { ARTIST_SORT_LABELS, type ArtistSort } from '@/lib/artistSort';
|
||||
import { TRACK_SORT_LABELS, type TrackSort } from '@/lib/trackSort';
|
||||
import { usePlaylistStore } from './playlistStore';
|
||||
import { useSettingsStore } from './settingsStore';
|
||||
|
||||
@@ -28,6 +32,38 @@ import { useSettingsStore } from './settingsStore';
|
||||
*/
|
||||
type ViewMode = 'tracks' | 'albums' | 'artists' | 'playlists' | 'folders';
|
||||
|
||||
const VIEW_MODE_KEY = 'library_view_mode';
|
||||
const TRACK_SORT_KEY = 'library_track_sort';
|
||||
const ALBUM_SORT_KEY = 'library_album_sort';
|
||||
const ARTIST_SORT_KEY = 'library_artist_sort';
|
||||
|
||||
const VIEW_MODES: readonly ViewMode[] = ['tracks', 'albums', 'artists', 'playlists', 'folders'];
|
||||
|
||||
function parseViewMode(value: string | null): ViewMode | null {
|
||||
return VIEW_MODES.includes(value as ViewMode) ? (value as ViewMode) : null;
|
||||
}
|
||||
|
||||
function parseTrackSort(value: string | null): TrackSort | null {
|
||||
return value !== null && value in TRACK_SORT_LABELS ? (value as TrackSort) : null;
|
||||
}
|
||||
|
||||
function parseAlbumSort(value: string | null): AlbumSort | null {
|
||||
return value !== null && value in ALBUM_SORT_LABELS ? (value as AlbumSort) : null;
|
||||
}
|
||||
|
||||
function parseArtistSort(value: string | null): ArtistSort | null {
|
||||
return value !== null && value in ARTIST_SORT_LABELS ? (value as ArtistSort) : null;
|
||||
}
|
||||
|
||||
/** Fire-and-forget settings write so view/sort switching stays synchronous. */
|
||||
function persistSetting(key: string, value: string) {
|
||||
void openLibraryDb()
|
||||
.then((db) => setSetting(db, key, value))
|
||||
.catch(() => {
|
||||
// Losing a view preference write is harmless; never surface it.
|
||||
});
|
||||
}
|
||||
|
||||
export type FolderWithCount = LibraryFolder & { track_count: number };
|
||||
|
||||
interface ScanProgressState {
|
||||
@@ -49,6 +85,8 @@ interface LibraryStore {
|
||||
totalTrackCount: number;
|
||||
viewMode: ViewMode;
|
||||
trackSort: TrackSort;
|
||||
albumSort: AlbumSort;
|
||||
artistSort: ArtistSort;
|
||||
isScanning: boolean;
|
||||
scanProgress: ScanProgressState;
|
||||
scanError: string | null;
|
||||
@@ -59,6 +97,8 @@ interface LibraryStore {
|
||||
recomputeArtists: () => void;
|
||||
setViewMode: (mode: ViewMode) => void;
|
||||
setTrackSort: (sort: TrackSort) => void;
|
||||
setAlbumSort: (sort: AlbumSort) => void;
|
||||
setArtistSort: (sort: ArtistSort) => void;
|
||||
addFolder: () => Promise<void>;
|
||||
removeFolder: (folderId: number) => Promise<void>;
|
||||
rescan: () => Promise<void>;
|
||||
@@ -93,6 +133,8 @@ export const useLibraryStore = create<LibraryStore>((set, get) => {
|
||||
totalTrackCount: 0,
|
||||
viewMode: 'albums',
|
||||
trackSort: 'artist',
|
||||
albumSort: 'artist',
|
||||
artistSort: 'name',
|
||||
isScanning: false,
|
||||
scanProgress: { ...IDLE_PROGRESS },
|
||||
scanError: null,
|
||||
@@ -107,6 +149,26 @@ export const useLibraryStore = create<LibraryStore>((set, get) => {
|
||||
useSettingsStore.subscribe((state, prev) => {
|
||||
if (state.artistGroupingMode !== prev.artistGroupingMode) get().recomputeArtists();
|
||||
});
|
||||
// Restore view preferences before the first render of the library screen.
|
||||
const [savedViewMode, savedTrackSort, savedAlbumSort, savedArtistSort] =
|
||||
await Promise.all([
|
||||
getSetting(db, VIEW_MODE_KEY),
|
||||
getSetting(db, TRACK_SORT_KEY),
|
||||
getSetting(db, ALBUM_SORT_KEY),
|
||||
getSetting(db, ARTIST_SORT_KEY),
|
||||
]);
|
||||
const viewMode = parseViewMode(savedViewMode);
|
||||
const trackSort = parseTrackSort(savedTrackSort);
|
||||
const albumSort = parseAlbumSort(savedAlbumSort);
|
||||
const artistSort = parseArtistSort(savedArtistSort);
|
||||
if (viewMode || trackSort || albumSort || artistSort) {
|
||||
set({
|
||||
...(viewMode ? { viewMode } : null),
|
||||
...(trackSort ? { trackSort } : null),
|
||||
...(albumSort ? { albumSort } : null),
|
||||
...(artistSort ? { artistSort } : null),
|
||||
});
|
||||
}
|
||||
await get().refresh();
|
||||
set({ initialized: true });
|
||||
// One-time recovery: the v3 migration marks tracks stale (mtime = -1)
|
||||
@@ -161,9 +223,25 @@ export const useLibraryStore = create<LibraryStore>((set, get) => {
|
||||
artists: buildArtistList(state.tracks, useSettingsStore.getState().artistGroupingMode),
|
||||
})),
|
||||
|
||||
setViewMode: (viewMode) => set({ viewMode }),
|
||||
setViewMode: (viewMode) => {
|
||||
set({ viewMode });
|
||||
persistSetting(VIEW_MODE_KEY, viewMode);
|
||||
},
|
||||
|
||||
setTrackSort: (trackSort) => set({ trackSort }),
|
||||
setTrackSort: (trackSort) => {
|
||||
set({ trackSort });
|
||||
persistSetting(TRACK_SORT_KEY, trackSort);
|
||||
},
|
||||
|
||||
setAlbumSort: (albumSort) => {
|
||||
set({ albumSort });
|
||||
persistSetting(ALBUM_SORT_KEY, albumSort);
|
||||
},
|
||||
|
||||
setArtistSort: (artistSort) => {
|
||||
set({ artistSort });
|
||||
persistSetting(ARTIST_SORT_KEY, artistSort);
|
||||
},
|
||||
|
||||
addFolder: () => runScan(() => addFolderViaPicker({ onProgress })),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user