@behindthemusictree/app-kit-ui 33.2.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-FHGQGTCN.js → chunk-A7OWCEIK.js} +88 -34
- package/dist/chunk-A7OWCEIK.js.map +1 -0
- package/dist/genre-tree/index.cjs +145 -100
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +11 -8
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +145 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-FHGQGTCN.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":
|
|
@@ -2358,6 +2395,8 @@ function GenreTreeView({
|
|
|
2358
2395
|
onArtistExpandedChange,
|
|
2359
2396
|
getShareUrl,
|
|
2360
2397
|
extraSearchGroups = [],
|
|
2398
|
+
onSearchQueryChange,
|
|
2399
|
+
onSearchFocus,
|
|
2361
2400
|
artistSearch = true,
|
|
2362
2401
|
onArtistSelect,
|
|
2363
2402
|
artistSearchBaseUrl,
|
|
@@ -2423,7 +2462,7 @@ function GenreTreeView({
|
|
|
2423
2462
|
allowWheelRotation: internalAllowWheelRotation,
|
|
2424
2463
|
toggleWheelRotation,
|
|
2425
2464
|
onNodeHover: handleNodeHover
|
|
2426
|
-
} = (0,
|
|
2465
|
+
} = (0, import_genre_tree27.useGenreTreeViewState)({
|
|
2427
2466
|
scope,
|
|
2428
2467
|
getBackendBaseUrl,
|
|
2429
2468
|
viewMode: controlledViewMode,
|
|
@@ -2442,12 +2481,12 @@ function GenreTreeView({
|
|
|
2442
2481
|
restoreRootUuid = selectedGenrePlaylist.root.uuid;
|
|
2443
2482
|
setStackedRestoreOwner({ revision: restoreRevision, rootUuid: restoreRootUuid });
|
|
2444
2483
|
}
|
|
2445
|
-
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey:
|
|
2446
|
-
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);
|
|
2447
2486
|
const busy = deferredSizeMetric !== sizeMetric || isTreeFetching || isGenreUpdating;
|
|
2448
2487
|
const isArtistFiltered = artistUuid !== null;
|
|
2449
2488
|
const canSizeByViews = !isArtistFiltered && hasViewsCount(visibleGenrePlaylists);
|
|
2450
|
-
const artistResult = (0,
|
|
2489
|
+
const artistResult = (0, import_genre_tree27.useArtist)(artistUuid, artistSearchBaseUrl ?? getBackendBaseUrl);
|
|
2451
2490
|
const filterArtistName = artistResult.status === "success" ? artistResult.artist.name : null;
|
|
2452
2491
|
const filterArtist = (0, import_react16.useMemo)(
|
|
2453
2492
|
() => artistUuid !== null && filterArtistName !== null ? { uuid: artistUuid, name: filterArtistName } : null,
|
|
@@ -2655,6 +2694,7 @@ function GenreTreeView({
|
|
|
2655
2694
|
] }),
|
|
2656
2695
|
genreUuid,
|
|
2657
2696
|
genrePlaylist,
|
|
2697
|
+
catalogue: genrePlaylist.catalogue,
|
|
2658
2698
|
wikidataId: criteria.wikidataId,
|
|
2659
2699
|
scope,
|
|
2660
2700
|
getBackendBaseUrl,
|
|
@@ -2787,7 +2827,11 @@ function GenreTreeView({
|
|
|
2787
2827
|
selectedName: selectedGenrePlaylist?.name ?? (typeof builtInPanel?.title === "string" ? builtInPanel.title : null),
|
|
2788
2828
|
onClear: builtInSongPanel ? () => changeSong(null) : builtInArtistPanel ? () => changeArtist(null) : handleGenreSearchClear,
|
|
2789
2829
|
onPrevious: handlePrevious,
|
|
2790
|
-
onQueryChange:
|
|
2830
|
+
onQueryChange: (text) => {
|
|
2831
|
+
setSearchText(text);
|
|
2832
|
+
onSearchQueryChange?.(text);
|
|
2833
|
+
},
|
|
2834
|
+
onFocus: onSearchFocus,
|
|
2791
2835
|
extraGroups
|
|
2792
2836
|
}
|
|
2793
2837
|
),
|
|
@@ -2998,7 +3042,7 @@ var import_react17 = require("react");
|
|
|
2998
3042
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
2999
3043
|
var import_ui17 = require("@behindthemusictree/ui");
|
|
3000
3044
|
var import_lucide_react13 = require("lucide-react");
|
|
3001
|
-
var
|
|
3045
|
+
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3002
3046
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
3003
3047
|
var RELATIVE_ITEM_COUNT = 1;
|
|
3004
3048
|
function toNode(genre, parentId) {
|
|
@@ -3026,7 +3070,7 @@ function GenreDetailPanel({
|
|
|
3026
3070
|
edgeTab,
|
|
3027
3071
|
extras
|
|
3028
3072
|
}) {
|
|
3029
|
-
const { data: detail, isPending, isError } = (0,
|
|
3073
|
+
const { data: detail, isPending, isError } = (0, import_genre_tree28.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
|
|
3030
3074
|
const playback = useGenrePlaylistPlayback({ scope, genrePlaylists: [] });
|
|
3031
3075
|
const view = (0, import_react17.useMemo)(() => {
|
|
3032
3076
|
if (!detail) return null;
|
|
@@ -3042,7 +3086,7 @@ function GenreDetailPanel({
|
|
|
3042
3086
|
id: detail.uuid,
|
|
3043
3087
|
parentId: detail.parent?.uuid ?? null,
|
|
3044
3088
|
name: detail.name,
|
|
3045
|
-
itemCount: detail.tracksCount,
|
|
3089
|
+
itemCount: scope === "reference" ? (0, import_genre_tree28.genreMusicCount)(import_genre_tree28.GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist)) : detail.tracksCount,
|
|
3046
3090
|
wikidataId: detail.wikidataId
|
|
3047
3091
|
},
|
|
3048
3092
|
fill: rootColor,
|
|
@@ -3052,7 +3096,7 @@ function GenreDetailPanel({
|
|
|
3052
3096
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
3053
3097
|
)
|
|
3054
3098
|
};
|
|
3055
|
-
}, [detail]);
|
|
3099
|
+
}, [detail, scope]);
|
|
3056
3100
|
if (isError) {
|
|
3057
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." });
|
|
3058
3102
|
}
|
|
@@ -3105,7 +3149,8 @@ function GenreDetailPanel({
|
|
|
3105
3149
|
ancestors
|
|
3106
3150
|
] }),
|
|
3107
3151
|
genreUuid: detail.uuid,
|
|
3108
|
-
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,
|
|
3109
3154
|
wikidataId: detail.wikidataId,
|
|
3110
3155
|
scope,
|
|
3111
3156
|
getBackendBaseUrl,
|
|
@@ -3126,9 +3171,9 @@ var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
|
|
|
3126
3171
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3127
3172
|
var import_react18 = require("react");
|
|
3128
3173
|
var import_lucide_react14 = require("lucide-react");
|
|
3129
|
-
var
|
|
3130
|
-
var
|
|
3131
|
-
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");
|
|
3132
3177
|
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
3133
3178
|
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react18.useEffect : import_react18.useLayoutEffect;
|
|
3134
3179
|
function TrackListSidebar({
|
|
@@ -3142,8 +3187,8 @@ function TrackListSidebar({
|
|
|
3142
3187
|
renderArtistLink,
|
|
3143
3188
|
renderSongLink
|
|
3144
3189
|
}) {
|
|
3145
|
-
const { trackList, loadMore, autoAdvanceScrollRequest } = (0,
|
|
3146
|
-
const trackNoun = (0,
|
|
3190
|
+
const { trackList, loadMore, autoAdvanceScrollRequest } = (0, import_genre_tree29.useTrackList)();
|
|
3191
|
+
const trackNoun = (0, import_track_noun4.useTrackNoun)();
|
|
3147
3192
|
const trackListRef = (0, import_react18.useRef)(null);
|
|
3148
3193
|
const previousOriginRef = (0, import_react18.useRef)(trackList?.origin ?? null);
|
|
3149
3194
|
const handledAutoAdvanceRequestIdRef = (0, import_react18.useRef)(null);
|
|
@@ -3245,7 +3290,7 @@ function TrackListSidebar({
|
|
|
3245
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 }) })
|
|
3246
3291
|
] }),
|
|
3247
3292
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "info flex items-center text-sm text-[var(--color-text-muted)]", children: [
|
|
3248
|
-
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 `,
|
|
3249
3294
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3250
3295
|
] })
|
|
3251
3296
|
] }),
|
|
@@ -3296,12 +3341,12 @@ function TrackListSidebar({
|
|
|
3296
3341
|
var import_react19 = require("react");
|
|
3297
3342
|
var import_tailwind_merge = require("tailwind-merge");
|
|
3298
3343
|
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3299
|
-
var
|
|
3344
|
+
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3300
3345
|
var import_ui18 = require("@behindthemusictree/ui");
|
|
3301
3346
|
|
|
3302
3347
|
// src/genre-tree/PlayerControls.tsx
|
|
3303
3348
|
var import_lucide_react15 = require("lucide-react");
|
|
3304
|
-
var
|
|
3349
|
+
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3305
3350
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
3306
3351
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
3307
3352
|
function PlayerControls() {
|
|
@@ -3315,7 +3360,7 @@ function PlayerControls() {
|
|
|
3315
3360
|
setVolume,
|
|
3316
3361
|
volume
|
|
3317
3362
|
} = (0, import_player12.usePlayer)();
|
|
3318
|
-
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0,
|
|
3363
|
+
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0, import_genre_tree31.useTrackList)();
|
|
3319
3364
|
const currentTime = (0, import_player12.useCurrentTime)();
|
|
3320
3365
|
const isBusy = isLoading || playState === import_player12.PlayStates.LOADING;
|
|
3321
3366
|
const isReady = !!playerTrackObject?.isReady && !isBusy && !playerTrackObject.loadError;
|
|
@@ -3329,7 +3374,7 @@ function PlayerControls() {
|
|
|
3329
3374
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3330
3375
|
children: [
|
|
3331
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: [
|
|
3332
|
-
/* @__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) }),
|
|
3333
3378
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
3334
3379
|
"input",
|
|
3335
3380
|
{
|
|
@@ -3344,7 +3389,7 @@ function PlayerControls() {
|
|
|
3344
3389
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3345
3390
|
}
|
|
3346
3391
|
),
|
|
3347
|
-
/* @__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) })
|
|
3348
3393
|
] }),
|
|
3349
3394
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3350
3395
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
@@ -3423,7 +3468,7 @@ function PlayerPanel({
|
|
|
3423
3468
|
renderSongLink
|
|
3424
3469
|
}) {
|
|
3425
3470
|
const { playerTrackObject, retryPlayback } = (0, import_player13.usePlayer)();
|
|
3426
|
-
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0,
|
|
3471
|
+
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0, import_genre_tree32.useTrackListSidebarVisibility)();
|
|
3427
3472
|
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0, import_react19.useState)("");
|
|
3428
3473
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
3429
3474
|
(0, import_react19.useEffect)(() => {
|
|
@@ -3520,7 +3565,7 @@ function PlayerPanel({
|
|
|
3520
3565
|
// src/genre-tree/Rating.tsx
|
|
3521
3566
|
var import_uuid = require("uuid");
|
|
3522
3567
|
var import_ai = require("react-icons/ai");
|
|
3523
|
-
var
|
|
3568
|
+
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3524
3569
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3525
3570
|
function Rating({ rating, handleChange }) {
|
|
3526
3571
|
const instanceId = (0, import_uuid.v4)();
|
|
@@ -3532,7 +3577,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3532
3577
|
className: "w-6 h-6 opacity-0",
|
|
3533
3578
|
type: "radio",
|
|
3534
3579
|
name: "rating",
|
|
3535
|
-
value: i === 0 ?
|
|
3580
|
+
value: i === 0 ? import_genre_tree33.FORM_RATING_NULL_VALUE : i,
|
|
3536
3581
|
checked: rating === (i === 0 ? null : i),
|
|
3537
3582
|
onChange: handleChange
|
|
3538
3583
|
}
|
|
@@ -3541,7 +3586,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3541
3586
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3542
3587
|
import_ai.AiOutlineStar,
|
|
3543
3588
|
{
|
|
3544
|
-
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)]"}`
|
|
3545
3590
|
}
|
|
3546
3591
|
),
|
|
3547
3592
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex-grow w-8" }),
|