mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
perf(albums): page catalog through scoped browse
This commit is contained in:
@@ -247,6 +247,7 @@ export function useAlbumBrowseData({
|
||||
const loadGenerationRef = useRef(0);
|
||||
const pageRef = useRef(0);
|
||||
const catalogOffsetRef = useRef(0);
|
||||
const catalogCursorRef = useRef<string | null>(null);
|
||||
const catalogLoadingRef = useRef(false);
|
||||
const loadingRef = useRef(false);
|
||||
const loadPendingRef = useRef(false);
|
||||
@@ -295,6 +296,7 @@ export function useAlbumBrowseData({
|
||||
offset,
|
||||
CATALOG_CHUNK_SIZE,
|
||||
starredOverrides,
|
||||
append ? catalogCursorRef.current : undefined,
|
||||
);
|
||||
if (generation !== loadGenerationRef.current || chunk == null) return;
|
||||
setAlbums(prev => {
|
||||
@@ -303,6 +305,7 @@ export function useAlbumBrowseData({
|
||||
return next;
|
||||
});
|
||||
setCatalogHasMore(chunk.hasMore);
|
||||
catalogCursorRef.current = chunk.nextCursor ?? null;
|
||||
} finally {
|
||||
catalogLoadingRef.current = false;
|
||||
if (generation === loadGenerationRef.current) {
|
||||
@@ -383,7 +386,8 @@ export function useAlbumBrowseData({
|
||||
const cached = readAlbumBrowseCatalogCache(catalogLoadKey);
|
||||
if (!cached) return;
|
||||
pageRef.current = 0;
|
||||
catalogOffsetRef.current = cached.albums.length;
|
||||
catalogOffsetRef.current = cached.albums.length;
|
||||
catalogCursorRef.current = cached.nextCursor ?? null;
|
||||
loadPendingRef.current = false;
|
||||
catalogLoadingRef.current = false;
|
||||
// React Compiler set-state-in-effect rule: local state synced from the catalog cache before paint.
|
||||
@@ -419,6 +423,7 @@ export function useAlbumBrowseData({
|
||||
if (!joinInflight) {
|
||||
pageRef.current = 0;
|
||||
catalogOffsetRef.current = 0;
|
||||
catalogCursorRef.current = null;
|
||||
loadPendingRef.current = false;
|
||||
catalogLoadingRef.current = false;
|
||||
// React Compiler set-state-in-effect rule: state set from an async result resolved in this effect.
|
||||
@@ -512,6 +517,7 @@ export function useAlbumBrowseData({
|
||||
setBrowseMode('slice');
|
||||
setAlbums(preview.albums);
|
||||
catalogOffsetRef.current = preview.albums.length;
|
||||
catalogCursorRef.current = preview.nextCursor ?? null;
|
||||
const needsTail =
|
||||
preview.hasMore && preview.albums.length < CATALOG_CHUNK_SIZE;
|
||||
setCatalogHasMore(needsTail || preview.hasMore);
|
||||
@@ -541,8 +547,9 @@ export function useAlbumBrowseData({
|
||||
serverId,
|
||||
indexEnabled,
|
||||
browseQuery,
|
||||
tailOffset,
|
||||
tailSize,
|
||||
tailOffset,
|
||||
tailSize,
|
||||
preview.nextCursor,
|
||||
),
|
||||
{ offset: tailOffset, chunkSize: tailSize },
|
||||
),
|
||||
@@ -558,10 +565,12 @@ export function useAlbumBrowseData({
|
||||
storeAlbumBrowseCatalogCache(loadKey, {
|
||||
albums: merged,
|
||||
hasMore: tail.hasMore,
|
||||
nextCursor: tail.nextCursor,
|
||||
});
|
||||
return merged;
|
||||
});
|
||||
setCatalogHasMore(tail.hasMore);
|
||||
setCatalogHasMore(tail.hasMore);
|
||||
catalogCursorRef.current = tail.nextCursor ?? null;
|
||||
emitAlbumBrowseDebug('catalog_tail_done', {
|
||||
albumCount: tail.albums.length,
|
||||
totalOffset: tailOffset + tail.albums.length,
|
||||
@@ -595,8 +604,9 @@ export function useAlbumBrowseData({
|
||||
if (cancelled || generation !== loadGenerationRef.current) return;
|
||||
if (first != null) {
|
||||
setBrowseMode('slice');
|
||||
setAlbums(first.albums);
|
||||
catalogOffsetRef.current = first.albums.length;
|
||||
setAlbums(first.albums);
|
||||
catalogOffsetRef.current = first.albums.length;
|
||||
catalogCursorRef.current = first.nextCursor ?? null;
|
||||
setCatalogHasMore(first.hasMore);
|
||||
setLoading(false);
|
||||
emitAlbumBrowseDebug('loading_false', { source: 'slice', albumCount: first.albums.length });
|
||||
|
||||
@@ -8,6 +8,7 @@ import { fetchLocalAlbumCatalogChunk } from '@/lib/library/albumBrowseLoad';
|
||||
export type AlbumCatalogChunk = {
|
||||
albums: SubsonicAlbum[];
|
||||
hasMore: boolean;
|
||||
nextCursor?: string | null;
|
||||
};
|
||||
|
||||
export function mergeAlbumCatalogChunk(
|
||||
@@ -30,6 +31,7 @@ export async function fetchAlbumBrowseCatalogChunk(
|
||||
offset: number,
|
||||
chunkSize: number,
|
||||
starredOverrides: Record<string, boolean>,
|
||||
cursor?: string | null,
|
||||
): Promise<AlbumCatalogChunk | null> {
|
||||
if (isOfflineBrowseActive()) {
|
||||
return loadOfflineAlbumCatalogChunk(
|
||||
@@ -40,5 +42,5 @@ export async function fetchAlbumBrowseCatalogChunk(
|
||||
starredOverrides,
|
||||
);
|
||||
}
|
||||
return fetchLocalAlbumCatalogChunk(serverId, indexEnabled, query, offset, chunkSize);
|
||||
return fetchLocalAlbumCatalogChunk(serverId, indexEnabled, query, offset, chunkSize, cursor);
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ export {
|
||||
filterAlbumsByCompilation,
|
||||
filterAlbumsByStarred,
|
||||
} from './albumBrowseFilters';
|
||||
export { runLocalAlbumBrowse } from './albumBrowseLocal';
|
||||
export { runLocalAlbumBrowse, runLocalAlbumScopeBrowse } from './albumBrowseLocal';
|
||||
|
||||
import { albumBrowseHasServerFilters, countGenresFromAlbums, filterAlbumsByCompilation } from './albumBrowseFilters';
|
||||
import { runLocalAlbumBrowse } from './albumBrowseLocal';
|
||||
import { runLocalAlbumBrowse, runLocalAlbumScopeBrowse } from './albumBrowseLocal';
|
||||
import { fetchAlbumBrowseNetwork } from './albumBrowseNetwork';
|
||||
import { fetchStarredAlbumBrowse } from './albumBrowseStarredFetch';
|
||||
import { librarySelectionForServer } from '@/lib/api/subsonicClient';
|
||||
@@ -47,6 +47,7 @@ export async function fetchLocalAlbumCatalogChunk(
|
||||
query: AlbumBrowseQuery,
|
||||
offset: number,
|
||||
chunkSize: number,
|
||||
cursor?: string | null,
|
||||
): Promise<AlbumBrowsePageResult | null> {
|
||||
if (query.starredOnly) {
|
||||
return fetchAlbumBrowsePage(serverId, indexEnabled, query, offset, chunkSize);
|
||||
@@ -60,6 +61,10 @@ export async function fetchLocalAlbumCatalogChunk(
|
||||
: query.genres.length > 0 && offset === 0
|
||||
? GENRE_ALBUM_FETCH_LIMIT
|
||||
: chunkSize;
|
||||
if (albumBrowseBootstrapEligible(query)) {
|
||||
const scoped = await runLocalAlbumScopeBrowse(serverId, query.sort, limit, cursor);
|
||||
if (scoped) return scoped;
|
||||
}
|
||||
return runLocalAlbumBrowse(serverId, query, offset, limit);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ export type AlbumBrowseQuery = {
|
||||
export type AlbumBrowsePageResult = {
|
||||
albums: SubsonicAlbum[];
|
||||
hasMore: boolean;
|
||||
nextCursor?: string | null;
|
||||
};
|
||||
|
||||
export type AlbumBrowseFetchCallbacks = {
|
||||
|
||||
Reference in New Issue
Block a user