Files
Psychotoxical-psysonic/src/utils/library/albumBrowseCatalogChunk.ts
T
Psychotoxical 209dd61442 refactor(lib): consolidate generic infra into src/lib
Move domain-agnostic, feature-free helpers out of the flat utils/ and store/
roots into src/lib/ (plan M4, §3 lib/ layer):
- lib/format/: formatBytes, formatClockTime, formatDuration, formatHumanDuration,
  relativeTime (pure format/date/byte/clock helpers)
- lib/i18n.ts: i18next bootstrap (global app infra)
- lib/util/: sanitizeHtml, platform, dedupeById, safeStorage (pure helpers +
  the zustand storage adapter)

playbackScheduleFormat stays in utils/format (runtime usePlayerStore dep =
audio-core coupling, not generic). formatClockTime keeps a type-only
@/store/authStoreTypes import (erased, no runtime inversion — accepted per the
deviceSync precedent).

Pure move via deep @/lib/* specifiers (no barrel → no mock-collapse surface).
tsc 0, lint 0/0, full suite 319 files / 2353 tests green.

Tooling note: lib_move.py regex extended to also rewrite side-effect imports
(import './i18n') and vi.importActual paths — both were silent gaps.
2026-06-30 08:07:04 +02:00

45 lines
1.4 KiB
TypeScript

import type { SubsonicAlbum } from '@/lib/api/subsonicTypes';
import { dedupeById } from '@/lib/util/dedupeById';
import { isOfflineBrowseActive } from '@/features/offline';
import { loadOfflineAlbumCatalogChunk } from '@/features/offline';
import type { AlbumBrowseQuery } from './albumBrowseTypes';
import { fetchLocalAlbumCatalogChunk } from './albumBrowseLoad';
export type AlbumCatalogChunk = {
albums: SubsonicAlbum[];
hasMore: boolean;
};
export function mergeAlbumCatalogChunk(
prev: SubsonicAlbum[],
chunk: AlbumCatalogChunk,
append: boolean,
): { albums: SubsonicAlbum[]; offset: number } {
if (!append) {
return { albums: chunk.albums, offset: chunk.albums.length };
}
const merged = dedupeById([...prev, ...chunk.albums]);
return { albums: merged, offset: merged.length };
}
/** Local-index or offline-bytes catalog chunk for the albums grid. */
export async function fetchAlbumBrowseCatalogChunk(
serverId: string,
indexEnabled: boolean,
query: AlbumBrowseQuery,
offset: number,
chunkSize: number,
starredOverrides: Record<string, boolean>,
): Promise<AlbumCatalogChunk | null> {
if (isOfflineBrowseActive()) {
return loadOfflineAlbumCatalogChunk(
serverId,
query,
offset,
chunkSize,
starredOverrides,
);
}
return fetchLocalAlbumCatalogChunk(serverId, indexEnabled, query, offset, chunkSize);
}