@behindthemusictree/app-kit-ui 33.3.0 → 34.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-QMELESFB.js → chunk-A7OWCEIK.js} +81 -33
- package/dist/chunk-A7OWCEIK.js.map +1 -0
- package/dist/genre-tree/index.cjs +138 -99
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +6 -7
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +138 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-QMELESFB.js.map +0 -1
|
@@ -52,13 +52,14 @@ var import_lucide_react11 = require("lucide-react");
|
|
|
52
52
|
var import_lucide_react12 = require("lucide-react");
|
|
53
53
|
var import_ui16 = require("@behindthemusictree/ui");
|
|
54
54
|
var import_genre_tree_view4 = require("@behindthemusictree/genre-tree-view");
|
|
55
|
-
var
|
|
55
|
+
var import_genre_tree27 = require("@behindthemusictree/app-kit/genre-tree");
|
|
56
56
|
var import_popup5 = require("@behindthemusictree/app-kit/popup");
|
|
57
57
|
|
|
58
58
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
59
|
+
var import_genre_tree = require("@behindthemusictree/app-kit/genre-tree");
|
|
59
60
|
var hasViewsCount = (genrePlaylists) => genrePlaylists.every((genrePlaylist) => genrePlaylist.viewsCount !== void 0);
|
|
60
61
|
var genrePlaylistSize = (genrePlaylist, metric) => {
|
|
61
|
-
if (metric === "songs") return genrePlaylist
|
|
62
|
+
if (metric === "songs") return (0, import_genre_tree.genrePlaylistTrackCount)(genrePlaylist);
|
|
62
63
|
if (genrePlaylist.viewsCount === void 0) {
|
|
63
64
|
throw new Error(`Genre playlist ${genrePlaylist.uuid} has no viewsCount to size by views`);
|
|
64
65
|
}
|
|
@@ -82,6 +83,7 @@ function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
86
|
+
var import_genre_tree3 = require("@behindthemusictree/app-kit/genre-tree");
|
|
85
87
|
var import_react3 = require("react");
|
|
86
88
|
var import_genre_tree_view = require("@behindthemusictree/genre-tree-view");
|
|
87
89
|
var import_player = require("@behindthemusictree/app-kit/player");
|
|
@@ -306,29 +308,28 @@ var import_transport = require("@behindthemusictree/app-kit/transport");
|
|
|
306
308
|
|
|
307
309
|
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.ts
|
|
308
310
|
var import_react2 = require("react");
|
|
309
|
-
var
|
|
311
|
+
var import_genre_tree2 = require("@behindthemusictree/app-kit/genre-tree");
|
|
310
312
|
function useGenrePlaylistPlayback({
|
|
311
313
|
scope,
|
|
312
314
|
genrePlaylists,
|
|
313
315
|
artist = null
|
|
314
316
|
}) {
|
|
315
|
-
const { trackList, playNewTrackListFromGenrePlaylist
|
|
317
|
+
const { trackList, playNewTrackListFromGenrePlaylist } = (0, import_genre_tree2.useTrackList)();
|
|
316
318
|
const origin = trackList?.origin;
|
|
317
319
|
const playingNodeId = (0, import_react2.useMemo)(() => {
|
|
318
|
-
if (!origin) return null;
|
|
319
|
-
|
|
320
|
-
if (
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
},
|
|
330
|
-
|
|
331
|
-
);
|
|
320
|
+
if (!origin || origin.type !== import_genre_tree2.TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
321
|
+
const playlistOrigin = origin;
|
|
322
|
+
if (playlistOrigin.artistUuid !== artist?.uuid) return null;
|
|
323
|
+
const playlist = genrePlaylists.find((item) => item.uuid === origin.uuid) ?? playlistOrigin.criteriaPlaylist;
|
|
324
|
+
const expected = scope === "reference" && playlist && !("criteria" in playlist && playlist.criteria === null) ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
325
|
+
if (playlistOrigin.selection && expected && (0, import_genre_tree2.genreMusicSelectionKey)(playlistOrigin.selection).join() !== (0, import_genre_tree2.genreMusicSelectionKey)(expected).join()) return null;
|
|
326
|
+
return origin.uuid;
|
|
327
|
+
}, [origin, artist, genrePlaylists, scope]);
|
|
328
|
+
const play = (0, import_react2.useCallback)(async (playlist) => {
|
|
329
|
+
if (artist && !playlist.criteria) return;
|
|
330
|
+
const selection = scope === "reference" && playlist.criteria !== null ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
331
|
+
return selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope);
|
|
332
|
+
}, [artist, scope, playNewTrackListFromGenrePlaylist]);
|
|
332
333
|
return (0, import_react2.useMemo)(() => ({ playingNodeId, play }), [playingNodeId, play]);
|
|
333
334
|
}
|
|
334
335
|
|
|
@@ -363,7 +364,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
363
364
|
id: genrePlaylist.uuid,
|
|
364
365
|
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
365
366
|
name: genrePlaylist.name,
|
|
366
|
-
itemCount: genrePlaylist
|
|
367
|
+
itemCount: (0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist),
|
|
367
368
|
actionable: Boolean(genrePlaylist.criteria),
|
|
368
369
|
side: genrePlaylist.criteria?.side ?? void 0,
|
|
369
370
|
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
@@ -379,7 +380,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
379
380
|
setIsPlaying(!isPlaying);
|
|
380
381
|
return;
|
|
381
382
|
}
|
|
382
|
-
if (genrePlaylist
|
|
383
|
+
if ((0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
383
384
|
return;
|
|
384
385
|
}
|
|
385
386
|
play(genrePlaylist).catch((error) => {
|
|
@@ -443,6 +444,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
443
444
|
}
|
|
444
445
|
|
|
445
446
|
// src/genre-tree/playlist-tree/TreeWheel.tsx
|
|
447
|
+
var import_genre_tree4 = require("@behindthemusictree/app-kit/genre-tree");
|
|
446
448
|
var import_react4 = require("react");
|
|
447
449
|
var import_genre_tree_view2 = require("@behindthemusictree/genre-tree-view");
|
|
448
450
|
var import_player2 = require("@behindthemusictree/app-kit/player");
|
|
@@ -495,7 +497,7 @@ function GenrePlaylistTreeWheel({
|
|
|
495
497
|
setIsPlaying(!isPlaying);
|
|
496
498
|
return;
|
|
497
499
|
}
|
|
498
|
-
if (genrePlaylist
|
|
500
|
+
if ((0, import_genre_tree4.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
499
501
|
return;
|
|
500
502
|
}
|
|
501
503
|
play(genrePlaylist).catch((error) => {
|
|
@@ -560,6 +562,7 @@ function GenrePlaylistTreeWheel({
|
|
|
560
562
|
}
|
|
561
563
|
|
|
562
564
|
// src/genre-tree/playlist-tree/TreeWheelRadialPopCore.tsx
|
|
565
|
+
var import_genre_tree5 = require("@behindthemusictree/app-kit/genre-tree");
|
|
563
566
|
var import_react5 = require("react");
|
|
564
567
|
var import_genre_tree_view3 = require("@behindthemusictree/genre-tree-view");
|
|
565
568
|
var import_player3 = require("@behindthemusictree/app-kit/player");
|
|
@@ -604,7 +607,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
604
607
|
setIsPlaying(!isPlaying);
|
|
605
608
|
return;
|
|
606
609
|
}
|
|
607
|
-
if (genrePlaylist
|
|
610
|
+
if ((0, import_genre_tree5.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
608
611
|
return;
|
|
609
612
|
}
|
|
610
613
|
play(genrePlaylist).catch((error) => {
|
|
@@ -702,7 +705,7 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
702
705
|
// src/genre-tree/GenreSearch.tsx
|
|
703
706
|
var import_lucide_react3 = require("lucide-react");
|
|
704
707
|
var import_ui4 = require("@behindthemusictree/ui");
|
|
705
|
-
var
|
|
708
|
+
var import_genre_tree9 = require("@behindthemusictree/app-kit/genre-tree");
|
|
706
709
|
|
|
707
710
|
// src/genre-tree/search/SearchBox.tsx
|
|
708
711
|
var import_react7 = require("react");
|
|
@@ -758,10 +761,10 @@ var SEARCH_FAILED_STATUS = "Search failed";
|
|
|
758
761
|
var searchStatus = (state, count, noun) => state.isError ? SEARCH_FAILED_STATUS : state.settled && count === 0 ? `No ${noun} found` : "";
|
|
759
762
|
|
|
760
763
|
// src/genre-tree/search/useArtistSearchGroup.tsx
|
|
761
|
-
var
|
|
764
|
+
var import_genre_tree6 = require("@behindthemusictree/app-kit/genre-tree");
|
|
762
765
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
763
766
|
function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
764
|
-
const search = (0,
|
|
767
|
+
const search = (0, import_genre_tree6.useArtistSearch)(getBaseUrl, enabled ? text : "");
|
|
765
768
|
if (!enabled) return void 0;
|
|
766
769
|
return {
|
|
767
770
|
key: "artists",
|
|
@@ -789,17 +792,17 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
789
792
|
}
|
|
790
793
|
|
|
791
794
|
// src/genre-tree/search/useSongSearchGroup.tsx
|
|
792
|
-
var
|
|
795
|
+
var import_genre_tree7 = require("@behindthemusictree/app-kit/genre-tree");
|
|
793
796
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
794
797
|
function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
795
|
-
const search = (0,
|
|
798
|
+
const search = (0, import_genre_tree7.useSongSearch)(getBaseUrl, enabled ? text : "");
|
|
796
799
|
if (!enabled) return void 0;
|
|
797
800
|
return {
|
|
798
801
|
key: "songs",
|
|
799
802
|
label: "Songs",
|
|
800
803
|
items: search.songs.map((song) => ({
|
|
801
804
|
key: song.uuid,
|
|
802
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: (0,
|
|
805
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
803
806
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
804
807
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "block truncate text-xs text-[var(--color-neutral-500)]", children: [song.artists.map((artist) => artist.name).join(", "), song.genre?.name ?? "No genre"].filter(Boolean).join(" \xB7 ") })
|
|
805
808
|
] }),
|
|
@@ -811,10 +814,10 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
811
814
|
}
|
|
812
815
|
|
|
813
816
|
// src/genre-tree/search/useGenreRemoteSearchGroup.tsx
|
|
814
|
-
var
|
|
817
|
+
var import_genre_tree8 = require("@behindthemusictree/app-kit/genre-tree");
|
|
815
818
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
816
819
|
function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres", label = "Genres", filter, describe, ...options } = {}) {
|
|
817
|
-
const search = (0,
|
|
820
|
+
const search = (0, import_genre_tree8.useGenreRemoteSearch)(getBaseUrl, text, options);
|
|
818
821
|
const genres = filter ? search.genres.filter(filter) : search.genres;
|
|
819
822
|
return {
|
|
820
823
|
key,
|
|
@@ -848,7 +851,7 @@ function GenreSearch({
|
|
|
848
851
|
extraGroups = [],
|
|
849
852
|
onFocus
|
|
850
853
|
}) {
|
|
851
|
-
const { query, setQuery, results, canClear, clear, select } = (0,
|
|
854
|
+
const { query, setQuery, results, canClear, clear, select } = (0, import_genre_tree9.useGenreSearch)({
|
|
852
855
|
genrePlaylists,
|
|
853
856
|
onSelect,
|
|
854
857
|
selectedName,
|
|
@@ -900,6 +903,8 @@ function GenreSearch({
|
|
|
900
903
|
}
|
|
901
904
|
|
|
902
905
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
906
|
+
var import_genre_tree18 = require("@behindthemusictree/app-kit/genre-tree");
|
|
907
|
+
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
903
908
|
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
904
909
|
|
|
905
910
|
// src/genre-tree/GenreActionBand.tsx
|
|
@@ -1249,7 +1254,7 @@ function GenreActionBand({
|
|
|
1249
1254
|
|
|
1250
1255
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1251
1256
|
var import_ui6 = require("@behindthemusictree/ui");
|
|
1252
|
-
var
|
|
1257
|
+
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1253
1258
|
|
|
1254
1259
|
// src/genre-tree/ClampedText.tsx
|
|
1255
1260
|
var import_react10 = require("react");
|
|
@@ -1292,20 +1297,21 @@ var import_player4 = require("@behindthemusictree/app-kit/player");
|
|
|
1292
1297
|
var import_player5 = require("@behindthemusictree/app-kit/player");
|
|
1293
1298
|
var import_popup4 = require("@behindthemusictree/app-kit/popup");
|
|
1294
1299
|
var import_transport6 = require("@behindthemusictree/app-kit/transport");
|
|
1295
|
-
var
|
|
1296
|
-
var
|
|
1297
|
-
var
|
|
1298
|
-
var
|
|
1300
|
+
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1301
|
+
var import_genre_tree12 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1302
|
+
var import_genre_tree13 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1303
|
+
var import_genre_tree14 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1304
|
+
var import_genre_tree15 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1299
1305
|
|
|
1300
1306
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1301
|
-
var
|
|
1307
|
+
var import_genre_tree10 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1302
1308
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1303
1309
|
function MusicBrainzRecordingLink({
|
|
1304
1310
|
song,
|
|
1305
1311
|
children,
|
|
1306
1312
|
className: className2 = ""
|
|
1307
1313
|
}) {
|
|
1308
|
-
const url = (0,
|
|
1314
|
+
const url = (0, import_genre_tree10.musicBrainzRecordingUrl)(song);
|
|
1309
1315
|
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_jsx_runtime21.Fragment, { children });
|
|
1310
1316
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1311
1317
|
"a",
|
|
@@ -1322,11 +1328,11 @@ function MusicBrainzRecordingLink({
|
|
|
1322
1328
|
}
|
|
1323
1329
|
|
|
1324
1330
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1325
|
-
var
|
|
1331
|
+
var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1326
1332
|
var import_track_noun = require("@behindthemusictree/app-kit/track-noun");
|
|
1327
1333
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1328
1334
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1329
|
-
var SongPageSchema = (0, import_transport4.PaginatedResponseSchema)(
|
|
1335
|
+
var SongPageSchema = (0, import_transport4.PaginatedResponseSchema)(import_genre_tree14.SongDetailedSchema).extend({
|
|
1330
1336
|
overallTotal: import_zod.z.number().nullable(),
|
|
1331
1337
|
page: import_zod.z.number().nullable(),
|
|
1332
1338
|
totalPages: import_zod.z.number().nullable()
|
|
@@ -1344,6 +1350,7 @@ var nextCursor = (next) => {
|
|
|
1344
1350
|
function GenrePlaylistTracks({
|
|
1345
1351
|
genreUuid,
|
|
1346
1352
|
genrePlaylist,
|
|
1353
|
+
selection,
|
|
1347
1354
|
scope,
|
|
1348
1355
|
getBackendBaseUrl,
|
|
1349
1356
|
renderArtistLink,
|
|
@@ -1353,7 +1360,7 @@ function GenrePlaylistTracks({
|
|
|
1353
1360
|
renderTracksToolbar,
|
|
1354
1361
|
artist = null
|
|
1355
1362
|
}) {
|
|
1356
|
-
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist } = (0,
|
|
1363
|
+
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0, import_genre_tree15.useTrackList)();
|
|
1357
1364
|
const { session, sessionRestored } = (0, import_auth.useSession)();
|
|
1358
1365
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player4.usePlayer)();
|
|
1359
1366
|
const { showPopup } = (0, import_popup4.usePopup)();
|
|
@@ -1362,15 +1369,15 @@ function GenrePlaylistTracks({
|
|
|
1362
1369
|
const { fetch } = (0, import_transport3.useFetchWrapper)(getBackendBaseUrl);
|
|
1363
1370
|
const playback = (0, import_transport3.usePlaybackContext)();
|
|
1364
1371
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
|
|
1365
|
-
queryKey: [...scope === "me" ?
|
|
1372
|
+
queryKey: [...scope === "me" ? import_genre_tree12.genrePlaylistQueryKeys.me.tracks(uuid) : artist ? [...import_genre_tree13.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), "artist", artist.uuid] : import_genre_tree13.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), ...playback.key ? [playback.key] : []],
|
|
1366
1373
|
queryFn: async ({ pageParam }) => {
|
|
1367
1374
|
if (scope === "me") return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
|
|
1368
1375
|
const response = await fetch(
|
|
1369
|
-
|
|
1376
|
+
import_genre_tree13.libraryEndpoints.reference.songs.list(),
|
|
1370
1377
|
true,
|
|
1371
1378
|
false,
|
|
1372
1379
|
{},
|
|
1373
|
-
{ genre: genreUuid, ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1380
|
+
{ genre: genreUuid, ...(0, import_genre_tree11.genreMusicQueryParams)(selection), ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1374
1381
|
);
|
|
1375
1382
|
const parsed = (0, import_transport5.parseWithLog)(SongPageSchema, response, "GenrePlaylistTracks");
|
|
1376
1383
|
return { tracks: parsed.results, total: parsed.overallTotal, nextPage: parsed.next ? nextCursor(parsed.next) : null };
|
|
@@ -1394,7 +1401,12 @@ function GenrePlaylistTracks({
|
|
|
1394
1401
|
const tracks = pages.flatMap((page) => page.tracks);
|
|
1395
1402
|
const total = pages[0]?.total ?? void 0;
|
|
1396
1403
|
const play = (startSongUuid) => {
|
|
1397
|
-
const started = artist ? playNewTrackListFromArtist(artist, scope, {
|
|
1404
|
+
const started = artist ? playNewTrackListFromArtist(artist, scope, {
|
|
1405
|
+
startSongUuid,
|
|
1406
|
+
ordering: "title",
|
|
1407
|
+
genreUuid,
|
|
1408
|
+
...selection && { selection }
|
|
1409
|
+
}) : scope === "reference" ? playNewTrackListFromGenreCatalogue({ uuid: genreUuid, name: genrePlaylist.name }, scope, { startSongUuid, ...selection && { selection } }) : playNewTrackListFromGenrePlaylist(genrePlaylist, scope, { startSongUuid });
|
|
1398
1410
|
started.catch((error) => {
|
|
1399
1411
|
console.error("Failed to play genre playlist:", error);
|
|
1400
1412
|
showPopup(/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(InternalErrorPopup, { errorCode: import_transport6.ErrorCode.CLIENT_UNKNOWN }));
|
|
@@ -1414,14 +1426,14 @@ function GenrePlaylistTracks({
|
|
|
1414
1426
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1415
1427
|
const isPlaying = isCurrent && playState === import_player5.PlayStates.PLAYING;
|
|
1416
1428
|
const text = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1417
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0,
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree14.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1418
1430
|
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1419
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1431
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_genre_tree16.ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1420
1432
|
track.album && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1421
1433
|
] });
|
|
1422
1434
|
const leading = renderSongLeading?.(track, index);
|
|
1423
1435
|
const actions = renderSongActions?.(track);
|
|
1424
|
-
const isUnplayable = (0,
|
|
1436
|
+
const isUnplayable = (0, import_genre_tree14.isSong)(track) && (0, import_genre_tree14.songUnplayableReason)(track) !== null;
|
|
1425
1437
|
if (isUnplayable) {
|
|
1426
1438
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1427
1439
|
leading,
|
|
@@ -1475,6 +1487,7 @@ var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
|
1475
1487
|
function GenreDetailExtras({
|
|
1476
1488
|
genreUuid,
|
|
1477
1489
|
genrePlaylist,
|
|
1490
|
+
selection,
|
|
1478
1491
|
wikidataId,
|
|
1479
1492
|
scope,
|
|
1480
1493
|
getBackendBaseUrl,
|
|
@@ -1488,7 +1501,7 @@ function GenreDetailExtras({
|
|
|
1488
1501
|
...trackSlots
|
|
1489
1502
|
}) {
|
|
1490
1503
|
const trackNoun = (0, import_track_noun2.useTrackNoun)();
|
|
1491
|
-
const { data: overview, isPending } = (0,
|
|
1504
|
+
const { data: overview, isPending } = (0, import_genre_tree17.useFetchGenreOverview)(
|
|
1492
1505
|
genreUuid,
|
|
1493
1506
|
scope,
|
|
1494
1507
|
getBackendBaseUrl,
|
|
@@ -1541,6 +1554,7 @@ function GenreDetailExtras({
|
|
|
1541
1554
|
{
|
|
1542
1555
|
genreUuid,
|
|
1543
1556
|
genrePlaylist,
|
|
1557
|
+
selection,
|
|
1544
1558
|
scope,
|
|
1545
1559
|
getBackendBaseUrl,
|
|
1546
1560
|
renderArtistLink,
|
|
@@ -1570,7 +1584,7 @@ function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
|
1570
1584
|
GenreActionBand,
|
|
1571
1585
|
{
|
|
1572
1586
|
...bandProps,
|
|
1573
|
-
onPlayPause: genrePlaylist.tracksCount > 0 ? handlePlayPause : void 0,
|
|
1587
|
+
onPlayPause: ("genreOnlyTracksCount" in genrePlaylist ? (0, import_genre_tree18.genreMusicCount)(genrePlaylist) : genrePlaylist.tracksCount) > 0 ? handlePlayPause : void 0,
|
|
1574
1588
|
isPlaying: isCurrentTrackList && isPlaying
|
|
1575
1589
|
}
|
|
1576
1590
|
);
|
|
@@ -1580,6 +1594,7 @@ function GenreInfoPanelBody({
|
|
|
1580
1594
|
family,
|
|
1581
1595
|
genreUuid,
|
|
1582
1596
|
genrePlaylist,
|
|
1597
|
+
catalogue,
|
|
1583
1598
|
wikidataId,
|
|
1584
1599
|
scope,
|
|
1585
1600
|
getBackendBaseUrl,
|
|
@@ -1587,9 +1602,30 @@ function GenreInfoPanelBody({
|
|
|
1587
1602
|
band,
|
|
1588
1603
|
extras
|
|
1589
1604
|
}) {
|
|
1605
|
+
const noun = (0, import_track_noun3.useTrackNoun)();
|
|
1606
|
+
const summary = scope === "reference" ? import_genre_tree18.GenreCatalogueCountsSchema.parse(genrePlaylist) : void 0;
|
|
1607
|
+
const selection = summary ? (0, import_genre_tree18.defaultGenreMusicSelection)(summary) : void 0;
|
|
1608
|
+
const describeCounts = (counts) => {
|
|
1609
|
+
const scopes = counts.genreAndSubgenresTracksCount;
|
|
1610
|
+
return "canonical" in scopes ? `${counts.genreOnlyTracksCount} this genre only \xB7 ${scopes.canonical} with canonical subgenres \xB7 ${scopes.regional} with regional subgenres \xB7 ${scopes.all} with all subgenres` : `${counts.genreOnlyTracksCount} this genre only \xB7 ${scopes.all} with subgenres`;
|
|
1611
|
+
};
|
|
1590
1612
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
1591
1613
|
toolbar,
|
|
1592
1614
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }),
|
|
1615
|
+
summary && catalogue && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "px-3.5 py-3 text-sm text-[var(--color-text)]", children: [
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { children: [
|
|
1617
|
+
"Catalogue ",
|
|
1618
|
+
noun.plural,
|
|
1619
|
+
": ",
|
|
1620
|
+
describeCounts(catalogue)
|
|
1621
|
+
] }),
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { children: [
|
|
1623
|
+
"Playlist ",
|
|
1624
|
+
noun.plural,
|
|
1625
|
+
": ",
|
|
1626
|
+
describeCounts(summary)
|
|
1627
|
+
] })
|
|
1628
|
+
] }),
|
|
1593
1629
|
/* @__PURE__ */ (0, import_react12.createElement)(
|
|
1594
1630
|
GenreDetailExtras,
|
|
1595
1631
|
{
|
|
@@ -1598,6 +1634,7 @@ function GenreInfoPanelBody({
|
|
|
1598
1634
|
family,
|
|
1599
1635
|
genreUuid,
|
|
1600
1636
|
genrePlaylist,
|
|
1637
|
+
selection,
|
|
1601
1638
|
wikidataId,
|
|
1602
1639
|
scope,
|
|
1603
1640
|
getBackendBaseUrl
|
|
@@ -1608,7 +1645,7 @@ function GenreInfoPanelBody({
|
|
|
1608
1645
|
|
|
1609
1646
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
1610
1647
|
var import_react13 = require("react");
|
|
1611
|
-
var
|
|
1648
|
+
var import_genre_tree19 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1612
1649
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1613
1650
|
function ChangeParentPopup({
|
|
1614
1651
|
genrePlaylist,
|
|
@@ -1618,9 +1655,9 @@ function ChangeParentPopup({
|
|
|
1618
1655
|
onClose,
|
|
1619
1656
|
onParentChanged
|
|
1620
1657
|
}) {
|
|
1621
|
-
const { mutate, isPending, formErrors } = (0,
|
|
1658
|
+
const { mutate, isPending, formErrors } = (0, import_genre_tree19.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
1622
1659
|
const candidates = (0, import_react13.useMemo)(
|
|
1623
|
-
() => (0,
|
|
1660
|
+
() => (0, import_genre_tree19.getReparentCandidates)(genrePlaylists, genrePlaylist.uuid),
|
|
1624
1661
|
[genrePlaylists, genrePlaylist.uuid]
|
|
1625
1662
|
);
|
|
1626
1663
|
const handleSelect = (newParent) => {
|
|
@@ -1663,7 +1700,7 @@ function ChangeParentPopup({
|
|
|
1663
1700
|
|
|
1664
1701
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
1665
1702
|
var import_ui12 = require("@behindthemusictree/ui");
|
|
1666
|
-
var
|
|
1703
|
+
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1667
1704
|
|
|
1668
1705
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
1669
1706
|
var import_ui8 = require("@behindthemusictree/ui");
|
|
@@ -1830,12 +1867,12 @@ var import_react_query2 = require("@tanstack/react-query");
|
|
|
1830
1867
|
var import_lucide_react9 = require("lucide-react");
|
|
1831
1868
|
var import_ui11 = require("@behindthemusictree/ui");
|
|
1832
1869
|
var import_player10 = require("@behindthemusictree/app-kit/player");
|
|
1833
|
-
var
|
|
1870
|
+
var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1834
1871
|
var import_transport7 = require("@behindthemusictree/app-kit/transport");
|
|
1835
1872
|
|
|
1836
1873
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
1837
1874
|
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
1838
|
-
var
|
|
1875
|
+
var import_genre_tree20 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1839
1876
|
|
|
1840
1877
|
// src/genre-tree/TrackPositionPlayPause.tsx
|
|
1841
1878
|
var import_fa3 = require("react-icons/fa");
|
|
@@ -1890,8 +1927,8 @@ function TrackPositionPlayPause({
|
|
|
1890
1927
|
}
|
|
1891
1928
|
|
|
1892
1929
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
1893
|
-
var
|
|
1894
|
-
var
|
|
1930
|
+
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1931
|
+
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1895
1932
|
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1896
1933
|
function TrackItem({
|
|
1897
1934
|
track,
|
|
@@ -1902,11 +1939,11 @@ function TrackItem({
|
|
|
1902
1939
|
renderSongLink
|
|
1903
1940
|
}) {
|
|
1904
1941
|
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } = (0, import_player9.usePlayer)();
|
|
1905
|
-
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0,
|
|
1942
|
+
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0, import_genre_tree20.useTrackList)();
|
|
1906
1943
|
const scope = trackList?.origin?.scope ?? null;
|
|
1907
1944
|
const isCurrentTrack = playerTrackObject?.track.id === track.uuid;
|
|
1908
1945
|
const hasPlaybackError = isCurrentTrack && !!playerTrackObject?.loadError;
|
|
1909
|
-
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0,
|
|
1946
|
+
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0, import_genre_tree21.isSong)(track) && (0, import_genre_tree21.songUnplayableReason)(track) !== null;
|
|
1910
1947
|
const handlePlayPauseClick = (event) => {
|
|
1911
1948
|
event.stopPropagation();
|
|
1912
1949
|
if (isCurrentTrack) {
|
|
@@ -1939,8 +1976,8 @@ function TrackItem({
|
|
|
1939
1976
|
}
|
|
1940
1977
|
),
|
|
1941
1978
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
1942
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : (0,
|
|
1943
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1979
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree21.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
1980
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_genre_tree22.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
1944
1981
|
] }),
|
|
1945
1982
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "genre-name-container flex items-center justify-start w-[21.6%] min-w-0 shrink-0", children: track.genre ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-xs font-bold", children: track.genre.name }) : "" }),
|
|
1946
1983
|
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
@@ -1959,7 +1996,7 @@ function TrackItem({
|
|
|
1959
1996
|
|
|
1960
1997
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
1961
1998
|
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1962
|
-
var SongPageSchema2 = (0, import_transport7.PaginatedResponseSchema)(
|
|
1999
|
+
var SongPageSchema2 = (0, import_transport7.PaginatedResponseSchema)(import_genre_tree23.SongDetailedSchema);
|
|
1963
2000
|
var SORTS = [
|
|
1964
2001
|
{ ordering: "title", label: "Title" },
|
|
1965
2002
|
{ ordering: "-albumYear", label: "Year" }
|
|
@@ -1968,11 +2005,11 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
1968
2005
|
const [page, setPage] = (0, import_react14.useState)(1);
|
|
1969
2006
|
const [ordering, setOrdering] = (0, import_react14.useState)("title");
|
|
1970
2007
|
const { fetch } = (0, import_transport7.useFetchWrapper)(getBackendBaseUrl);
|
|
1971
|
-
const { playNewTrackListFromArtist } = (0,
|
|
2008
|
+
const { playNewTrackListFromArtist } = (0, import_genre_tree23.useTrackList)();
|
|
1972
2009
|
const { playerTrackObject } = (0, import_player10.usePlayer)();
|
|
1973
2010
|
const { data, isPending, isError } = (0, import_transport7.useQueryWithParse)({
|
|
1974
2011
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
1975
|
-
queryFn: () => fetch(
|
|
2012
|
+
queryFn: () => fetch(import_genre_tree23.libraryEndpoints.reference.songs.list(), true, false, void 0, {
|
|
1976
2013
|
artist: artist.uuid,
|
|
1977
2014
|
ordering,
|
|
1978
2015
|
page
|
|
@@ -1987,7 +2024,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
1987
2024
|
});
|
|
1988
2025
|
const handleRowClickCapture = (event, song) => {
|
|
1989
2026
|
if (!(event.target instanceof Element) || !event.target.closest(".track-position-play-pause")) return;
|
|
1990
|
-
if (playerTrackObject?.track.id === song.uuid || (0,
|
|
2027
|
+
if (playerTrackObject?.track.id === song.uuid || (0, import_genre_tree23.songUnplayableReason)(song) !== null) return;
|
|
1991
2028
|
event.stopPropagation();
|
|
1992
2029
|
void play(song.uuid);
|
|
1993
2030
|
};
|
|
@@ -2046,7 +2083,7 @@ function useArtistPanel({
|
|
|
2046
2083
|
onExpandedChange,
|
|
2047
2084
|
onClose
|
|
2048
2085
|
}) {
|
|
2049
|
-
const result = (0,
|
|
2086
|
+
const result = (0, import_genre_tree24.useArtist)(uuid, getBackendBaseUrl);
|
|
2050
2087
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2051
2088
|
switch (result.status) {
|
|
2052
2089
|
case "idle":
|
|
@@ -2107,21 +2144,21 @@ function useArtistPanel({
|
|
|
2107
2144
|
|
|
2108
2145
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2109
2146
|
var import_ui14 = require("@behindthemusictree/ui");
|
|
2110
|
-
var
|
|
2147
|
+
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2111
2148
|
|
|
2112
2149
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2113
2150
|
var import_react15 = require("react");
|
|
2114
2151
|
var import_lucide_react10 = require("lucide-react");
|
|
2115
2152
|
var import_ui13 = require("@behindthemusictree/ui");
|
|
2116
2153
|
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2117
|
-
var
|
|
2154
|
+
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2118
2155
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2119
2156
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2120
2157
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2121
2158
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
2122
2159
|
function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
2123
2160
|
const [open, setOpen] = (0, import_react15.useState)(false);
|
|
2124
|
-
const history = (0,
|
|
2161
|
+
const history = (0, import_genre_tree25.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2125
2162
|
let body = null;
|
|
2126
2163
|
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui13.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2127
2164
|
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
@@ -2162,13 +2199,13 @@ function SongPanelContent({
|
|
|
2162
2199
|
genrePath,
|
|
2163
2200
|
onSelectGenre
|
|
2164
2201
|
}) {
|
|
2165
|
-
const { playNewTrackListFromTrackUuid } = (0,
|
|
2202
|
+
const { playNewTrackListFromTrackUuid } = (0, import_genre_tree25.useTrackList)();
|
|
2166
2203
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player11.usePlayer)();
|
|
2167
|
-
const unplayableReason = (0,
|
|
2204
|
+
const unplayableReason = (0, import_genre_tree25.songUnplayableReason)(song);
|
|
2168
2205
|
const isCurrent = playerTrackObject?.track.id === song.uuid;
|
|
2169
2206
|
const isPlaying = isCurrent && playState === import_player11.PlayStates.PLAYING;
|
|
2170
2207
|
const shareTarget = { kind: "song", uuid: song.uuid, name: song.title, scope };
|
|
2171
|
-
const musicBrainzUrl = (0,
|
|
2208
|
+
const musicBrainzUrl = (0, import_genre_tree25.musicBrainzRecordingUrl)(song);
|
|
2172
2209
|
const fields = [];
|
|
2173
2210
|
if (song.genre) {
|
|
2174
2211
|
const path = genrePath.length > 0 ? genrePath : null;
|
|
@@ -2227,7 +2264,7 @@ function SongPanelContent({
|
|
|
2227
2264
|
),
|
|
2228
2265
|
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2229
2266
|
] }) }),
|
|
2230
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "px-6 pt-2.5 text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2267
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "px-6 pt-2.5 text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_genre_tree25.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2231
2268
|
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui13.FieldList, { items: fields }),
|
|
2232
2269
|
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui13.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2233
2270
|
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
@@ -2248,7 +2285,7 @@ function useSongPanel({
|
|
|
2248
2285
|
onExpandedChange,
|
|
2249
2286
|
onClose
|
|
2250
2287
|
}) {
|
|
2251
|
-
const result = (0,
|
|
2288
|
+
const result = (0, import_genre_tree26.useSong)(uuid, getBackendBaseUrl);
|
|
2252
2289
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2253
2290
|
switch (result.status) {
|
|
2254
2291
|
case "idle":
|
|
@@ -2425,7 +2462,7 @@ function GenreTreeView({
|
|
|
2425
2462
|
allowWheelRotation: internalAllowWheelRotation,
|
|
2426
2463
|
toggleWheelRotation,
|
|
2427
2464
|
onNodeHover: handleNodeHover
|
|
2428
|
-
} = (0,
|
|
2465
|
+
} = (0, import_genre_tree27.useGenreTreeViewState)({
|
|
2429
2466
|
scope,
|
|
2430
2467
|
getBackendBaseUrl,
|
|
2431
2468
|
viewMode: controlledViewMode,
|
|
@@ -2444,12 +2481,12 @@ function GenreTreeView({
|
|
|
2444
2481
|
restoreRootUuid = selectedGenrePlaylist.root.uuid;
|
|
2445
2482
|
setStackedRestoreOwner({ revision: restoreRevision, rootUuid: restoreRootUuid });
|
|
2446
2483
|
}
|
|
2447
|
-
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey:
|
|
2448
|
-
const { mutate: updateGenre } = (0,
|
|
2484
|
+
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey: import_genre_tree27.genreUpdateMutationKey }) > 0;
|
|
2485
|
+
const { mutate: updateGenre } = (0, import_genre_tree27.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
2449
2486
|
const busy = deferredSizeMetric !== sizeMetric || isTreeFetching || isGenreUpdating;
|
|
2450
2487
|
const isArtistFiltered = artistUuid !== null;
|
|
2451
2488
|
const canSizeByViews = !isArtistFiltered && hasViewsCount(visibleGenrePlaylists);
|
|
2452
|
-
const artistResult = (0,
|
|
2489
|
+
const artistResult = (0, import_genre_tree27.useArtist)(artistUuid, artistSearchBaseUrl ?? getBackendBaseUrl);
|
|
2453
2490
|
const filterArtistName = artistResult.status === "success" ? artistResult.artist.name : null;
|
|
2454
2491
|
const filterArtist = (0, import_react16.useMemo)(
|
|
2455
2492
|
() => artistUuid !== null && filterArtistName !== null ? { uuid: artistUuid, name: filterArtistName } : null,
|
|
@@ -2657,6 +2694,7 @@ function GenreTreeView({
|
|
|
2657
2694
|
] }),
|
|
2658
2695
|
genreUuid,
|
|
2659
2696
|
genrePlaylist,
|
|
2697
|
+
catalogue: genrePlaylist.catalogue,
|
|
2660
2698
|
wikidataId: criteria.wikidataId,
|
|
2661
2699
|
scope,
|
|
2662
2700
|
getBackendBaseUrl,
|
|
@@ -3004,7 +3042,7 @@ var import_react17 = require("react");
|
|
|
3004
3042
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
3005
3043
|
var import_ui17 = require("@behindthemusictree/ui");
|
|
3006
3044
|
var import_lucide_react13 = require("lucide-react");
|
|
3007
|
-
var
|
|
3045
|
+
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3008
3046
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
3009
3047
|
var RELATIVE_ITEM_COUNT = 1;
|
|
3010
3048
|
function toNode(genre, parentId) {
|
|
@@ -3032,7 +3070,7 @@ function GenreDetailPanel({
|
|
|
3032
3070
|
edgeTab,
|
|
3033
3071
|
extras
|
|
3034
3072
|
}) {
|
|
3035
|
-
const { data: detail, isPending, isError } = (0,
|
|
3073
|
+
const { data: detail, isPending, isError } = (0, import_genre_tree28.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
|
|
3036
3074
|
const playback = useGenrePlaylistPlayback({ scope, genrePlaylists: [] });
|
|
3037
3075
|
const view = (0, import_react17.useMemo)(() => {
|
|
3038
3076
|
if (!detail) return null;
|
|
@@ -3048,7 +3086,7 @@ function GenreDetailPanel({
|
|
|
3048
3086
|
id: detail.uuid,
|
|
3049
3087
|
parentId: detail.parent?.uuid ?? null,
|
|
3050
3088
|
name: detail.name,
|
|
3051
|
-
itemCount: detail.tracksCount,
|
|
3089
|
+
itemCount: scope === "reference" ? (0, import_genre_tree28.genreMusicCount)(import_genre_tree28.GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist)) : detail.tracksCount,
|
|
3052
3090
|
wikidataId: detail.wikidataId
|
|
3053
3091
|
},
|
|
3054
3092
|
fill: rootColor,
|
|
@@ -3058,7 +3096,7 @@ function GenreDetailPanel({
|
|
|
3058
3096
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
3059
3097
|
)
|
|
3060
3098
|
};
|
|
3061
|
-
}, [detail]);
|
|
3099
|
+
}, [detail, scope]);
|
|
3062
3100
|
if (isError) {
|
|
3063
3101
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { role: "alert", className: "p-4 text-sm text-[var(--color-text)]", children: "This genre could not be loaded." });
|
|
3064
3102
|
}
|
|
@@ -3111,7 +3149,8 @@ function GenreDetailPanel({
|
|
|
3111
3149
|
ancestors
|
|
3112
3150
|
] }),
|
|
3113
3151
|
genreUuid: detail.uuid,
|
|
3114
|
-
genrePlaylist: { ...detail.criteriaPlaylist, tracksCount: detail.tracksCount },
|
|
3152
|
+
genrePlaylist: scope === "reference" ? import_genre_tree28.GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist) : { ...detail.criteriaPlaylist, tracksCount: detail.tracksCount },
|
|
3153
|
+
catalogue: detail.catalogue,
|
|
3115
3154
|
wikidataId: detail.wikidataId,
|
|
3116
3155
|
scope,
|
|
3117
3156
|
getBackendBaseUrl,
|
|
@@ -3132,9 +3171,9 @@ var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
|
|
|
3132
3171
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3133
3172
|
var import_react18 = require("react");
|
|
3134
3173
|
var import_lucide_react14 = require("lucide-react");
|
|
3135
|
-
var
|
|
3136
|
-
var
|
|
3137
|
-
var
|
|
3174
|
+
var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3175
|
+
var import_genre_tree30 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3176
|
+
var import_track_noun4 = require("@behindthemusictree/app-kit/track-noun");
|
|
3138
3177
|
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
3139
3178
|
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react18.useEffect : import_react18.useLayoutEffect;
|
|
3140
3179
|
function TrackListSidebar({
|
|
@@ -3148,8 +3187,8 @@ function TrackListSidebar({
|
|
|
3148
3187
|
renderArtistLink,
|
|
3149
3188
|
renderSongLink
|
|
3150
3189
|
}) {
|
|
3151
|
-
const { trackList, loadMore, autoAdvanceScrollRequest } = (0,
|
|
3152
|
-
const trackNoun = (0,
|
|
3190
|
+
const { trackList, loadMore, autoAdvanceScrollRequest } = (0, import_genre_tree29.useTrackList)();
|
|
3191
|
+
const trackNoun = (0, import_track_noun4.useTrackNoun)();
|
|
3153
3192
|
const trackListRef = (0, import_react18.useRef)(null);
|
|
3154
3193
|
const previousOriginRef = (0, import_react18.useRef)(trackList?.origin ?? null);
|
|
3155
3194
|
const handledAutoAdvanceRequestIdRef = (0, import_react18.useRef)(null);
|
|
@@ -3251,7 +3290,7 @@ function TrackListSidebar({
|
|
|
3251
3290
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "name-container flex flex-col justify-center items-center text-[var(--color-text)] font-bold pr-2 max-w-[27.5rem]", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3252
3291
|
] }),
|
|
3253
3292
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "info flex items-center text-sm text-[var(--color-text-muted)]", children: [
|
|
3254
|
-
trackList.origin.type ===
|
|
3293
|
+
trackList.origin.type === import_genre_tree30.TrackListOriginType.GENRE_PLAYLIST ? "Genre \u2022 " : trackList.origin.type === import_genre_tree30.TrackListOriginType.ARTIST ? "Artist \u2022 " : `${trackNoun.singular} playlist \u2022 `,
|
|
3255
3294
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3256
3295
|
] })
|
|
3257
3296
|
] }),
|
|
@@ -3302,12 +3341,12 @@ function TrackListSidebar({
|
|
|
3302
3341
|
var import_react19 = require("react");
|
|
3303
3342
|
var import_tailwind_merge = require("tailwind-merge");
|
|
3304
3343
|
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3305
|
-
var
|
|
3344
|
+
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3306
3345
|
var import_ui18 = require("@behindthemusictree/ui");
|
|
3307
3346
|
|
|
3308
3347
|
// src/genre-tree/PlayerControls.tsx
|
|
3309
3348
|
var import_lucide_react15 = require("lucide-react");
|
|
3310
|
-
var
|
|
3349
|
+
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3311
3350
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
3312
3351
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
3313
3352
|
function PlayerControls() {
|
|
@@ -3321,7 +3360,7 @@ function PlayerControls() {
|
|
|
3321
3360
|
setVolume,
|
|
3322
3361
|
volume
|
|
3323
3362
|
} = (0, import_player12.usePlayer)();
|
|
3324
|
-
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0,
|
|
3363
|
+
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0, import_genre_tree31.useTrackList)();
|
|
3325
3364
|
const currentTime = (0, import_player12.useCurrentTime)();
|
|
3326
3365
|
const isBusy = isLoading || playState === import_player12.PlayStates.LOADING;
|
|
3327
3366
|
const isReady = !!playerTrackObject?.isReady && !isBusy && !playerTrackObject.loadError;
|
|
@@ -3335,7 +3374,7 @@ function PlayerControls() {
|
|
|
3335
3374
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3336
3375
|
children: [
|
|
3337
3376
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3338
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { "aria-label": "Elapsed time", children: (0,
|
|
3377
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree31.formatTime)(safeCurrentTime) }),
|
|
3339
3378
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
3340
3379
|
"input",
|
|
3341
3380
|
{
|
|
@@ -3350,7 +3389,7 @@ function PlayerControls() {
|
|
|
3350
3389
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3351
3390
|
}
|
|
3352
3391
|
),
|
|
3353
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { "aria-label": "Duration", children: (0,
|
|
3392
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree31.formatTime)(safeDuration) })
|
|
3354
3393
|
] }),
|
|
3355
3394
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3356
3395
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
@@ -3429,7 +3468,7 @@ function PlayerPanel({
|
|
|
3429
3468
|
renderSongLink
|
|
3430
3469
|
}) {
|
|
3431
3470
|
const { playerTrackObject, retryPlayback } = (0, import_player13.usePlayer)();
|
|
3432
|
-
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0,
|
|
3471
|
+
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0, import_genre_tree32.useTrackListSidebarVisibility)();
|
|
3433
3472
|
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0, import_react19.useState)("");
|
|
3434
3473
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
3435
3474
|
(0, import_react19.useEffect)(() => {
|
|
@@ -3526,7 +3565,7 @@ function PlayerPanel({
|
|
|
3526
3565
|
// src/genre-tree/Rating.tsx
|
|
3527
3566
|
var import_uuid = require("uuid");
|
|
3528
3567
|
var import_ai = require("react-icons/ai");
|
|
3529
|
-
var
|
|
3568
|
+
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3530
3569
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3531
3570
|
function Rating({ rating, handleChange }) {
|
|
3532
3571
|
const instanceId = (0, import_uuid.v4)();
|
|
@@ -3538,7 +3577,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3538
3577
|
className: "w-6 h-6 opacity-0",
|
|
3539
3578
|
type: "radio",
|
|
3540
3579
|
name: "rating",
|
|
3541
|
-
value: i === 0 ?
|
|
3580
|
+
value: i === 0 ? import_genre_tree33.FORM_RATING_NULL_VALUE : i,
|
|
3542
3581
|
checked: rating === (i === 0 ? null : i),
|
|
3543
3582
|
onChange: handleChange
|
|
3544
3583
|
}
|
|
@@ -3547,7 +3586,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3547
3586
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3548
3587
|
import_ai.AiOutlineStar,
|
|
3549
3588
|
{
|
|
3550
|
-
className: `w-7 h-7 absolute top-0 left-0 ${rating ===
|
|
3589
|
+
className: `w-7 h-7 absolute top-0 left-0 ${rating === import_genre_tree33.FORM_RATING_NULL_VALUE ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
3551
3590
|
}
|
|
3552
3591
|
),
|
|
3553
3592
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex-grow w-8" }),
|