mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
7e9cb60763
Move the Subsonic + Navidrome protocol clients and the library IPC facade (subsonic*, navidrome*, library.ts + tests) from src/api/ into src/lib/api/, the feature-free infra layer (plan M4, decision §10.3: shared client core → lib/). Pure move: deep-path import specifiers @/api/* -> @/lib/api/* across ~150 consumers; no behaviour change. Domain REST (lyrics/events) and cover/analysis infra stay in src/api/ pending their own M4 placement. tsc 0, lint 0/0, full suite 319 files / 2353 tests green.
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import { useEffect } from 'react';
|
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
|
import { coverPrefetchRegister } from './prefetchRegistry';
|
|
import {
|
|
resolveAlbumCoverRefsFromLibrary,
|
|
resolveArtistCoverRefsFromLibrary,
|
|
resolveTrackCoverRefsFromLibrary,
|
|
} from './resolveEntryLibrary';
|
|
import { COVER_SCOPE_ACTIVE, type CoverPrefetchPriority, type CoverServerScope, type CoverSurfaceKind } from './types';
|
|
|
|
export type LibraryCoverPrefetchBucket = {
|
|
albums?: ReadonlyArray<{ id: string; coverArt?: string | null }>;
|
|
artists?: ReadonlyArray<{ id: string; coverArt?: string | null }>;
|
|
songs?: ReadonlyArray<Pick<SubsonicSong, 'id' | 'albumId' | 'coverArt' | 'discNumber'>>;
|
|
limit?: number;
|
|
priority: CoverPrefetchPriority;
|
|
surface?: CoverSurfaceKind;
|
|
serverScope?: CoverServerScope;
|
|
};
|
|
|
|
/** Register cover prefetch after resolving refs from the local library index. */
|
|
export function useLibraryCoverPrefetch(
|
|
buckets: LibraryCoverPrefetchBucket[],
|
|
deps: readonly unknown[],
|
|
): void {
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
const unregisters: Array<() => void> = [];
|
|
|
|
void (async () => {
|
|
for (const bucket of buckets) {
|
|
const scope = bucket.serverScope ?? COVER_SCOPE_ACTIVE;
|
|
const refs = [
|
|
...(bucket.albums?.length
|
|
? await resolveAlbumCoverRefsFromLibrary(bucket.albums, scope)
|
|
: []),
|
|
...(bucket.artists?.length
|
|
? await resolveArtistCoverRefsFromLibrary(bucket.artists, scope)
|
|
: []),
|
|
...(bucket.songs?.length
|
|
? await resolveTrackCoverRefsFromLibrary(bucket.songs, scope)
|
|
: []),
|
|
];
|
|
const capped = bucket.limit != null ? refs.slice(0, bucket.limit) : refs;
|
|
if (cancelled || capped.length === 0) continue;
|
|
unregisters.push(
|
|
coverPrefetchRegister(capped, {
|
|
surface: bucket.surface ?? 'dense',
|
|
priority: bucket.priority,
|
|
}),
|
|
);
|
|
}
|
|
})();
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
for (const unreg of unregisters) unreg();
|
|
};
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- caller supplies `deps` for bucket inputs
|
|
}, deps);
|
|
}
|