From 53ed4f795b255f5a53a8fcba08255d67943d456c Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 20:15:31 -0600 Subject: [PATCH 001/107] more favorites stuff --- components/Album/component.tsx | 4 ++-- components/Artist/component.tsx | 4 ++-- components/Global/components/favorite-button.tsx | 15 +++++++++++---- components/Player/screens/index.tsx | 4 ++-- pages/index.html | 7 ------- 5 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 pages/index.html diff --git a/components/Album/component.tsx b/components/Album/component.tsx index b7fc96a0..2206155f 100644 --- a/components/Album/component.tsx +++ b/components/Album/component.tsx @@ -12,7 +12,7 @@ import { RunTimeTicks } from "../Global/helpers/time-codes"; import Track from "../Global/components/track"; import { useItemTracks } from "../../api/queries/tracks"; import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context"; -import FavoriteHeaderButton from "../Global/components/favorite-button"; +import FavoriteButton from "../Global/components/favorite-button"; import { useEffect } from "react"; import Client from "../../api/client"; @@ -26,7 +26,7 @@ export default function Album(props: AlbumProps): React.JSX.Element { props.navigation.setOptions({ headerRight: () => { return ( - + ) } }) diff --git a/components/Artist/component.tsx b/components/Artist/component.tsx index 631bf0bf..2e91177b 100644 --- a/components/Artist/component.tsx +++ b/components/Artist/component.tsx @@ -11,7 +11,7 @@ import { BaseItemDto, ImageType } from "@jellyfin/sdk/lib/generated-client/model import { queryConfig } from "../../api/queries/query.config"; import { getImageApi } from "@jellyfin/sdk/lib/utils/api"; import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context"; -import FavoriteHeaderButton from "../Global/components/favorite-button"; +import FavoriteButton from "../Global/components/favorite-button"; import Client from "../../api/client"; interface ArtistProps { @@ -24,7 +24,7 @@ export default function Artist(props: ArtistProps): React.JSX.Element { props.navigation.setOptions({ headerRight: () => { return ( - + ) } }); diff --git a/components/Global/components/favorite-button.tsx b/components/Global/components/favorite-button.tsx index 3df6c92d..d4c9b155 100644 --- a/components/Global/components/favorite-button.tsx +++ b/components/Global/components/favorite-button.tsx @@ -14,7 +14,7 @@ interface SetFavoriteMutation { item: BaseItemDto, } -export default function FavoriteHeaderButton({ +export default function FavoriteButton({ item, onToggle }: { @@ -37,8 +37,7 @@ export default function FavoriteHeaderButton({ }, onSuccess: () => { setIsFavorite(true); - if (onToggle) - onToggle(); + onToggle ? onToggle() : {}; } }) @@ -51,6 +50,7 @@ export default function FavoriteHeaderButton({ }, onSuccess: () => { setIsFavorite(false); + onToggle ? onToggle(): {}; } }) @@ -62,7 +62,10 @@ export default function FavoriteHeaderButton({ } useEffect(() => { - if (isFetched && data && data.IsFavorite) + if (isFetched + && !isUndefined(data) + && !isUndefined(data.IsFavorite) + ) setIsFavorite(data.IsFavorite) }, [ isFetched, @@ -82,6 +85,10 @@ export default function FavoriteHeaderButton({ useEffect(() => { if (nowPlayingIsFavorite !== isFavorite && nowPlaying?.item.Id === item.Id) { setIsFavorite(nowPlayingIsFavorite); + + // Trigger toggle event if player controls performed + // the favoriting + onToggle ? onToggle(): {}; } }, [ nowPlayingIsFavorite diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 77e39a32..3a384caf 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -15,7 +15,7 @@ import { H5, Text } from "../../../components/Global/helpers/text"; import Icon from "../../../components/Global/helpers/icon"; import { Colors } from "../../../enums/colors"; import { State } from "react-native-track-player"; -import FavoriteHeaderButton from "../../Global/components/favorite-button"; +import FavoriteButton from "../../Global/components/favorite-button"; import Client from "../../../api/client"; export default function PlayerScreen({ navigation }: { navigation: NativeStackNavigationProp}): React.JSX.Element { @@ -141,7 +141,7 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa - setNowPlayingIsFavorite(!nowPlayingIsFavorite)} /> diff --git a/pages/index.html b/pages/index.html deleted file mode 100644 index 3345db19..00000000 --- a/pages/index.html +++ /dev/null @@ -1,7 +0,0 @@ - - - Jellify: A music app for Jellyfin - - -

Hello world!

