Merge pull request #133 from anultravioletaurora/59-improve-onboarding-experience

More Memory Spillage
This commit is contained in:
Violet Caulfield
2025-02-14 20:26:03 -06:00
committed by GitHub
16 changed files with 113 additions and 136 deletions

View File

@@ -4,26 +4,6 @@ import { getItemsApi } from "@jellyfin/sdk/lib/utils/api"
import { BaseItemKind, ItemSortBy, SortOrder } from "@jellyfin/sdk/lib/generated-client/models"
import Client from "../client"
export const useArtistAlbums = (artistId: string) => useQuery({
queryKey: [QueryKeys.ArtistAlbums, artistId],
queryFn: ({ queryKey }) => {
return getItemsApi(Client.api!).getItems({
includeItemTypes: [BaseItemKind.MusicAlbum],
recursive: true,
excludeItemIds: [queryKey[1] as string],
sortBy: [
ItemSortBy.PremiereDate,
ItemSortBy.ProductionYear,
ItemSortBy.SortName
],
sortOrder: [SortOrder.Descending],
artistIds: [queryKey[1] as string],
})
.then((response) => {
return response.data.Items ? response.data.Items! : [];
})
}
})
export const useArtistFeaturedOnAlbums = (artistId: string) => useQuery({

View File

@@ -1,23 +0,0 @@
import { QueryKeys } from "../../enums/query-keys";
import { useQuery } from "@tanstack/react-query";
import { fetchFavoriteAlbums, fetchFavoriteArtists, fetchFavoritePlaylists, fetchFavoriteTracks, fetchUserData } from "./functions/favorites";
export const useFavoriteArtists = () => useQuery({
queryKey: [QueryKeys.FavoriteArtists],
queryFn: () => fetchFavoriteArtists()
});
export const useFavoriteAlbums = () => useQuery({
queryKey: [QueryKeys.FavoriteAlbums],
queryFn: () => fetchFavoriteAlbums()
});
export const useFavoritePlaylists = () => useQuery({
queryKey: [QueryKeys.FavoritePlaylists],
queryFn: () => fetchFavoritePlaylists()
});
export const useFavoriteTracks = () => useQuery({
queryKey: [QueryKeys.FavoriteTracks],
queryFn: () => fetchFavoriteTracks()
});

View File

@@ -1,16 +0,0 @@
import { QueryKeys } from "../../enums/query-keys";
import { useQuery } from "@tanstack/react-query";
import { fetchUserPlaylists } from "./functions/playlists";
import { fetchFavoritePlaylists } from "./functions/favorites";
import { ItemSortBy } from "@jellyfin/sdk/lib/generated-client/models";
export const useFavoritePlaylists = () => useQuery({
queryKey: [QueryKeys.FavoritePlaylists],
queryFn: () => fetchFavoritePlaylists()
});
export const useUserPlaylists = (sortBy: ItemSortBy[] = []) => useQuery({
queryKey: [QueryKeys.UserPlaylists, sortBy],
queryFn: () => fetchUserPlaylists(sortBy)
});

View File

@@ -1,8 +0,0 @@
import { useQuery } from "@tanstack/react-query";
import { QueryKeys } from "../../enums/query-keys";
import { fetchRecentlyPlayed, fetchRecentlyPlayedArtists } from "./functions/recents";
export const useRecentlyPlayedArtists = (offset?: number | undefined) => useQuery({
queryKey: [QueryKeys.RecentlyPlayedArtists, offset],
queryFn: () => fetchRecentlyPlayedArtists(offset)
});

View File

@@ -1,8 +0,0 @@
import { QueryKeys } from "../../enums/query-keys";
import { useQuery } from "@tanstack/react-query";
import { fetchSearchSuggestions } from "./functions/suggestions";
export const useSearchSuggestions = () => useQuery({
queryKey: [QueryKeys.SearchSuggestions],
queryFn: () => fetchSearchSuggestions()
})

View File

@@ -1,31 +0,0 @@
import { QueryKeys } from "../../enums/query-keys";
import { ItemSortBy } from "@jellyfin/sdk/lib/generated-client/models/item-sort-by";
import { getItemsApi } from "@jellyfin/sdk/lib/utils/api/items-api";
import { useQuery } from "@tanstack/react-query";
import Client from "../client";
export const useItemTracks = (itemId: string, sort: boolean = false) => useQuery({
queryKey: [QueryKeys.ItemTracks, itemId, sort],
queryFn: () => {
console.debug(`Fetching item tracks ${sort ? "sorted" : "unsorted"}`)
let sortBy: ItemSortBy[] = [];
if (sort) {
sortBy = [
ItemSortBy.ParentIndexNumber,
ItemSortBy.IndexNumber,
ItemSortBy.SortName
]
}
return getItemsApi(Client.api!).getItems({
parentId: itemId,
sortBy
})
.then((response) => {
return response.data.Items ? response.data.Items! : [];
})
},
})

View File

@@ -1,16 +1,19 @@
import { StackParamList } from "../types";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { YStack, XStack, Separator } from "tamagui";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { BaseItemDto, ItemSortBy } from "@jellyfin/sdk/lib/generated-client/models";
import { H3, H5, Text } from "../Global/helpers/text";
import { FlatList } from "react-native";
import { RunTimeTicks } from "../Global/helpers/time-codes";
import Track from "../Global/components/track";
import { useItemTracks } from "../../api/queries/tracks";
import { useSafeAreaFrame } from "react-native-safe-area-context";
import FavoriteButton from "../Global/components/favorite-button";
import BlurhashedImage from "../Global/components/blurhashed-image";
import Avatar from "../Global/components/avatar";
import { useQuery } from "@tanstack/react-query";
import { QueryKeys } from "../../enums/query-keys";
import { getItemsApi } from "@jellyfin/sdk/lib/utils/api";
import Client from "../../api/client";
interface AlbumProps {
album: BaseItemDto,
@@ -31,7 +34,27 @@ export default function Album({
})
const { width } = useSafeAreaFrame();
const { data: tracks } = useItemTracks(album.Id!, true);
const { data: tracks } = useQuery({
queryKey: [QueryKeys.ItemTracks, album.Id!],
queryFn: () => {
let sortBy: ItemSortBy[] = [];
sortBy = [
ItemSortBy.ParentIndexNumber,
ItemSortBy.IndexNumber,
ItemSortBy.SortName
]
return getItemsApi(Client.api!).getItems({
parentId: album.Id!,
sortBy
})
.then((response) => {
return response.data.Items ? response.data.Items! : [];
})
},
});
return (
<FlatList

View File

@@ -1,11 +1,16 @@
import { useFavoriteAlbums } from "../../api/queries/favorites";
import { AlbumsProps } from "../types";
import { useSafeAreaFrame } from "react-native-safe-area-context";
import { ItemCard } from "../Global/components/item-card";
import { FlatList, RefreshControl } from "react-native";
import { useQuery } from "@tanstack/react-query";
import { QueryKeys } from "../../enums/query-keys";
import { fetchFavoriteAlbums } from "../../api/queries/functions/favorites";
export default function Albums({ navigation }: AlbumsProps) : React.JSX.Element {
const { data: albums, refetch, isPending } = useFavoriteAlbums();
const { data: albums, refetch, isPending } = useQuery({
queryKey: [QueryKeys.FavoriteAlbums],
queryFn: () => fetchFavoriteAlbums()
});
const { width } = useSafeAreaFrame();

View File

@@ -1,15 +1,18 @@
import { ScrollView, YStack } from "tamagui";
import { useArtistAlbums } from "../../api/queries/artist";
import { FlatList } from "react-native";
import { ItemCard } from "../Global/components/item-card";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { StackParamList } from "../types";
import { H2 } from "../Global/helpers/text";
import { useState } from "react";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { BaseItemDto, BaseItemKind, ItemSortBy, SortOrder } from "@jellyfin/sdk/lib/generated-client/models";
import { useSafeAreaFrame } from "react-native-safe-area-context";
import FavoriteButton from "../Global/components/favorite-button";
import BlurhashedImage from "../Global/components/blurhashed-image";
import { useQuery } from "@tanstack/react-query";
import { QueryKeys } from "../../enums/query-keys";
import Client from "../../api/client";
import { getItemsApi } from "@jellyfin/sdk/lib/utils/api";
interface ArtistProps {
artist: BaseItemDto
@@ -35,7 +38,26 @@ export default function Artist({
const bannerHeight = height / 6;
const { data: albums } = useArtistAlbums(artist.Id!);
const { data: albums } = useQuery({
queryKey: [QueryKeys.ArtistAlbums, artist.Id!],
queryFn: ({ queryKey }) => {
return getItemsApi(Client.api!).getItems({
includeItemTypes: [BaseItemKind.MusicAlbum],
recursive: true,
excludeItemIds: [queryKey[1] as string],
sortBy: [
ItemSortBy.PremiereDate,
ItemSortBy.ProductionYear,
ItemSortBy.SortName
],
sortOrder: [SortOrder.Descending],
artistIds: [queryKey[1] as string],
})
.then((response) => {
return response.data.Items ? response.data.Items! : [];
})
}
});
return (
<ScrollView

View File

@@ -1,12 +1,12 @@
import { useFavoriteArtists } from "../../api/queries/favorites";
import { useSafeAreaFrame } from "react-native-safe-area-context";
import React from "react";
import { FlatList, RefreshControl } from "react-native";
import { ItemCard } from "../Global/components/item-card";
import { ArtistsProps } from "../types";
import { QueryKeys } from "../../enums/query-keys";
import { useRecentlyPlayedArtists } from "../../api/queries/recently-played";
import { horizontalCardLimit } from "../Global/component.config";
import { useQuery } from "@tanstack/react-query";
import { fetchRecentlyPlayedArtists } from "../../api/queries/functions/recents";
import { fetchFavoriteArtists } from "../../api/queries/functions/favorites";
export default function Artists({
navigation,
@@ -15,9 +15,20 @@ export default function Artists({
const { data: artists, refetch, isPending } =
route.params.query ===
QueryKeys.FavoriteArtists ? useFavoriteArtists() :
QueryKeys.RecentlyPlayedArtists ? useRecentlyPlayedArtists(horizontalCardLimit + 3) :
useFavoriteArtists();
QueryKeys.FavoriteArtists ? useQuery({
queryKey: [QueryKeys.FavoriteArtists],
queryFn: () => fetchFavoriteArtists()
}) :
QueryKeys.RecentlyPlayedArtists ? useQuery({
queryKey: [QueryKeys.RecentlyPlayedArtists],
queryFn: () => fetchRecentlyPlayedArtists()
}) :
useQuery({
queryKey: [QueryKeys.FavoriteArtists],
queryFn: () => fetchFavoriteArtists()
});
const { width } = useSafeAreaFrame();

View File

@@ -1,17 +1,20 @@
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useUserPlaylists } from "../../../api/queries/playlist";
import { ItemCard } from "../../Global/components/item-card";
import { H2 } from "../../../components/Global/helpers/text";
import { StackParamList } from "../../../components/types";
import React from "react";
import { FlatList } from "react-native";
import { getToken, View, XStack, YStack } from "tamagui";
import Icon from "../../../components/Global/helpers/icon";
import { ItemSortBy } from "@jellyfin/sdk/lib/generated-client/models";
import { View, XStack } from "tamagui";
import { useQuery } from "@tanstack/react-query";
import { QueryKeys } from "../../../enums/query-keys";
import { fetchUserPlaylists } from "../../../api/queries/functions/playlists";
export default function Playlists({ navigation }: { navigation: NativeStackNavigationProp<StackParamList>}) : React.JSX.Element {
const { data: playlists } = useUserPlaylists([ItemSortBy.DatePlayed]);
const { data: playlists } = useQuery({
queryKey: [QueryKeys.UserPlaylists],
queryFn: () => fetchUserPlaylists()
});
return (
<View>

View File

@@ -7,7 +7,6 @@ import { QueuingType } from "../../../enums/queuing-type";
import { useSafeAreaFrame } from "react-native-safe-area-context";
import IconButton from "../../../components/Global/helpers/icon-button";
import { Text } from "../../../components/Global/helpers/text";
import { useUserPlaylists } from "../../../api/queries/playlist";
import React from "react";
import BlurhashedImage from "../../../components/Global/components/blurhashed-image";
import { useMutation, useQuery } from "@tanstack/react-query";
@@ -17,6 +16,7 @@ import { trigger } from "react-native-haptic-feedback";
import { queryClient } from "../../../constants/query-client";
import { QueryKeys } from "../../../enums/query-keys";
import { fetchItem } from "../../../api/queries/functions/item";
import { fetchUserPlaylists } from "../../../api/queries/functions/playlists";
interface TrackOptionsProps {
track: BaseItemDto;
@@ -39,7 +39,11 @@ export default function TrackOptions({
queryFn: () => fetchItem(track.AlbumId!)
});;
const { data: playlists, isPending : playlistsFetchPending, isSuccess: playlistsFetchSuccess, refetch } = useUserPlaylists();
const { data: playlists, isPending : playlistsFetchPending, isSuccess: playlistsFetchSuccess, refetch } = useQuery({
queryKey: [QueryKeys.UserPlaylists],
queryFn: () => fetchUserPlaylists()
});
;
const { useAddToQueue } = usePlayerContext();

View File

@@ -1,10 +1,12 @@
import { useFavoritePlaylists } from "../../api/queries/favorites";
import { FlatList, RefreshControl } from "react-native-gesture-handler";
import { useSafeAreaFrame } from "react-native-safe-area-context";
import { ItemCard } from "../Global/components/item-card";
import { FavoritePlaylistsProps } from "../types";
import Icon from "../Global/helpers/icon";
import { getToken } from "tamagui";
import { fetchFavoritePlaylists } from "../../api/queries/functions/favorites";
import { QueryKeys } from "../../enums/query-keys";
import { useQuery } from "@tanstack/react-query";
export default function FavoritePlaylists({ navigation }: FavoritePlaylistsProps) : React.JSX.Element {
@@ -18,7 +20,10 @@ export default function FavoritePlaylists({ navigation }: FavoritePlaylistsProps
}
});
const { data: playlists, isPending, refetch } = useFavoritePlaylists();
const { data: playlists, isPending, refetch } = useQuery({
queryKey: [QueryKeys.UserPlaylists],
queryFn: () => fetchFavoritePlaylists()
});
const { width } = useSafeAreaFrame();

View File

@@ -8,6 +8,7 @@ import { fetchSearchResults } from "../../api/queries/functions/search";
import { useQuery } from "@tanstack/react-query";
import { FlatList, useColorScheme } from "react-native";
import { Text } from "../Global/helpers/text";
import { fetchSearchSuggestions } from "../../api/queries/functions/suggestions";
export default function Search({
navigation
@@ -15,13 +16,17 @@ export default function Search({
navigation: NativeStackNavigationProp<StackParamList>
}): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
const [searchString, setSearchString] = useState<string | undefined>(undefined);
const { data: items, refetch, isFetched, isFetching } = useQuery({
const { data: items, refetch, isFetching } = useQuery({
queryKey: [QueryKeys.Search, searchString],
queryFn: () => fetchSearchResults(searchString)
})
});
const { data } = useQuery({
queryKey: [QueryKeys.SearchSuggestions],
queryFn: () => fetchSearchSuggestions()
});
const search = useCallback(() => {
@@ -54,7 +59,7 @@ export default function Search({
)}
data={items}
refreshing={isFetching}
renderItem={({ index, item }) => {
renderItem={({ item }) => {
return (
<Item item={item} queueName={searchString ?? "Search"} navigation={navigation} />
)

View File

@@ -1,12 +1,17 @@
import { useFavoriteTracks } from "../../api/queries/favorites";
import { StackParamList } from "../types";
import { FlatList, RefreshControl } from "react-native";
import Track from "../Global/components/track";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { fetchFavoriteTracks } from "../../api/queries/functions/favorites";
import { QueryKeys } from "../../enums/query-keys";
import { useQuery } from "@tanstack/react-query";
export default function Tracks({ navigation }: { navigation: NativeStackNavigationProp<StackParamList> }) : React.JSX.Element {
const { data: tracks, refetch, isPending } = useFavoriteTracks();
const { data: tracks, refetch, isPending } = useQuery({
queryKey: [QueryKeys.FavoriteTracks],
queryFn: () => fetchFavoriteTracks()
});
return (
<FlatList

View File

@@ -4,7 +4,7 @@ export const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: (1000 * 60 * 60 * 24) * 5, // 5 days, for maximum cache-age
staleTime: (1000 * 60 * 1), // 1 minute,
staleTime: (1000 * 60 * 30), // 30 minutes, this can be refreshed manually anyways
}
}
});