@behindthemusictree/app-kit-ui 35.0.0 → 36.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.
@@ -1096,7 +1096,7 @@ import { z } from "zod";
1096
1096
  import { FaPlay, FaPause } from "react-icons/fa";
1097
1097
  import { PanelSection, RingLoader, Skeleton } from "@behindthemusictree/ui";
1098
1098
  import { useSession } from "@behindthemusictree/app-kit/auth";
1099
- import { usePlaybackContext, useFetchWrapper } from "@behindthemusictree/app-kit/transport";
1099
+ import { usePlaybackContext, usePlaybackFetch } from "@behindthemusictree/app-kit/transport";
1100
1100
  import { PaginatedResponseSchema } from "@behindthemusictree/app-kit/transport";
1101
1101
  import { parseWithLog } from "@behindthemusictree/app-kit/transport";
1102
1102
  import { usePlayer as usePlayer4 } from "@behindthemusictree/app-kit/player";
@@ -1174,7 +1174,7 @@ function GenrePlaylistTracks({
1174
1174
  const trackNoun = useTrackNoun();
1175
1175
  const uuid = genrePlaylist?.uuid;
1176
1176
  const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
1177
- const { fetch } = useFetchWrapper(getBackendBaseUrl);
1177
+ const { fetchBound } = usePlaybackFetch(getBackendBaseUrl);
1178
1178
  const playback = usePlaybackContext();
1179
1179
  const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = useInfiniteQuery({
1180
1180
  queryKey: [...scope === "me" ? uuid ? genrePlaylistQueryKeys.me.tracks(uuid) : ["missing-personal-genre-playlist", genreUuid] : artist ? [...libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), "artist", artist.uuid] : libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), ...playback.key ? [playback.key] : []],
@@ -1183,7 +1183,7 @@ function GenrePlaylistTracks({
1183
1183
  if (!uuid) throw new Error("Personal genre has no playlist");
1184
1184
  return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
1185
1185
  }
1186
- const response = await fetch(
1186
+ const response = await fetchBound(
1187
1187
  libraryEndpoints.reference.songs.list(),
1188
1188
  true,
1189
1189
  false,
@@ -1195,7 +1195,9 @@ function GenrePlaylistTracks({
1195
1195
  },
1196
1196
  initialPageParam: scope === "me" ? 1 : "",
1197
1197
  getNextPageParam: (lastPage) => lastPage.nextPage ?? void 0,
1198
- enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken)
1198
+ enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken),
1199
+ retry: (failureCount, error) => failureCount < 1 && error instanceof DOMException && error.name === "AbortError",
1200
+ retryDelay: 0
1199
1201
  });
1200
1202
  const [sentinel, setSentinel] = useState6(null);
1201
1203
  useEffect3(() => {
@@ -1852,7 +1854,7 @@ import {
1852
1854
  songUnplayableReason as songUnplayableReason3,
1853
1855
  useTrackList as useTrackList4
1854
1856
  } from "@behindthemusictree/app-kit/genre-tree";
1855
- import { PaginatedResponseSchema as PaginatedResponseSchema2, useFetchWrapper as useFetchWrapper2, useQueryWithParse } from "@behindthemusictree/app-kit/transport";
1857
+ import { PaginatedResponseSchema as PaginatedResponseSchema2, usePlaybackQuery } from "@behindthemusictree/app-kit/transport";
1856
1858
 
1857
1859
  // src/genre-tree/track-list-sidebar/TrackItem.tsx
1858
1860
  import { usePlayer as usePlayer7 } from "@behindthemusictree/app-kit/player";
@@ -1988,12 +1990,12 @@ var SORTS = [
1988
1990
  function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
1989
1991
  const [page, setPage] = useState7(1);
1990
1992
  const [ordering, setOrdering] = useState7("title");
1991
- const { fetch } = useFetchWrapper2(getBackendBaseUrl);
1992
1993
  const { playNewTrackListFromArtist } = useTrackList4();
1993
1994
  const { playerTrackObject } = usePlayer8();
1994
- const { data, isPending, isError } = useQueryWithParse({
1995
+ const { data, isPending, isError } = usePlaybackQuery({
1996
+ getBackendBaseUrl,
1995
1997
  queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
1996
- queryFn: () => fetch(libraryEndpoints2.reference.songs.list(), true, false, void 0, {
1998
+ queryFn: (fetchBound) => fetchBound(libraryEndpoints2.reference.songs.list(), true, false, void 0, {
1997
1999
  artist: artist.uuid,
1998
2000
  ordering,
1999
2001
  page
@@ -2439,6 +2441,8 @@ function GenreTreeView({
2439
2441
  };
2440
2442
  const {
2441
2443
  isLoading,
2444
+ isError,
2445
+ refetch,
2442
2446
  isFetching: isTreeFetching,
2443
2447
  genrePlaylistByNodeId,
2444
2448
  visibleGenrePlaylists,
@@ -2571,7 +2575,7 @@ function GenreTreeView({
2571
2575
  }, [selectedGenreUuid, artistUuid, songUuid]);
2572
2576
  const [isWheelRevealed, setIsWheelRevealed] = useState9(false);
2573
2577
  const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
2574
- const isTreeReady = !isLoading && (!usesHandoff || isWheelRevealed);
2578
+ const isTreeReady = !isLoading && !isError && (!usesHandoff || isWheelRevealed);
2575
2579
  const [resolveStyle, setResolveStyle] = useState9(null);
2576
2580
  const handleNodeStyleResolverChange = useCallback6(
2577
2581
  (resolver) => setResolveStyle(() => resolver),
@@ -2751,7 +2755,7 @@ function GenreTreeView({
2751
2755
  ] });
2752
2756
  };
2753
2757
  const actions = /* @__PURE__ */ jsxs26(Fragment14, { children: [
2754
- !isLoading && /* @__PURE__ */ jsx34(
2758
+ !isLoading && !isError && /* @__PURE__ */ jsx34(
2755
2759
  GenreTreeSearch,
2756
2760
  {
2757
2761
  artistBaseUrl,
@@ -2782,9 +2786,9 @@ function GenreTreeView({
2782
2786
  extraGroups: extraSearchGroups
2783
2787
  }
2784
2788
  ),
2785
- !isLoading && filterArtist && /* @__PURE__ */ jsx34("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
2789
+ !isLoading && !isError && filterArtist && /* @__PURE__ */ jsx34("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
2786
2790
  /* @__PURE__ */ jsxs26("div", { className: "contents max-md:flex max-md:w-full max-md:items-center max-md:gap-2 max-md:overflow-x-auto max-md:[scrollbar-width:none] max-md:[&>*]:shrink-0", children: [
2787
- !isLoading && !isControlled && /* @__PURE__ */ jsx34(
2791
+ !isLoading && !isError && !isControlled && /* @__PURE__ */ jsx34(
2788
2792
  SegmentedControl2,
2789
2793
  {
2790
2794
  "aria-label": "Tree view mode",
@@ -2798,7 +2802,7 @@ function GenreTreeView({
2798
2802
  ]
2799
2803
  }
2800
2804
  ),
2801
- !isLoading && showDisplayOptions && /* @__PURE__ */ jsx34(
2805
+ !isLoading && !isError && showDisplayOptions && /* @__PURE__ */ jsx34(
2802
2806
  "div",
2803
2807
  {
2804
2808
  className: "flex items-center gap-1",
@@ -2815,7 +2819,7 @@ function GenreTreeView({
2815
2819
  )
2816
2820
  }
2817
2821
  ),
2818
- !isLoading && !readOnly && showAddRoot && /* @__PURE__ */ jsx34(
2822
+ !isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ jsx34(
2819
2823
  IconTextButton,
2820
2824
  {
2821
2825
  icon: Plus2,
@@ -2838,7 +2842,7 @@ function GenreTreeView({
2838
2842
  children: actions
2839
2843
  }
2840
2844
  ),
2841
- !isLoading && filterArtist && /* @__PURE__ */ jsx34(
2845
+ !isLoading && !isError && filterArtist && /* @__PURE__ */ jsx34(
2842
2846
  "div",
2843
2847
  {
2844
2848
  className: `absolute left-1/2 z-30 hidden -translate-x-1/2 md:block ${placement === "regions" ? "top-[calc(var(--layout-gutter)+var(--layout-panel-inset))]" : "top-5"}`,
@@ -2846,8 +2850,12 @@ function GenreTreeView({
2846
2850
  }
2847
2851
  ),
2848
2852
  /* @__PURE__ */ jsx34("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ jsxs26("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
2849
- !isLoading && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ jsx34("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
2850
- isLoading ? /* @__PURE__ */ jsx34(GenreTreeViewSkeleton, { viewMode }) : viewMode === "wheel" ? (
2853
+ !isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ jsx34("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
2854
+ isLoading ? /* @__PURE__ */ jsx34(GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ jsxs26("p", { role: "alert", className: "m-auto text-center", children: [
2855
+ "Couldn't load the genre tree.",
2856
+ " ",
2857
+ /* @__PURE__ */ jsx34("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
2858
+ ] }) : viewMode === "wheel" ? (
2851
2859
  // The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
2852
2860
  // and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
2853
2861
  // Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
@@ -3453,4 +3461,4 @@ export {
3453
3461
  GenreTreeViewSkeleton2 as GenreTreeViewSkeleton,
3454
3462
  GenreTreeOutlineSkeleton
3455
3463
  };
3456
- //# sourceMappingURL=chunk-YC3WBUVO.js.map
3464
+ //# sourceMappingURL=chunk-RTXLUHJY.js.map