Repository navigation
Expand file tree
/
Copy pathuseSlideshowLayer.ts
More file actions
55 lines (53 loc) Β· 2.6 KB
/
Copy pathuseSlideshowLayer.ts
File metadata and controls
55 lines (53 loc) Β· 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { useArtistImage } from "./useArtistImage";
import { useCoverSlideshow } from "./useCoverSlideshow";
import { usePrefersReducedMotion } from "./usePrefersReducedMotion";
import { isStreamTrack } from "../lib/playerSources";
import type { Track } from "../lib/tauri/track";
export interface SlideshowLayer {
/** Whether the slideshow owns the cover slot right now. */
active: boolean;
/** The photo to crossfade in, or `null` when there is none (yet). */
artistSrc: string | null;
}
/**
* Resolve the cover β artist slideshow (issue #466) for one now-playing
* surface: the per-profile toggle, reduced motion, the track's eligibility
* and the artist photo, folded into the one boolean `<CoverSlideshow>`
* takes.
*
* Extracted when the mini-player became the third surface to want it
* (issue #702) β the gate had been copied twice already, and a third copy
* is how the three drift apart.
*
* **`blocked` is the precedence chain above the slideshow.** The
* documented order is Canvas > motion cover > slideshow > static cover, so
* a surface that renders those layers passes whether one of them owns the
* slot; a surface that renders neither (the mini-player) passes nothing.
*
* **`artistSrc` is for a surface that already has the photo.** The panel
* enriches the artist for its "About the artist" block anyway, so it hands
* the result in rather than making this ask the backend a second time.
* `undefined` means "no override, resolve it yourself" β `null` is a real
* answer (that surface looked and found no photo), which is why the two
* are told apart rather than treated as one falsy value.
*/
export function useSlideshowLayer(
track: Track | null | undefined,
options: { blocked?: boolean; artistSrc?: string | null } = {},
): SlideshowLayer {
const { blocked = false, artistSrc: provided } = options;
const enabled = useCoverSlideshow().enabled;
const reducedMotion = usePrefersReducedMotion();
// Radio (negative sentinel id) and other streamed tracks have no library
// artist to enrich, so they never get a slideshow.
const eligible = !!track && !isStreamTrack(track);
const running = enabled && !reducedMotion && !blocked && eligible;
// Only enrich when the slideshow could actually run β the toggle is off by
// default, and a Canvas or motion cover would own the slot anyway β so a
// profile that never opted in makes no artist call at all.
const fetched = useArtistImage(
running && provided === undefined ? track?.artist_id : null,
);
const artistSrc = provided === undefined ? fetched : provided;
return { active: running && !!artistSrc, artistSrc };
}