mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 14:05:41 +00:00
7c724a642f
* chore(eslint): add eslint toolchain and configs * fix(eslint): resolve gradual-config errors (rules-of-hooks, no-empty, prefer-const, …) * chore(eslint): clear unused vars in config, contexts, app and test * chore(eslint): clear unused vars in api and music-network * chore(eslint): clear unused vars in utils * chore(eslint): clear unused vars in store * chore(eslint): clear unused vars in cover and hooks * chore(eslint): clear unused vars in components * chore(eslint): clear unused vars in pages * chore(eslint): remove explicit any in src * chore(eslint): align react-hooks exhaustive-deps * chore(eslint): zero gradual config on src * chore(eslint): strict hook rules in store and utils * chore(eslint): strict hook rules in hooks and cover * chore(eslint): strict hook rules in components * chore(eslint): strict hook rules in pages and contexts * chore(eslint): document scripts ignore in eslint config * chore(eslint): add lint script and zero strict findings * chore(eslint): address review round 1 (gradual 0/0, per-site disable reasons) * chore(eslint): tighten two set-state disable comments (review round 2 LOW) * chore(nix): sync npmDepsHash with package-lock.json * docs(changelog): add Under the Hood entry for ESLint setup (PR #1165) --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { resolveAlbum, resolveArtist, resolveMediaServerId } from '../../utils/offline/offlineMediaResolve';
|
|
import { AddToPlaylistSubmenu } from './AddToPlaylistSubmenu';
|
|
|
|
interface AlbumProps {
|
|
albumId: string;
|
|
onDone: () => void;
|
|
triggerId?: string;
|
|
}
|
|
|
|
export function AlbumToPlaylistSubmenu({ albumId, onDone, triggerId }: AlbumProps) {
|
|
const [resolvedIds, setResolvedIds] = useState<string[] | null>(null);
|
|
|
|
useEffect(() => {
|
|
const serverId = resolveMediaServerId();
|
|
if (!serverId) {
|
|
// React Compiler set-state-in-effect rule: state set from an async result resolved in this effect.
|
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
setResolvedIds([]);
|
|
return;
|
|
}
|
|
resolveAlbum(serverId, albumId).then((data) => {
|
|
setResolvedIds(data ? data.songs.map((s) => s.id) : []);
|
|
}).catch(() => setResolvedIds([]));
|
|
}, [albumId]);
|
|
|
|
if (resolvedIds === null) {
|
|
return (
|
|
<div className="context-submenu" style={{ display: 'flex', justifyContent: 'center', padding: '0.75rem' }}>
|
|
<div className="spinner" style={{ width: 16, height: 16 }} />
|
|
</div>
|
|
);
|
|
}
|
|
if (resolvedIds.length === 0) return null;
|
|
return <AddToPlaylistSubmenu songIds={resolvedIds} onDone={onDone} triggerId={triggerId} />;
|
|
}
|
|
|
|
interface ArtistProps {
|
|
artistId: string;
|
|
onDone: () => void;
|
|
triggerId?: string;
|
|
}
|
|
|
|
export function ArtistToPlaylistSubmenu({ artistId, onDone, triggerId }: ArtistProps) {
|
|
const [resolvedIds, setResolvedIds] = useState<string[] | null>(null);
|
|
|
|
useEffect(() => {
|
|
(async () => {
|
|
const serverId = resolveMediaServerId();
|
|
if (!serverId) {
|
|
setResolvedIds([]);
|
|
return;
|
|
}
|
|
const artistData = await resolveArtist(serverId, artistId);
|
|
if (!artistData) {
|
|
setResolvedIds([]);
|
|
return;
|
|
}
|
|
const albumSongs = await Promise.all(
|
|
artistData.albums.map(a => resolveAlbum(serverId, a.id).then(r => r?.songs ?? [])),
|
|
);
|
|
setResolvedIds(albumSongs.flat().map(s => s.id));
|
|
})().catch(() => setResolvedIds([]));
|
|
}, [artistId]);
|
|
|
|
if (resolvedIds === null) {
|
|
return (
|
|
<div className="context-submenu" style={{ display: 'flex', justifyContent: 'center', padding: '0.75rem' }}>
|
|
<div className="spinner" style={{ width: 16, height: 16 }} />
|
|
</div>
|
|
);
|
|
}
|
|
if (resolvedIds.length === 0) return null;
|
|
return <AddToPlaylistSubmenu songIds={resolvedIds} onDone={onDone} triggerId={triggerId} />;
|
|
}
|