@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
package/dist/index.cjs
CHANGED
|
@@ -593,13 +593,14 @@ var import_lucide_react15 = require("lucide-react");
|
|
|
593
593
|
var import_lucide_react16 = require("lucide-react");
|
|
594
594
|
var import_ui19 = require("@behindthemusictree/ui");
|
|
595
595
|
var import_genre_tree_view4 = require("@behindthemusictree/genre-tree-view");
|
|
596
|
-
var
|
|
596
|
+
var import_genre_tree27 = require("@behindthemusictree/app-kit/genre-tree");
|
|
597
597
|
var import_popup6 = require("@behindthemusictree/app-kit/popup");
|
|
598
598
|
|
|
599
599
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
600
|
+
var import_genre_tree = require("@behindthemusictree/app-kit/genre-tree");
|
|
600
601
|
var hasViewsCount = (genrePlaylists) => genrePlaylists.every((genrePlaylist) => genrePlaylist.viewsCount !== void 0);
|
|
601
602
|
var genrePlaylistSize = (genrePlaylist, metric) => {
|
|
602
|
-
if (metric === "songs") return genrePlaylist
|
|
603
|
+
if (metric === "songs") return (0, import_genre_tree.genrePlaylistTrackCount)(genrePlaylist);
|
|
603
604
|
if (genrePlaylist.viewsCount === void 0) {
|
|
604
605
|
throw new Error(`Genre playlist ${genrePlaylist.uuid} has no viewsCount to size by views`);
|
|
605
606
|
}
|
|
@@ -623,6 +624,7 @@ function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
|
623
624
|
}
|
|
624
625
|
|
|
625
626
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
627
|
+
var import_genre_tree3 = require("@behindthemusictree/app-kit/genre-tree");
|
|
626
628
|
var import_react4 = require("react");
|
|
627
629
|
var import_genre_tree_view = require("@behindthemusictree/genre-tree-view");
|
|
628
630
|
var import_player = require("@behindthemusictree/app-kit/player");
|
|
@@ -631,29 +633,28 @@ var import_transport3 = require("@behindthemusictree/app-kit/transport");
|
|
|
631
633
|
|
|
632
634
|
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.ts
|
|
633
635
|
var import_react3 = require("react");
|
|
634
|
-
var
|
|
636
|
+
var import_genre_tree2 = require("@behindthemusictree/app-kit/genre-tree");
|
|
635
637
|
function useGenrePlaylistPlayback({
|
|
636
638
|
scope,
|
|
637
639
|
genrePlaylists,
|
|
638
640
|
artist = null
|
|
639
641
|
}) {
|
|
640
|
-
const { trackList, playNewTrackListFromGenrePlaylist
|
|
642
|
+
const { trackList, playNewTrackListFromGenrePlaylist } = (0, import_genre_tree2.useTrackList)();
|
|
641
643
|
const origin = trackList?.origin;
|
|
642
644
|
const playingNodeId = (0, import_react3.useMemo)(() => {
|
|
643
|
-
if (!origin) return null;
|
|
644
|
-
|
|
645
|
-
if (
|
|
646
|
-
const
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
},
|
|
655
|
-
|
|
656
|
-
);
|
|
645
|
+
if (!origin || origin.type !== import_genre_tree2.TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
646
|
+
const playlistOrigin = origin;
|
|
647
|
+
if (playlistOrigin.artistUuid !== artist?.uuid) return null;
|
|
648
|
+
const playlist = genrePlaylists.find((item) => item.uuid === origin.uuid) ?? playlistOrigin.criteriaPlaylist;
|
|
649
|
+
const expected = scope === "reference" && playlist && !("criteria" in playlist && playlist.criteria === null) ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
650
|
+
if (playlistOrigin.selection && expected && (0, import_genre_tree2.genreMusicSelectionKey)(playlistOrigin.selection).join() !== (0, import_genre_tree2.genreMusicSelectionKey)(expected).join()) return null;
|
|
651
|
+
return origin.uuid;
|
|
652
|
+
}, [origin, artist, genrePlaylists, scope]);
|
|
653
|
+
const play = (0, import_react3.useCallback)(async (playlist) => {
|
|
654
|
+
if (artist && !playlist.criteria) return;
|
|
655
|
+
const selection = scope === "reference" && playlist.criteria !== null ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
656
|
+
return selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope);
|
|
657
|
+
}, [artist, scope, playNewTrackListFromGenrePlaylist]);
|
|
657
658
|
return (0, import_react3.useMemo)(() => ({ playingNodeId, play }), [playingNodeId, play]);
|
|
658
659
|
}
|
|
659
660
|
|
|
@@ -688,7 +689,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
688
689
|
id: genrePlaylist.uuid,
|
|
689
690
|
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
690
691
|
name: genrePlaylist.name,
|
|
691
|
-
itemCount: genrePlaylist
|
|
692
|
+
itemCount: (0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist),
|
|
692
693
|
actionable: Boolean(genrePlaylist.criteria),
|
|
693
694
|
side: genrePlaylist.criteria?.side ?? void 0,
|
|
694
695
|
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
@@ -704,7 +705,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
704
705
|
setIsPlaying(!isPlaying);
|
|
705
706
|
return;
|
|
706
707
|
}
|
|
707
|
-
if (genrePlaylist
|
|
708
|
+
if ((0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
708
709
|
return;
|
|
709
710
|
}
|
|
710
711
|
play(genrePlaylist).catch((error) => {
|
|
@@ -768,6 +769,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
768
769
|
}
|
|
769
770
|
|
|
770
771
|
// src/genre-tree/playlist-tree/TreeWheel.tsx
|
|
772
|
+
var import_genre_tree4 = require("@behindthemusictree/app-kit/genre-tree");
|
|
771
773
|
var import_react5 = require("react");
|
|
772
774
|
var import_genre_tree_view2 = require("@behindthemusictree/genre-tree-view");
|
|
773
775
|
var import_player2 = require("@behindthemusictree/app-kit/player");
|
|
@@ -820,7 +822,7 @@ function GenrePlaylistTreeWheel({
|
|
|
820
822
|
setIsPlaying(!isPlaying);
|
|
821
823
|
return;
|
|
822
824
|
}
|
|
823
|
-
if (genrePlaylist
|
|
825
|
+
if ((0, import_genre_tree4.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
824
826
|
return;
|
|
825
827
|
}
|
|
826
828
|
play(genrePlaylist).catch((error) => {
|
|
@@ -885,6 +887,7 @@ function GenrePlaylistTreeWheel({
|
|
|
885
887
|
}
|
|
886
888
|
|
|
887
889
|
// src/genre-tree/playlist-tree/TreeWheelRadialPopCore.tsx
|
|
890
|
+
var import_genre_tree5 = require("@behindthemusictree/app-kit/genre-tree");
|
|
888
891
|
var import_react6 = require("react");
|
|
889
892
|
var import_genre_tree_view3 = require("@behindthemusictree/genre-tree-view");
|
|
890
893
|
var import_player3 = require("@behindthemusictree/app-kit/player");
|
|
@@ -929,7 +932,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
929
932
|
setIsPlaying(!isPlaying);
|
|
930
933
|
return;
|
|
931
934
|
}
|
|
932
|
-
if (genrePlaylist
|
|
935
|
+
if ((0, import_genre_tree5.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
933
936
|
return;
|
|
934
937
|
}
|
|
935
938
|
play(genrePlaylist).catch((error) => {
|
|
@@ -1027,7 +1030,7 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
1027
1030
|
// src/genre-tree/GenreSearch.tsx
|
|
1028
1031
|
var import_lucide_react7 = require("lucide-react");
|
|
1029
1032
|
var import_ui7 = require("@behindthemusictree/ui");
|
|
1030
|
-
var
|
|
1033
|
+
var import_genre_tree9 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1031
1034
|
|
|
1032
1035
|
// src/genre-tree/search/SearchBox.tsx
|
|
1033
1036
|
var import_react8 = require("react");
|
|
@@ -1083,10 +1086,10 @@ var SEARCH_FAILED_STATUS = "Search failed";
|
|
|
1083
1086
|
var searchStatus = (state, count, noun) => state.isError ? SEARCH_FAILED_STATUS : state.settled && count === 0 ? `No ${noun} found` : "";
|
|
1084
1087
|
|
|
1085
1088
|
// src/genre-tree/search/useArtistSearchGroup.tsx
|
|
1086
|
-
var
|
|
1089
|
+
var import_genre_tree6 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1087
1090
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1088
1091
|
function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
1089
|
-
const search = (0,
|
|
1092
|
+
const search = (0, import_genre_tree6.useArtistSearch)(getBaseUrl, enabled ? text : "");
|
|
1090
1093
|
if (!enabled) return void 0;
|
|
1091
1094
|
return {
|
|
1092
1095
|
key: "artists",
|
|
@@ -1114,17 +1117,17 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1114
1117
|
}
|
|
1115
1118
|
|
|
1116
1119
|
// src/genre-tree/search/useSongSearchGroup.tsx
|
|
1117
|
-
var
|
|
1120
|
+
var import_genre_tree7 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1118
1121
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1119
1122
|
function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
1120
|
-
const search = (0,
|
|
1123
|
+
const search = (0, import_genre_tree7.useSongSearch)(getBaseUrl, enabled ? text : "");
|
|
1121
1124
|
if (!enabled) return void 0;
|
|
1122
1125
|
return {
|
|
1123
1126
|
key: "songs",
|
|
1124
1127
|
label: "Songs",
|
|
1125
1128
|
items: search.songs.map((song) => ({
|
|
1126
1129
|
key: song.uuid,
|
|
1127
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: (0,
|
|
1130
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
1128
1131
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
1129
1132
|
/* @__PURE__ */ (0, import_jsx_runtime18.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 ") })
|
|
1130
1133
|
] }),
|
|
@@ -1136,10 +1139,10 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1136
1139
|
}
|
|
1137
1140
|
|
|
1138
1141
|
// src/genre-tree/search/useGenreRemoteSearchGroup.tsx
|
|
1139
|
-
var
|
|
1142
|
+
var import_genre_tree8 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1140
1143
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1141
1144
|
function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres", label = "Genres", filter, describe, ...options } = {}) {
|
|
1142
|
-
const search = (0,
|
|
1145
|
+
const search = (0, import_genre_tree8.useGenreRemoteSearch)(getBaseUrl, text, options);
|
|
1143
1146
|
const genres = filter ? search.genres.filter(filter) : search.genres;
|
|
1144
1147
|
return {
|
|
1145
1148
|
key,
|
|
@@ -1173,7 +1176,7 @@ function GenreSearch({
|
|
|
1173
1176
|
extraGroups = [],
|
|
1174
1177
|
onFocus
|
|
1175
1178
|
}) {
|
|
1176
|
-
const { query, setQuery, results, canClear, clear, select } = (0,
|
|
1179
|
+
const { query, setQuery, results, canClear, clear, select } = (0, import_genre_tree9.useGenreSearch)({
|
|
1177
1180
|
genrePlaylists,
|
|
1178
1181
|
onSelect,
|
|
1179
1182
|
selectedName,
|
|
@@ -1225,6 +1228,8 @@ function GenreSearch({
|
|
|
1225
1228
|
}
|
|
1226
1229
|
|
|
1227
1230
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
1231
|
+
var import_genre_tree18 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1232
|
+
var import_track_noun4 = require("@behindthemusictree/app-kit/track-noun");
|
|
1228
1233
|
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
1229
1234
|
|
|
1230
1235
|
// src/genre-tree/GenreActionBand.tsx
|
|
@@ -1547,7 +1552,7 @@ function GenreActionBand({
|
|
|
1547
1552
|
|
|
1548
1553
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1549
1554
|
var import_ui9 = require("@behindthemusictree/ui");
|
|
1550
|
-
var
|
|
1555
|
+
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1551
1556
|
|
|
1552
1557
|
// src/genre-tree/ClampedText.tsx
|
|
1553
1558
|
var import_react10 = require("react");
|
|
@@ -1590,20 +1595,21 @@ var import_player4 = require("@behindthemusictree/app-kit/player");
|
|
|
1590
1595
|
var import_player5 = require("@behindthemusictree/app-kit/player");
|
|
1591
1596
|
var import_popup5 = require("@behindthemusictree/app-kit/popup");
|
|
1592
1597
|
var import_transport8 = require("@behindthemusictree/app-kit/transport");
|
|
1593
|
-
var
|
|
1594
|
-
var
|
|
1595
|
-
var
|
|
1596
|
-
var
|
|
1598
|
+
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1599
|
+
var import_genre_tree12 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1600
|
+
var import_genre_tree13 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1601
|
+
var import_genre_tree14 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1602
|
+
var import_genre_tree15 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1597
1603
|
|
|
1598
1604
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1599
|
-
var
|
|
1605
|
+
var import_genre_tree10 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1600
1606
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1601
1607
|
function MusicBrainzRecordingLink({
|
|
1602
1608
|
song,
|
|
1603
1609
|
children,
|
|
1604
1610
|
className: className2 = ""
|
|
1605
1611
|
}) {
|
|
1606
|
-
const url = (0,
|
|
1612
|
+
const url = (0, import_genre_tree10.musicBrainzRecordingUrl)(song);
|
|
1607
1613
|
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children });
|
|
1608
1614
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1609
1615
|
"a",
|
|
@@ -1620,11 +1626,11 @@ function MusicBrainzRecordingLink({
|
|
|
1620
1626
|
}
|
|
1621
1627
|
|
|
1622
1628
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1623
|
-
var
|
|
1629
|
+
var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1624
1630
|
var import_track_noun2 = require("@behindthemusictree/app-kit/track-noun");
|
|
1625
1631
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1626
1632
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1627
|
-
var SongPageSchema = (0, import_transport6.PaginatedResponseSchema)(
|
|
1633
|
+
var SongPageSchema = (0, import_transport6.PaginatedResponseSchema)(import_genre_tree14.SongDetailedSchema).extend({
|
|
1628
1634
|
overallTotal: import_zod.z.number().nullable(),
|
|
1629
1635
|
page: import_zod.z.number().nullable(),
|
|
1630
1636
|
totalPages: import_zod.z.number().nullable()
|
|
@@ -1642,6 +1648,7 @@ var nextCursor = (next) => {
|
|
|
1642
1648
|
function GenrePlaylistTracks({
|
|
1643
1649
|
genreUuid,
|
|
1644
1650
|
genrePlaylist,
|
|
1651
|
+
selection,
|
|
1645
1652
|
scope,
|
|
1646
1653
|
getBackendBaseUrl,
|
|
1647
1654
|
renderArtistLink,
|
|
@@ -1651,7 +1658,7 @@ function GenrePlaylistTracks({
|
|
|
1651
1658
|
renderTracksToolbar,
|
|
1652
1659
|
artist = null
|
|
1653
1660
|
}) {
|
|
1654
|
-
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist } = (0,
|
|
1661
|
+
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0, import_genre_tree15.useTrackList)();
|
|
1655
1662
|
const { session, sessionRestored } = (0, import_auth2.useSession)();
|
|
1656
1663
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player4.usePlayer)();
|
|
1657
1664
|
const { showPopup } = (0, import_popup5.usePopup)();
|
|
@@ -1660,15 +1667,15 @@ function GenrePlaylistTracks({
|
|
|
1660
1667
|
const { fetch } = (0, import_transport5.useFetchWrapper)(getBackendBaseUrl);
|
|
1661
1668
|
const playback = (0, import_transport5.usePlaybackContext)();
|
|
1662
1669
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
|
|
1663
|
-
queryKey: [...scope === "me" ?
|
|
1670
|
+
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] : []],
|
|
1664
1671
|
queryFn: async ({ pageParam }) => {
|
|
1665
1672
|
if (scope === "me") return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
|
|
1666
1673
|
const response = await fetch(
|
|
1667
|
-
|
|
1674
|
+
import_genre_tree13.libraryEndpoints.reference.songs.list(),
|
|
1668
1675
|
true,
|
|
1669
1676
|
false,
|
|
1670
1677
|
{},
|
|
1671
|
-
{ genre: genreUuid, ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1678
|
+
{ genre: genreUuid, ...(0, import_genre_tree11.genreMusicQueryParams)(selection), ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1672
1679
|
);
|
|
1673
1680
|
const parsed = (0, import_transport7.parseWithLog)(SongPageSchema, response, "GenrePlaylistTracks");
|
|
1674
1681
|
return { tracks: parsed.results, total: parsed.overallTotal, nextPage: parsed.next ? nextCursor(parsed.next) : null };
|
|
@@ -1692,7 +1699,12 @@ function GenrePlaylistTracks({
|
|
|
1692
1699
|
const tracks = pages.flatMap((page) => page.tracks);
|
|
1693
1700
|
const total = pages[0]?.total ?? void 0;
|
|
1694
1701
|
const play = (startSongUuid) => {
|
|
1695
|
-
const started = artist ? playNewTrackListFromArtist(artist, scope, {
|
|
1702
|
+
const started = artist ? playNewTrackListFromArtist(artist, scope, {
|
|
1703
|
+
startSongUuid,
|
|
1704
|
+
ordering: "title",
|
|
1705
|
+
genreUuid,
|
|
1706
|
+
...selection && { selection }
|
|
1707
|
+
}) : scope === "reference" ? playNewTrackListFromGenreCatalogue({ uuid: genreUuid, name: genrePlaylist.name }, scope, { startSongUuid, ...selection && { selection } }) : playNewTrackListFromGenrePlaylist(genrePlaylist, scope, { startSongUuid });
|
|
1696
1708
|
started.catch((error) => {
|
|
1697
1709
|
console.error("Failed to play genre playlist:", error);
|
|
1698
1710
|
showPopup(/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(InternalErrorPopup, { errorCode: import_transport8.ErrorCode.CLIENT_UNKNOWN }));
|
|
@@ -1712,14 +1724,14 @@ function GenrePlaylistTracks({
|
|
|
1712
1724
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1713
1725
|
const isPlaying = isCurrent && playState === import_player5.PlayStates.PLAYING;
|
|
1714
1726
|
const text = /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1715
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0,
|
|
1727
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree14.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1716
1728
|
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1717
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1729
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_genre_tree16.ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1718
1730
|
track.album && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1719
1731
|
] });
|
|
1720
1732
|
const leading = renderSongLeading?.(track, index);
|
|
1721
1733
|
const actions = renderSongActions?.(track);
|
|
1722
|
-
const isUnplayable = (0,
|
|
1734
|
+
const isUnplayable = (0, import_genre_tree14.isSong)(track) && (0, import_genre_tree14.songUnplayableReason)(track) !== null;
|
|
1723
1735
|
if (isUnplayable) {
|
|
1724
1736
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1725
1737
|
leading,
|
|
@@ -1773,6 +1785,7 @@ var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
|
1773
1785
|
function GenreDetailExtras({
|
|
1774
1786
|
genreUuid,
|
|
1775
1787
|
genrePlaylist,
|
|
1788
|
+
selection,
|
|
1776
1789
|
wikidataId,
|
|
1777
1790
|
scope,
|
|
1778
1791
|
getBackendBaseUrl,
|
|
@@ -1786,7 +1799,7 @@ function GenreDetailExtras({
|
|
|
1786
1799
|
...trackSlots
|
|
1787
1800
|
}) {
|
|
1788
1801
|
const trackNoun = (0, import_track_noun3.useTrackNoun)();
|
|
1789
|
-
const { data: overview, isPending } = (0,
|
|
1802
|
+
const { data: overview, isPending } = (0, import_genre_tree17.useFetchGenreOverview)(
|
|
1790
1803
|
genreUuid,
|
|
1791
1804
|
scope,
|
|
1792
1805
|
getBackendBaseUrl,
|
|
@@ -1839,6 +1852,7 @@ function GenreDetailExtras({
|
|
|
1839
1852
|
{
|
|
1840
1853
|
genreUuid,
|
|
1841
1854
|
genrePlaylist,
|
|
1855
|
+
selection,
|
|
1842
1856
|
scope,
|
|
1843
1857
|
getBackendBaseUrl,
|
|
1844
1858
|
renderArtistLink,
|
|
@@ -1868,7 +1882,7 @@ function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
|
1868
1882
|
GenreActionBand,
|
|
1869
1883
|
{
|
|
1870
1884
|
...bandProps,
|
|
1871
|
-
onPlayPause: genrePlaylist.tracksCount > 0 ? handlePlayPause : void 0,
|
|
1885
|
+
onPlayPause: ("genreOnlyTracksCount" in genrePlaylist ? (0, import_genre_tree18.genreMusicCount)(genrePlaylist) : genrePlaylist.tracksCount) > 0 ? handlePlayPause : void 0,
|
|
1872
1886
|
isPlaying: isCurrentTrackList && isPlaying
|
|
1873
1887
|
}
|
|
1874
1888
|
);
|
|
@@ -1878,6 +1892,7 @@ function GenreInfoPanelBody({
|
|
|
1878
1892
|
family,
|
|
1879
1893
|
genreUuid,
|
|
1880
1894
|
genrePlaylist,
|
|
1895
|
+
catalogue,
|
|
1881
1896
|
wikidataId,
|
|
1882
1897
|
scope,
|
|
1883
1898
|
getBackendBaseUrl,
|
|
@@ -1885,9 +1900,30 @@ function GenreInfoPanelBody({
|
|
|
1885
1900
|
band,
|
|
1886
1901
|
extras
|
|
1887
1902
|
}) {
|
|
1903
|
+
const noun = (0, import_track_noun4.useTrackNoun)();
|
|
1904
|
+
const summary = scope === "reference" ? import_genre_tree18.GenreCatalogueCountsSchema.parse(genrePlaylist) : void 0;
|
|
1905
|
+
const selection = summary ? (0, import_genre_tree18.defaultGenreMusicSelection)(summary) : void 0;
|
|
1906
|
+
const describeCounts = (counts) => {
|
|
1907
|
+
const scopes = counts.genreAndSubgenresTracksCount;
|
|
1908
|
+
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`;
|
|
1909
|
+
};
|
|
1888
1910
|
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1889
1911
|
toolbar,
|
|
1890
1912
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }),
|
|
1913
|
+
summary && catalogue && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "px-3.5 py-3 text-sm text-[var(--color-text)]", children: [
|
|
1914
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("p", { children: [
|
|
1915
|
+
"Catalogue ",
|
|
1916
|
+
noun.plural,
|
|
1917
|
+
": ",
|
|
1918
|
+
describeCounts(catalogue)
|
|
1919
|
+
] }),
|
|
1920
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("p", { children: [
|
|
1921
|
+
"Playlist ",
|
|
1922
|
+
noun.plural,
|
|
1923
|
+
": ",
|
|
1924
|
+
describeCounts(summary)
|
|
1925
|
+
] })
|
|
1926
|
+
] }),
|
|
1891
1927
|
/* @__PURE__ */ (0, import_react12.createElement)(
|
|
1892
1928
|
GenreDetailExtras,
|
|
1893
1929
|
{
|
|
@@ -1896,6 +1932,7 @@ function GenreInfoPanelBody({
|
|
|
1896
1932
|
family,
|
|
1897
1933
|
genreUuid,
|
|
1898
1934
|
genrePlaylist,
|
|
1935
|
+
selection,
|
|
1899
1936
|
wikidataId,
|
|
1900
1937
|
scope,
|
|
1901
1938
|
getBackendBaseUrl
|
|
@@ -1906,7 +1943,7 @@ function GenreInfoPanelBody({
|
|
|
1906
1943
|
|
|
1907
1944
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
1908
1945
|
var import_react13 = require("react");
|
|
1909
|
-
var
|
|
1946
|
+
var import_genre_tree19 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1910
1947
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1911
1948
|
function ChangeParentPopup({
|
|
1912
1949
|
genrePlaylist,
|
|
@@ -1916,9 +1953,9 @@ function ChangeParentPopup({
|
|
|
1916
1953
|
onClose,
|
|
1917
1954
|
onParentChanged
|
|
1918
1955
|
}) {
|
|
1919
|
-
const { mutate, isPending, formErrors } = (0,
|
|
1956
|
+
const { mutate, isPending, formErrors } = (0, import_genre_tree19.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
1920
1957
|
const candidates = (0, import_react13.useMemo)(
|
|
1921
|
-
() => (0,
|
|
1958
|
+
() => (0, import_genre_tree19.getReparentCandidates)(genrePlaylists, genrePlaylist.uuid),
|
|
1922
1959
|
[genrePlaylists, genrePlaylist.uuid]
|
|
1923
1960
|
);
|
|
1924
1961
|
const handleSelect = (newParent) => {
|
|
@@ -1961,7 +1998,7 @@ function ChangeParentPopup({
|
|
|
1961
1998
|
|
|
1962
1999
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
1963
2000
|
var import_ui15 = require("@behindthemusictree/ui");
|
|
1964
|
-
var
|
|
2001
|
+
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1965
2002
|
|
|
1966
2003
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
1967
2004
|
var import_ui11 = require("@behindthemusictree/ui");
|
|
@@ -2128,12 +2165,12 @@ var import_react_query2 = require("@tanstack/react-query");
|
|
|
2128
2165
|
var import_lucide_react13 = require("lucide-react");
|
|
2129
2166
|
var import_ui14 = require("@behindthemusictree/ui");
|
|
2130
2167
|
var import_player10 = require("@behindthemusictree/app-kit/player");
|
|
2131
|
-
var
|
|
2168
|
+
var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2132
2169
|
var import_transport9 = require("@behindthemusictree/app-kit/transport");
|
|
2133
2170
|
|
|
2134
2171
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2135
2172
|
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
2136
|
-
var
|
|
2173
|
+
var import_genre_tree20 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2137
2174
|
|
|
2138
2175
|
// src/genre-tree/TrackPositionPlayPause.tsx
|
|
2139
2176
|
var import_fa5 = require("react-icons/fa");
|
|
@@ -2188,8 +2225,8 @@ function TrackPositionPlayPause({
|
|
|
2188
2225
|
}
|
|
2189
2226
|
|
|
2190
2227
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2191
|
-
var
|
|
2192
|
-
var
|
|
2228
|
+
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2229
|
+
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2193
2230
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2194
2231
|
function TrackItem({
|
|
2195
2232
|
track,
|
|
@@ -2200,11 +2237,11 @@ function TrackItem({
|
|
|
2200
2237
|
renderSongLink
|
|
2201
2238
|
}) {
|
|
2202
2239
|
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } = (0, import_player9.usePlayer)();
|
|
2203
|
-
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0,
|
|
2240
|
+
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0, import_genre_tree20.useTrackList)();
|
|
2204
2241
|
const scope = trackList?.origin?.scope ?? null;
|
|
2205
2242
|
const isCurrentTrack = playerTrackObject?.track.id === track.uuid;
|
|
2206
2243
|
const hasPlaybackError = isCurrentTrack && !!playerTrackObject?.loadError;
|
|
2207
|
-
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0,
|
|
2244
|
+
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0, import_genre_tree21.isSong)(track) && (0, import_genre_tree21.songUnplayableReason)(track) !== null;
|
|
2208
2245
|
const handlePlayPauseClick = (event) => {
|
|
2209
2246
|
event.stopPropagation();
|
|
2210
2247
|
if (isCurrentTrack) {
|
|
@@ -2237,8 +2274,8 @@ function TrackItem({
|
|
|
2237
2274
|
}
|
|
2238
2275
|
),
|
|
2239
2276
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2240
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : (0,
|
|
2241
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2277
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.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_runtime38.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2278
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_genre_tree22.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
2242
2279
|
] }),
|
|
2243
2280
|
/* @__PURE__ */ (0, import_jsx_runtime38.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_runtime38.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-xs font-bold", children: track.genre.name }) : "" }),
|
|
2244
2281
|
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
@@ -2257,7 +2294,7 @@ function TrackItem({
|
|
|
2257
2294
|
|
|
2258
2295
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2259
2296
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2260
|
-
var SongPageSchema2 = (0, import_transport9.PaginatedResponseSchema)(
|
|
2297
|
+
var SongPageSchema2 = (0, import_transport9.PaginatedResponseSchema)(import_genre_tree23.SongDetailedSchema);
|
|
2261
2298
|
var SORTS = [
|
|
2262
2299
|
{ ordering: "title", label: "Title" },
|
|
2263
2300
|
{ ordering: "-albumYear", label: "Year" }
|
|
@@ -2266,11 +2303,11 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2266
2303
|
const [page, setPage] = (0, import_react14.useState)(1);
|
|
2267
2304
|
const [ordering, setOrdering] = (0, import_react14.useState)("title");
|
|
2268
2305
|
const { fetch } = (0, import_transport9.useFetchWrapper)(getBackendBaseUrl);
|
|
2269
|
-
const { playNewTrackListFromArtist } = (0,
|
|
2306
|
+
const { playNewTrackListFromArtist } = (0, import_genre_tree23.useTrackList)();
|
|
2270
2307
|
const { playerTrackObject } = (0, import_player10.usePlayer)();
|
|
2271
2308
|
const { data, isPending, isError } = (0, import_transport9.useQueryWithParse)({
|
|
2272
2309
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
2273
|
-
queryFn: () => fetch(
|
|
2310
|
+
queryFn: () => fetch(import_genre_tree23.libraryEndpoints.reference.songs.list(), true, false, void 0, {
|
|
2274
2311
|
artist: artist.uuid,
|
|
2275
2312
|
ordering,
|
|
2276
2313
|
page
|
|
@@ -2285,7 +2322,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2285
2322
|
});
|
|
2286
2323
|
const handleRowClickCapture = (event, song) => {
|
|
2287
2324
|
if (!(event.target instanceof Element) || !event.target.closest(".track-position-play-pause")) return;
|
|
2288
|
-
if (playerTrackObject?.track.id === song.uuid || (0,
|
|
2325
|
+
if (playerTrackObject?.track.id === song.uuid || (0, import_genre_tree23.songUnplayableReason)(song) !== null) return;
|
|
2289
2326
|
event.stopPropagation();
|
|
2290
2327
|
void play(song.uuid);
|
|
2291
2328
|
};
|
|
@@ -2344,7 +2381,7 @@ function useArtistPanel({
|
|
|
2344
2381
|
onExpandedChange,
|
|
2345
2382
|
onClose
|
|
2346
2383
|
}) {
|
|
2347
|
-
const result = (0,
|
|
2384
|
+
const result = (0, import_genre_tree24.useArtist)(uuid, getBackendBaseUrl);
|
|
2348
2385
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2349
2386
|
switch (result.status) {
|
|
2350
2387
|
case "idle":
|
|
@@ -2405,21 +2442,21 @@ function useArtistPanel({
|
|
|
2405
2442
|
|
|
2406
2443
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2407
2444
|
var import_ui17 = require("@behindthemusictree/ui");
|
|
2408
|
-
var
|
|
2445
|
+
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2409
2446
|
|
|
2410
2447
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2411
2448
|
var import_react15 = require("react");
|
|
2412
2449
|
var import_lucide_react14 = require("lucide-react");
|
|
2413
2450
|
var import_ui16 = require("@behindthemusictree/ui");
|
|
2414
2451
|
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2415
|
-
var
|
|
2452
|
+
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2416
2453
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2417
2454
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2418
2455
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2419
2456
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
2420
2457
|
function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
2421
2458
|
const [open, setOpen] = (0, import_react15.useState)(false);
|
|
2422
|
-
const history = (0,
|
|
2459
|
+
const history = (0, import_genre_tree25.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2423
2460
|
let body = null;
|
|
2424
2461
|
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui16.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2425
2462
|
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
@@ -2460,13 +2497,13 @@ function SongPanelContent({
|
|
|
2460
2497
|
genrePath,
|
|
2461
2498
|
onSelectGenre
|
|
2462
2499
|
}) {
|
|
2463
|
-
const { playNewTrackListFromTrackUuid } = (0,
|
|
2500
|
+
const { playNewTrackListFromTrackUuid } = (0, import_genre_tree25.useTrackList)();
|
|
2464
2501
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player11.usePlayer)();
|
|
2465
|
-
const unplayableReason = (0,
|
|
2502
|
+
const unplayableReason = (0, import_genre_tree25.songUnplayableReason)(song);
|
|
2466
2503
|
const isCurrent = playerTrackObject?.track.id === song.uuid;
|
|
2467
2504
|
const isPlaying = isCurrent && playState === import_player11.PlayStates.PLAYING;
|
|
2468
2505
|
const shareTarget = { kind: "song", uuid: song.uuid, name: song.title, scope };
|
|
2469
|
-
const musicBrainzUrl = (0,
|
|
2506
|
+
const musicBrainzUrl = (0, import_genre_tree25.musicBrainzRecordingUrl)(song);
|
|
2470
2507
|
const fields = [];
|
|
2471
2508
|
if (song.genre) {
|
|
2472
2509
|
const path = genrePath.length > 0 ? genrePath : null;
|
|
@@ -2525,7 +2562,7 @@ function SongPanelContent({
|
|
|
2525
2562
|
),
|
|
2526
2563
|
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2527
2564
|
] }) }),
|
|
2528
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "px-6 pt-2.5 text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2565
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "px-6 pt-2.5 text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_genre_tree25.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2529
2566
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui16.FieldList, { items: fields }),
|
|
2530
2567
|
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui16.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2531
2568
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
@@ -2546,7 +2583,7 @@ function useSongPanel({
|
|
|
2546
2583
|
onExpandedChange,
|
|
2547
2584
|
onClose
|
|
2548
2585
|
}) {
|
|
2549
|
-
const result = (0,
|
|
2586
|
+
const result = (0, import_genre_tree26.useSong)(uuid, getBackendBaseUrl);
|
|
2550
2587
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2551
2588
|
switch (result.status) {
|
|
2552
2589
|
case "idle":
|
|
@@ -2656,6 +2693,8 @@ function GenreTreeView({
|
|
|
2656
2693
|
onArtistExpandedChange,
|
|
2657
2694
|
getShareUrl,
|
|
2658
2695
|
extraSearchGroups = [],
|
|
2696
|
+
onSearchQueryChange,
|
|
2697
|
+
onSearchFocus,
|
|
2659
2698
|
artistSearch = true,
|
|
2660
2699
|
onArtistSelect,
|
|
2661
2700
|
artistSearchBaseUrl,
|
|
@@ -2721,7 +2760,7 @@ function GenreTreeView({
|
|
|
2721
2760
|
allowWheelRotation: internalAllowWheelRotation,
|
|
2722
2761
|
toggleWheelRotation,
|
|
2723
2762
|
onNodeHover: handleNodeHover
|
|
2724
|
-
} = (0,
|
|
2763
|
+
} = (0, import_genre_tree27.useGenreTreeViewState)({
|
|
2725
2764
|
scope,
|
|
2726
2765
|
getBackendBaseUrl,
|
|
2727
2766
|
viewMode: controlledViewMode,
|
|
@@ -2740,12 +2779,12 @@ function GenreTreeView({
|
|
|
2740
2779
|
restoreRootUuid = selectedGenrePlaylist.root.uuid;
|
|
2741
2780
|
setStackedRestoreOwner({ revision: restoreRevision, rootUuid: restoreRootUuid });
|
|
2742
2781
|
}
|
|
2743
|
-
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey:
|
|
2744
|
-
const { mutate: updateGenre } = (0,
|
|
2782
|
+
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey: import_genre_tree27.genreUpdateMutationKey }) > 0;
|
|
2783
|
+
const { mutate: updateGenre } = (0, import_genre_tree27.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
2745
2784
|
const busy = deferredSizeMetric !== sizeMetric || isTreeFetching || isGenreUpdating;
|
|
2746
2785
|
const isArtistFiltered = artistUuid !== null;
|
|
2747
2786
|
const canSizeByViews = !isArtistFiltered && hasViewsCount(visibleGenrePlaylists);
|
|
2748
|
-
const artistResult = (0,
|
|
2787
|
+
const artistResult = (0, import_genre_tree27.useArtist)(artistUuid, artistSearchBaseUrl ?? getBackendBaseUrl);
|
|
2749
2788
|
const filterArtistName = artistResult.status === "success" ? artistResult.artist.name : null;
|
|
2750
2789
|
const filterArtist = (0, import_react16.useMemo)(
|
|
2751
2790
|
() => artistUuid !== null && filterArtistName !== null ? { uuid: artistUuid, name: filterArtistName } : null,
|
|
@@ -2953,6 +2992,7 @@ function GenreTreeView({
|
|
|
2953
2992
|
] }),
|
|
2954
2993
|
genreUuid,
|
|
2955
2994
|
genrePlaylist,
|
|
2995
|
+
catalogue: genrePlaylist.catalogue,
|
|
2956
2996
|
wikidataId: criteria.wikidataId,
|
|
2957
2997
|
scope,
|
|
2958
2998
|
getBackendBaseUrl,
|
|
@@ -3085,7 +3125,11 @@ function GenreTreeView({
|
|
|
3085
3125
|
selectedName: selectedGenrePlaylist?.name ?? (typeof builtInPanel?.title === "string" ? builtInPanel.title : null),
|
|
3086
3126
|
onClear: builtInSongPanel ? () => changeSong(null) : builtInArtistPanel ? () => changeArtist(null) : handleGenreSearchClear,
|
|
3087
3127
|
onPrevious: handlePrevious,
|
|
3088
|
-
onQueryChange:
|
|
3128
|
+
onQueryChange: (text) => {
|
|
3129
|
+
setSearchText(text);
|
|
3130
|
+
onSearchQueryChange?.(text);
|
|
3131
|
+
},
|
|
3132
|
+
onFocus: onSearchFocus,
|
|
3089
3133
|
extraGroups
|
|
3090
3134
|
}
|
|
3091
3135
|
),
|
|
@@ -3296,7 +3340,7 @@ var import_react17 = require("react");
|
|
|
3296
3340
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
3297
3341
|
var import_ui20 = require("@behindthemusictree/ui");
|
|
3298
3342
|
var import_lucide_react17 = require("lucide-react");
|
|
3299
|
-
var
|
|
3343
|
+
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3300
3344
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3301
3345
|
var RELATIVE_ITEM_COUNT = 1;
|
|
3302
3346
|
function toNode(genre, parentId) {
|
|
@@ -3324,7 +3368,7 @@ function GenreDetailPanel({
|
|
|
3324
3368
|
edgeTab,
|
|
3325
3369
|
extras
|
|
3326
3370
|
}) {
|
|
3327
|
-
const { data: detail, isPending, isError } = (0,
|
|
3371
|
+
const { data: detail, isPending, isError } = (0, import_genre_tree28.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
|
|
3328
3372
|
const playback = useGenrePlaylistPlayback({ scope, genrePlaylists: [] });
|
|
3329
3373
|
const view = (0, import_react17.useMemo)(() => {
|
|
3330
3374
|
if (!detail) return null;
|
|
@@ -3340,7 +3384,7 @@ function GenreDetailPanel({
|
|
|
3340
3384
|
id: detail.uuid,
|
|
3341
3385
|
parentId: detail.parent?.uuid ?? null,
|
|
3342
3386
|
name: detail.name,
|
|
3343
|
-
itemCount: detail.tracksCount,
|
|
3387
|
+
itemCount: scope === "reference" ? (0, import_genre_tree28.genreMusicCount)(import_genre_tree28.GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist)) : detail.tracksCount,
|
|
3344
3388
|
wikidataId: detail.wikidataId
|
|
3345
3389
|
},
|
|
3346
3390
|
fill: rootColor,
|
|
@@ -3350,7 +3394,7 @@ function GenreDetailPanel({
|
|
|
3350
3394
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
3351
3395
|
)
|
|
3352
3396
|
};
|
|
3353
|
-
}, [detail]);
|
|
3397
|
+
}, [detail, scope]);
|
|
3354
3398
|
if (isError) {
|
|
3355
3399
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { role: "alert", className: "p-4 text-sm text-[var(--color-text)]", children: "This genre could not be loaded." });
|
|
3356
3400
|
}
|
|
@@ -3403,7 +3447,8 @@ function GenreDetailPanel({
|
|
|
3403
3447
|
ancestors
|
|
3404
3448
|
] }),
|
|
3405
3449
|
genreUuid: detail.uuid,
|
|
3406
|
-
genrePlaylist: { ...detail.criteriaPlaylist, tracksCount: detail.tracksCount },
|
|
3450
|
+
genrePlaylist: scope === "reference" ? import_genre_tree28.GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist) : { ...detail.criteriaPlaylist, tracksCount: detail.tracksCount },
|
|
3451
|
+
catalogue: detail.catalogue,
|
|
3407
3452
|
wikidataId: detail.wikidataId,
|
|
3408
3453
|
scope,
|
|
3409
3454
|
getBackendBaseUrl,
|
|
@@ -3424,9 +3469,9 @@ var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
|
|
|
3424
3469
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3425
3470
|
var import_react18 = require("react");
|
|
3426
3471
|
var import_lucide_react18 = require("lucide-react");
|
|
3427
|
-
var
|
|
3428
|
-
var
|
|
3429
|
-
var
|
|
3472
|
+
var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3473
|
+
var import_genre_tree30 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3474
|
+
var import_track_noun5 = require("@behindthemusictree/app-kit/track-noun");
|
|
3430
3475
|
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
3431
3476
|
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react18.useEffect : import_react18.useLayoutEffect;
|
|
3432
3477
|
function TrackListSidebar({
|
|
@@ -3440,8 +3485,8 @@ function TrackListSidebar({
|
|
|
3440
3485
|
renderArtistLink,
|
|
3441
3486
|
renderSongLink
|
|
3442
3487
|
}) {
|
|
3443
|
-
const { trackList, loadMore, autoAdvanceScrollRequest } = (0,
|
|
3444
|
-
const trackNoun = (0,
|
|
3488
|
+
const { trackList, loadMore, autoAdvanceScrollRequest } = (0, import_genre_tree29.useTrackList)();
|
|
3489
|
+
const trackNoun = (0, import_track_noun5.useTrackNoun)();
|
|
3445
3490
|
const trackListRef = (0, import_react18.useRef)(null);
|
|
3446
3491
|
const previousOriginRef = (0, import_react18.useRef)(trackList?.origin ?? null);
|
|
3447
3492
|
const handledAutoAdvanceRequestIdRef = (0, import_react18.useRef)(null);
|
|
@@ -3543,7 +3588,7 @@ function TrackListSidebar({
|
|
|
3543
3588
|
/* @__PURE__ */ (0, import_jsx_runtime46.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_runtime46.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3544
3589
|
] }),
|
|
3545
3590
|
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "info flex items-center text-sm text-[var(--color-text-muted)]", children: [
|
|
3546
|
-
trackList.origin.type ===
|
|
3591
|
+
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 `,
|
|
3547
3592
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3548
3593
|
] })
|
|
3549
3594
|
] }),
|
|
@@ -3594,12 +3639,12 @@ function TrackListSidebar({
|
|
|
3594
3639
|
var import_react19 = require("react");
|
|
3595
3640
|
var import_tailwind_merge = require("tailwind-merge");
|
|
3596
3641
|
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3597
|
-
var
|
|
3642
|
+
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3598
3643
|
var import_ui21 = require("@behindthemusictree/ui");
|
|
3599
3644
|
|
|
3600
3645
|
// src/genre-tree/PlayerControls.tsx
|
|
3601
3646
|
var import_lucide_react19 = require("lucide-react");
|
|
3602
|
-
var
|
|
3647
|
+
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3603
3648
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
3604
3649
|
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
3605
3650
|
function PlayerControls() {
|
|
@@ -3613,7 +3658,7 @@ function PlayerControls() {
|
|
|
3613
3658
|
setVolume,
|
|
3614
3659
|
volume
|
|
3615
3660
|
} = (0, import_player12.usePlayer)();
|
|
3616
|
-
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0,
|
|
3661
|
+
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0, import_genre_tree31.useTrackList)();
|
|
3617
3662
|
const currentTime = (0, import_player12.useCurrentTime)();
|
|
3618
3663
|
const isBusy = isLoading || playState === import_player12.PlayStates.LOADING;
|
|
3619
3664
|
const isReady = !!playerTrackObject?.isReady && !isBusy && !playerTrackObject.loadError;
|
|
@@ -3627,7 +3672,7 @@ function PlayerControls() {
|
|
|
3627
3672
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3628
3673
|
children: [
|
|
3629
3674
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3630
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-label": "Elapsed time", children: (0,
|
|
3675
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree31.formatTime)(safeCurrentTime) }),
|
|
3631
3676
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3632
3677
|
"input",
|
|
3633
3678
|
{
|
|
@@ -3642,7 +3687,7 @@ function PlayerControls() {
|
|
|
3642
3687
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3643
3688
|
}
|
|
3644
3689
|
),
|
|
3645
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-label": "Duration", children: (0,
|
|
3690
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree31.formatTime)(safeDuration) })
|
|
3646
3691
|
] }),
|
|
3647
3692
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3648
3693
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
@@ -3721,7 +3766,7 @@ function PlayerPanel({
|
|
|
3721
3766
|
renderSongLink
|
|
3722
3767
|
}) {
|
|
3723
3768
|
const { playerTrackObject, retryPlayback } = (0, import_player13.usePlayer)();
|
|
3724
|
-
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0,
|
|
3769
|
+
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0, import_genre_tree32.useTrackListSidebarVisibility)();
|
|
3725
3770
|
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0, import_react19.useState)("");
|
|
3726
3771
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
3727
3772
|
(0, import_react19.useEffect)(() => {
|
|
@@ -3818,7 +3863,7 @@ function PlayerPanel({
|
|
|
3818
3863
|
// src/genre-tree/Rating.tsx
|
|
3819
3864
|
var import_uuid = require("uuid");
|
|
3820
3865
|
var import_ai = require("react-icons/ai");
|
|
3821
|
-
var
|
|
3866
|
+
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3822
3867
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3823
3868
|
function Rating({ rating, handleChange }) {
|
|
3824
3869
|
const instanceId = (0, import_uuid.v4)();
|
|
@@ -3830,7 +3875,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3830
3875
|
className: "w-6 h-6 opacity-0",
|
|
3831
3876
|
type: "radio",
|
|
3832
3877
|
name: "rating",
|
|
3833
|
-
value: i === 0 ?
|
|
3878
|
+
value: i === 0 ? import_genre_tree33.FORM_RATING_NULL_VALUE : i,
|
|
3834
3879
|
checked: rating === (i === 0 ? null : i),
|
|
3835
3880
|
onChange: handleChange
|
|
3836
3881
|
}
|
|
@@ -3839,7 +3884,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3839
3884
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3840
3885
|
import_ai.AiOutlineStar,
|
|
3841
3886
|
{
|
|
3842
|
-
className: `w-7 h-7 absolute top-0 left-0 ${rating ===
|
|
3887
|
+
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)]"}`
|
|
3843
3888
|
}
|
|
3844
3889
|
),
|
|
3845
3890
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex-grow w-8" }),
|