- \ No newline at end of file From f4d3ac43be3e0225515087f688f72656248b6f35 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 20:41:53 -0600 Subject: [PATCH 002/107] fix build --- components/ItemDetail/component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 9b9a36f8..6b9d0ab9 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -6,7 +6,7 @@ import TrackOptions from "./helpers/TrackOptions"; import { View, XStack, YStack } from "tamagui"; import BlurhashedImage from "../Global/helpers/blurhashed-image"; import { Text } from "../Global/helpers/text"; -import { Colors } from "@/enums/colors"; +import { Colors } from "../../enums/colors"; export default function ItemDetail({ item, From c82a22bb02b49b05eef14e5692efa05ac0d9572c Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 20:57:54 -0600 Subject: [PATCH 003/107] fix build --- api/queries/functions/images.ts | 2 +- components/Settings/screens/account-details.tsx | 2 +- components/Settings/screens/root.tsx | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index 7991ff74..8be76bcd 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -3,7 +3,7 @@ import { ImageFormat, ImageType } from "@jellyfin/sdk/lib/generated-client/model import { getImageApi } from "@jellyfin/sdk/lib/utils/api" import _ from "lodash" import { queryConfig } from "../query.config" -import Client from "@/api/client" +import Client from "../../../api/client" diff --git a/components/Settings/screens/account-details.tsx b/components/Settings/screens/account-details.tsx index 12940e7a..4e414db6 100644 --- a/components/Settings/screens/account-details.tsx +++ b/components/Settings/screens/account-details.tsx @@ -1,4 +1,4 @@ -import { StackParamList } from "@/components/types"; +import { StackParamList } from "../../../components/types"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; export default function AccountDetails({ diff --git a/components/Settings/screens/root.tsx b/components/Settings/screens/root.tsx index ee5d1f0b..6ac88a84 100644 --- a/components/Settings/screens/root.tsx +++ b/components/Settings/screens/root.tsx @@ -1,12 +1,11 @@ import React from "react"; import { SafeAreaView } from "react-native"; import { ListItem, ScrollView, Separator, YGroup } from "tamagui"; -import AccountDetails from "../helpers/account-details"; import SignOut from "../helpers/sign-out"; import ServerDetails from "../helpers/server-details"; import LibraryDetails from "../helpers/library-details"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -import { StackParamList } from "@/components/types"; +import { StackParamList } from "../../../components/types"; export default function Root({ navigation From 2cf1db787c547f37d7736428e0b7c404e1507adf Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 21:09:16 -0600 Subject: [PATCH 004/107] oh baby --- api/queries/functions/images.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index 8be76bcd..a2dd4099 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -36,7 +36,7 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu format: ImageFormat.Jpg }) .then((response) => { - console.log(convertFileToBase64(response.data)) + console.log(response.data) return convertFileToBase64(response.data); }); } From 7adc57d9fab1307ca5ee1f1ce79740a7d0bc6706 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 21:12:11 -0600 Subject: [PATCH 005/107] performing some surgery on this --- components/Global/components/favorite-button.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/Global/components/favorite-button.tsx b/components/Global/components/favorite-button.tsx index d4c9b155..8bbd4e1b 100644 --- a/components/Global/components/favorite-button.tsx +++ b/components/Global/components/favorite-button.tsx @@ -74,10 +74,6 @@ export default function FavoriteButton({ useEffect(() => { refetch(); - setIsFavorite( - isUndefined(item.UserData) ? false - : item.UserData.IsFavorite ?? false - ); }, [ item ]); From 1cf131d375f8d972b5e00163ccb0fbac4c9a7400 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 21:14:33 -0600 Subject: [PATCH 006/107] mayber I can't have that --- components/Global/components/favorite-button.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/components/Global/components/favorite-button.tsx b/components/Global/components/favorite-button.tsx index 8bbd4e1b..cb3ba8e7 100644 --- a/components/Global/components/favorite-button.tsx +++ b/components/Global/components/favorite-button.tsx @@ -78,18 +78,6 @@ export default function FavoriteButton({ item ]); - useEffect(() => { - if (nowPlayingIsFavorite !== isFavorite && nowPlaying?.item.Id === item.Id) { - setIsFavorite(nowPlayingIsFavorite); - - // Trigger toggle event if player controls performed - // the favoriting - onToggle ? onToggle(): {}; - } - }, [ - nowPlayingIsFavorite - ]) - return ( isFetching && isUndefined(item.UserData) ? ( From e0c42dc68e57680917ea7723cf7bc2a843453f3e Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 21:19:51 -0600 Subject: [PATCH 007/107] refetch home --- components/Home/screens/index.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/components/Home/screens/index.tsx b/components/Home/screens/index.tsx index 717e5683..6336107e 100644 --- a/components/Home/screens/index.tsx +++ b/components/Home/screens/index.tsx @@ -9,19 +9,29 @@ import { useHomeContext } from "../provider"; import { H3 } from "../../../components/Global/helpers/text"; import Avatar from "../../../components/Global/helpers/avatar"; import Client from "../../../api/client"; +import { usePlayerContext } from "@/player/provider"; +import { useEffect } from "react"; export function ProvidedHome({ route, navigation }: ProvidedHomeProps): React.JSX.Element { const { refreshing: refetching, onRefresh: onRefetch } = useHomeContext() + const { nowPlayingIsFavorite } = usePlayerContext(); + + useEffect(() => { + onRefetch() + }, [ + nowPlayingIsFavorite + ]) + return ( }> From 56abd8f41a45f8ce50ca334ec74c6a8fb160b90d Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Mon, 20 Jan 2025 21:31:47 -0600 Subject: [PATCH 008/107] that's super groovy --- components/ItemDetail/component.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 6b9d0ab9..6b86f8bf 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -64,6 +64,7 @@ export default function ItemDetail({ color={Colors.Primary} onPress={() => { if (item.ArtistItems) { + navigation.goBack() // Dismiss menu navigation.navigate("Artist", { artist: item.ArtistItems[0] }); From 68e463394de9d31fdef8188e439db51097539c9a Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 08:37:40 -0600 Subject: [PATCH 009/107] navigation changes and miniplayer tweaks --- components/ItemDetail/component.tsx | 1 - components/Player/mini-player.tsx | 7 ++++++- components/Player/screens/index.tsx | 3 +-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 6b86f8bf..6b9d0ab9 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -64,7 +64,6 @@ export default function ItemDetail({ color={Colors.Primary} onPress={() => { if (item.ArtistItems) { - navigation.goBack() // Dismiss menu navigation.navigate("Artist", { artist: item.ArtistItems[0] }); diff --git a/components/Player/mini-player.tsx b/components/Player/mini-player.tsx index def55398..be652d1f 100644 --- a/components/Player/mini-player.tsx +++ b/components/Player/mini-player.tsx @@ -55,7 +55,12 @@ export function Miniplayer({ navigation }: { navigation : NavigationHelpers - + { if (nowPlaying!.item.ArtistItems) { - navigation.goBack(); // Dismiss player modal - navigation.push("Artist", { + navigation.navigate("Artist", { artist: nowPlaying!.item.ArtistItems![0], }); } From bf9ad2995c60576affc5b102476f6619585b0003 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 08:41:53 -0600 Subject: [PATCH 010/107] fix build --- components/Home/screens/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Home/screens/index.tsx b/components/Home/screens/index.tsx index 6336107e..1c28df03 100644 --- a/components/Home/screens/index.tsx +++ b/components/Home/screens/index.tsx @@ -9,7 +9,7 @@ import { useHomeContext } from "../provider"; import { H3 } from "../../../components/Global/helpers/text"; import Avatar from "../../../components/Global/helpers/avatar"; import Client from "../../../api/client"; -import { usePlayerContext } from "@/player/provider"; +import { usePlayerContext } from "../../../player/provider"; import { useEffect } from "react"; export function ProvidedHome({ route, navigation }: ProvidedHomeProps): React.JSX.Element { From 3ab6698a1af41c895bc6bab16404de4f81c08682 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 08:46:38 -0600 Subject: [PATCH 011/107] adjust mini player margin --- components/Player/mini-player.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Player/mini-player.tsx b/components/Player/mini-player.tsx index be652d1f..236ff63a 100644 --- a/components/Player/mini-player.tsx +++ b/components/Player/mini-player.tsx @@ -57,7 +57,7 @@ export function Miniplayer({ navigation }: { navigation : NavigationHelpers From d4997740d2b7471419d6f7f3d16ca10bb09f8243 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 09:05:16 -0600 Subject: [PATCH 012/107] adjust miniplayer max width --- components/Player/mini-player.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Player/mini-player.tsx b/components/Player/mini-player.tsx index 236ff63a..40eb16ca 100644 --- a/components/Player/mini-player.tsx +++ b/components/Player/mini-player.tsx @@ -59,9 +59,9 @@ export function Miniplayer({ navigation }: { navigation : NavigationHelpers - Date: Tue, 21 Jan 2025 09:17:01 -0600 Subject: [PATCH 013/107] image loading changes adjust queue screen header --- api/queries/functions/images.ts | 2 ++ components/Player/stack.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index a2dd4099..d61bbefa 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -34,6 +34,8 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu itemId, imageType: imageType ? imageType : ImageType.Primary, format: ImageFormat.Jpg + }, { + responseType: "arraybuffer" }) .then((response) => { console.log(response.data) diff --git a/components/Player/stack.tsx b/components/Player/stack.tsx index 05ced874..d6c5909c 100644 --- a/components/Player/stack.tsx +++ b/components/Player/stack.tsx @@ -35,7 +35,7 @@ export default function Player({ navigation }: { navigation: NativeStackNavigati name="Details" component={DetailsScreen} options={{ - headerShown: false + headerTitle: "" }} /> From b3838a3c75c7a3410accc7f1f95e2d3179b438c7 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 09:49:43 -0600 Subject: [PATCH 014/107] adjust favorites --- api/queries/functions/images.ts | 9 ++++----- player/service.ts | 33 +++++++-------------------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index d61bbefa..d6b14c6c 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -34,12 +34,11 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu itemId, imageType: imageType ? imageType : ImageType.Primary, format: ImageFormat.Jpg - }, { - responseType: "arraybuffer" }) - .then((response) => { + .then(async (response) => { console.log(response.data) - return convertFileToBase64(response.data); + + return convertFileToBase64(response.data) }); } @@ -47,7 +46,7 @@ function base64toJpeg(encode: string) : string { return `data:image/jpeg;base64,${encode}`; } -function convertFileToBase64(file: any): string { +function convertFileToBase64(file: string): string { console.debug("Converting file to base64", file) let encode = base64toJpeg(Buffer.from(file, 'binary').toString('base64')); diff --git a/player/service.ts b/player/service.ts index f27cf31e..dc5ddb27 100644 --- a/player/service.ts +++ b/player/service.ts @@ -2,7 +2,7 @@ import Client from "../api/client"; import { JellifyTrack } from "../types/JellifyTrack"; import { getUserLibraryApi } from "@jellyfin/sdk/lib/utils/api"; import TrackPlayer, { Event, RatingType } from "react-native-track-player"; -import { getActiveTrack } from "react-native-track-player/lib/src/trackPlayer"; +import { getActiveTrack, getActiveTrackIndex } from "react-native-track-player/lib/src/trackPlayer"; /** * Jellify Playback Service. @@ -41,50 +41,31 @@ export async function PlaybackService() { TrackPlayer.addEventListener(Event.RemoteLike, async () => { - const progress = await TrackPlayer.getProgress(); const nowPlaying = await getActiveTrack() as JellifyTrack; + const nowPlayingIndex = await getActiveTrackIndex(); await getUserLibraryApi(Client.api!) .markFavoriteItem({ itemId: nowPlaying.item.Id! }); - await TrackPlayer.updateOptions({ - likeOptions: { - isActive: false, - title: "Favorite" - }, - dislikeOptions: { - isActive: true, - title: "Unfavorite" - } - }); + await TrackPlayer.updateMetadataForTrack(nowPlayingIndex!, { + rating: RatingType.Heart + }) }); TrackPlayer.addEventListener(Event.RemoteDislike, async () => { - const progress = await TrackPlayer.getProgress(); const nowPlaying = await getActiveTrack() as JellifyTrack; + const nowPlayingIndex = await getActiveTrackIndex(); await getUserLibraryApi(Client.api!) .markFavoriteItem({ itemId: nowPlaying.item.Id! }); - await TrackPlayer.updateNowPlayingMetadata({ - elapsedTime: progress.position, + await TrackPlayer.updateMetadataForTrack(nowPlayingIndex!, { rating: undefined }); - - await TrackPlayer.updateOptions({ - likeOptions: { - isActive: true, - title: "Favorite" - }, - dislikeOptions: { - isActive: false, - title: "Unfavorite" - } - }); }); } \ No newline at end of file From 01c41a27f76fffd81c84a7e007f65c01abc2a429 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 10:48:30 -0600 Subject: [PATCH 015/107] dismiss item modal --- components/ItemDetail/component.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 6b9d0ab9..6cb23fff 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -64,6 +64,7 @@ export default function ItemDetail({ color={Colors.Primary} onPress={() => { if (item.ArtistItems) { + navigation.goBack(); // Dismiss modal if exists navigation.navigate("Artist", { artist: item.ArtistItems[0] }); From 7f79cf759567ab08ffc9a3a4d1f9033cac9615ed Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 10:56:19 -0600 Subject: [PATCH 016/107] Hide like dislike capabilities, we can handle that in a future update --- player/hooks/index.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/player/hooks/index.ts b/player/hooks/index.ts index 987cd6bb..09db70a8 100644 --- a/player/hooks/index.ts +++ b/player/hooks/index.ts @@ -11,8 +11,8 @@ const CAPABILITIES: Capability[] = [ // Capability.JumpBackward, Capability.SkipToNext, Capability.SkipToPrevious, - Capability.Like, - Capability.Dislike + // Capability.Like, + // Capability.Dislike ] export const useSetupPlayer = () => useQuery({ @@ -31,15 +31,15 @@ export const useSetupPlayer = () => useQuery({ capabilities: CAPABILITIES, notificationCapabilities: CAPABILITIES, compactCapabilities: CAPABILITIES, - ratingType: RatingType.Heart, - likeOptions: { - isActive: false, - title: "Favorite" - }, - dislikeOptions: { - isActive: true, - title: "Unfavorite" - } + // ratingType: RatingType.Heart, + // likeOptions: { + // isActive: false, + // title: "Favorite" + // }, + // dislikeOptions: { + // isActive: true, + // title: "Unfavorite" + // } }); }); } From daba81bdb9451ff420c66234199ee5441ab0070b Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Tue, 21 Jan 2025 12:18:02 -0600 Subject: [PATCH 017/107] what does this do? --- components/ItemDetail/component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 6cb23fff..1fed153e 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -65,7 +65,7 @@ export default function ItemDetail({ onPress={() => { if (item.ArtistItems) { navigation.goBack(); // Dismiss modal if exists - navigation.navigate("Artist", { + navigation.getParent()!.navigate("Artist", { artist: item.ArtistItems[0] }); } From ec3cbfc75f55e9543b9f3108012e146c47d39d0d Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 04:44:12 -0600 Subject: [PATCH 018/107] idk maybe? --- api/queries/functions/images.ts | 44 ++++++++------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index d6b14c6c..040b3def 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -1,32 +1,8 @@ -import { Api } from "@jellyfin/sdk/lib/api" import { ImageFormat, ImageType } from "@jellyfin/sdk/lib/generated-client/models" import { getImageApi } from "@jellyfin/sdk/lib/utils/api" import _ from "lodash" -import { queryConfig } from "../query.config" import Client from "../../../api/client" - - - -export function fetchImage(api: Api, itemId: string, imageType?: ImageType) : Promise { - return new Promise(async (resolve) => { - let imageResponse = await api.axiosInstance - .get(getImageApi(api).getItemImageUrlById( - itemId, - imageType, - { - format: queryConfig.images.format, - fillHeight: queryConfig.images.fillHeight, - fillWidth: queryConfig.images.fillWidth - } - )) - - console.debug(convertFileToBase64(imageResponse.data)); - console.debug(typeof imageResponse.data) - resolve(convertFileToBase64(imageResponse.data)); - }); -} - export function fetchItemImage(itemId: string, imageType?: ImageType, width?: number) { return getImageApi(Client.api!) @@ -37,8 +13,9 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu }) .then(async (response) => { console.log(response.data) - - return convertFileToBase64(response.data) + return new Blob(response.data) + }).then(async (blob) => { + return await blobToBase64(blob) }); } @@ -46,11 +23,10 @@ function base64toJpeg(encode: string) : string { return `data:image/jpeg;base64,${encode}`; } -function convertFileToBase64(file: string): string { - console.debug("Converting file to base64", file) - let encode = base64toJpeg(Buffer.from(file, 'binary').toString('base64')); - - console.debug(encode); - - return encode; -} \ No newline at end of file +function blobToBase64(blob : Blob) : Promise { + return new Promise((resolve, _) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result.toString()); + reader.readAsDataURL(blob); + }); + } \ No newline at end of file From a44cfb47d87fde862686d96d643ff29ab1ff87d3 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 04:49:41 -0600 Subject: [PATCH 019/107] maybe this? --- api/queries/functions/images.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index 040b3def..c459dea3 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -10,6 +10,8 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu itemId, imageType: imageType ? imageType : ImageType.Primary, format: ImageFormat.Jpg + }, { + responseType: 'blob' }) .then(async (response) => { console.log(response.data) From bc7971d19adc4dd36b64b2a37e908517ae275de9 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 04:51:01 -0600 Subject: [PATCH 020/107] can we style this differently? --- components/Player/mini-player.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/Player/mini-player.tsx b/components/Player/mini-player.tsx index 40eb16ca..f1d74248 100644 --- a/components/Player/mini-player.tsx +++ b/components/Player/mini-player.tsx @@ -1,9 +1,8 @@ import React, { } from "react"; -import { XStack, YStack } from "tamagui"; +import { View, XStack, YStack } from "tamagui"; import { usePlayerContext } from "../../player/provider"; import { BottomTabNavigationEventMap } from "@react-navigation/bottom-tabs"; import { NavigationHelpers, ParamListBase } from "@react-navigation/native"; -import { BlurView } from "@react-native-community/blur"; import Icon from "../Global/helpers/icon"; import { Text } from "../Global/helpers/text"; import { Colors } from "../../enums/colors"; @@ -23,7 +22,7 @@ export function Miniplayer({ navigation }: { navigation : NavigationHelpers + { nowPlaying && ( )} - + ) } \ No newline at end of file From 829a788fed392577a4b294a76b1ee9b433677cfa Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 04:54:12 -0600 Subject: [PATCH 021/107] omg!! --- api/queries/functions/images.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index c459dea3..c204f9a1 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -17,7 +17,9 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu console.log(response.data) return new Blob(response.data) }).then(async (blob) => { - return await blobToBase64(blob) + const encoding = await blobToBase64(blob) + console.debug(encoding); + return encoding; }); } From afd4f97a1b604bfabc8261bd2e1b6d2af7a33980 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 06:29:13 -0600 Subject: [PATCH 022/107] hello deepseek? --- api/queries/functions/images.ts | 8 ++------ components/Global/helpers/blurhashed-image.tsx | 6 ++++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index c204f9a1..8d28ddbd 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -15,12 +15,8 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu }) .then(async (response) => { console.log(response.data) - return new Blob(response.data) - }).then(async (blob) => { - const encoding = await blobToBase64(blob) - console.debug(encoding); - return encoding; - }); + return URL.createObjectURL(response.data) + }) } function base64toJpeg(encode: string) : string { diff --git a/components/Global/helpers/blurhashed-image.tsx b/components/Global/helpers/blurhashed-image.tsx index 65a0538a..2ee0be01 100644 --- a/components/Global/helpers/blurhashed-image.tsx +++ b/components/Global/helpers/blurhashed-image.tsx @@ -19,11 +19,13 @@ export default function BlurhashedImage({ item, size, type }: { item: BaseItemDt : undefined; return ( - + { isSuccess ? ( Date: Wed, 22 Jan 2025 06:35:26 -0600 Subject: [PATCH 023/107] just log this plz --- api/queries/functions/images.ts | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index 8d28ddbd..e762c2b7 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -13,20 +13,8 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, width?: nu }, { responseType: 'blob' }) - .then(async (response) => { - console.log(response.data) + .then((response) => { + console.log(response) return URL.createObjectURL(response.data) - }) -} - -function base64toJpeg(encode: string) : string { - return `data:image/jpeg;base64,${encode}`; -} - -function blobToBase64(blob : Blob) : Promise { - return new Promise((resolve, _) => { - const reader = new FileReader(); - reader.onloadend = () => resolve(reader.result.toString()); - reader.readAsDataURL(blob); - }); - } \ No newline at end of file + }); +} \ No newline at end of file From 90082413cd908d5877ca07500e61e1f8d0a52df1 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 06:45:48 -0600 Subject: [PATCH 024/107] omfg this WOPRKS?? --- components/ItemDetail/component.tsx | 5 ++++- components/Player/screens/index.tsx | 10 +++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 1fed153e..e92093b7 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -54,7 +54,10 @@ export default function ItemDetail({ size={width / 3} /> - + { item.Name ?? "Untitled Track" } diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 5c1259a0..5642ffd6 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -17,6 +17,7 @@ import { Colors } from "../../../enums/colors"; import { State } from "react-native-track-player"; import FavoriteButton from "../../Global/components/favorite-button"; import Client from "../../../api/client"; +import BlurhashedImage from "@/components/Global/helpers/blurhashed-image"; export default function PlayerScreen({ navigation }: { navigation: NativeStackNavigationProp}): React.JSX.Element { @@ -65,7 +66,6 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa - + {/* + /> */} From 6e2627fe4d0ea3f7b87a440b94e16048a7dd1fd3 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 06:47:26 -0600 Subject: [PATCH 025/107] fix build --- components/Player/screens/index.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 5642ffd6..44753814 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -1,11 +1,7 @@ -import { queryConfig } from "../../../api/queries/query.config"; import { HorizontalSlider } from "../../../components/Global/helpers/slider"; import { RunTimeSeconds } from "../../../components/Global/helpers/time-codes"; import { StackParamList } from "../../../components/types"; import { usePlayerContext } from "../../../player/provider"; -import { CachedImage } from "@georstat/react-native-image-cache"; -import { ImageType } from "@jellyfin/sdk/lib/generated-client/models"; -import { getImageApi } from "@jellyfin/sdk/lib/utils/api"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import React, { useState, useEffect } from "react"; import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context"; @@ -14,10 +10,8 @@ import PlayPauseButton from "../helpers/buttons"; import { H5, Text } from "../../../components/Global/helpers/text"; import Icon from "../../../components/Global/helpers/icon"; import { Colors } from "../../../enums/colors"; -import { State } from "react-native-track-player"; import FavoriteButton from "../../Global/components/favorite-button"; -import Client from "../../../api/client"; -import BlurhashedImage from "@/components/Global/helpers/blurhashed-image"; +import BlurhashedImage from "../../../components/Global/helpers/blurhashed-image"; export default function PlayerScreen({ navigation }: { navigation: NativeStackNavigationProp}): React.JSX.Element { From b740253b4d809ecbe90ecf5efe0267a330dbfab2 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 06:52:05 -0600 Subject: [PATCH 026/107] maybe if I define an image? --- api/queries/functions/images.ts | 7 +++++-- api/queries/image.ts | 6 +++--- api/queries/query.config.ts | 4 ++-- components/Global/helpers/blurhashed-image.tsx | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index e762c2b7..d0f45076 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -2,14 +2,17 @@ import { ImageFormat, ImageType } from "@jellyfin/sdk/lib/generated-client/model import { getImageApi } from "@jellyfin/sdk/lib/utils/api" import _ from "lodash" import Client from "../../../api/client" +import { queryConfig } from "../query.config"; -export function fetchItemImage(itemId: string, imageType?: ImageType, width?: number) { +export function fetchItemImage(itemId: string, imageType?: ImageType, size?: number) { return getImageApi(Client.api!) .getItemImage({ itemId, imageType: imageType ? imageType : ImageType.Primary, - format: ImageFormat.Jpg + format: ImageFormat.Jpg, + height: size ?? queryConfig.images.height, + width: size ?? queryConfig.images.width }, { responseType: 'blob' }) diff --git a/api/queries/image.ts b/api/queries/image.ts index 4db62e82..9d89f31d 100644 --- a/api/queries/image.ts +++ b/api/queries/image.ts @@ -3,7 +3,7 @@ import { QueryKeys } from "../../enums/query-keys"; import { fetchItemImage } from "./functions/images"; import { ImageType } from "@jellyfin/sdk/lib/generated-client/models"; -export const useItemImage = (itemId: string, imageType?: ImageType, width?: number) => useQuery({ - queryKey: [QueryKeys.ItemImage, itemId, imageType, width], - queryFn: () => fetchItemImage(itemId, imageType, width) +export const useItemImage = (itemId: string, imageType?: ImageType, size?: number) => useQuery({ + queryKey: [QueryKeys.ItemImage, itemId, imageType, size], + queryFn: () => fetchItemImage(itemId, imageType, size) }); \ No newline at end of file diff --git a/api/queries/query.config.ts b/api/queries/query.config.ts index 8f209917..c74fd8d3 100644 --- a/api/queries/query.config.ts +++ b/api/queries/query.config.ts @@ -5,8 +5,8 @@ export const queryConfig = { recents: 50 // TODO: Adjust this when we add a list navigator to the end of the recents }, images: { - fillHeight: 300, - fillWidth: 300, + height: 300, + width: 300, format: ImageFormat.Jpg }, banners: { diff --git a/components/Global/helpers/blurhashed-image.tsx b/components/Global/helpers/blurhashed-image.tsx index 2ee0be01..f433d45c 100644 --- a/components/Global/helpers/blurhashed-image.tsx +++ b/components/Global/helpers/blurhashed-image.tsx @@ -11,7 +11,7 @@ interface BlurhashLoadingProps { export default function BlurhashedImage({ item, size, type }: { item: BaseItemDto, size: number, type?: ImageType }) : React.JSX.Element { - const { data: image, isSuccess } = useItemImage(item.Id!, type); + const { data: image, isSuccess } = useItemImage(item.Id!, type, size); const blurhash = !isEmpty(item.ImageBlurHashes) && !isEmpty(item.ImageBlurHashes.Primary) From 7057c868cd3430ebced92757bea3e9af000b72cd Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 06:54:57 -0600 Subject: [PATCH 027/107] idk --- components/Global/helpers/blurhashed-image.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Global/helpers/blurhashed-image.tsx b/components/Global/helpers/blurhashed-image.tsx index f433d45c..2ee0be01 100644 --- a/components/Global/helpers/blurhashed-image.tsx +++ b/components/Global/helpers/blurhashed-image.tsx @@ -11,7 +11,7 @@ interface BlurhashLoadingProps { export default function BlurhashedImage({ item, size, type }: { item: BaseItemDto, size: number, type?: ImageType }) : React.JSX.Element { - const { data: image, isSuccess } = useItemImage(item.Id!, type, size); + const { data: image, isSuccess } = useItemImage(item.Id!, type); const blurhash = !isEmpty(item.ImageBlurHashes) && !isEmpty(item.ImageBlurHashes.Primary) From e0e88a38beb9caca452fa9e7e4340ea35dca78cd Mon Sep 17 00:00:00 2001 From: Violet Caulfield <42452695+anultravioletaurora@users.noreply.github.com> Date: Wed, 22 Jan 2025 08:01:25 -0600 Subject: [PATCH 028/107] add top safe area to item detail component --- components/ItemDetail/component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index e92093b7..1925d7d0 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -47,7 +47,7 @@ export default function ItemDetail({ } return ( - + Date: Wed, 22 Jan 2025 09:34:44 -0600 Subject: [PATCH 029/107] Add favorite button to itemdetail modal --- components/ItemDetail/component.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index e92093b7..6951eda9 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -7,6 +7,7 @@ import { View, XStack, YStack } from "tamagui"; import BlurhashedImage from "../Global/helpers/blurhashed-image"; import { Text } from "../Global/helpers/text"; import { Colors } from "../../enums/colors"; +import FavoriteButton from "../Global/components/favorite-button"; export default function ItemDetail({ item, @@ -51,7 +52,7 @@ export default function ItemDetail({ { item.Album ?? "" } + + From 6c6e744209244a064812ff732ebbfa6bca382709 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 13:22:04 -0600 Subject: [PATCH 030/107] ItemDetail menu options --- components/ItemDetail/component.tsx | 4 +++- components/ItemDetail/helpers/TrackOptions.tsx | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 9a73e7a0..2a590913 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -58,6 +58,7 @@ export default function ItemDetail({ { item.Name ?? "Untitled Track" } @@ -85,10 +86,11 @@ export default function ItemDetail({ + + { options ?? } - { options ?? } ) } \ No newline at end of file diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 3c22740b..b38ed002 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -1,7 +1,8 @@ +import Icon from "../../../components/Global/helpers/icon"; import { StackParamList } from "../../../components/types"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -import { View } from "tamagui"; +import { XStack } from "tamagui"; export default function TrackOptions({ item, @@ -12,8 +13,10 @@ export default function TrackOptions({ }) : React.JSX.Element { return ( - - - + + + + + ) } \ No newline at end of file From 10dfb0ea61dd80d8517e137e5393993d9e46b96d Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 13:28:01 -0600 Subject: [PATCH 031/107] Item detail layout changes --- components/ItemDetail/component.tsx | 8 ++++++-- components/ItemDetail/helpers/TrackOptions.tsx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 2a590913..9f6e0008 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -3,7 +3,7 @@ import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context"; import { StackParamList } from "../types"; import TrackOptions from "./helpers/TrackOptions"; -import { View, XStack, YStack } from "tamagui"; +import { Spacer, View, XStack, YStack } from "tamagui"; import BlurhashedImage from "../Global/helpers/blurhashed-image"; import { Text } from "../Global/helpers/text"; import { Colors } from "../../enums/colors"; @@ -58,7 +58,7 @@ export default function ItemDetail({ { item.Name ?? "Untitled Track" } @@ -85,8 +85,12 @@ export default function ItemDetail({ { item.Album ?? "" } + + + + { options ?? } diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index b38ed002..0e9c08c2 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -13,7 +13,7 @@ export default function TrackOptions({ }) : React.JSX.Element { return ( - + From 38198d3da6fc15e1fab235acbe5baf84e9b0434c Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 13:43:41 -0600 Subject: [PATCH 032/107] long press for recently played? --- components/Home/helpers/playlists.tsx | 5 +++-- components/Home/helpers/recent-artists.tsx | 7 ++++--- components/Home/helpers/recently-played.tsx | 13 ++++++++++++- components/Home/screens/index.tsx | 15 ++++++++++----- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/components/Home/helpers/playlists.tsx b/components/Home/helpers/playlists.tsx index 951cfd0e..d7deab6f 100644 --- a/components/Home/helpers/playlists.tsx +++ b/components/Home/helpers/playlists.tsx @@ -1,12 +1,13 @@ +import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { useUserPlaylists } from "../../../api/queries/playlist"; import { ItemCard } from "../../../components/Global/helpers/item-card"; import { H2 } from "../../../components/Global/helpers/text"; -import { ProvidedHomeProps } from "../../../components/types"; +import { StackParamList } from "../../../components/types"; import React from "react"; import { FlatList } from "react-native"; import { View } from "tamagui"; -export default function Playlists({ navigation }: ProvidedHomeProps) : React.JSX.Element { +export default function Playlists({ navigation }: { navigation: NativeStackNavigationProp}) : React.JSX.Element { const { data: playlists } = useUserPlaylists(); diff --git a/components/Home/helpers/recent-artists.tsx b/components/Home/helpers/recent-artists.tsx index ff61949b..4c1911f0 100644 --- a/components/Home/helpers/recent-artists.tsx +++ b/components/Home/helpers/recent-artists.tsx @@ -1,13 +1,14 @@ -import React, { useEffect } from "react"; +import React from "react"; import { View } from "tamagui"; import { useHomeContext } from "../provider"; import { H2 } from "../../Global/helpers/text"; -import { ProvidedHomeProps } from "../../types"; +import { StackParamList } from "../../types"; import { FlatList } from "react-native"; import { ItemCard } from "../../Global/helpers/item-card"; import { getPrimaryBlurhashFromDto } from "../../../helpers/blurhash"; +import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -export default function RecentArtists({ navigation }: ProvidedHomeProps): React.JSX.Element { +export default function RecentArtists({ navigation }: { navigation: NativeStackNavigationProp}): React.JSX.Element { const { recentArtists } = useHomeContext(); diff --git a/components/Home/helpers/recently-played.tsx b/components/Home/helpers/recently-played.tsx index 0c0ddd58..8aeb50d8 100644 --- a/components/Home/helpers/recently-played.tsx +++ b/components/Home/helpers/recently-played.tsx @@ -4,8 +4,14 @@ import { useHomeContext } from "../provider"; import { H2 } from "../../Global/helpers/text"; import { ItemCard } from "../../Global/helpers/item-card"; import { usePlayerContext } from "../../../player/provider"; +import { StackParamList } from "../../../components/types"; +import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -export default function RecentlyPlayed(): React.JSX.Element { +export default function RecentlyPlayed({ + navigation +} : { + navigation: NativeStackNavigationProp +}): React.JSX.Element { const { usePlayNewQueue } = usePlayerContext(); const { recentTracks } = useHomeContext(); @@ -30,6 +36,11 @@ export default function RecentlyPlayed(): React.JSX.Element { queueName: "Recently Played" }); }} + onLongPress={() => { + navigation.push("Details", { + item: recentlyPlayedTrack + }) + }} /> ) })} diff --git a/components/Home/screens/index.tsx b/components/Home/screens/index.tsx index 1c28df03..a8d8255e 100644 --- a/components/Home/screens/index.tsx +++ b/components/Home/screens/index.tsx @@ -1,4 +1,4 @@ -import { ProvidedHomeProps } from "../../../components/types"; +import { ProvidedHomeProps, StackParamList } from "../../../components/types"; import { ScrollView, RefreshControl } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; import { YStack, XStack, Separator } from "tamagui"; @@ -11,8 +11,13 @@ import Avatar from "../../../components/Global/helpers/avatar"; import Client from "../../../api/client"; import { usePlayerContext } from "../../../player/provider"; import { useEffect } from "react"; +import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -export function ProvidedHome({ route, navigation }: ProvidedHomeProps): React.JSX.Element { +export function ProvidedHome({ + navigation +} : { + navigation: NativeStackNavigationProp +}): React.JSX.Element { const { refreshing: refetching, onRefresh: onRefetch } = useHomeContext() @@ -43,15 +48,15 @@ export function ProvidedHome({ route, navigation }: ProvidedHomeProps): React.JS - + - + - + From 614c57d2c9d7648bc84b409e96ac9c484b83c093 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 14:55:04 -0600 Subject: [PATCH 033/107] trigger impact on long press --- components/Home/helpers/recently-played.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/Home/helpers/recently-played.tsx b/components/Home/helpers/recently-played.tsx index 8aeb50d8..08e7343b 100644 --- a/components/Home/helpers/recently-played.tsx +++ b/components/Home/helpers/recently-played.tsx @@ -6,6 +6,7 @@ import { ItemCard } from "../../Global/helpers/item-card"; import { usePlayerContext } from "../../../player/provider"; import { StackParamList } from "../../../components/types"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; +import { trigger } from "react-native-haptic-feedback"; export default function RecentlyPlayed({ navigation @@ -37,6 +38,7 @@ export default function RecentlyPlayed({ }); }} onLongPress={() => { + trigger("impactLight"); navigation.push("Details", { item: recentlyPlayedTrack }) From 71846e2ff33c4c66a33e0078be7d63d31af27650 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 15:17:49 -0600 Subject: [PATCH 034/107] update update interval in player so scrubber moves smoother --- components/Search/screen.tsx | 0 components/Search/stack.tsx | 0 player/config.ts | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 components/Search/screen.tsx create mode 100644 components/Search/stack.tsx diff --git a/components/Search/screen.tsx b/components/Search/screen.tsx new file mode 100644 index 00000000..e69de29b diff --git a/components/Search/stack.tsx b/components/Search/stack.tsx new file mode 100644 index 00000000..e69de29b diff --git a/player/config.ts b/player/config.ts index 8227bc7c..00eb056d 100644 --- a/player/config.ts +++ b/player/config.ts @@ -1 +1 @@ -export const UPDATE_INTERVAL: number = 1000 \ No newline at end of file +export const UPDATE_INTERVAL: number = 500 \ No newline at end of file From 724a74b362eb0658358eac0054ca78bba0da9e46 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 15:31:58 -0600 Subject: [PATCH 035/107] Add link to album on track item detail --- api/queries/album.ts | 6 ----- api/queries/functions/item.ts | 20 +++++++++++++++ api/queries/item.ts | 8 ++++++ .../ItemDetail/helpers/TrackOptions.tsx | 25 ++++++++++++++++--- enums/query-keys.ts | 1 + player/config.ts | 2 +- 6 files changed, 52 insertions(+), 10 deletions(-) delete mode 100644 api/queries/album.ts create mode 100644 api/queries/functions/item.ts create mode 100644 api/queries/item.ts diff --git a/api/queries/album.ts b/api/queries/album.ts deleted file mode 100644 index 937b859b..00000000 --- a/api/queries/album.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Api } from "@jellyfin/sdk"; -import { useQuery } from "@tanstack/react-query"; -import { QueryKeys } from "../../enums/query-keys"; -import { getItemsApi } from "@jellyfin/sdk/lib/utils/api"; -import { ItemSortBy } from "@jellyfin/sdk/lib/generated-client/models"; - diff --git a/api/queries/functions/item.ts b/api/queries/functions/item.ts new file mode 100644 index 00000000..d8f7ea5e --- /dev/null +++ b/api/queries/functions/item.ts @@ -0,0 +1,20 @@ +import Client from "@/api/client"; +import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; +import { getItemsApi } from "@jellyfin/sdk/lib/utils/api"; + +export async function fetchItem(itemId: string) : Promise { + return new Promise((resolve, reject) => { + getItemsApi(Client.api!) + .getItems({ + ids: [ + itemId + ] + }) + .then((response) => { + if (response.data.Items && response.data.TotalRecordCount == 1) + resolve(response.data.Items[0]) + else + reject(`${response.data.TotalRecordCount} items returned for ID`); + }) + }); +} \ No newline at end of file diff --git a/api/queries/item.ts b/api/queries/item.ts new file mode 100644 index 00000000..35640bd6 --- /dev/null +++ b/api/queries/item.ts @@ -0,0 +1,8 @@ +import { useQuery } from "@tanstack/react-query"; +import { QueryKeys } from "../../enums/query-keys"; +import { fetchItem } from "./functions/item"; + +export const useItem = (itemId: string) => useQuery({ + queryKey: [QueryKeys.Item, itemId], + queryFn: () => fetchItem(itemId) +}); \ No newline at end of file diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 0e9c08c2..9571f8a2 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -1,3 +1,4 @@ +import { useItem } from "../../../api/queries/item"; import Icon from "../../../components/Global/helpers/icon"; import { StackParamList } from "../../../components/types"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; @@ -11,12 +12,30 @@ export default function TrackOptions({ item: BaseItemDto, navigation: NativeStackNavigationProp }) : React.JSX.Element { + + const { data: album, isSuccess } = useItem(item.AlbumId ?? "") return ( - - + - + { isSuccess && ( + { + navigation.navigate("Album", { + album + }) + }} + /> + )} + + + + ) } \ No newline at end of file diff --git a/enums/query-keys.ts b/enums/query-keys.ts index 05645f4a..16fa18cf 100644 --- a/enums/query-keys.ts +++ b/enums/query-keys.ts @@ -35,4 +35,5 @@ export enum QueryKeys { FavoriteTracks = "FavoriteTracks", UserData = "UserData", UpdatePlayerOptions = "UpdatePlayerOptions", + Item = "Item", } \ No newline at end of file diff --git a/player/config.ts b/player/config.ts index 00eb056d..b6e425d7 100644 --- a/player/config.ts +++ b/player/config.ts @@ -1 +1 @@ -export const UPDATE_INTERVAL: number = 500 \ No newline at end of file +export const UPDATE_INTERVAL: number = 1000 // We need to do better rounding in the player scrubber before lowering this value for silky smoothness \ No newline at end of file From fea81ad45dd5512b90064b479092554d95902da3 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 15:33:50 -0600 Subject: [PATCH 036/107] fix build --- api/queries/functions/item.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/queries/functions/item.ts b/api/queries/functions/item.ts index d8f7ea5e..213d1a8f 100644 --- a/api/queries/functions/item.ts +++ b/api/queries/functions/item.ts @@ -1,4 +1,4 @@ -import Client from "@/api/client"; +import Client from "../../../api/client"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { getItemsApi } from "@jellyfin/sdk/lib/utils/api"; From fd70809e40f691090ee48dc75872866f70cca720 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 15:38:06 -0600 Subject: [PATCH 037/107] Album button changes --- .../ItemDetail/helpers/TrackOptions.tsx | 8 ++--- player/interfaces.ts | 2 ++ player/provider.tsx | 32 ++++++++++++++++--- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 9571f8a2..0bb4adf7 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -16,15 +16,15 @@ export default function TrackOptions({ const { data: album, isSuccess } = useItem(item.AlbumId ?? "") return ( - - + { isSuccess && ( { - navigation.navigate("Album", { + navigation.goBack() // Dismiss modal if it exists + navigation.getParent()!.navigate("Album", { album - }) + }); }} /> )} diff --git a/player/interfaces.ts b/player/interfaces.ts index a05c4ba2..31246ff3 100644 --- a/player/interfaces.ts +++ b/player/interfaces.ts @@ -1,3 +1,4 @@ +import { QueuingType } from "../enums/queuing-type"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; export interface QueueMutation { @@ -5,4 +6,5 @@ export interface QueueMutation { index?: number | undefined; tracklist: BaseItemDto[]; queueName: string; + queuingType?: QueuingType | undefined; } \ No newline at end of file diff --git a/player/provider.tsx b/player/provider.tsx index c6724dd1..851367ae 100644 --- a/player/provider.tsx +++ b/player/provider.tsx @@ -2,7 +2,7 @@ import { createContext, ReactNode, SetStateAction, useContext, useEffect, useSta import { JellifyTrack } from "../types/JellifyTrack"; import { storage } from "../constants/storage"; import { MMKVStorageKeys } from "../enums/mmkv-storage-keys"; -import { findPlayQueueIndexStart } from "./helpers/index"; +import { findPlayNextIndexStart, findPlayQueueIndexStart } from "./helpers/index"; import TrackPlayer, { Event, Progress, State, usePlaybackState, useProgress, useTrackPlayerEvents } from "react-native-track-player"; import _, { isEqual, isUndefined } from "lodash"; import { getPlaystateApi } from "@jellyfin/sdk/lib/utils/api"; @@ -10,13 +10,13 @@ import { handlePlaybackProgressUpdated, handlePlaybackState } from "./handlers"; import { useSetupPlayer, useUpdateOptions } from "../player/hooks"; import { UPDATE_INTERVAL } from "./config"; import { useMutation, UseMutationResult } from "@tanstack/react-query"; -import { QueueMutation } from "./interfaces"; import { mapDtoToTrack } from "../helpers/mappings"; import { QueuingType } from "../enums/queuing-type"; import { trigger } from "react-native-haptic-feedback"; import { getQueue, pause, seekTo, skip, skipToNext, skipToPrevious } from "react-native-track-player/lib/src/trackPlayer"; -import { convertRunTimeTicksToSeconds } from "..//helpers/runtimeticks"; +import { convertRunTimeTicksToSeconds } from "../helpers/runtimeticks"; import Client from "../api/client"; +import { QueueMutation } from "./interfaces"; interface PlayerContext { showPlayer: boolean; @@ -74,7 +74,7 @@ const PlayerContextInitializer = () => { } const addToQueue = async (tracks: JellifyTrack[]) => { - let insertIndex = findPlayQueueIndexStart(queue); + const insertIndex = findPlayQueueIndexStart(queue); console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`) await TrackPlayer.add(tracks, insertIndex); @@ -83,9 +83,33 @@ const PlayerContextInitializer = () => { setShowMiniplayer(true); } + + const addToNext = async (tracks: JellifyTrack[]) => { + const insertIndex = findPlayNextIndexStart(queue); + + console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`); + + await TrackPlayer.add(tracks, insertIndex); + + setQueue(await getQueue() as JellifyTrack[]); + + setShowMiniplayer(true); + } //#endregion Functions //#region Hooks + const useQueueMutation = useMutation({ + mutationFn: async (mutation: QueueMutation) => { + trigger("impactLight"); + + if (mutation.queuingType === QueuingType.PlayingNext) + return addToNext([mapDtoToTrack(mutation.track)]); + + else + return addToQueue([mapDtoToTrack(mutation.track)]) + } + }) + const useTogglePlayback = useMutation({ mutationFn: async (index?: number | undefined) => { trigger("impactLight"); From 2b94302e690293a5404b541238087d1b530038f9 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Wed, 22 Jan 2025 15:41:36 -0600 Subject: [PATCH 038/107] lots of color in this one --- components/Global/helpers/icon.tsx | 2 +- enums/colors.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Global/helpers/icon.tsx b/components/Global/helpers/icon.tsx index d52728f9..97a85319 100644 --- a/components/Global/helpers/icon.tsx +++ b/components/Global/helpers/icon.tsx @@ -16,7 +16,7 @@ export default function Icon({ name, onPress, small, large, color }: { name: str return ( Date: Wed, 22 Jan 2025 15:47:05 -0600 Subject: [PATCH 039/107] what if tho? --- player/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/player/config.ts b/player/config.ts index b6e425d7..185450c3 100644 --- a/player/config.ts +++ b/player/config.ts @@ -1 +1 @@ -export const UPDATE_INTERVAL: number = 1000 // We need to do better rounding in the player scrubber before lowering this value for silky smoothness \ No newline at end of file +export const UPDATE_INTERVAL: number = 250 // We need to do better rounding in the player scrubber before lowering this value for silky smoothness \ No newline at end of file From f2219d22aadafafa5e9b9f600b05e03f7058984d Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Thu, 23 Jan 2025 07:01:15 -0600 Subject: [PATCH 040/107] adjust player artwork resolution and query stale time --- api/queries/functions/images.ts | 4 +--- api/queries/query.config.ts | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index d0f45076..66a8797f 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -10,9 +10,7 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, size?: num .getItemImage({ itemId, imageType: imageType ? imageType : ImageType.Primary, - format: ImageFormat.Jpg, - height: size ?? queryConfig.images.height, - width: size ?? queryConfig.images.width + ...queryConfig.playerArtwork, }, { responseType: 'blob' }) diff --git a/api/queries/query.config.ts b/api/queries/query.config.ts index c74fd8d3..23812e58 100644 --- a/api/queries/query.config.ts +++ b/api/queries/query.config.ts @@ -20,9 +20,9 @@ export const queryConfig = { format: ImageFormat.Png }, playerArtwork: { - fillHeight: 1000, - fillWidth: 1000, + height: 1000, + width: 1000, format: ImageFormat.Jpg }, - staleTime: 1000 * 60 + staleTime: 1000 * 60 * 60 * 24 // 1 Day } \ No newline at end of file From a036b85208225e9216efabce18681296e7cbd9e5 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Thu, 23 Jan 2025 07:01:54 -0600 Subject: [PATCH 041/107] thank you alyssa --- components/Global/helpers/icon.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Global/helpers/icon.tsx b/components/Global/helpers/icon.tsx index 97a85319..d52728f9 100644 --- a/components/Global/helpers/icon.tsx +++ b/components/Global/helpers/icon.tsx @@ -16,7 +16,7 @@ export default function Icon({ name, onPress, small, large, color }: { name: str return ( Date: Thu, 23 Jan 2025 14:25:54 -0600 Subject: [PATCH 042/107] navigation changes --- components/ItemDetail/component.tsx | 2 +- components/ItemDetail/helpers/TrackOptions.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 9f6e0008..9702d413 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -70,7 +70,7 @@ export default function ItemDetail({ onPress={() => { if (item.ArtistItems) { navigation.goBack(); // Dismiss modal if exists - navigation.getParent()!.navigate("Artist", { + navigation.push("Artist", { artist: item.ArtistItems[0] }); } diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 0bb4adf7..55cb3ea2 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -22,7 +22,7 @@ export default function TrackOptions({ name="music-box" onPress={() => { navigation.goBack() // Dismiss modal if it exists - navigation.getParent()!.navigate("Album", { + navigation.push("Album", { album }); }} From 2cc50496ed79f505978afe179c10f9d0ac2038b7 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Thu, 23 Jan 2025 14:31:01 -0600 Subject: [PATCH 043/107] navigation changes --- api/queries/functions/downloads.ts | 11 +++++++++++ components/Albums/component.tsx | 2 +- components/Artist/component.tsx | 2 +- components/Artists/component.tsx | 2 +- components/Favorites/screens/index.tsx | 2 +- components/Home/helpers/playlists.tsx | 2 +- components/Home/helpers/recent-artists.tsx | 2 +- components/Player/screens/index.tsx | 3 ++- 8 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 api/queries/functions/downloads.ts diff --git a/api/queries/functions/downloads.ts b/api/queries/functions/downloads.ts new file mode 100644 index 00000000..8239b225 --- /dev/null +++ b/api/queries/functions/downloads.ts @@ -0,0 +1,11 @@ +import Client from "../../../api/client"; +import { getLibraryApi } from "@jellyfin/sdk/lib/utils/api"; + +export async function downloadTrack(itemId: string) : Promise { + getLibraryApi(Client.api!) + .getDownload({ + itemId + }, { + 'responseType': 'blob' + }) +} \ No newline at end of file diff --git a/components/Albums/component.tsx b/components/Albums/component.tsx index afc132df..f980986e 100644 --- a/components/Albums/component.tsx +++ b/components/Albums/component.tsx @@ -29,7 +29,7 @@ export default function Albums({ navigation }: AlbumsProps) : React.JSX.Element subCaption={album.ProductionYear?.toString() ?? ""} cornered onPress={() => { - navigation.navigate("Album", { album }) + navigation.push("Album", { album }) }} width={width / 2.1} /> diff --git a/components/Artist/component.tsx b/components/Artist/component.tsx index 2e91177b..1de96fdd 100644 --- a/components/Artist/component.tsx +++ b/components/Artist/component.tsx @@ -77,7 +77,7 @@ export default function Artist(props: ArtistProps): React.JSX.Element { cornered itemId={album.Id!} onPress={() => { - props.navigation.navigate('Album', { + props.navigation.push('Album', { album }) }} diff --git a/components/Artists/component.tsx b/components/Artists/component.tsx index 5f10d163..835dd557 100644 --- a/components/Artists/component.tsx +++ b/components/Artists/component.tsx @@ -30,7 +30,7 @@ export default function Artists({ navigation }: ArtistsProps): React.JSX.Element itemId={artist.Id!} caption={artist.Name ?? "Unknown Artist"} onPress={() => { - navigation.navigate("Artist", { artist }) + navigation.push("Artist", { artist }) }} width={width / 2.1} /> diff --git a/components/Favorites/screens/index.tsx b/components/Favorites/screens/index.tsx index df09b6c0..7ad4f491 100644 --- a/components/Favorites/screens/index.tsx +++ b/components/Favorites/screens/index.tsx @@ -29,7 +29,7 @@ export default function FavoritesScreen({ caption={item.name} width={width / 2.1} onPress={() => { - navigation.navigate(item.name) + navigation.push(item.name) }} /> ) diff --git a/components/Home/helpers/playlists.tsx b/components/Home/helpers/playlists.tsx index d7deab6f..83a46a89 100644 --- a/components/Home/helpers/playlists.tsx +++ b/components/Home/helpers/playlists.tsx @@ -22,7 +22,7 @@ export default function Playlists({ navigation }: { navigation: NativeStackNavig itemId={playlist.Id!} caption={playlist.Name ?? "Untitled Playlist"} onPress={() => { - navigation.navigate('Playlist', { + navigation.push('Playlist', { playlist }) }} /> diff --git a/components/Home/helpers/recent-artists.tsx b/components/Home/helpers/recent-artists.tsx index 4c1911f0..4268bd4f 100644 --- a/components/Home/helpers/recent-artists.tsx +++ b/components/Home/helpers/recent-artists.tsx @@ -25,7 +25,7 @@ export default function RecentArtists({ navigation }: { navigation: NativeStackN itemId={recentArtist.Id!} caption={recentArtist.Name ?? "Unknown Artist"} onPress={() => { - navigation.navigate('Artist', + navigation.push('Artist', { artist: recentArtist, } diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 44753814..504a00cc 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -103,7 +103,8 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa color={Colors.Primary} onPress={() => { if (nowPlaying!.item.ArtistItems) { - navigation.navigate("Artist", { + navigation.goBack(); + navigation.push("Artist", { artist: nowPlaying!.item.ArtistItems![0], }); } From 97883d606f2b87ffb03b47f11d17398161c3c832 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 05:10:27 -0600 Subject: [PATCH 044/107] navigation changes --- components/ItemDetail/component.tsx | 14 ++++++++++---- components/ItemDetail/helpers/TrackOptions.tsx | 3 ++- components/ItemDetail/screen.tsx | 5 ++++- components/Player/screens/index.tsx | 5 ++++- components/types.tsx | 3 ++- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 9702d413..692403d9 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -11,10 +11,12 @@ import FavoriteButton from "../Global/components/favorite-button"; export default function ItemDetail({ item, - navigation + navigation, + onNavigate } : { item: BaseItemDto, - navigation: NativeStackNavigationProp + navigation: NativeStackNavigationProp, + onNavigate?: () => void | undefined }) : React.JSX.Element { let options: React.JSX.Element | undefined = undefined; @@ -23,7 +25,7 @@ export default function ItemDetail({ switch (item.Type) { case "Audio": { - options = TrackOptions({ item, navigation }); + options = TrackOptions({ item, navigation, onNavigate }); break; } @@ -69,7 +71,11 @@ export default function ItemDetail({ color={Colors.Primary} onPress={() => { if (item.ArtistItems) { - navigation.goBack(); // Dismiss modal if exists + + if (onNavigate) + onNavigate(); + + navigation.goBack(); navigation.push("Artist", { artist: item.ArtistItems[0] }); diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 55cb3ea2..eac5635d 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -10,7 +10,8 @@ export default function TrackOptions({ navigation } : { item: BaseItemDto, - navigation: NativeStackNavigationProp + navigation: NativeStackNavigationProp, + onNavigate?: () => void | undefined }) : React.JSX.Element { const { data: album, isSuccess } = useItem(item.AlbumId ?? "") diff --git a/components/ItemDetail/screen.tsx b/components/ItemDetail/screen.tsx index 91021ba6..a6cd2fc1 100644 --- a/components/ItemDetail/screen.tsx +++ b/components/ItemDetail/screen.tsx @@ -6,15 +6,18 @@ import React from "react"; export default function DetailsScreen({ route, - navigation + navigation, + onNavigate, } : { route: RouteProp, navigation: NativeStackNavigationProp + onNavigate?: () => void | undefined }) : React.JSX.Element { return ( ) } \ No newline at end of file diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 504a00cc..627ff930 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -132,7 +132,10 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa name="dots-horizontal-circle-outline" onPress={() => { navigation.navigate("Details", { - item: nowPlaying!.item + item: nowPlaying!.item, + onNavigate: () => { + navigation.goBack(); + } }); }} /> diff --git a/components/types.tsx b/components/types.tsx index 749143f6..d8d797ad 100644 --- a/components/types.tsx +++ b/components/types.tsx @@ -34,7 +34,8 @@ export type StackParamList = { playlist: BaseItemDto }; Details: { - item: BaseItemDto + item: BaseItemDto, + onNavigate?: () => void | undefined } } From 3355c612bc1ea57f565404bcc761cf9dd26746ae Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 05:27:45 -0600 Subject: [PATCH 045/107] adjust navigation and item details add long press to track component --- components/Global/components/track.tsx | 15 +++++++--- components/ItemDetail/component.tsx | 28 +++++++++++-------- .../ItemDetail/helpers/TrackOptions.tsx | 21 ++++++++++---- components/ItemDetail/screen.tsx | 4 +-- components/Player/screens/index.tsx | 7 ++--- components/types.tsx | 2 +- 6 files changed, 46 insertions(+), 31 deletions(-) diff --git a/components/Global/components/track.tsx b/components/Global/components/track.tsx index d82bd503..044534b9 100644 --- a/components/Global/components/track.tsx +++ b/components/Global/components/track.tsx @@ -30,7 +30,7 @@ export default function Track({ index, queueName, showArtwork, - onPress + onPress, } : { track: BaseItemDto, tracklist: BaseItemDto[], @@ -38,7 +38,7 @@ export default function Track({ index?: number | undefined, queueName?: string | undefined, showArtwork?: boolean | undefined, - onPress?: () => void | undefined + onPress?: () => void | undefined, }) : React.JSX.Element { const { width } = useSafeAreaFrame(); @@ -64,6 +64,12 @@ export default function Track({ }); } }} + onLongPress={() => { + navigation.push("Details", { + item: track, + isModal: false + }) + }} paddingVertical={"$2"} marginHorizontal={"$1"} > @@ -143,8 +149,9 @@ export default function Track({ > { navigation.push("Details", { - item: track - }) + item: track, + isModal: false + }); }} /> diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 692403d9..f7bf83cf 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -12,11 +12,11 @@ import FavoriteButton from "../Global/components/favorite-button"; export default function ItemDetail({ item, navigation, - onNavigate + isModal = false } : { item: BaseItemDto, navigation: NativeStackNavigationProp, - onNavigate?: () => void | undefined + isModal: boolean }) : React.JSX.Element { let options: React.JSX.Element | undefined = undefined; @@ -25,7 +25,7 @@ export default function ItemDetail({ switch (item.Type) { case "Audio": { - options = TrackOptions({ item, navigation, onNavigate }); + options = TrackOptions({ item, navigation, isModal }); break; } @@ -51,7 +51,7 @@ export default function ItemDetail({ return ( - + @@ -72,13 +72,17 @@ export default function ItemDetail({ onPress={() => { if (item.ArtistItems) { - if (onNavigate) - onNavigate(); + if (isModal) + navigation.navigate("Artist", { + artist: item.ArtistItems[0] + }) - navigation.goBack(); - navigation.push("Artist", { - artist: item.ArtistItems[0] - }); + else { + navigation.goBack(); + navigation.push("Artist", { + artist: item.ArtistItems[0] + }); + } } }}> { item.Artists?.join(", ") ?? "Unknown Artist"} @@ -100,7 +104,7 @@ export default function ItemDetail({ { options ?? } - + ) } \ No newline at end of file diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index eac5635d..6d2030a9 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -7,11 +7,12 @@ import { XStack } from "tamagui"; export default function TrackOptions({ item, - navigation + navigation, + isModal = false, } : { item: BaseItemDto, navigation: NativeStackNavigationProp, - onNavigate?: () => void | undefined + isModal: boolean }) : React.JSX.Element { const { data: album, isSuccess } = useItem(item.AlbumId ?? "") @@ -22,10 +23,18 @@ export default function TrackOptions({ { - navigation.goBack() // Dismiss modal if it exists - navigation.push("Album", { - album - }); + + if (isModal) { + navigation.navigate("Album", { + album + }); + } else { + + navigation.goBack(); + navigation.push("Album", { + album + }); + } }} /> )} diff --git a/components/ItemDetail/screen.tsx b/components/ItemDetail/screen.tsx index a6cd2fc1..a63f3d4e 100644 --- a/components/ItemDetail/screen.tsx +++ b/components/ItemDetail/screen.tsx @@ -7,17 +7,15 @@ import React from "react"; export default function DetailsScreen({ route, navigation, - onNavigate, } : { route: RouteProp, navigation: NativeStackNavigationProp - onNavigate?: () => void | undefined }) : React.JSX.Element { return ( ) } \ No newline at end of file diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 627ff930..d440a488 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -103,8 +103,7 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa color={Colors.Primary} onPress={() => { if (nowPlaying!.item.ArtistItems) { - navigation.goBack(); - navigation.push("Artist", { + navigation.navigate("Artist", { artist: nowPlaying!.item.ArtistItems![0], }); } @@ -133,9 +132,7 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa onPress={() => { navigation.navigate("Details", { item: nowPlaying!.item, - onNavigate: () => { - navigation.goBack(); - } + isModal: true }); }} /> diff --git a/components/types.tsx b/components/types.tsx index d8d797ad..6aaf58a2 100644 --- a/components/types.tsx +++ b/components/types.tsx @@ -35,7 +35,7 @@ export type StackParamList = { }; Details: { item: BaseItemDto, - onNavigate?: () => void | undefined + isModal: boolean } } From 9201deb24b782cb9806eb6bd6573018c3db2f6f5 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 05:39:07 -0600 Subject: [PATCH 046/107] itemdetail stuff --- components/Global/components/track.tsx | 4 +-- components/ItemDetail/component.tsx | 30 +++++++++++-------- .../ItemDetail/helpers/TrackOptions.tsx | 20 +++++-------- components/ItemDetail/screen.tsx | 2 +- components/Player/screens/index.tsx | 2 +- components/types.tsx | 2 +- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/components/Global/components/track.tsx b/components/Global/components/track.tsx index 044534b9..48f71cd1 100644 --- a/components/Global/components/track.tsx +++ b/components/Global/components/track.tsx @@ -67,7 +67,7 @@ export default function Track({ onLongPress={() => { navigation.push("Details", { item: track, - isModal: false + isNested: false }) }} paddingVertical={"$2"} @@ -150,7 +150,7 @@ export default function Track({ { navigation.push("Details", { item: track, - isModal: false + isNested: false }); }} /> diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index f7bf83cf..cb6fa9ce 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -8,24 +8,32 @@ import BlurhashedImage from "../Global/helpers/blurhashed-image"; import { Text } from "../Global/helpers/text"; import { Colors } from "../../enums/colors"; import FavoriteButton from "../Global/components/favorite-button"; +import { useEffect } from "react"; +import { trigger } from "react-native-haptic-feedback"; export default function ItemDetail({ item, navigation, - isModal = false + isNested } : { item: BaseItemDto, navigation: NativeStackNavigationProp, - isModal: boolean + isNested?: boolean | undefined }) : React.JSX.Element { let options: React.JSX.Element | undefined = undefined; + useEffect(() => { + trigger("impactMedium"); + }, [ + item + ]); + const { width } = useSafeAreaFrame(); switch (item.Type) { case "Audio": { - options = TrackOptions({ item, navigation, isModal }); + options = TrackOptions({ item, navigation, isNested }); break; } @@ -72,17 +80,13 @@ export default function ItemDetail({ onPress={() => { if (item.ArtistItems) { - if (isModal) - navigation.navigate("Artist", { - artist: item.ArtistItems[0] - }) - - else { + if (isNested) navigation.goBack(); - navigation.push("Artist", { - artist: item.ArtistItems[0] - }); - } + + navigation.goBack(); + navigation.push("Artist", { + artist: item.ArtistItems[0] + }); } }}> { item.Artists?.join(", ") ?? "Unknown Artist"} diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 6d2030a9..24eccab1 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -8,11 +8,11 @@ import { XStack } from "tamagui"; export default function TrackOptions({ item, navigation, - isModal = false, + isNested } : { item: BaseItemDto, navigation: NativeStackNavigationProp, - isModal: boolean + isNested: boolean | undefined// Whether this is nested in the player modal }) : React.JSX.Element { const { data: album, isSuccess } = useItem(item.AlbumId ?? "") @@ -24,17 +24,13 @@ export default function TrackOptions({ name="music-box" onPress={() => { - if (isModal) { - navigation.navigate("Album", { - album - }); - } else { - + if (isNested) navigation.goBack(); - navigation.push("Album", { - album - }); - } + + navigation.goBack(); + navigation.push("Album", { + album + }); }} /> )} diff --git a/components/ItemDetail/screen.tsx b/components/ItemDetail/screen.tsx index a63f3d4e..76ff7428 100644 --- a/components/ItemDetail/screen.tsx +++ b/components/ItemDetail/screen.tsx @@ -15,7 +15,7 @@ export default function DetailsScreen({ ) } \ No newline at end of file diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index d440a488..ea85d4d1 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -132,7 +132,7 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa onPress={() => { navigation.navigate("Details", { item: nowPlaying!.item, - isModal: true + isNested: true }); }} /> diff --git a/components/types.tsx b/components/types.tsx index 6aaf58a2..7e5d35bd 100644 --- a/components/types.tsx +++ b/components/types.tsx @@ -35,7 +35,7 @@ export type StackParamList = { }; Details: { item: BaseItemDto, - isModal: boolean + isNested: boolean | undefined } } From d9bdd05a28152584deb83fadeee00d228b561586 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:12:50 -0600 Subject: [PATCH 047/107] Adding the crudest search functionality --- api/queries/functions/search.ts | 39 ++++++++++++ api/queries/functions/suggestions.ts | 90 ++++++++++++++++++++++++++++ api/queries/search.ts | 8 +++ api/queries/suggestions.ts | 8 +++ components/Search/component.tsx | 37 ++++++++++-- enums/query-keys.ts | 2 + 6 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 api/queries/functions/search.ts create mode 100644 api/queries/functions/suggestions.ts create mode 100644 api/queries/search.ts create mode 100644 api/queries/suggestions.ts diff --git a/api/queries/functions/search.ts b/api/queries/functions/search.ts new file mode 100644 index 00000000..84a146d1 --- /dev/null +++ b/api/queries/functions/search.ts @@ -0,0 +1,39 @@ +import Client from "../../../api/client"; +import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; +import { getItemsApi } from "@jellyfin/sdk/lib/utils/api"; +import { isEmpty, trim } from "lodash"; + +/** + * Performs a search for items against the Jellyfin server, trimming whitespace + * around the search term for the best possible results. + * @param searchString The search term to look up against + * @returns A promise of a BaseItemDto array, be it empty or not + */ +export async function search(searchString: string | undefined) : Promise { + return new Promise((resolve, reject) => { + + if (isEmpty(searchString)) + resolve([]); + + getItemsApi(Client.api!) + .getItems({ + searchTerm: trim(searchString), + recursive: true, + includeItemTypes: [ + 'Audio', + 'MusicAlbum', + 'MusicArtist', + 'Playlist' + ] + }) + .then((response) => { + if (response.data.Items) + resolve(response.data.Items) + else + resolve([]); + }) + .catch((error) => { + reject(error) + }); + }) +} \ No newline at end of file diff --git a/api/queries/functions/suggestions.ts b/api/queries/functions/suggestions.ts new file mode 100644 index 00000000..d088947e --- /dev/null +++ b/api/queries/functions/suggestions.ts @@ -0,0 +1,90 @@ +import Client from "../../../api/client"; +import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; +import { getSuggestionsApi } from "@jellyfin/sdk/lib/utils/api"; + +export async function fetchSearchSuggestions() : Promise { + return new Promise((resolve, reject) => { + getSuggestionsApi(Client.api!) + .getSuggestions({ + userId: Client.user!.id, + type: [ + 'MusicArtist', + 'MusicAlbum', + 'Audio', + 'Playlist' + ] + }) + .then((response) => { + if (response.data.Items) + resolve(response.data.Items) + else + resolve([]); + }) + .catch((error) => { + reject(error); + }) + }) +} + +export async function fetchSuggestedArtists() : Promise { + return new Promise((resolve, reject) => { + getSuggestionsApi(Client.api!) + .getSuggestions({ + userId: Client.user!.id, + type: [ + 'MusicArtist' + ] + }) + .then((response) => { + if (response.data.Items) + resolve(response.data.Items) + else + resolve([]); + }) + .catch((error) => { + reject(error); + }) + }) +} + +export async function fetchSuggestedAlbums() : Promise { + return new Promise((resolve, reject) => { + getSuggestionsApi(Client.api!) + .getSuggestions({ + userId: Client.user!.id, + type: [ + 'MusicAlbum' + ] + }) + .then((response) => { + if (response.data.Items) + resolve(response.data.Items) + else + resolve([]); + }) + .catch((error) => { + reject(error); + }) + }) +} + +export async function fetchSuggestedTracks() : Promise { + return new Promise((resolve, reject) => { + getSuggestionsApi(Client.api!) + .getSuggestions({ + userId: Client.user!.id, + type: [ + 'Audio' + ] + }) + .then((response) => { + if (response.data.Items) + resolve(response.data.Items) + else + resolve([]); + }) + .catch((error) => { + reject(error); + }) + }) +} \ No newline at end of file diff --git a/api/queries/search.ts b/api/queries/search.ts new file mode 100644 index 00000000..1ec0c89e --- /dev/null +++ b/api/queries/search.ts @@ -0,0 +1,8 @@ +import { QueryKeys } from "../../enums/query-keys"; +import { useQuery } from "@tanstack/react-query"; +import { search } from "./functions/search"; + +export const useSearch = (searchString: string | undefined) => useQuery({ + queryKey: [QueryKeys.Search, searchString], + queryFn: () => search(searchString) +}) \ No newline at end of file diff --git a/api/queries/suggestions.ts b/api/queries/suggestions.ts new file mode 100644 index 00000000..64f1297b --- /dev/null +++ b/api/queries/suggestions.ts @@ -0,0 +1,8 @@ +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() +}) \ No newline at end of file diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 5b34a020..98dd3b48 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -1,10 +1,37 @@ -import React from "react"; -import { View } from "tamagui"; +import React, { useEffect, useState } from "react"; +import { SafeAreaView } from "react-native-safe-area-context"; +import Input from "../Global/helpers/input"; +import { debounce } from "lodash"; +import { useSearch } from "../../api/queries/search"; +import { Text } from "../Global/helpers/text"; export default function Search(): React.JSX.Element { + + const [searchString, setSearchString] = useState(undefined); + + const { data: items, refetch } = useSearch(searchString) + + useEffect(() => { + debounce(() => { + refetch() + }, 500) + }, [ + searchString + ]) + return ( - - - + + setSearchString(value)} + value={searchString} + /> + + { items?.map(item => { + return ( + { item.Name ?? "" } + ) + })} + ) } \ No newline at end of file diff --git a/enums/query-keys.ts b/enums/query-keys.ts index 16fa18cf..b90fa46c 100644 --- a/enums/query-keys.ts +++ b/enums/query-keys.ts @@ -36,4 +36,6 @@ export enum QueryKeys { UserData = "UserData", UpdatePlayerOptions = "UpdatePlayerOptions", Item = "Item", + Search = "Search", + SearchSuggestions = "SearchSuggestions", } \ No newline at end of file From 099b73394c1e4388154161bd6befab1cf7135a64 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:26:51 -0600 Subject: [PATCH 048/107] kk crudest search ever just got less crude --- components/Global/components/item.tsx | 65 +++++++++++++++++++++++++++ components/Search/component.tsx | 12 +++-- 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 components/Global/components/item.tsx diff --git a/components/Global/components/item.tsx b/components/Global/components/item.tsx new file mode 100644 index 00000000..809a427f --- /dev/null +++ b/components/Global/components/item.tsx @@ -0,0 +1,65 @@ +import { usePlayerContext } from "../../../player/provider"; +import { StackParamList } from "../../../components/types"; +import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; +import { NativeStackNavigationProp } from "@react-navigation/native-stack"; +import { Separator, View, XStack } from "tamagui"; +import { Text } from "../helpers/text"; + +export default function Item({ + item, + queueName, + navigation, +} : { + item: BaseItemDto, + queueName: string, + navigation: NativeStackNavigationProp +}) : React.JSX.Element { + + const { usePlayNewQueue } = usePlayerContext(); + + return ( + + + + { + switch (item.Type) { + case ("MusicArtist") : { + navigation.push("Artist", { + artist: item + }) + break; + } + + case ("MusicAlbum") : { + navigation.push("Album", { + album: item + }) + break; + } + + case ("Audio") : { + usePlayNewQueue.mutate({ + track: item, + tracklist: [item], + queueName + }) + break; + } + } + + }} + onLongPress={() => { + navigation.push("Details", { + item, + isNested: false + }) + }} + > + { item.Name ?? ""} + + + ) +} \ No newline at end of file diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 98dd3b48..f831ee9b 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -3,9 +3,15 @@ import { SafeAreaView } from "react-native-safe-area-context"; import Input from "../Global/helpers/input"; import { debounce } from "lodash"; import { useSearch } from "../../api/queries/search"; -import { Text } from "../Global/helpers/text"; +import Item from "../Global/components/item"; +import { NativeStackNavigationProp } from "@react-navigation/native-stack"; +import { StackParamList } from "../types"; -export default function Search(): React.JSX.Element { +export default function Search({ + navigation + }: { + navigation: NativeStackNavigationProp +}): React.JSX.Element { const [searchString, setSearchString] = useState(undefined); @@ -29,7 +35,7 @@ export default function Search(): React.JSX.Element { { items?.map(item => { return ( - { item.Name ?? "" } + ) })} From 9fa227d014e7492ae77e14d844cadfb05693ee53 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:32:39 -0600 Subject: [PATCH 049/107] make search great again --- components/Global/components/item.tsx | 20 +++++++++++++++++++- components/Search/component.tsx | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/components/Global/components/item.tsx b/components/Global/components/item.tsx index 809a427f..53c66b0e 100644 --- a/components/Global/components/item.tsx +++ b/components/Global/components/item.tsx @@ -2,8 +2,12 @@ import { usePlayerContext } from "../../../player/provider"; import { StackParamList } from "../../../components/types"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -import { Separator, View, XStack } from "tamagui"; +import { Separator, Spacer, View, XStack } from "tamagui"; import { Text } from "../helpers/text"; +import { useSafeAreaFrame } from "react-native-safe-area-context"; +import BlurhashedImage from "../helpers/blurhashed-image"; +import Icon from "../helpers/icon"; +import { Colors } from "../../../enums/colors"; export default function Item({ item, @@ -17,6 +21,8 @@ export default function Item({ const { usePlayNewQueue } = usePlayerContext(); + const { width } = useSafeAreaFrame(); + return ( @@ -24,6 +30,7 @@ export default function Item({ { switch (item.Type) { case ("MusicArtist") : { @@ -58,7 +65,18 @@ export default function Item({ }) }} > + { item.Name ?? ""} + + { item.UserData?.IsFavorite ? ( + + ) : ( + + )} ) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index f831ee9b..3c7c16ef 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -20,7 +20,7 @@ export default function Search({ useEffect(() => { debounce(() => { refetch() - }, 500) + }, 750) }, [ searchString ]) From 1aca2b83144b220cc65e34cca607e8db41773c5f Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:39:03 -0600 Subject: [PATCH 050/107] whoa there champ --- api/queries/functions/images.ts | 4 ++-- api/queries/functions/recents.ts | 4 ++-- api/queries/functions/search.ts | 4 +++- api/queries/query.config.ts | 11 ++++++++--- api/queries/tracks.ts | 4 ++-- components/Album/component.tsx | 4 ++-- components/Artist/component.tsx | 4 ++-- components/Global/components/track.tsx | 4 ++-- components/Global/helpers/item-card.tsx | 6 +++--- components/Player/mini-player.tsx | 4 ++-- components/Playlist/component.tsx | 4 ++-- 11 files changed, 30 insertions(+), 23 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index 66a8797f..40f7f491 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -2,7 +2,7 @@ import { ImageFormat, ImageType } from "@jellyfin/sdk/lib/generated-client/model import { getImageApi } from "@jellyfin/sdk/lib/utils/api" import _ from "lodash" import Client from "../../../api/client" -import { queryConfig } from "../query.config"; +import { QueryConfig } from "../query.config"; export function fetchItemImage(itemId: string, imageType?: ImageType, size?: number) { @@ -10,7 +10,7 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, size?: num .getItemImage({ itemId, imageType: imageType ? imageType : ImageType.Primary, - ...queryConfig.playerArtwork, + ...QueryConfig.playerArtwork, }, { responseType: 'blob' }) diff --git a/api/queries/functions/recents.ts b/api/queries/functions/recents.ts index da382bb8..95d0ddd5 100644 --- a/api/queries/functions/recents.ts +++ b/api/queries/functions/recents.ts @@ -1,6 +1,6 @@ import { BaseItemDto, BaseItemKind, ItemSortBy, SortOrder } from "@jellyfin/sdk/lib/generated-client/models"; import { getItemsApi } from "@jellyfin/sdk/lib/utils/api/items-api"; -import { queryConfig } from "../query.config"; +import { QueryConfig } from "../query.config"; import Client from "../../client"; export function fetchRecentlyPlayed(): Promise { @@ -13,7 +13,7 @@ export function fetchRecentlyPlayed(): Promise { includeItemTypes: [ BaseItemKind.Audio ], - limit: queryConfig.limits.recents, + limit: QueryConfig.limits.recents, parentId: Client.library!.musicLibraryId, recursive: true, sortBy: [ diff --git a/api/queries/functions/search.ts b/api/queries/functions/search.ts index 84a146d1..920d6970 100644 --- a/api/queries/functions/search.ts +++ b/api/queries/functions/search.ts @@ -2,6 +2,7 @@ import Client from "../../../api/client"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { getItemsApi } from "@jellyfin/sdk/lib/utils/api"; import { isEmpty, trim } from "lodash"; +import { QueryConfig } from "../query.config"; /** * Performs a search for items against the Jellyfin server, trimming whitespace @@ -24,7 +25,8 @@ export async function search(searchString: string | undefined) : Promise { if (response.data.Items) diff --git a/api/queries/query.config.ts b/api/queries/query.config.ts index 23812e58..b3720731 100644 --- a/api/queries/query.config.ts +++ b/api/queries/query.config.ts @@ -1,8 +1,9 @@ import { ImageFormat } from "@jellyfin/sdk/lib/generated-client/models"; -export const queryConfig = { +export const QueryConfig = { limits: { - recents: 50 // TODO: Adjust this when we add a list navigator to the end of the recents + recents: 50, // TODO: Adjust this when we add a list navigator to the end of the recents + search: 25, }, images: { height: 300, @@ -24,5 +25,9 @@ export const queryConfig = { width: 1000, format: ImageFormat.Jpg }, - staleTime: 1000 * 60 * 60 * 24 // 1 Day + staleTime: { + oneDay: 1000 * 60 * 60 * 24, // 1 Day + oneWeek: 1000 * 60 * 60 * 24 * 7, // 7 Days + oneFortnight: 1000 * 60 * 60 * 24 * 7 * 14 // 14 Days + } } \ No newline at end of file diff --git a/api/queries/tracks.ts b/api/queries/tracks.ts index a709e638..e1bc3f13 100644 --- a/api/queries/tracks.ts +++ b/api/queries/tracks.ts @@ -2,7 +2,7 @@ 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 { queryConfig } from "./query.config"; +import { QueryConfig } from "./query.config"; import Client from "../client"; export const useItemTracks = (itemId: string, sort: boolean = false) => useQuery({ @@ -29,5 +29,5 @@ export const useItemTracks = (itemId: string, sort: boolean = false) => useQuery return response.data.Items ? response.data.Items! : []; }) }, - staleTime: queryConfig.staleTime + staleTime: QueryConfig.staleTime.oneDay }) \ No newline at end of file diff --git a/components/Album/component.tsx b/components/Album/component.tsx index 2206155f..50bb24f6 100644 --- a/components/Album/component.tsx +++ b/components/Album/component.tsx @@ -4,7 +4,7 @@ import { ScrollView, YStack, XStack } from "tamagui"; import { CachedImage } from "@georstat/react-native-image-cache"; import { getImageApi } from "@jellyfin/sdk/lib/utils/api"; import { BaseItemDto, ImageType } from "@jellyfin/sdk/lib/generated-client/models"; -import { queryConfig } from "../../api/queries/query.config"; +import { QueryConfig } from "../../api/queries/query.config"; import { H4, H5, Text } from "../Global/helpers/text"; import { FlatList } from "react-native"; import { usePlayerContext } from "../../player/provider"; @@ -52,7 +52,7 @@ export default function Album(props: AlbumProps): React.JSX.Element { .getItemImageUrlById( props.album.Id!, ImageType.Primary, - { ...queryConfig.playerArtwork})} + { ...QueryConfig.playerArtwork})} imageStyle={{ position: "relative", width: width / 1.1, diff --git a/components/Artist/component.tsx b/components/Artist/component.tsx index 1de96fdd..fcf8a1bb 100644 --- a/components/Artist/component.tsx +++ b/components/Artist/component.tsx @@ -8,7 +8,7 @@ import { H2 } from "../Global/helpers/text"; import { useState } from "react"; import { CachedImage } from "@georstat/react-native-image-cache"; import { BaseItemDto, ImageType } from "@jellyfin/sdk/lib/generated-client/models"; -import { queryConfig } from "../../api/queries/query.config"; +import { QueryConfig } from "../../api/queries/query.config"; import { getImageApi } from "@jellyfin/sdk/lib/utils/api"; import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context"; import FavoriteButton from "../Global/components/favorite-button"; @@ -48,7 +48,7 @@ export default function Artist(props: ArtistProps): React.JSX.Element { .getItemImageUrlById( props.artist.Id!, ImageType.Primary, - { ...queryConfig.banners}) + { ...QueryConfig.banners}) } imageStyle={{ width: width, diff --git a/components/Global/components/track.tsx b/components/Global/components/track.tsx index 48f71cd1..ce01029c 100644 --- a/components/Global/components/track.tsx +++ b/components/Global/components/track.tsx @@ -7,7 +7,7 @@ import { BaseItemDto, ImageType } from "@jellyfin/sdk/lib/generated-client/model import { Colors } from "../../../enums/colors"; import { CachedImage } from "@georstat/react-native-image-cache"; import { getImageApi } from "@jellyfin/sdk/lib/utils/api/image-api"; -import { queryConfig } from "../../../api/queries/query.config"; +import { QueryConfig } from "../../../api/queries/query.config"; import { useSafeAreaFrame } from "react-native-safe-area-context"; import Icon from "../helpers/icon"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; @@ -85,7 +85,7 @@ export default function Track({ .getItemImageUrlById( track.AlbumId ?? "", ImageType.Primary, - { ...queryConfig.images } + { ...QueryConfig.images } ) } imageStyle={{ diff --git a/components/Global/helpers/item-card.tsx b/components/Global/helpers/item-card.tsx index a46a52c1..d4de7f70 100644 --- a/components/Global/helpers/item-card.tsx +++ b/components/Global/helpers/item-card.tsx @@ -6,7 +6,7 @@ import { ImageType } from "@jellyfin/sdk/lib/generated-client/models"; import { CachedImage } from "@georstat/react-native-image-cache"; import invert from "invert-color" import { Blurhash } from "react-native-blurhash" -import { queryConfig } from "../../../api/queries/query.config"; +import { QueryConfig } from "../../../api/queries/query.config"; import { Text } from "./text"; import Client from "../../../api/client"; @@ -52,7 +52,7 @@ export function ItemCard(props: CardProps) { .getItemImageUrlById( props.itemId, ImageType.Logo, - { ...queryConfig.logos}) + { ...QueryConfig.logos}) } imageStyle={{ ...logoDimensions, @@ -72,7 +72,7 @@ export function ItemCard(props: CardProps) { .getItemImageUrlById( props.itemId, ImageType.Primary, - { ...queryConfig.images}) + { ...QueryConfig.images}) } imageStyle={{ ...dimensions, diff --git a/components/Player/mini-player.tsx b/components/Player/mini-player.tsx index f1d74248..9a0d6a9f 100644 --- a/components/Player/mini-player.tsx +++ b/components/Player/mini-player.tsx @@ -9,7 +9,7 @@ import { Colors } from "../../enums/colors"; import { CachedImage } from "@georstat/react-native-image-cache"; import { ImageType } from "@jellyfin/sdk/lib/generated-client/models"; import { getImageApi } from "@jellyfin/sdk/lib/utils/api"; -import { queryConfig } from "../../api/queries/query.config"; +import { QueryConfig } from "../../api/queries/query.config"; import TextTicker from 'react-native-text-ticker'; import PlayPauseButton from "./helpers/buttons"; import { useSafeAreaFrame } from "react-native-safe-area-context"; @@ -40,7 +40,7 @@ export function Miniplayer({ navigation }: { navigation : NavigationHelpers Date: Fri, 24 Jan 2025 06:42:20 -0600 Subject: [PATCH 051/107] bruh --- components/Search/component.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 3c7c16ef..7bb1a3bd 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -15,7 +15,7 @@ export default function Search({ const [searchString, setSearchString] = useState(undefined); - const { data: items, refetch } = useSearch(searchString) + const { data: items, refetch, isFetched, isFetching } = useSearch(searchString) useEffect(() => { debounce(() => { @@ -33,7 +33,7 @@ export default function Search({ value={searchString} /> - { items?.map(item => { + { !isFetching && isFetched && items!.map(item => { return ( ) From b23dd3fe4872249595d554cb0a7153f3d3eb7913 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:42:48 -0600 Subject: [PATCH 052/107] add some logging --- api/queries/functions/search.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/queries/functions/search.ts b/api/queries/functions/search.ts index 920d6970..792f5ea1 100644 --- a/api/queries/functions/search.ts +++ b/api/queries/functions/search.ts @@ -13,6 +13,8 @@ import { QueryConfig } from "../query.config"; export async function search(searchString: string | undefined) : Promise { return new Promise((resolve, reject) => { + console.debug("Searching Jellyfin for items") + if (isEmpty(searchString)) resolve([]); From 85ca9e83240ca36b1e71b2529c9431423980fbb0 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:47:34 -0600 Subject: [PATCH 053/107] make this actually usable --- components/Search/component.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 7bb1a3bd..910c0c90 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -6,6 +6,8 @@ import { useSearch } from "../../api/queries/search"; import Item from "../Global/components/item"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { StackParamList } from "../types"; +import { ScrollView } from "tamagui"; +import { FlatList } from "react-native"; export default function Search({ navigation @@ -33,11 +35,16 @@ export default function Search({ value={searchString} /> - { !isFetching && isFetched && items!.map(item => { - return ( - - ) - })} + { !isFetching && isFetched && ( + { + return ( + + ) + }} + /> + )} ) } \ No newline at end of file From 9e2c81870f8c9a3636999dfd2f3273447f553143 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:56:11 -0600 Subject: [PATCH 054/107] Add screens to search stack --- components/Home/component.tsx | 2 +- components/Search/screen.tsx | 17 +++++++++ components/Search/stack.tsx | 70 +++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/components/Home/component.tsx b/components/Home/component.tsx index a7f48c5c..9a716760 100644 --- a/components/Home/component.tsx +++ b/components/Home/component.tsx @@ -72,7 +72,7 @@ export default function Home(): React.JSX.Element { headerShown: false, presentation: "modal" }} - /> + /> diff --git a/components/Search/screen.tsx b/components/Search/screen.tsx index e69de29b..75901698 100644 --- a/components/Search/screen.tsx +++ b/components/Search/screen.tsx @@ -0,0 +1,17 @@ +import { RouteProp } from "@react-navigation/native"; +import { StackParamList } from "../types"; +import { NativeStackNavigationProp } from "@react-navigation/native-stack"; +import React from "react"; +import Search from "./component"; + +export default function SearchScreen({ + route, + navigation +} : { + route: RouteProp, + navigation: NativeStackNavigationProp +}) : React.JSX.Element { + return ( + + ) +} \ No newline at end of file diff --git a/components/Search/stack.tsx b/components/Search/stack.tsx index e69de29b..4d172cda 100644 --- a/components/Search/stack.tsx +++ b/components/Search/stack.tsx @@ -0,0 +1,70 @@ +import { createNativeStackNavigator } from "@react-navigation/native-stack" +import SearchScreen from "./screen"; +import { StackParamList } from "../types"; +import { ArtistScreen } from "../Artist/screens"; +import { AlbumScreen } from "../Album/screens"; +import { PlaylistScreen } from "../Playlist/screens"; +import DetailsScreen from "../ItemDetail/screen"; + +const Stack = createNativeStackNavigator(); + +export default function SearchStack() : React.JSX.Element { + return ( + + + + + ({ + title: route.params.artist.Name ?? "Unknown Artist", + headerLargeTitle: true, + headerLargeTitleStyle: { + fontFamily: 'Aileron-Bold' + } + })} + /> + + ({ + headerShown: true, + headerTitle: "" + })} + /> + + ({ + headerShown: true, + headerTitle: "" + })} + /> + + + + + + + + ) +} \ No newline at end of file From c74e7168d6da3731cbcf7a19e6aa65b7ccd57f84 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 06:59:20 -0600 Subject: [PATCH 055/107] This should render the stack, not the component --- components/Search/stack.tsx | 5 ++++- components/tabs.tsx | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/components/Search/stack.tsx b/components/Search/stack.tsx index 4d172cda..11abc9a7 100644 --- a/components/Search/stack.tsx +++ b/components/Search/stack.tsx @@ -10,7 +10,10 @@ const Stack = createNativeStackNavigator(); export default function SearchStack() : React.JSX.Element { return ( - + ( From aabe229376e4e7f84dedb4b894c6fad46d405221 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 07:00:00 -0600 Subject: [PATCH 056/107] hide tab screen header since it'll be redundant --- components/tabs.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/tabs.tsx b/components/tabs.tsx index c4c4e8e3..2e9cfef4 100644 --- a/components/tabs.tsx +++ b/components/tabs.tsx @@ -65,6 +65,7 @@ export function Tabs() : React.JSX.Element { name="Search" component={SearchStack} options={{ + headerShown: false, tabBarIcon: ({color, size }) => ( ) From e4cab2207224c89429f326bb449ffa0f0facfd59 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 07:06:48 -0600 Subject: [PATCH 057/107] make this just a flatlist --- components/Global/components/item.tsx | 12 ++++++++-- components/Search/component.tsx | 34 ++++++++++++++------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/components/Global/components/item.tsx b/components/Global/components/item.tsx index 53c66b0e..8048b43e 100644 --- a/components/Global/components/item.tsx +++ b/components/Global/components/item.tsx @@ -2,7 +2,7 @@ import { usePlayerContext } from "../../../player/provider"; import { StackParamList } from "../../../components/types"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -import { Separator, Spacer, View, XStack } from "tamagui"; +import { Separator, Spacer, View, XStack, YStack } from "tamagui"; import { Text } from "../helpers/text"; import { useSafeAreaFrame } from "react-native-safe-area-context"; import BlurhashedImage from "../helpers/blurhashed-image"; @@ -66,7 +66,15 @@ export default function Item({ }} > - { item.Name ?? ""} + + + { item.Name ?? ""} + { item.Type === 'Audio' || item.Type === 'MusicAlbum' ? ( + { item.AlbumArtist ?? "Untitled Artist" } + ) : ( + + )} + { item.UserData?.IsFavorite ? ( - setSearchString(value)} - value={searchString} + { + return ( + setSearchString(value)} + value={searchString} + /> + ) + }} + data={items} + refreshing={isFetching} + renderItem={({ index, item }) => { + return ( + + ) + }} /> - - { !isFetching && isFetched && ( - { - return ( - - ) - }} - /> - )} ) } \ No newline at end of file From f72e74e1bf2289c355b4de3ba2b15901b3f83932 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 07:12:55 -0600 Subject: [PATCH 058/107] plz --- components/Search/component.tsx | 14 +++++--------- components/Search/stack.tsx | 3 +-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index c3658c55..a93d62c1 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -28,17 +28,13 @@ export default function Search({ return ( + setSearchString(value)} + value={searchString} + /> { - return ( - setSearchString(value)} - value={searchString} - /> - ) - }} data={items} refreshing={isFetching} renderItem={({ index, item }) => { diff --git a/components/Search/stack.tsx b/components/Search/stack.tsx index 11abc9a7..e364dc05 100644 --- a/components/Search/stack.tsx +++ b/components/Search/stack.tsx @@ -12,8 +12,7 @@ export default function SearchStack() : React.JSX.Element { return ( + > Date: Fri, 24 Jan 2025 07:27:18 -0600 Subject: [PATCH 059/107] maybe? --- components/Search/component.tsx | 2 +- components/Search/stack.tsx | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index a93d62c1..01370d39 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -27,7 +27,7 @@ export default function Search({ ]) return ( - + setSearchString(value)} diff --git a/components/Search/stack.tsx b/components/Search/stack.tsx index e364dc05..aad8fee9 100644 --- a/components/Search/stack.tsx +++ b/components/Search/stack.tsx @@ -13,18 +13,18 @@ export default function SearchStack() : React.JSX.Element { - - + + Date: Fri, 24 Jan 2025 07:29:54 -0600 Subject: [PATCH 060/107] maybe maybe? --- components/Search/stack.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/Search/stack.tsx b/components/Search/stack.tsx index aad8fee9..a180b82d 100644 --- a/components/Search/stack.tsx +++ b/components/Search/stack.tsx @@ -13,7 +13,6 @@ export default function SearchStack() : React.JSX.Element { - - - - - ) } \ No newline at end of file From 1ed0b945c753205eeaffed772985f43ed1e5ea92 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 07:32:54 -0600 Subject: [PATCH 061/107] idfk --- components/Search/component.tsx | 37 +++++++++++++++++---------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 01370d39..f0a3fbd7 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useState } from "react"; -import { SafeAreaView } from "react-native-safe-area-context"; import Input from "../Global/helpers/input"; import { debounce } from "lodash"; import { useSearch } from "../../api/queries/search"; @@ -27,22 +26,24 @@ export default function Search({ ]) return ( - - setSearchString(value)} - value={searchString} - /> - { - return ( - - ) - }} - /> - + { + return ( + setSearchString(value)} + value={searchString} + /> + ) + }} + data={items} + refreshing={isFetching} + renderItem={({ index, item }) => { + return ( + + ) + }} + /> ) } \ No newline at end of file From 4ca659d60c8340e0e27bc0660b4d41fa7908c83f Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 07:39:36 -0600 Subject: [PATCH 062/107] debounce better --- components/Search/component.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index f0a3fbd7..a1079404 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import Input from "../Global/helpers/input"; import { debounce } from "lodash"; import { useSearch } from "../../api/queries/search"; @@ -17,10 +17,15 @@ export default function Search({ const { data: items, refetch, isFetched, isFetching } = useSearch(searchString) - useEffect(() => { + const search = useCallback( debounce(() => { - refetch() - }, 750) + refetch(); + }, 750), + [] + ); + + useEffect(() => { + search(); }, [ searchString ]) From 64608bdccc61f044f32520124eaf4793caa48f1f Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 07:42:21 -0600 Subject: [PATCH 063/107] don't I just want this? --- components/Search/component.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index a1079404..501a9d06 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -17,12 +17,9 @@ export default function Search({ const { data: items, refetch, isFetched, isFetching } = useSearch(searchString) - const search = useCallback( - debounce(() => { + const search = debounce(() => { refetch(); - }, 750), - [] - ); + }, 750); useEffect(() => { search(); From d2739fa13873a6012d5549e417e24a0f18eb619c Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 07:46:08 -0600 Subject: [PATCH 064/107] I don't think this is gonna fix it but I'm gonna try anyways --- components/Global/components/item.tsx | 14 ++++++++------ components/Search/component.tsx | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/components/Global/components/item.tsx b/components/Global/components/item.tsx index 8048b43e..a02752c9 100644 --- a/components/Global/components/item.tsx +++ b/components/Global/components/item.tsx @@ -76,15 +76,17 @@ export default function Item({ )} - { item.UserData?.IsFavorite ? ( - + { item.UserData?.IsFavorite ? ( + - ) : ( - - )} + /> + ) : ( + + )} + ) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 501a9d06..92ff4eec 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -17,15 +17,17 @@ export default function Search({ const { data: items, refetch, isFetched, isFetching } = useSearch(searchString) - const search = debounce(() => { + const search = useCallback( + debounce(() => { refetch(); - }, 750); + }, 750), + [] + ); - useEffect(() => { + const handleSearchStringUpdate = (value: string | undefined) => { + setSearchString(value) search(); - }, [ - searchString - ]) + } return ( Date: Fri, 24 Jan 2025 07:47:50 -0600 Subject: [PATCH 065/107] I need this tho --- components/Global/helpers/input.tsx | 4 ++-- components/Search/component.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/Global/helpers/input.tsx b/components/Global/helpers/input.tsx index a95368fd..897fbcdd 100644 --- a/components/Global/helpers/input.tsx +++ b/components/Global/helpers/input.tsx @@ -1,9 +1,9 @@ import { Colors } from '../../../enums/colors'; -import React, { SetStateAction } from 'react'; +import React from 'react'; import { Input as TamaguiInput} from 'tamagui'; interface InputProps { - onChangeText: React.Dispatch>, + onChangeText: (value: string | undefined) => void, placeholder: string value: string | undefined; secureTextEntry?: boolean | undefined; diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 92ff4eec..81f6e7d2 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -36,7 +36,7 @@ export default function Search({ return ( setSearchString(value)} + onChangeText={(value) => handleSearchStringUpdate(value)} value={searchString} /> ) From 7c34289e3a6860f59416219651082f0a36ea79a1 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 21:38:18 -0600 Subject: [PATCH 066/107] does that fix the keyboard disappearing? --- api/queries/functions/search.ts | 2 +- api/queries/search.ts | 8 -------- components/Search/component.tsx | 12 ++++++++---- 3 files changed, 9 insertions(+), 13 deletions(-) delete mode 100644 api/queries/search.ts diff --git a/api/queries/functions/search.ts b/api/queries/functions/search.ts index 792f5ea1..fa49ce01 100644 --- a/api/queries/functions/search.ts +++ b/api/queries/functions/search.ts @@ -10,7 +10,7 @@ import { QueryConfig } from "../query.config"; * @param searchString The search term to look up against * @returns A promise of a BaseItemDto array, be it empty or not */ -export async function search(searchString: string | undefined) : Promise { +export async function fetchSearchResults(searchString: string | undefined) : Promise { return new Promise((resolve, reject) => { console.debug("Searching Jellyfin for items") diff --git a/api/queries/search.ts b/api/queries/search.ts deleted file mode 100644 index 1ec0c89e..00000000 --- a/api/queries/search.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { QueryKeys } from "../../enums/query-keys"; -import { useQuery } from "@tanstack/react-query"; -import { search } from "./functions/search"; - -export const useSearch = (searchString: string | undefined) => useQuery({ - queryKey: [QueryKeys.Search, searchString], - queryFn: () => search(searchString) -}) \ No newline at end of file diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 81f6e7d2..575b7910 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -1,11 +1,13 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useState } from "react"; import Input from "../Global/helpers/input"; import { debounce } from "lodash"; -import { useSearch } from "../../api/queries/search"; import Item from "../Global/components/item"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { StackParamList } from "../types"; import { FlatList } from "react-native"; +import { QueryKeys } from "../../enums/query-keys"; +import { fetchSearchResults } from "@/api/queries/functions/search"; +import { useQuery } from "@tanstack/react-query"; export default function Search({ navigation @@ -15,7 +17,10 @@ export default function Search({ const [searchString, setSearchString] = useState(undefined); - const { data: items, refetch, isFetched, isFetching } = useSearch(searchString) + const { data: items, refetch, isFetched, isFetching } = useQuery({ + queryKey: [QueryKeys.Search, searchString], + queryFn: () => fetchSearchResults(searchString) + }) const search = useCallback( debounce(() => { @@ -42,7 +47,6 @@ export default function Search({ ) }} data={items} - refreshing={isFetching} renderItem={({ index, item }) => { return ( From b9ad1b1df705ab73b702d95715a3d9128593c7bc Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 21:39:38 -0600 Subject: [PATCH 067/107] build --- components/Search/component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 575b7910..3a1fff98 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -6,7 +6,7 @@ import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { StackParamList } from "../types"; import { FlatList } from "react-native"; import { QueryKeys } from "../../enums/query-keys"; -import { fetchSearchResults } from "@/api/queries/functions/search"; +import { fetchSearchResults } from "../../api/queries/functions/search"; import { useQuery } from "@tanstack/react-query"; export default function Search({ From bdb81db108550971d475e15c594f6c417407c7d7 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 21:42:28 -0600 Subject: [PATCH 068/107] update search component ENTIRELY --- components/Search/component.tsx | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 3a1fff98..f15e3204 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -8,6 +8,7 @@ import { FlatList } from "react-native"; import { QueryKeys } from "../../enums/query-keys"; import { fetchSearchResults } from "../../api/queries/functions/search"; import { useQuery } from "@tanstack/react-query"; +import { SafeAreaView } from "react-native-safe-area-context"; export default function Search({ navigation @@ -35,23 +36,22 @@ export default function Search({ } return ( - { - return ( - handleSearchStringUpdate(value)} - value={searchString} - /> - ) - }} - data={items} - renderItem={({ index, item }) => { - return ( - - ) - }} - /> + + handleSearchStringUpdate(value)} + value={searchString} + /> + + { + return ( + + ) + }} + /> + ) } \ No newline at end of file From b78b4b63a45207c7f301b05d68ca85179806efc7 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 21:45:54 -0600 Subject: [PATCH 069/107] navigation on track when in queue screen --- components/Global/components/track.tsx | 7 +++++-- components/Player/screens/queue.tsx | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/components/Global/components/track.tsx b/components/Global/components/track.tsx index ce01029c..a442b099 100644 --- a/components/Global/components/track.tsx +++ b/components/Global/components/track.tsx @@ -21,6 +21,7 @@ interface TrackProps { index: number | undefined; showArtwork?: boolean | undefined; onPress?: () => void | undefined; + isNested?: boolean | undefined } export default function Track({ @@ -31,6 +32,7 @@ export default function Track({ queueName, showArtwork, onPress, + isNested } : { track: BaseItemDto, tracklist: BaseItemDto[], @@ -39,6 +41,7 @@ export default function Track({ queueName?: string | undefined, showArtwork?: boolean | undefined, onPress?: () => void | undefined, + isNested?: boolean | undefined }) : React.JSX.Element { const { width } = useSafeAreaFrame(); @@ -67,7 +70,7 @@ export default function Track({ onLongPress={() => { navigation.push("Details", { item: track, - isNested: false + isNested: isNested }) }} paddingVertical={"$2"} @@ -150,7 +153,7 @@ export default function Track({ { navigation.push("Details", { item: track, - isNested: false + isNested: isNested }); }} /> diff --git a/components/Player/screens/queue.tsx b/components/Player/screens/queue.tsx index a5ec9117..7a466469 100644 --- a/components/Player/screens/queue.tsx +++ b/components/Player/screens/queue.tsx @@ -34,6 +34,7 @@ export default function Queue({ navigation }: { navigation: NativeStackNavigatio console.debug(`Skipping to index ${index}`) useSkip.mutate(index); }} + isNested /> ) }} From 0b686ea6423009289b9561bd9de72e67a5f36328 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 21:52:29 -0600 Subject: [PATCH 070/107] nice preventing rerenders --- components/Search/component.tsx | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index f15e3204..e5803fc5 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -8,7 +8,6 @@ import { FlatList } from "react-native"; import { QueryKeys } from "../../enums/query-keys"; import { fetchSearchResults } from "../../api/queries/functions/search"; import { useQuery } from "@tanstack/react-query"; -import { SafeAreaView } from "react-native-safe-area-context"; export default function Search({ navigation @@ -36,22 +35,21 @@ export default function Search({ } return ( - - handleSearchStringUpdate(value)} - value={searchString} - /> - - { - return ( - - ) - }} + handleSearchStringUpdate(value)} + value={searchString} /> - + )} + data={items} + renderItem={({ index, item }) => { + return ( + + ) + }} + /> ) } \ No newline at end of file From 67bb22d5d9c5012914846793c73250ca54bf22c3 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 22:01:05 -0600 Subject: [PATCH 071/107] stuff --- components/ItemDetail/component.tsx | 2 +- components/Search/component.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index cb6fa9ce..2c15b6fc 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -81,7 +81,7 @@ export default function ItemDetail({ if (item.ArtistItems) { if (isNested) - navigation.goBack(); + navigation.getParent()!.goBack(); navigation.goBack(); navigation.push("Artist", { diff --git a/components/Search/component.tsx b/components/Search/component.tsx index e5803fc5..52d4a5b5 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -45,6 +45,7 @@ export default function Search({ /> )} data={items} + refreshing={isFetching} renderItem={({ index, item }) => { return ( From b5fa4da606fb0ca5e56834c974da30b4828979c5 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 22:18:49 -0600 Subject: [PATCH 072/107] Make the flatlist render faster? --- api/queries/functions/images.ts | 3 ++- components/Global/helpers/blurhashed-image.tsx | 2 +- components/ItemDetail/helpers/TrackOptions.tsx | 2 +- components/Search/component.tsx | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/api/queries/functions/images.ts b/api/queries/functions/images.ts index 40f7f491..ee7cdd7b 100644 --- a/api/queries/functions/images.ts +++ b/api/queries/functions/images.ts @@ -10,7 +10,8 @@ export function fetchItemImage(itemId: string, imageType?: ImageType, size?: num .getItemImage({ itemId, imageType: imageType ? imageType : ImageType.Primary, - ...QueryConfig.playerArtwork, + width: size ?? QueryConfig.playerArtwork.width, + height: size ?? QueryConfig.playerArtwork.height }, { responseType: 'blob' }) diff --git a/components/Global/helpers/blurhashed-image.tsx b/components/Global/helpers/blurhashed-image.tsx index 2ee0be01..f433d45c 100644 --- a/components/Global/helpers/blurhashed-image.tsx +++ b/components/Global/helpers/blurhashed-image.tsx @@ -11,7 +11,7 @@ interface BlurhashLoadingProps { export default function BlurhashedImage({ item, size, type }: { item: BaseItemDto, size: number, type?: ImageType }) : React.JSX.Element { - const { data: image, isSuccess } = useItemImage(item.Id!, type); + const { data: image, isSuccess } = useItemImage(item.Id!, type, size); const blurhash = !isEmpty(item.ImageBlurHashes) && !isEmpty(item.ImageBlurHashes.Primary) diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 24eccab1..c86daa0b 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -25,7 +25,7 @@ export default function TrackOptions({ onPress={() => { if (isNested) - navigation.goBack(); + navigation.getParent()!.goBack(); navigation.goBack(); navigation.push("Album", { diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 52d4a5b5..26d773fa 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -4,10 +4,10 @@ import { debounce } from "lodash"; import Item from "../Global/components/item"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { StackParamList } from "../types"; -import { FlatList } from "react-native"; import { QueryKeys } from "../../enums/query-keys"; import { fetchSearchResults } from "../../api/queries/functions/search"; import { useQuery } from "@tanstack/react-query"; +import { FlatList } from "react-native/Libraries/Lists/FlatList"; export default function Search({ navigation From 30e1c38a5e25a8fa02f60dbff57cfbdbf664edbc Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 22:21:58 -0600 Subject: [PATCH 073/107] bruh --- components/Search/component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index 26d773fa..a0bc859c 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -7,7 +7,7 @@ import { StackParamList } from "../types"; import { QueryKeys } from "../../enums/query-keys"; import { fetchSearchResults } from "../../api/queries/functions/search"; import { useQuery } from "@tanstack/react-query"; -import { FlatList } from "react-native/Libraries/Lists/FlatList"; +import { FlatList } from "react-native"; export default function Search({ navigation From d94f50ff71bd837c7b69de7f68bd431e66b2da15 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 22:26:22 -0600 Subject: [PATCH 074/107] Show clear text button --- components/Global/helpers/input.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/Global/helpers/input.tsx b/components/Global/helpers/input.tsx index 897fbcdd..9f3d1cc8 100644 --- a/components/Global/helpers/input.tsx +++ b/components/Global/helpers/input.tsx @@ -21,6 +21,7 @@ export default function Input(props: InputProps): React.JSX.Element { value={props.value} flexGrow={props.flexGrow ? 1 : "unset"} secureTextEntry={props.secureTextEntry} + clearButtonMode="always" /> ) } \ No newline at end of file From c0e6c849cbdb98a90b862483ae84c31c89714fe9 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 22:28:08 -0600 Subject: [PATCH 075/107] let's see if it still plays audio --- helpers/mappings.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/helpers/mappings.ts b/helpers/mappings.ts index ef08b17a..208d5a11 100644 --- a/helpers/mappings.ts +++ b/helpers/mappings.ts @@ -1,22 +1,19 @@ import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { JellifyTrack } from "../types/JellifyTrack"; import { RatingType, TrackType } from "react-native-track-player"; -import { Api } from "@jellyfin/sdk"; import { QueuingType } from "../enums/queuing-type"; import querystring from "querystring" import { getImageApi } from "@jellyfin/sdk/lib/utils/api"; import Client from "../api/client"; import { isUndefined } from "lodash"; -const container = "opus,mp3,aac,m4a,flac,webma,webm,wav,ogg,mpa,wma"; - // TODO: Make this configurable const transcodingContainer = "m4a"; export function mapDtoToTrack(item: BaseItemDto, queuingType?: QueuingType) : JellifyTrack { const urlParams = { - "Container": container, + "Container": item.Container, "TranscodingContainer": transcodingContainer, "TranscodingProtocol": "hls", "EnableRemoteMedia": true, From d5c95c7c83bf9612af4d1efdd9022ab5bca3519b Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 22:36:07 -0600 Subject: [PATCH 076/107] clean up item search result component --- components/Global/components/item.tsx | 11 ++++++++--- components/Home/screens/index.tsx | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/components/Global/components/item.tsx b/components/Global/components/item.tsx index a02752c9..77809981 100644 --- a/components/Global/components/item.tsx +++ b/components/Global/components/item.tsx @@ -64,11 +64,16 @@ export default function Item({ isNested: false }) }} + paddingVertical={"$2"} + marginHorizontal={"$1"} > - - { item.Name ?? ""} + + { item.Name ?? ""} { item.Type === 'Audio' || item.Type === 'MusicAlbum' ? ( { item.AlbumArtist ?? "Untitled Artist" } ) : ( @@ -76,7 +81,7 @@ export default function Item({ )} - + { item.UserData?.IsFavorite ? ( Date: Fri, 24 Jan 2025 22:55:07 -0600 Subject: [PATCH 077/107] trying to fix carplay --- .../Settings/screens/account-details.tsx | 5 +- components/Settings/screens/root.tsx | 55 ++++++++++--------- components/Settings/stack.tsx | 2 +- components/carplay.tsx | 2 +- components/jellify.tsx | 10 ++-- 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/components/Settings/screens/account-details.tsx b/components/Settings/screens/account-details.tsx index 4e414db6..d68848bc 100644 --- a/components/Settings/screens/account-details.tsx +++ b/components/Settings/screens/account-details.tsx @@ -1,13 +1,14 @@ import { StackParamList } from "../../../components/types"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; +import AccountDetails from "../helpers/account-details"; -export default function AccountDetails({ +export default function AccountDetailsScreen({ navigation } : { navigation: NativeStackNavigationProp }) : React.JSX.Element { return ( - + ) } \ No newline at end of file diff --git a/components/Settings/screens/root.tsx b/components/Settings/screens/root.tsx index 6ac88a84..880095bf 100644 --- a/components/Settings/screens/root.tsx +++ b/components/Settings/screens/root.tsx @@ -6,6 +6,7 @@ import ServerDetails from "../helpers/server-details"; import LibraryDetails from "../helpers/library-details"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { StackParamList } from "../../../components/types"; +import { useSafeAreaFrame } from "react-native-safe-area-context"; export default function Root({ navigation @@ -13,33 +14,33 @@ export default function Root({ navigation: NativeStackNavigationProp }) : React.JSX.Element { - return ( - - - - - { - navigation.push("AccountDetails") - }} - /> - - + const { width } = useSafeAreaFrame(); - - - - - - + return ( + + + + { + navigation.push("AccountDetails") + }} + /> + + + + + + + + ) } \ No newline at end of file diff --git a/components/Settings/stack.tsx b/components/Settings/stack.tsx index f8038b0d..95218f54 100644 --- a/components/Settings/stack.tsx +++ b/components/Settings/stack.tsx @@ -21,7 +21,7 @@ export default function Settings(): React.JSX.Element { /> + ) diff --git a/components/jellify.tsx b/components/jellify.tsx index fdadac0a..584c44db 100644 --- a/components/jellify.tsx +++ b/components/jellify.tsx @@ -58,15 +58,15 @@ function App(): React.JSX.Element { }); return carPlayConnected ? ( - - { loggedIn ? ( - + loggedIn ? ( + + + ) : ( Please login in the app before using CarPlay - )} - + ) ) : ( From 856e80e6d1b3e7e194414bf4f3c43db0fcc467c5 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:00:31 -0600 Subject: [PATCH 078/107] I think I need this? --- ios/Jellify-Bridging-Header.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/Jellify-Bridging-Header.h b/ios/Jellify-Bridging-Header.h index 2d689618..d727b23d 100644 --- a/ios/Jellify-Bridging-Header.h +++ b/ios/Jellify-Bridging-Header.h @@ -1,4 +1,5 @@ #import "RNCarPlay.h" +#import #ifdef DEBUG #ifdef FB_SONARKIT_ENABLED From e15d8e8b920275c99e8ac5c971e9a1da66d3b59e Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:07:19 -0600 Subject: [PATCH 079/107] maybe i need this too? --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index e78588c2..4c96b389 100644 --- a/index.js +++ b/index.js @@ -7,5 +7,6 @@ import TrackPlayer from 'react-native-track-player'; import Client from './api/client'; AppRegistry.registerComponent(appName, () => App); +AppRegistry.registerComponent('RNCarPlayScene', () => App) TrackPlayer.registerPlaybackService(() => PlaybackService); Client.instance; \ No newline at end of file From c2c8ae458f026385c832abf15db2a939dadc47a3 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:12:37 -0600 Subject: [PATCH 080/107] maybe? --- index.js | 4 ++-- ios/Jellify/AppDelegate.swift | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 4c96b389..ec0bcabb 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ import { PlaybackService } from './player/service' import TrackPlayer from 'react-native-track-player'; import Client from './api/client'; +Client.instance; AppRegistry.registerComponent(appName, () => App); AppRegistry.registerComponent('RNCarPlayScene', () => App) -TrackPlayer.registerPlaybackService(() => PlaybackService); -Client.instance; \ No newline at end of file +TrackPlayer.registerPlaybackService(() => PlaybackService); \ No newline at end of file diff --git a/ios/Jellify/AppDelegate.swift b/ios/Jellify/AppDelegate.swift index e5ed5151..a7975081 100644 --- a/ios/Jellify/AppDelegate.swift +++ b/ios/Jellify/AppDelegate.swift @@ -47,6 +47,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, RCTBridgeDelegate { func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { } + override func bundleURL() -> URL? { + return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index"); + } + private func initializeFlipper(with application: UIApplication) { #if DEBUG #if FB_SONARKIT_ENABLED From a74e6139d27644f9f92e80606b4499d9c67a38fa Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:22:30 -0600 Subject: [PATCH 081/107] buh --- components/jellify.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/components/jellify.tsx b/components/jellify.tsx index 584c44db..3cfdeeb2 100644 --- a/components/jellify.tsx +++ b/components/jellify.tsx @@ -58,15 +58,15 @@ function App(): React.JSX.Element { }); return carPlayConnected ? ( - loggedIn ? ( - - - - ) : ( - - Please login in the app before using CarPlay - - ) + + { loggedIn ? ( + <> + ) : ( + + Please login in the app before using CarPlay + + )} + ) : ( From 2b6e366bf1f7ba18f94d8a3f214b27b0317db915 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:27:27 -0600 Subject: [PATCH 082/107] What about this? --- components/jellify.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/jellify.tsx b/components/jellify.tsx index 3cfdeeb2..29d4932e 100644 --- a/components/jellify.tsx +++ b/components/jellify.tsx @@ -12,7 +12,8 @@ import { PortalProvider } from "tamagui"; import Client from "../api/client"; import { JellifyProvider, useJellifyContext } from "./provider"; import { CarPlay } from "react-native-carplay" -import JellifyCarplay from "./carplay"; +import { createStackNavigator } from "@react-navigation/stack"; +import { NowPlaying } from "./CarPlay/NowPlaying"; export default function Jellify(): React.JSX.Element { @@ -25,6 +26,8 @@ export default function Jellify(): React.JSX.Element { ); } +const CarPlayStack = createStackNavigator(); + function App(): React.JSX.Element { const isDarkMode = useColorScheme() === "dark"; @@ -60,8 +63,10 @@ function App(): React.JSX.Element { return carPlayConnected ? ( { loggedIn ? ( - <> - ) : ( + + + + ) : ( Please login in the app before using CarPlay From 0f10aab2cbb00dbd8435d537c71b8c8d074f40dc Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:31:44 -0600 Subject: [PATCH 083/107] maybe? --- components/CarPlay/NowPlaying.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/CarPlay/NowPlaying.tsx b/components/CarPlay/NowPlaying.tsx index 8951d38b..0535becb 100644 --- a/components/CarPlay/NowPlaying.tsx +++ b/components/CarPlay/NowPlaying.tsx @@ -6,10 +6,13 @@ export function NowPlaying() { useEffect(() => { const template = new NowPlayingTemplate({ albumArtistButtonEnabled: true, + buttons: [ + { + id: "favorite", + type: "add-to-library" + } + ], upNextButtonEnabled: false, - onUpNextButtonPressed() { - console.log('up next was pressed'); - }, onButtonPressed(e) { console.log(e); }, From 91f4a2d31368c1fa7a4fe48eb1177a8a6580120a Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:36:35 -0600 Subject: [PATCH 084/107] Can this at least work? --- components/CarPlay/Home.tsx | 10 +++++++++ components/CarPlay/NowPlaying.tsx | 37 ------------------------------- components/carplay.tsx | 13 ----------- components/jellify.tsx | 6 ++--- 4 files changed, 13 insertions(+), 53 deletions(-) create mode 100644 components/CarPlay/Home.tsx delete mode 100644 components/CarPlay/NowPlaying.tsx delete mode 100644 components/carplay.tsx diff --git a/components/CarPlay/Home.tsx b/components/CarPlay/Home.tsx new file mode 100644 index 00000000..c842c511 --- /dev/null +++ b/components/CarPlay/Home.tsx @@ -0,0 +1,10 @@ +import { View } from "tamagui"; +import { Text } from "../Global/helpers/text"; + +export default function CarPlayHome() : React.JSX.Element { + return ( + + Yeet + + ) +} \ No newline at end of file diff --git a/components/CarPlay/NowPlaying.tsx b/components/CarPlay/NowPlaying.tsx deleted file mode 100644 index 0535becb..00000000 --- a/components/CarPlay/NowPlaying.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React, {useEffect} from 'react'; -import {Text, View} from 'react-native'; -import {CarPlay, NowPlayingTemplate} from 'react-native-carplay'; - -export function NowPlaying() { - useEffect(() => { - const template = new NowPlayingTemplate({ - albumArtistButtonEnabled: true, - buttons: [ - { - id: "favorite", - type: "add-to-library" - } - ], - upNextButtonEnabled: false, - onButtonPressed(e) { - console.log(e); - }, - }); - - CarPlay.enableNowPlaying(true); - CarPlay.pushTemplate(template); - - return () => {}; - - }, []); - - return ( - - Now Playing - - ); -} - -NowPlaying.navigationOptions = { - headerTitle: 'Now Playing Template', -}; \ No newline at end of file diff --git a/components/carplay.tsx b/components/carplay.tsx deleted file mode 100644 index 88f67e9f..00000000 --- a/components/carplay.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { createStackNavigator } from "@react-navigation/stack" -import { NowPlaying } from "./CarPlay/NowPlaying"; - -const Stack = createStackNavigator(); - -export default function JellifyCarplay(): React.JSX.Element { - - return ( - - - - ) -} \ No newline at end of file diff --git a/components/jellify.tsx b/components/jellify.tsx index 29d4932e..797a5868 100644 --- a/components/jellify.tsx +++ b/components/jellify.tsx @@ -13,7 +13,7 @@ import Client from "../api/client"; import { JellifyProvider, useJellifyContext } from "./provider"; import { CarPlay } from "react-native-carplay" import { createStackNavigator } from "@react-navigation/stack"; -import { NowPlaying } from "./CarPlay/NowPlaying"; +import CarPlayHome from "./CarPlay/Home"; export default function Jellify(): React.JSX.Element { @@ -63,8 +63,8 @@ function App(): React.JSX.Element { return carPlayConnected ? ( { loggedIn ? ( - - + + ) : ( From 48adf69bafbc5aafe8c766ca56870af5e5e01c8a Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:42:28 -0600 Subject: [PATCH 085/107] So I can just stick this here right? --- components/jellify.tsx | 42 +---------------------------------------- components/provider.tsx | 33 ++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 47 deletions(-) diff --git a/components/jellify.tsx b/components/jellify.tsx index 797a5868..ea7e0a68 100644 --- a/components/jellify.tsx +++ b/components/jellify.tsx @@ -26,53 +26,13 @@ export default function Jellify(): React.JSX.Element { ); } -const CarPlayStack = createStackNavigator(); - function App(): React.JSX.Element { const isDarkMode = useColorScheme() === "dark"; const { loggedIn } = useJellifyContext(); - const [carPlayConnected, setCarPlayConnected] = useState(CarPlay.connected); - - useEffect(() => { - console.debug("Client instance changed") - }, [ - Client.instance - ]) - - useEffect(() => { - - function onConnect() { - setCarPlayConnected(true) - } - - function onDisconnect() { - setCarPlayConnected(false) - } - - CarPlay.registerOnConnect(onConnect); - CarPlay.registerOnDisconnect(onDisconnect); - return () => { - CarPlay.unregisterOnConnect(onConnect) - CarPlay.unregisterOnDisconnect(onDisconnect) - }; - }); - - return carPlayConnected ? ( - - { loggedIn ? ( - - - - ) : ( - - Please login in the app before using CarPlay - - )} - - ) : ( + return ( { loggedIn ? ( diff --git a/components/provider.tsx b/components/provider.tsx index ca8ad7b6..cc268429 100644 --- a/components/provider.tsx +++ b/components/provider.tsx @@ -1,10 +1,11 @@ import Client from "../api/client"; import { isUndefined } from "lodash"; -import { createContext, ReactNode, useContext, useState } from "react"; +import { createContext, ReactNode, useContext, useEffect, useState } from "react"; +import { CarPlay } from "react-native-carplay"; interface JellifyContext { loggedIn: boolean; - setLoggedIn: React.Dispatch>; + carPlayConnected: boolean; } const JellifyContextInitializer = () => { @@ -15,15 +16,35 @@ const JellifyContextInitializer = () => { !isUndefined(Client.server) ); + const [carPlayConnected, setCarPlayConnected] = useState(CarPlay.connected); + + useEffect(() => { + + function onConnect() { + setCarPlayConnected(true) + } + + function onDisconnect() { + setCarPlayConnected(false) + } + + CarPlay.registerOnConnect(onConnect); + CarPlay.registerOnDisconnect(onDisconnect); + return () => { + CarPlay.unregisterOnConnect(onConnect) + CarPlay.unregisterOnDisconnect(onDisconnect) + }; + }); + return { loggedIn, - setLoggedIn, + carPlayConnected } } const JellifyContext = createContext({ loggedIn: false, - setLoggedIn: () => {} + carPlayConnected: false }); export const JellifyProvider: ({ children }: { @@ -31,14 +52,14 @@ export const JellifyProvider: ({ children }: { }) => React.JSX.Element = ({ children }: { children: ReactNode }) => { const { loggedIn, - setLoggedIn + carPlayConnected } = JellifyContextInitializer(); return ( {children} From 958109cce4ea28c150e6d401a22794ef3acd9e82 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Fri, 24 Jan 2025 23:52:14 -0600 Subject: [PATCH 086/107] item detail page changes --- components/ItemDetail/component.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 2c15b6fc..978fb683 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -59,10 +59,10 @@ export default function ItemDetail({ return ( - + Date: Sat, 25 Jan 2025 05:38:14 -0600 Subject: [PATCH 087/107] itemdetail --- components/ItemDetail/component.tsx | 19 ++++++++++++------- components/Settings/stack.tsx | 1 + 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 978fb683..ecf64cfe 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -3,7 +3,7 @@ import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context"; import { StackParamList } from "../types"; import TrackOptions from "./helpers/TrackOptions"; -import { Spacer, View, XStack, YStack } from "tamagui"; +import { ScrollView, Spacer, View, XStack, YStack } from "tamagui"; import BlurhashedImage from "../Global/helpers/blurhashed-image"; import { Text } from "../Global/helpers/text"; import { Colors } from "../../enums/colors"; @@ -58,17 +58,22 @@ export default function ItemDetail({ } return ( - + - + + + + + { item.Name ?? "Untitled Track" } @@ -109,6 +114,6 @@ export default function ItemDetail({ - + ) } \ No newline at end of file diff --git a/components/Settings/stack.tsx b/components/Settings/stack.tsx index 95218f54..f0795152 100644 --- a/components/Settings/stack.tsx +++ b/components/Settings/stack.tsx @@ -24,6 +24,7 @@ export default function Settings(): React.JSX.Element { name="AccountDetails" component={AccountDetails} options={{ + title: "Account", headerLargeTitle: true, headerLargeTitleStyle: { fontFamily: 'Aileron-Bold' From 89fd94bb71df848706f71a89f4a2e9abadf5fb14 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 05:41:47 -0600 Subject: [PATCH 088/107] itemdetail --- components/ItemDetail/component.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index ecf64cfe..f262be20 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -59,9 +59,13 @@ export default function ItemDetail({ return ( - + - + From ef3db28200e747784580b93ccacefdc697fc7f28 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 05:50:46 -0600 Subject: [PATCH 089/107] play next and add to queue --- components/Home/helpers/recently-played.tsx | 2 +- .../ItemDetail/helpers/TrackOptions.tsx | 17 +++++++- player/interfaces.ts | 5 +++ player/provider.tsx | 40 ++++++++++++++----- 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/components/Home/helpers/recently-played.tsx b/components/Home/helpers/recently-played.tsx index 08e7343b..f28575b9 100644 --- a/components/Home/helpers/recently-played.tsx +++ b/components/Home/helpers/recently-played.tsx @@ -38,7 +38,7 @@ export default function RecentlyPlayed({ }); }} onLongPress={() => { - trigger("impactLight"); + trigger("impactMedium"); navigation.push("Details", { item: recentlyPlayedTrack }) diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index c86daa0b..1e709a9b 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -1,9 +1,11 @@ +import { usePlayerContext } from "@/player/provider"; import { useItem } from "../../../api/queries/item"; import Icon from "../../../components/Global/helpers/icon"; import { StackParamList } from "../../../components/types"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { XStack } from "tamagui"; +import { QueuingType } from "@/enums/queuing-type"; export default function TrackOptions({ item, @@ -15,7 +17,9 @@ export default function TrackOptions({ isNested: boolean | undefined// Whether this is nested in the player modal }) : React.JSX.Element { - const { data: album, isSuccess } = useItem(item.AlbumId ?? "") + const { data: album, isSuccess } = useItem(item.AlbumId ?? ""); + + const { useAddToQueue } = usePlayerContext(); return ( @@ -37,10 +41,21 @@ export default function TrackOptions({ { + useAddToQueue.mutate({ + track: item, + queuingType: QueuingType.PlayingNext + }) + }} /> { + useAddToQueue.mutate({ + track: item + }) + }} /> ) diff --git a/player/interfaces.ts b/player/interfaces.ts index 31246ff3..1a50ff9f 100644 --- a/player/interfaces.ts +++ b/player/interfaces.ts @@ -7,4 +7,9 @@ export interface QueueMutation { tracklist: BaseItemDto[]; queueName: string; queuingType?: QueuingType | undefined; +} + +export interface AddToQueueMutation { + track: BaseItemDto, + queuingType?: QueuingType | undefined; } \ No newline at end of file diff --git a/player/provider.tsx b/player/provider.tsx index 851367ae..86730936 100644 --- a/player/provider.tsx +++ b/player/provider.tsx @@ -16,7 +16,7 @@ import { trigger } from "react-native-haptic-feedback"; import { getQueue, pause, seekTo, skip, skipToNext, skipToPrevious } from "react-native-track-player/lib/src/trackPlayer"; import { convertRunTimeTicksToSeconds } from "../helpers/runtimeticks"; import Client from "../api/client"; -import { QueueMutation } from "./interfaces"; +import { AddToQueueMutation, QueueMutation } from "./interfaces"; interface PlayerContext { showPlayer: boolean; @@ -28,6 +28,7 @@ interface PlayerContext { nowPlaying: JellifyTrack | undefined; queue: JellifyTrack[]; queueName: string | undefined; + useAddToQueue: UseMutationResult; useTogglePlayback: UseMutationResult; useSeekTo: UseMutationResult; useSkip: UseMutationResult; @@ -98,9 +99,9 @@ const PlayerContextInitializer = () => { //#endregion Functions //#region Hooks - const useQueueMutation = useMutation({ - mutationFn: async (mutation: QueueMutation) => { - trigger("impactLight"); + const useAddToQueue = useMutation({ + mutationFn: async (mutation: AddToQueueMutation) => { + trigger("impactMedium"); if (mutation.queuingType === QueuingType.PlayingNext) return addToNext([mapDtoToTrack(mutation.track)]); @@ -112,7 +113,7 @@ const PlayerContextInitializer = () => { const useTogglePlayback = useMutation({ mutationFn: async (index?: number | undefined) => { - trigger("impactLight"); + trigger("impactMedium"); if (playbackState === State.Playing) await pause(); else @@ -122,7 +123,7 @@ const PlayerContextInitializer = () => { const useSeekTo = useMutation({ mutationFn: async (position: number) => { - trigger('impactLight'); + trigger('impactMedium'); await seekTo(position); handlePlaybackProgressUpdated(Client.sessionId, playStateApi, nowPlaying!, { @@ -135,7 +136,7 @@ const PlayerContextInitializer = () => { const useSkip = useMutation({ mutationFn: async (index?: number | undefined) => { - trigger("impactLight") + trigger("impactMedium") if (!isUndefined(index)) { setIsSkipping(true); setNowPlaying(queue[index]); @@ -152,7 +153,7 @@ const PlayerContextInitializer = () => { const usePrevious = useMutation({ mutationFn: async () => { - trigger("impactLight"); + trigger("impactMedium"); const nowPlayingIndex = queue.findIndex((track) => track.item.Id === nowPlaying!.item.Id); @@ -165,7 +166,7 @@ const PlayerContextInitializer = () => { const usePlayNewQueue = useMutation({ mutationFn: async (mutation: QueueMutation) => { - trigger("impactLight"); + trigger("impactMedium"); setIsSkipping(true); @@ -285,6 +286,7 @@ const PlayerContextInitializer = () => { nowPlaying, queue, queueName, + useAddToQueue, useTogglePlayback, useSeekTo, useSkip, @@ -307,6 +309,24 @@ export const PlayerContext = createContext({ nowPlaying: undefined, queue: [], queueName: undefined, + useAddToQueue: { + mutate: () => {}, + mutateAsync: async () => {}, + data: undefined, + error: null, + variables: undefined, + isError: false, + isIdle: true, + isPaused: false, + isPending: false, + isSuccess: false, + status: "idle", + reset: () => {}, + context: {}, + failureCount: 0, + failureReason: null, + submittedAt: 0 + }, useTogglePlayback: { mutate: () => {}, mutateAsync: async () => {}, @@ -413,6 +433,7 @@ export const PlayerProvider: ({ children }: { children: ReactNode }) => React.JS nowPlaying, queue, queueName, + useAddToQueue, useTogglePlayback, useSeekTo, useSkip, @@ -432,6 +453,7 @@ export const PlayerProvider: ({ children }: { children: ReactNode }) => React.JS nowPlaying, queue, queueName, + useAddToQueue, useTogglePlayback, useSeekTo, useSkip, From b7371daddf38c22fe47c45c67409cb5cec99aab1 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 05:52:33 -0600 Subject: [PATCH 090/107] fix build --- components/ItemDetail/helpers/TrackOptions.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/ItemDetail/helpers/TrackOptions.tsx b/components/ItemDetail/helpers/TrackOptions.tsx index 1e709a9b..171230a0 100644 --- a/components/ItemDetail/helpers/TrackOptions.tsx +++ b/components/ItemDetail/helpers/TrackOptions.tsx @@ -1,11 +1,11 @@ -import { usePlayerContext } from "@/player/provider"; +import { usePlayerContext } from "../../../player/provider"; import { useItem } from "../../../api/queries/item"; import Icon from "../../../components/Global/helpers/icon"; import { StackParamList } from "../../../components/types"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { XStack } from "tamagui"; -import { QueuingType } from "@/enums/queuing-type"; +import { QueuingType } from "../../../enums/queuing-type"; export default function TrackOptions({ item, From f894f24130b6cbdcd8e3037ab8789bd4a9eb1d64 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 06:03:37 -0600 Subject: [PATCH 091/107] play next and add to queue changes --- player/helpers/index.ts | 21 +++++++++++++++------ player/provider.tsx | 6 +++--- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/player/helpers/index.ts b/player/helpers/index.ts index 902035dc..25d9113d 100644 --- a/player/helpers/index.ts +++ b/player/helpers/index.ts @@ -1,17 +1,18 @@ import { isEmpty } from "lodash"; import { QueuingType } from "../../enums/queuing-type"; import { JellifyTrack } from "../../types/JellifyTrack"; +import { getActiveTrackIndex } from "react-native-track-player/lib/src/trackPlayer"; /** * Finds and returns the index of the player queue to insert additional tracks into * @param playQueue The current player queue * @returns The index to insert songs to play next at */ -export const findPlayNextIndexStart = (playQueue: JellifyTrack[]) => { - if (playQueue.length > 0) - return 1 +export const findPlayNextIndexStart = async (playQueue: JellifyTrack[]) => { + if (isEmpty(playQueue)) + return 0; - return 0; + return (await getActiveTrackIndex())! + 1; } /** @@ -19,10 +20,18 @@ export const findPlayNextIndexStart = (playQueue: JellifyTrack[]) => { * @param playQueue The current player queue * @returns The index to insert songs to add to the user queue */ -export const findPlayQueueIndexStart = (playQueue: JellifyTrack[]) => { +export const findPlayQueueIndexStart = async (playQueue: JellifyTrack[]) => { if (isEmpty(playQueue)) return 0; - return playQueue.findIndex(queuedTrack => queuedTrack.QueuingType === QueuingType.FromSelection); + const activeIndex = await getActiveTrackIndex(); + + if (playQueue.findIndex(track => track.QueuingType === QueuingType.FromSelection) === -1) + return activeIndex! + 1 + + return playQueue.findIndex((queuedTrack, index) => + queuedTrack.QueuingType === QueuingType.FromSelection && + index > activeIndex! + ); } \ No newline at end of file diff --git a/player/provider.tsx b/player/provider.tsx index 86730936..026c163c 100644 --- a/player/provider.tsx +++ b/player/provider.tsx @@ -3,7 +3,7 @@ import { JellifyTrack } from "../types/JellifyTrack"; import { storage } from "../constants/storage"; import { MMKVStorageKeys } from "../enums/mmkv-storage-keys"; import { findPlayNextIndexStart, findPlayQueueIndexStart } from "./helpers/index"; -import TrackPlayer, { Event, Progress, State, usePlaybackState, useProgress, useTrackPlayerEvents } from "react-native-track-player"; +import TrackPlayer, { Event, Progress, State, Track, usePlaybackState, useProgress, useTrackPlayerEvents } from "react-native-track-player"; import _, { isEqual, isUndefined } from "lodash"; import { getPlaystateApi } from "@jellyfin/sdk/lib/utils/api"; import { handlePlaybackProgressUpdated, handlePlaybackState } from "./handlers"; @@ -75,7 +75,7 @@ const PlayerContextInitializer = () => { } const addToQueue = async (tracks: JellifyTrack[]) => { - const insertIndex = findPlayQueueIndexStart(queue); + const insertIndex = await findPlayQueueIndexStart(queue); console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`) await TrackPlayer.add(tracks, insertIndex); @@ -86,7 +86,7 @@ const PlayerContextInitializer = () => { } const addToNext = async (tracks: JellifyTrack[]) => { - const insertIndex = findPlayNextIndexStart(queue); + const insertIndex = await findPlayNextIndexStart(queue); console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`); From 5c1dc6a205df1750b8010568b4939f521648e25d Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 06:10:04 -0600 Subject: [PATCH 092/107] getting queuing type to work --- components/Global/components/item.tsx | 4 +++- components/Global/components/track.tsx | 4 +++- components/Home/helpers/recently-played.tsx | 7 +++++-- player/provider.tsx | 4 ++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/components/Global/components/item.tsx b/components/Global/components/item.tsx index 77809981..d5ab4a69 100644 --- a/components/Global/components/item.tsx +++ b/components/Global/components/item.tsx @@ -8,6 +8,7 @@ import { useSafeAreaFrame } from "react-native-safe-area-context"; import BlurhashedImage from "../helpers/blurhashed-image"; import Icon from "../helpers/icon"; import { Colors } from "../../../enums/colors"; +import { QueuingType } from "../../../enums/queuing-type"; export default function Item({ item, @@ -51,7 +52,8 @@ export default function Item({ usePlayNewQueue.mutate({ track: item, tracklist: [item], - queueName + queueName, + queuingType: QueuingType.FromSelection }) break; } diff --git a/components/Global/components/track.tsx b/components/Global/components/track.tsx index a442b099..afb20fea 100644 --- a/components/Global/components/track.tsx +++ b/components/Global/components/track.tsx @@ -13,6 +13,7 @@ import Icon from "../helpers/icon"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { StackParamList } from "../../../components/types"; import Client from "../../../api/client"; +import { QueuingType } from "../../../enums/queuing-type"; interface TrackProps { track: BaseItemDto; @@ -63,7 +64,8 @@ export default function Track({ track, index, tracklist, - queueName: queueName ? queueName : track.Album ? track.Album! : "Queue" + queueName: queueName ? queueName : track.Album ? track.Album! : "Queue", + queuingType: QueuingType.FromSelection }); } }} diff --git a/components/Home/helpers/recently-played.tsx b/components/Home/helpers/recently-played.tsx index f28575b9..84090e0e 100644 --- a/components/Home/helpers/recently-played.tsx +++ b/components/Home/helpers/recently-played.tsx @@ -7,6 +7,7 @@ import { usePlayerContext } from "../../../player/provider"; import { StackParamList } from "../../../components/types"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { trigger } from "react-native-haptic-feedback"; +import { QueuingType } from "../../../enums/queuing-type"; export default function RecentlyPlayed({ navigation @@ -34,13 +35,15 @@ export default function RecentlyPlayed({ track: recentlyPlayedTrack, index: index, tracklist: recentTracks, - queueName: "Recently Played" + queueName: "Recently Played", + queuingType: QueuingType.FromSelection }); }} onLongPress={() => { trigger("impactMedium"); navigation.push("Details", { - item: recentlyPlayedTrack + item: recentlyPlayedTrack, + isNested: false }) }} /> diff --git a/player/provider.tsx b/player/provider.tsx index 026c163c..22ddaf4e 100644 --- a/player/provider.tsx +++ b/player/provider.tsx @@ -104,10 +104,10 @@ const PlayerContextInitializer = () => { trigger("impactMedium"); if (mutation.queuingType === QueuingType.PlayingNext) - return addToNext([mapDtoToTrack(mutation.track)]); + return addToNext([mapDtoToTrack(mutation.track, mutation.queuingType)]); else - return addToQueue([mapDtoToTrack(mutation.track)]) + return addToQueue([mapDtoToTrack(mutation.track, mutation.queuingType)]) } }) From 3a194c1a28f57ca55239751657852ff960212c78 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 06:24:05 -0600 Subject: [PATCH 093/107] background stuff? --- package-lock.json | 23 ++++++++++++++++++++++ package.json | 1 + player/provider.tsx | 47 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 527444f5..f28a3157 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "nativewind": "4.0.36", "react": "18.3.1", "react-native": "0.75.2", + "react-native-background-actions": "^4.0.1", "react-native-blurhash": "^2.1.0", "react-native-carplay": "^2.4.1-beta.0", "react-native-device-info": "^11.1.0", @@ -9796,6 +9797,12 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -15417,6 +15424,22 @@ } } }, + "node_modules/react-native-background-actions": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/react-native-background-actions/-/react-native-background-actions-4.0.1.tgz", + "integrity": "sha512-LADhnb4ag1oH5Lotq0j8K9e2cFmrafFyg2PCME88VkTjqDUgNcJonkNdMCTHN0N3fh+hwAA7nDR4Cxkj9Q8eCw==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.7" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/Rapsssito" + }, + "peerDependencies": { + "react-native": ">=0.47.0" + } + }, "node_modules/react-native-blurhash": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/react-native-blurhash/-/react-native-blurhash-2.1.0.tgz", diff --git a/package.json b/package.json index 64a1f1e9..7293f62c 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "nativewind": "4.0.36", "react": "18.3.1", "react-native": "0.75.2", + "react-native-background-actions": "^4.0.1", "react-native-blurhash": "^2.1.0", "react-native-carplay": "^2.4.1-beta.0", "react-native-device-info": "^11.1.0", diff --git a/player/provider.tsx b/player/provider.tsx index 22ddaf4e..4cc82d0f 100644 --- a/player/provider.tsx +++ b/player/provider.tsx @@ -17,6 +17,7 @@ import { getQueue, pause, seekTo, skip, skipToNext, skipToPrevious } from "react import { convertRunTimeTicksToSeconds } from "../helpers/runtimeticks"; import Client from "../api/client"; import { AddToQueueMutation, QueueMutation } from "./interfaces"; +import BackgroundService from 'react-native-background-actions'; interface PlayerContext { showPlayer: boolean; @@ -74,7 +75,11 @@ const PlayerContextInitializer = () => { setShowMiniplayer(!hideMiniplayer) } - const addToQueue = async (tracks: JellifyTrack[]) => { + const addToQueue = async (tracks: JellifyTrack[] | undefined) => { + + if (isUndefined(tracks)) + return; + const insertIndex = await findPlayQueueIndexStart(queue); console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`) @@ -85,7 +90,11 @@ const PlayerContextInitializer = () => { setShowMiniplayer(true); } - const addToNext = async (tracks: JellifyTrack[]) => { + const addToNext = async (tracks: JellifyTrack[] | undefined) => { + + if (isUndefined(tracks)) + return; + const insertIndex = await findPlayNextIndexStart(queue); console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`); @@ -103,8 +112,20 @@ const PlayerContextInitializer = () => { mutationFn: async (mutation: AddToQueueMutation) => { trigger("impactMedium"); - if (mutation.queuingType === QueuingType.PlayingNext) - return addToNext([mapDtoToTrack(mutation.track, mutation.queuingType)]); + if (mutation.queuingType === QueuingType.PlayingNext) { + await BackgroundService.start(addToNext, { + parameters: [mapDtoToTrack(mutation.track, mutation.queuingType)], + taskName: "", + taskTitle: "", + taskDesc: "", + taskIcon: { + name: "", + type: "", + package: undefined + } + }); + await BackgroundService.stop(); + } else return addToQueue([mapDtoToTrack(mutation.track, mutation.queuingType)]) @@ -174,9 +195,21 @@ const PlayerContextInitializer = () => { setNowPlaying(mapDtoToTrack(mutation.tracklist[mutation.index ?? 0], QueuingType.FromSelection)); await resetQueue(false); - await addToQueue(mutation.tracklist.map((track) => { - return mapDtoToTrack(track, QueuingType.FromSelection) - })); + + await BackgroundService.start(addToQueue, { + parameters: mutation.tracklist.map((track) => { + return mapDtoToTrack(track, QueuingType.FromSelection); + }), + taskName: "", + taskTitle: "", + taskDesc: "", + taskIcon: { + name: "", + type: "", + package: undefined + } + }); + await BackgroundService.stop(); setQueueName(mutation.queueName); }, From b2e74a41a1e10d637bb2a1b7e3f4c1080bc908eb Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 06:27:32 -0600 Subject: [PATCH 094/107] fuck --- player/provider.tsx | 47 +++++++-------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/player/provider.tsx b/player/provider.tsx index 4cc82d0f..22ddaf4e 100644 --- a/player/provider.tsx +++ b/player/provider.tsx @@ -17,7 +17,6 @@ import { getQueue, pause, seekTo, skip, skipToNext, skipToPrevious } from "react import { convertRunTimeTicksToSeconds } from "../helpers/runtimeticks"; import Client from "../api/client"; import { AddToQueueMutation, QueueMutation } from "./interfaces"; -import BackgroundService from 'react-native-background-actions'; interface PlayerContext { showPlayer: boolean; @@ -75,11 +74,7 @@ const PlayerContextInitializer = () => { setShowMiniplayer(!hideMiniplayer) } - const addToQueue = async (tracks: JellifyTrack[] | undefined) => { - - if (isUndefined(tracks)) - return; - + const addToQueue = async (tracks: JellifyTrack[]) => { const insertIndex = await findPlayQueueIndexStart(queue); console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`) @@ -90,11 +85,7 @@ const PlayerContextInitializer = () => { setShowMiniplayer(true); } - const addToNext = async (tracks: JellifyTrack[] | undefined) => { - - if (isUndefined(tracks)) - return; - + const addToNext = async (tracks: JellifyTrack[]) => { const insertIndex = await findPlayNextIndexStart(queue); console.debug(`Adding ${tracks.length} to queue at index ${insertIndex}`); @@ -112,20 +103,8 @@ const PlayerContextInitializer = () => { mutationFn: async (mutation: AddToQueueMutation) => { trigger("impactMedium"); - if (mutation.queuingType === QueuingType.PlayingNext) { - await BackgroundService.start(addToNext, { - parameters: [mapDtoToTrack(mutation.track, mutation.queuingType)], - taskName: "", - taskTitle: "", - taskDesc: "", - taskIcon: { - name: "", - type: "", - package: undefined - } - }); - await BackgroundService.stop(); - } + if (mutation.queuingType === QueuingType.PlayingNext) + return addToNext([mapDtoToTrack(mutation.track, mutation.queuingType)]); else return addToQueue([mapDtoToTrack(mutation.track, mutation.queuingType)]) @@ -195,21 +174,9 @@ const PlayerContextInitializer = () => { setNowPlaying(mapDtoToTrack(mutation.tracklist[mutation.index ?? 0], QueuingType.FromSelection)); await resetQueue(false); - - await BackgroundService.start(addToQueue, { - parameters: mutation.tracklist.map((track) => { - return mapDtoToTrack(track, QueuingType.FromSelection); - }), - taskName: "", - taskTitle: "", - taskDesc: "", - taskIcon: { - name: "", - type: "", - package: undefined - } - }); - await BackgroundService.stop(); + await addToQueue(mutation.tracklist.map((track) => { + return mapDtoToTrack(track, QueuingType.FromSelection) + })); setQueueName(mutation.queueName); }, From 44e90ed155bfea5aeebe3186fbeebdba8f00f8be Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 06:38:47 -0600 Subject: [PATCH 095/107] item detail stuff --- components/Global/components/item.tsx | 16 ++++++++++++++-- components/ItemDetail/component.tsx | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/components/Global/components/item.tsx b/components/Global/components/item.tsx index d5ab4a69..b028867c 100644 --- a/components/Global/components/item.tsx +++ b/components/Global/components/item.tsx @@ -25,7 +25,7 @@ export default function Item({ const { width } = useSafeAreaFrame(); return ( - + { item.Name ?? ""} { item.Type === 'Audio' || item.Type === 'MusicAlbum' ? ( @@ -83,7 +84,7 @@ export default function Item({ )} - + { item.UserData?.IsFavorite ? ( )} + + { + navigation.push("Details", { + item, + isNested: false + }) + }} + /> diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index f262be20..7d5ca0fc 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -1,6 +1,6 @@ import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; -import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context"; +import { useSafeAreaFrame } from "react-native-safe-area-context"; import { StackParamList } from "../types"; import TrackOptions from "./helpers/TrackOptions"; import { ScrollView, Spacer, View, XStack, YStack } from "tamagui"; @@ -59,10 +59,11 @@ export default function ItemDetail({ return ( - + @@ -76,6 +77,7 @@ export default function ItemDetail({ From 90d6367131c5f103fad1e479a3d6ff51b8b15c89 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 06:39:40 -0600 Subject: [PATCH 096/107] progress view offset in search? --- components/Search/component.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/Search/component.tsx b/components/Search/component.tsx index a0bc859c..d75ac4bd 100644 --- a/components/Search/component.tsx +++ b/components/Search/component.tsx @@ -37,6 +37,7 @@ export default function Search({ return ( Date: Sat, 25 Jan 2025 07:05:51 -0600 Subject: [PATCH 097/107] tamagui theming --- components/Album/component.tsx | 2 +- components/ItemDetail/component.tsx | 2 +- components/Player/screens/index.tsx | 2 +- components/Playlist/component.tsx | 2 +- tamagui.config.ts | 26 +++++++++++++++++++++++--- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/components/Album/component.tsx b/components/Album/component.tsx index 50bb24f6..0be9d7f8 100644 --- a/components/Album/component.tsx +++ b/components/Album/component.tsx @@ -83,7 +83,7 @@ export default function Album(props: AlbumProps): React.JSX.Element { Total Runtime: diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index 7d5ca0fc..b607f534 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -104,7 +104,7 @@ export default function ItemDetail({ { item.Album ?? "" } diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index ea85d4d1..4075adb7 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -114,7 +114,7 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa { nowPlaying!.album ?? "" } diff --git a/components/Playlist/component.tsx b/components/Playlist/component.tsx index 7ef077ca..211185c1 100644 --- a/components/Playlist/component.tsx +++ b/components/Playlist/component.tsx @@ -74,7 +74,7 @@ export default function Playlist(props: PlaylistProps): React.JSX.Element { Total Runtime: diff --git a/tamagui.config.ts b/tamagui.config.ts index e7339a31..a81c719c 100644 --- a/tamagui.config.ts +++ b/tamagui.config.ts @@ -1,7 +1,18 @@ -import { animations, tokens, themes, media, shorthands } from '@tamagui/config/v3' -import { createTamagui } from 'tamagui' // or '@tamagui/core' +import { animations, tokens as TamaguiTokens, media, shorthands } from '@tamagui/config/v3' +import { createTamagui, createTokens } from 'tamagui' // or '@tamagui/core' import { headingFont, bodyFont } from './fonts.config' +const tokens = createTokens({ + ...TamaguiTokens, + color: { + purpleDark: "#070217", + purple: "#100538", + purpleGray: "#B5AADC", + white: "#ffffff", + black: "#000000" + }, +}) + const jellifyConfig = createTamagui({ animations, fonts:{ @@ -11,7 +22,16 @@ const jellifyConfig = createTamagui({ media, shorthands, tokens, - themes, + themes: { + dark: { + background: tokens.color.purpleDark, + color: tokens.color.white + }, + light: { + background: tokens.color.white, + color: tokens.color.purpleDark + } + } }); export type JellifyConfig = typeof jellifyConfig From a5e036216f28499c8a3ccb6a0c94776d89cd09c9 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 07:13:05 -0600 Subject: [PATCH 098/107] stuff and things --- components/Global/helpers/time-codes.tsx | 2 +- tamagui.config.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/Global/helpers/time-codes.tsx b/components/Global/helpers/time-codes.tsx index d34f253a..a5e98288 100644 --- a/components/Global/helpers/time-codes.tsx +++ b/components/Global/helpers/time-codes.tsx @@ -12,7 +12,7 @@ export function RunTimeTicks({ children } : { children?: number | null | undefin let time = calculateRunTimeFromTicks(children); - return { time } + return { time } } function calculateRunTimeFromSeconds(seconds: number) : string { diff --git a/tamagui.config.ts b/tamagui.config.ts index a81c719c..72b24ae7 100644 --- a/tamagui.config.ts +++ b/tamagui.config.ts @@ -25,6 +25,7 @@ const jellifyConfig = createTamagui({ themes: { dark: { background: tokens.color.purpleDark, + borderColor: tokens.color.purple, color: tokens.color.white }, light: { From 3722620af88cf70d582630f20988a1f0fb8041b2 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 07:22:53 -0600 Subject: [PATCH 099/107] track should work with light mode now? --- components/Global/components/track.tsx | 11 ++++++----- components/Global/helpers/icon.tsx | 3 ++- tamagui.config.ts | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/components/Global/components/track.tsx b/components/Global/components/track.tsx index afb20fea..35e88741 100644 --- a/components/Global/components/track.tsx +++ b/components/Global/components/track.tsx @@ -1,10 +1,9 @@ import { usePlayerContext } from "../../../player/provider"; import React from "react"; -import { Separator, Spacer, View, XStack, YStack } from "tamagui"; +import { Separator, Spacer, useTheme, View, XStack, YStack } from "tamagui"; import { Text } from "../helpers/text"; import { RunTimeTicks } from "../helpers/time-codes"; import { BaseItemDto, ImageType } from "@jellyfin/sdk/lib/generated-client/models"; -import { Colors } from "../../../enums/colors"; import { CachedImage } from "@georstat/react-native-image-cache"; import { getImageApi } from "@jellyfin/sdk/lib/utils/api/image-api"; import { QueryConfig } from "../../../api/queries/query.config"; @@ -50,6 +49,8 @@ export default function Track({ const isPlaying = nowPlaying?.item.Id === track.Id; + const theme = useTheme(); + return ( @@ -102,7 +103,7 @@ export default function Track({ /> ) : ( - + { track.IndexNumber?.toString() ?? "" } )} @@ -111,7 +112,7 @@ export default function Track({ @@ -135,7 +136,7 @@ export default function Track({ minWidth={24} > { track.UserData?.IsFavorite ? ( - + ) : ( )} diff --git a/components/Global/helpers/icon.tsx b/components/Global/helpers/icon.tsx index d52728f9..0ebde6e6 100644 --- a/components/Global/helpers/icon.tsx +++ b/components/Global/helpers/icon.tsx @@ -2,6 +2,7 @@ import React from "react" import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons" import { Colors } from "../../../enums/colors" import { useColorScheme } from "react-native"; +import { ColorTokens } from "tamagui"; const smallSize = 24; @@ -9,7 +10,7 @@ const regularSize = 36; const largeSize = 48 -export default function Icon({ name, onPress, small, large, color }: { name: string, onPress?: () => void, small?: boolean, large?: boolean, color?: Colors }) : React.JSX.Element { +export default function Icon({ name, onPress, small, large, color }: { name: string, onPress?: () => void, small?: boolean, large?: boolean, color?: ColorTokens}) : React.JSX.Element { const isDarkMode = useColorScheme() === "dark" let size = large ? largeSize : small ? smallSize : regularSize diff --git a/tamagui.config.ts b/tamagui.config.ts index 72b24ae7..4984041c 100644 --- a/tamagui.config.ts +++ b/tamagui.config.ts @@ -8,6 +8,7 @@ const tokens = createTokens({ purpleDark: "#070217", purple: "#100538", purpleGray: "#B5AADC", + telemagenta: "#cc2f71", white: "#ffffff", black: "#000000" }, From 3b204f22589606413baa6959a4d54713c92b6c05 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 07:25:39 -0600 Subject: [PATCH 100/107] miniplayer should respect lightmode --- components/Player/mini-player.tsx | 9 +++++++-- tamagui.config.ts | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/components/Player/mini-player.tsx b/components/Player/mini-player.tsx index 9a0d6a9f..fd872ea1 100644 --- a/components/Player/mini-player.tsx +++ b/components/Player/mini-player.tsx @@ -1,5 +1,5 @@ import React, { } from "react"; -import { View, XStack, YStack } from "tamagui"; +import { useTheme, View, XStack, YStack } from "tamagui"; import { usePlayerContext } from "../../player/provider"; import { BottomTabNavigationEventMap } from "@react-navigation/bottom-tabs"; import { NavigationHelpers, ParamListBase } from "@react-navigation/native"; @@ -17,12 +17,17 @@ import Client from "../../api/client"; export function Miniplayer({ navigation }: { navigation : NavigationHelpers }) : React.JSX.Element { + const theme = useTheme(); + const { nowPlaying, useSkip } = usePlayerContext(); const { width } = useSafeAreaFrame(); return ( - + { nowPlaying && ( Date: Sat, 25 Jan 2025 07:41:44 -0600 Subject: [PATCH 101/107] texttickers every fucking where in teh player --- components/Player/component.config.ts | 8 +++ components/Player/mini-player.tsx | 15 +---- components/Player/screens/index.tsx | 83 +++++++++++++-------------- 3 files changed, 51 insertions(+), 55 deletions(-) create mode 100644 components/Player/component.config.ts diff --git a/components/Player/component.config.ts b/components/Player/component.config.ts new file mode 100644 index 00000000..7852a3f1 --- /dev/null +++ b/components/Player/component.config.ts @@ -0,0 +1,8 @@ +import { TextTickerProps } from "react-native-text-ticker"; + +export const TextTickerConfig : TextTickerProps = { + duration: 5000, + loop: true, + repeatSpacer: 20, + marqueeDelay: 1000 +} \ No newline at end of file diff --git a/components/Player/mini-player.tsx b/components/Player/mini-player.tsx index fd872ea1..49b852a6 100644 --- a/components/Player/mini-player.tsx +++ b/components/Player/mini-player.tsx @@ -14,6 +14,7 @@ import TextTicker from 'react-native-text-ticker'; import PlayPauseButton from "./helpers/buttons"; import { useSafeAreaFrame } from "react-native-safe-area-context"; import Client from "../../api/client"; +import { TextTickerConfig } from "./component.config"; export function Miniplayer({ navigation }: { navigation : NavigationHelpers }) : React.JSX.Element { @@ -65,21 +66,11 @@ export function Miniplayer({ navigation }: { navigation : NavigationHelpers - + {nowPlaying?.title ?? "Nothing Playing"} - + {nowPlaying?.artist ?? ""} diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 4075adb7..32d0c60a 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -12,6 +12,8 @@ import Icon from "../../../components/Global/helpers/icon"; import { Colors } from "../../../enums/colors"; import FavoriteButton from "../../Global/components/favorite-button"; import BlurhashedImage from "../../../components/Global/helpers/blurhashed-image"; +import TextTicker from "react-native-text-ticker"; +import { TextTickerConfig } from "../component.config"; export default function PlayerScreen({ navigation }: { navigation: NativeStackNavigationProp}): React.JSX.Element { @@ -54,9 +56,14 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa <> - + Playing from -
{ queueName ?? "Queue"}
+ +
{ queueName ?? "Queue"}
+
- {/* */} - - {nowPlaying!.title ?? "Untitled Track"} - + + + {nowPlaying!.title ?? "Untitled Track"} + + - { - if (nowPlaying!.item.ArtistItems) { - navigation.navigate("Artist", { - artist: nowPlaying!.item.ArtistItems![0], - }); - } - }} - > - {nowPlaying.artist ?? "Unknown Artist"} - + + { + if (nowPlaying!.item.ArtistItems) { + navigation.navigate("Artist", { + artist: nowPlaying!.item.ArtistItems![0], + }); + } + }} + > + {nowPlaying.artist ?? "Unknown Artist"} + + - - { nowPlaying!.album ?? "" } - + + + { nowPlaying!.album ?? "" } + + Date: Sat, 25 Jan 2025 07:43:51 -0600 Subject: [PATCH 102/107] Update purplegray color token value to something darker and grayer --- enums/colors.ts | 2 +- tamagui.config.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/enums/colors.ts b/enums/colors.ts index 10e10c19..caab2fd6 100644 --- a/enums/colors.ts +++ b/enums/colors.ts @@ -1,6 +1,6 @@ export enum Colors { Primary = "#cc2f71", // Telemagenta - Secondary = "#B5AADC", // Wisteria + Secondary = "#66617B", // Wisteria Borders = "#100538", // Russian Violet Background = "#070217", // Rich Black diff --git a/tamagui.config.ts b/tamagui.config.ts index d76ee066..d504eb45 100644 --- a/tamagui.config.ts +++ b/tamagui.config.ts @@ -7,7 +7,7 @@ const tokens = createTokens({ color: { purpleDark: "#070217", purple: "#100538", - purpleGray: "#B5AADC", + purpleGray: "#66617B", telemagenta: "#cc2f71", white: "#ffffff", black: "#000000" @@ -26,7 +26,7 @@ const jellifyConfig = createTamagui({ themes: { dark: { background: tokens.color.purpleDark, - borderColor: tokens.color.purple, + borderColor: tokens.color.purpleGray, color: tokens.color.white }, light: { From ac57bdba70ad6a39604faf293a317a467284d52d Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 07:52:03 -0600 Subject: [PATCH 103/107] alignment on album and itemdetail page --- components/Album/component.tsx | 9 +++++++-- components/ItemDetail/component.tsx | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/components/Album/component.tsx b/components/Album/component.tsx index 0be9d7f8..abfcfb3c 100644 --- a/components/Album/component.tsx +++ b/components/Album/component.tsx @@ -46,7 +46,11 @@ export default function Album(props: AlbumProps): React.JSX.Element { return ( - + - + Total Runtime: diff --git a/components/ItemDetail/component.tsx b/components/ItemDetail/component.tsx index b607f534..10c79199 100644 --- a/components/ItemDetail/component.tsx +++ b/components/ItemDetail/component.tsx @@ -80,11 +80,12 @@ export default function ItemDetail({ justifyContent="center" flex={2} > - + { item.Name ?? "Untitled Track" } { @@ -103,6 +104,7 @@ export default function ItemDetail({ From b9770a6a26902703cead12c255be548de00683db Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 07:53:56 -0600 Subject: [PATCH 104/107] flex player top controls more --- components/Player/screens/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Player/screens/index.tsx b/components/Player/screens/index.tsx index 32d0c60a..0aa8ac65 100644 --- a/components/Player/screens/index.tsx +++ b/components/Player/screens/index.tsx @@ -120,7 +120,7 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa {/* Buttons for favorites, song menu go here */} From 0a248595f9d0c7c526106f2b264dc75fadd4a631 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 07:59:03 -0600 Subject: [PATCH 105/107] time to break the player slider --- components/Global/helpers/slider.tsx | 30 ++++++++-------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/components/Global/helpers/slider.tsx b/components/Global/helpers/slider.tsx index 50421d63..dfc03942 100644 --- a/components/Global/helpers/slider.tsx +++ b/components/Global/helpers/slider.tsx @@ -1,6 +1,5 @@ -import { Colors } from "../../../enums/colors"; import React from "react"; -import { SliderProps as TamaguiSliderProps, SliderVerticalProps, Slider as TamaguiSlider, styled, Slider } from "tamagui"; +import { SliderProps as TamaguiSliderProps, SliderVerticalProps, Slider as TamaguiSlider } from "tamagui"; interface SliderProps { value?: number | undefined; @@ -9,19 +8,6 @@ interface SliderProps { props: TamaguiSliderProps } -const JellifySliderThumb = styled(Slider.Thumb, { - backgroundColor: Colors.Primary, - borderColor: Colors.Background, -}) - -const JellifySliderTrack = styled(Slider.Track, { - backgroundColor: Colors.Borders -}); - -const JellifyActiveSliderTrack = styled(Slider.TrackActive, { - backgroundColor: Colors.Primary -}) - export function HorizontalSlider({ value, max, @@ -45,9 +31,9 @@ export function HorizontalSlider({ marginHorizontal={10} { ...props } > - - - + + + ) @@ -65,10 +51,10 @@ export function VerticalSlider(props: SliderVerticalProps) : React.JSX.Element { orientation="vertical" marginVertical={10} > - - - - + + + + ) } \ No newline at end of file From 2be8c7459b77f489ed4ed069e88a24bbb7d24f5d Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 08:02:54 -0600 Subject: [PATCH 106/107] roll that back and do it differently --- components/Global/helpers/slider.tsx | 30 ++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/components/Global/helpers/slider.tsx b/components/Global/helpers/slider.tsx index dfc03942..2213b9ba 100644 --- a/components/Global/helpers/slider.tsx +++ b/components/Global/helpers/slider.tsx @@ -1,5 +1,6 @@ +import { Colors } from "../../../enums/colors"; import React from "react"; -import { SliderProps as TamaguiSliderProps, SliderVerticalProps, Slider as TamaguiSlider } from "tamagui"; +import { SliderProps as TamaguiSliderProps, SliderVerticalProps, Slider as TamaguiSlider, styled, Slider, getTokens } from "tamagui"; interface SliderProps { value?: number | undefined; @@ -8,6 +9,19 @@ interface SliderProps { props: TamaguiSliderProps } +const JellifySliderThumb = styled(Slider.Thumb, { + backgroundColor: getTokens().color.$telemagenta, + borderColor: getTokens().color.$purpleGray, +}) + +const JellifySliderTrack = styled(Slider.Track, { + backgroundColor: getTokens().color.$purpleGray +}); + +const JellifyActiveSliderTrack = styled(Slider.TrackActive, { + backgroundColor: getTokens().color.$telemagenta +}) + export function HorizontalSlider({ value, max, @@ -31,9 +45,9 @@ export function HorizontalSlider({ marginHorizontal={10} { ...props } > - - - + + + ) @@ -51,10 +65,10 @@ export function VerticalSlider(props: SliderVerticalProps) : React.JSX.Element { orientation="vertical" marginVertical={10} > - - - - + + + + ) } \ No newline at end of file From a25ce86ae1911b6f4586d10838040c4a4dd99a70 Mon Sep 17 00:00:00 2001 From: Violet Caulfield Date: Sat, 25 Jan 2025 08:08:59 -0600 Subject: [PATCH 107/107] button color changes --- components/Global/helpers/icon.tsx | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/components/Global/helpers/icon.tsx b/components/Global/helpers/icon.tsx index 0ebde6e6..605e27e6 100644 --- a/components/Global/helpers/icon.tsx +++ b/components/Global/helpers/icon.tsx @@ -1,8 +1,7 @@ import React from "react" import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons" -import { Colors } from "../../../enums/colors" import { useColorScheme } from "react-native"; -import { ColorTokens } from "tamagui"; +import { ColorTokens, getTokens } from "tamagui"; const smallSize = 24; @@ -10,14 +9,28 @@ const regularSize = 36; const largeSize = 48 -export default function Icon({ name, onPress, small, large, color }: { name: string, onPress?: () => void, small?: boolean, large?: boolean, color?: ColorTokens}) : React.JSX.Element { +export default function Icon({ + name, onPress, + small, + large, + color +}: { + name: string, + onPress?: () => void, + small?: boolean, + large?: boolean, + color?: ColorTokens +}) : React.JSX.Element { const isDarkMode = useColorScheme() === "dark" let size = large ? largeSize : small ? smallSize : regularSize return (