@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.
@@ -1417,7 +1417,7 @@ function GenrePlaylistTracks({
1417
1417
  const trackNoun = (0, import_track_noun.useTrackNoun)();
1418
1418
  const uuid = genrePlaylist?.uuid;
1419
1419
  const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
1420
- const { fetch } = (0, import_transport3.useFetchWrapper)(getBackendBaseUrl);
1420
+ const { fetchBound } = (0, import_transport3.usePlaybackFetch)(getBackendBaseUrl);
1421
1421
  const playback = (0, import_transport3.usePlaybackContext)();
1422
1422
  const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
1423
1423
  queryKey: [...scope === "me" ? uuid ? import_genre_tree12.genrePlaylistQueryKeys.me.tracks(uuid) : ["missing-personal-genre-playlist", genreUuid] : 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] : []],
@@ -1426,7 +1426,7 @@ function GenrePlaylistTracks({
1426
1426
  if (!uuid) throw new Error("Personal genre has no playlist");
1427
1427
  return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
1428
1428
  }
1429
- const response = await fetch(
1429
+ const response = await fetchBound(
1430
1430
  import_genre_tree13.libraryEndpoints.reference.songs.list(),
1431
1431
  true,
1432
1432
  false,
@@ -1438,7 +1438,9 @@ function GenrePlaylistTracks({
1438
1438
  },
1439
1439
  initialPageParam: scope === "me" ? 1 : "",
1440
1440
  getNextPageParam: (lastPage) => lastPage.nextPage ?? void 0,
1441
- enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken)
1441
+ enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken),
1442
+ retry: (failureCount, error) => failureCount < 1 && error instanceof DOMException && error.name === "AbortError",
1443
+ retryDelay: 0
1442
1444
  });
1443
1445
  const [sentinel, setSentinel] = (0, import_react12.useState)(null);
1444
1446
  (0, import_react12.useEffect)(() => {
@@ -2214,12 +2216,12 @@ var SORTS = [
2214
2216
  function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
2215
2217
  const [page, setPage] = (0, import_react16.useState)(1);
2216
2218
  const [ordering, setOrdering] = (0, import_react16.useState)("title");
2217
- const { fetch } = (0, import_transport7.useFetchWrapper)(getBackendBaseUrl);
2218
2219
  const { playNewTrackListFromArtist } = (0, import_genre_tree24.useTrackList)();
2219
2220
  const { playerTrackObject } = (0, import_player10.usePlayer)();
2220
- const { data, isPending, isError } = (0, import_transport7.useQueryWithParse)({
2221
+ const { data, isPending, isError } = (0, import_transport7.usePlaybackQuery)({
2222
+ getBackendBaseUrl,
2221
2223
  queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
2222
- queryFn: () => fetch(import_genre_tree24.libraryEndpoints.reference.songs.list(), true, false, void 0, {
2224
+ queryFn: (fetchBound) => fetchBound(import_genre_tree24.libraryEndpoints.reference.songs.list(), true, false, void 0, {
2223
2225
  artist: artist.uuid,
2224
2226
  ordering,
2225
2227
  page
@@ -2657,6 +2659,8 @@ function GenreTreeView({
2657
2659
  };
2658
2660
  const {
2659
2661
  isLoading,
2662
+ isError,
2663
+ refetch,
2660
2664
  isFetching: isTreeFetching,
2661
2665
  genrePlaylistByNodeId,
2662
2666
  visibleGenrePlaylists,
@@ -2789,7 +2793,7 @@ function GenreTreeView({
2789
2793
  }, [selectedGenreUuid, artistUuid, songUuid]);
2790
2794
  const [isWheelRevealed, setIsWheelRevealed] = (0, import_react18.useState)(false);
2791
2795
  const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
2792
- const isTreeReady = !isLoading && (!usesHandoff || isWheelRevealed);
2796
+ const isTreeReady = !isLoading && !isError && (!usesHandoff || isWheelRevealed);
2793
2797
  const [resolveStyle, setResolveStyle] = (0, import_react18.useState)(null);
2794
2798
  const handleNodeStyleResolverChange = (0, import_react18.useCallback)(
2795
2799
  (resolver) => setResolveStyle(() => resolver),
@@ -2969,7 +2973,7 @@ function GenreTreeView({
2969
2973
  ] });
2970
2974
  };
2971
2975
  const actions = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
2972
- !isLoading && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
2976
+ !isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
2973
2977
  GenreTreeSearch,
2974
2978
  {
2975
2979
  artistBaseUrl,
@@ -3000,9 +3004,9 @@ function GenreTreeView({
3000
3004
  extraGroups: extraSearchGroups
3001
3005
  }
3002
3006
  ),
3003
- !isLoading && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
3007
+ !isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
3004
3008
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("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: [
3005
- !isLoading && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3009
+ !isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3006
3010
  import_ui17.SegmentedControl,
3007
3011
  {
3008
3012
  "aria-label": "Tree view mode",
@@ -3016,7 +3020,7 @@ function GenreTreeView({
3016
3020
  ]
3017
3021
  }
3018
3022
  ),
3019
- !isLoading && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3023
+ !isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3020
3024
  "div",
3021
3025
  {
3022
3026
  className: "flex items-center gap-1",
@@ -3033,7 +3037,7 @@ function GenreTreeView({
3033
3037
  )
3034
3038
  }
3035
3039
  ),
3036
- !isLoading && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3040
+ !isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3037
3041
  import_ui17.IconTextButton,
3038
3042
  {
3039
3043
  icon: import_lucide_react12.Plus,
@@ -3056,7 +3060,7 @@ function GenreTreeView({
3056
3060
  children: actions
3057
3061
  }
3058
3062
  ),
3059
- !isLoading && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3063
+ !isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3060
3064
  "div",
3061
3065
  {
3062
3066
  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"}`,
@@ -3064,8 +3068,12 @@ function GenreTreeView({
3064
3068
  }
3065
3069
  ),
3066
3070
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
3067
- !isLoading && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
3068
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : viewMode === "wheel" ? (
3071
+ !isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
3072
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { role: "alert", className: "m-auto text-center", children: [
3073
+ "Couldn't load the genre tree.",
3074
+ " ",
3075
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
3076
+ ] }) : viewMode === "wheel" ? (
3069
3077
  // The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
3070
3078
  // and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
3071
3079
  // Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.