mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
72030f17fd
First Phase F slice. Splits the 1333-LOC `api/subsonic.ts` along its two most obvious axes: - `subsonicTypes.ts` — all ~24 exported interfaces + type aliases (album/song/artist/playlist/directory/genre/now-playing/radio, random-songs filters, three statistics shapes, search + starred results, AlbumInfo, structured-lyrics types, etc.) plus the `RADIO_PAGE_SIZE` constant. - `subsonicClient.ts` — token-auth + `getClient` + `api<T>()` + `libraryFilterParams` + `secureRandomSalt` / `getAuthParams` / `SUBSONIC_CLIENT`. The credential-bearing API helpers (`pingWithCredentials`, `apiWithCredentials`, `restBaseFromUrl`, `probeInstantMixWithCredentials`) stay in `subsonic.ts` for now — they could move into the client module in a follow-up. 66 external call sites migrated to direct imports from the new modules (no re-export shims in `subsonic.ts`). Pure code-move; contract test stays green. subsonic.ts: 1333 → 1078 LOC (−255).
55 lines
1.5 KiB
TypeScript
55 lines
1.5 KiB
TypeScript
import type { SubsonicAlbum } from '../api/subsonicTypes';
|
|
import React, { useEffect, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { ndListLosslessAlbumsPage } from '../api/navidromeBrowse';
|
|
import AlbumRow from './AlbumRow';
|
|
import { useAuthStore } from '../store/authStore';
|
|
|
|
interface Props {
|
|
disableArtwork?: boolean;
|
|
artworkSize?: number;
|
|
windowArtworkByViewport?: boolean;
|
|
initialArtworkBudget?: number;
|
|
}
|
|
|
|
const TARGET_ALBUMS = 20;
|
|
|
|
export default function LosslessAlbumsRail({
|
|
disableArtwork = false,
|
|
artworkSize,
|
|
windowArtworkByViewport,
|
|
initialArtworkBudget,
|
|
}: Props) {
|
|
const { t } = useTranslation();
|
|
const activeServerId = useAuthStore(s => s.activeServerId);
|
|
const [albums, setAlbums] = useState<SubsonicAlbum[]>([]);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
(async () => {
|
|
try {
|
|
const page = await ndListLosslessAlbumsPage({ targetNewAlbums: TARGET_ALBUMS });
|
|
if (cancelled) return;
|
|
setAlbums(page.entries.map(e => e.album));
|
|
} catch {
|
|
if (!cancelled) setAlbums([]);
|
|
}
|
|
})();
|
|
return () => { cancelled = true; };
|
|
}, [activeServerId]);
|
|
|
|
if (albums.length === 0) return null;
|
|
|
|
return (
|
|
<AlbumRow
|
|
title={t('home.losslessAlbums')}
|
|
titleLink="/lossless-albums"
|
|
albums={albums}
|
|
disableArtwork={disableArtwork}
|
|
artworkSize={artworkSize}
|
|
windowArtworkByViewport={windowArtworkByViewport}
|
|
initialArtworkBudget={initialArtworkBudget}
|
|
/>
|
|
);
|
|
}
|