From 425a100ed97f5bdca47deb35e7673786d6053ed8 Mon Sep 17 00:00:00 2001 From: Violet Caulfield <42452695+anultravioletaurora@users.noreply.github.com> Date: Sat, 8 Nov 2025 02:46:01 -0600 Subject: [PATCH] styling fixes make buttons animate consistently styling and animations for the library switcher fix issue where the second line of the toast message wasn't using the figtree font --- src/api/mutations/authentication/index.ts | 4 +- src/components/AddToPlaylist/index.tsx | 28 +++++- src/components/Context/index.tsx | 61 ++++++------ src/components/Global/components/icon.tsx | 2 +- src/components/Global/components/image.tsx | 42 ++++---- .../Global/components/library-selector.tsx | 99 +++++++++++-------- src/components/Global/helpers/button.tsx | 12 ++- src/components/Player/index.tsx | 2 +- .../Settings/components/preferences-tab.tsx | 7 +- src/components/jellify.tsx | 2 +- src/{constants => configs}/toast.config.ts | 12 ++- tamagui.config.ts | 9 -- 12 files changed, 165 insertions(+), 115 deletions(-) rename src/{constants => configs}/toast.config.ts (78%) diff --git a/src/api/mutations/authentication/index.ts b/src/api/mutations/authentication/index.ts index bb2f539b..a7bd712d 100644 --- a/src/api/mutations/authentication/index.ts +++ b/src/api/mutations/authentication/index.ts @@ -9,7 +9,7 @@ import { useApi, useJellifyUser } from '../../../stores' interface AuthenticateUserByNameMutation { onSuccess?: () => void - onError?: () => void + onError?: (error: Error) => void } const useAuthenticateUserByName = ({ onSuccess, onError }: AuthenticateUserByNameMutation) => { @@ -51,7 +51,7 @@ const useAuthenticateUserByName = ({ onSuccess, onError }: AuthenticateUserByNam onError: async (error: Error) => { console.error('An error occurred connecting to the Jellyfin instance', error) - if (onError) onError() + if (onError) onError(error) }, retry: 0, gcTime: 0, diff --git a/src/components/AddToPlaylist/index.tsx b/src/components/AddToPlaylist/index.tsx index 1fb82da7..bbf79bae 100644 --- a/src/components/AddToPlaylist/index.tsx +++ b/src/components/AddToPlaylist/index.tsx @@ -3,7 +3,18 @@ import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models' import { addManyToPlaylist, addToPlaylist } from '../../api/mutations/playlists' import { useState } from 'react' import Toast from 'react-native-toast-message' -import { YStack, XStack, Spacer, YGroup, Separator, ListItem, getTokens, ScrollView } from 'tamagui' +import { + YStack, + XStack, + Spacer, + YGroup, + Separator, + ListItem, + getTokens, + ScrollView, + useTheme, + Spinner, +} from 'tamagui' import Icon from '../Global/components/icon' import { AddToPlaylistMutation } from './types' import { Text } from '../Global/helpers/text' @@ -16,6 +27,7 @@ import { usePlaylistTracks, useUserPlaylists } from '../../api/queries/playlist' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { useApi, useJellifyUser } from '../../stores' import Animated, { FadeIn, FadeOut } from 'react-native-reanimated' +import JellifyToastConfig from '../../configs/toast.config' export default function AddToPlaylist({ track, @@ -28,6 +40,8 @@ export default function AddToPlaylist({ }): React.JSX.Element { const { bottom } = useSafeAreaInsets() + const theme = useTheme() + const { data: playlists, isPending: playlistsFetchPending, @@ -69,6 +83,12 @@ export default function AddToPlaylist({ ))} )} + + ) } @@ -133,8 +153,8 @@ function AddToPlaylistRow({ animation={'quick'} disabled={isInPlaylist} hoverTheme - opacity={isInPlaylist ? 0.7 : 1} - pressStyle={{ opacity: 0.5 }} + opacity={isInPlaylist ? 0.5 : 1} + pressStyle={{ opacity: 0.6 }} onPress={() => { if (!isInPlaylist) { useAddToPlaylist.mutate({ @@ -159,6 +179,8 @@ function AddToPlaylistRow({ {isInPlaylist ? ( + ) : fetchingPlaylistTracks ? ( + ) : ( )} diff --git a/src/components/Context/index.tsx b/src/components/Context/index.tsx index e31eae8a..f86f005f 100644 --- a/src/components/Context/index.tsx +++ b/src/components/Context/index.tsx @@ -109,45 +109,40 @@ export default function ItemContext({ return ( // Tons of padding top for iOS on the scrollview otherwise the context sheet header overlaps the content - - - + + - {renderAddToQueueRow && } + {renderAddToQueueRow && } - {renderAddToQueueRow && } + {renderAddToQueueRow && } - {renderAddToPlaylistRow && ( - d.data) : undefined} - source={isAlbum ? item : undefined} - /> - )} + {renderAddToPlaylistRow && ( + d.data) : undefined} + source={isAlbum ? item : undefined} + /> + )} - {(streamingMediaSourceInfo || downloadedMediaSourceInfo) && ( - - )} + {(streamingMediaSourceInfo || downloadedMediaSourceInfo) && ( + + )} - {renderViewAlbumRow && ( - - )} + {renderViewAlbumRow && ( + + )} - {!isPlaylist && ( - - )} - - + {!isPlaylist && ( + + )} + ) } diff --git a/src/components/Global/components/icon.tsx b/src/components/Global/components/icon.tsx index 777903fc..00c85fc3 100644 --- a/src/components/Global/components/icon.tsx +++ b/src/components/Global/components/icon.tsx @@ -44,7 +44,7 @@ export default function Icon({ return ( (false) const imageViewStyle = useMemo( () => @@ -137,21 +136,24 @@ function Image({ ) return ( - - {image ? ( - - ) : ( - - )} - + + (!isLoaded && ( + + )) + setIsLoaded(true)} + testID={testID} + entering={FadeIn} + exiting={FadeOut} + style={Styles.blurhash} + /> + ) } diff --git a/src/components/Global/components/library-selector.tsx b/src/components/Global/components/library-selector.tsx index aa9b9e62..b02177d0 100644 --- a/src/components/Global/components/library-selector.tsx +++ b/src/components/Global/components/library-selector.tsx @@ -1,5 +1,5 @@ -import React, { useEffect, useState } from 'react' -import { getToken, Spinner, ToggleGroup, YStack } from 'tamagui' +import React, { useEffect, useMemo, useState } from 'react' +import { Spinner, ToggleGroup, XStack, YStack } from 'tamagui' import { H2, Text } from '../helpers/text' import Button from '../helpers/button' import { SafeAreaView } from 'react-native-safe-area-context' @@ -85,10 +85,37 @@ export default function LibrarySelector({ } }, [isPending, isSuccess, libraries]) + const libraryToggleItems = useMemo( + () => + musicLibraries.map((library) => { + const isSelected: boolean = selectedLibraryId === library.Id! + + return ( + + + {library.Name ?? 'Unnamed Library'} + + + ) + }), + [selectedLibraryId, musicLibraries], + ) + return ( - +

{title}

@@ -99,7 +126,7 @@ export default function LibrarySelector({ )}
- + {isPending ? ( ) : isError ? ( @@ -110,50 +137,42 @@ export default function LibrarySelector({ - {musicLibraries.map((library) => ( - - {library.Name ?? 'Unnamed Library'} - - ))} + {libraryToggleItems} )} - - - - - {showCancelButton && ( - - )} - + + + {showCancelButton && ( + + )} + + +
) diff --git a/src/components/Global/helpers/button.tsx b/src/components/Global/helpers/button.tsx index b185730c..2c51d98c 100644 --- a/src/components/Global/helpers/button.tsx +++ b/src/components/Global/helpers/button.tsx @@ -8,5 +8,15 @@ interface ButtonProps extends TamaguiButtonProps { } export default function Button(props: ButtonProps): React.JSX.Element { - return + return ( + + ) } diff --git a/src/components/Player/index.tsx b/src/components/Player/index.tsx index 39fc507a..a2e476ff 100644 --- a/src/components/Player/index.tsx +++ b/src/components/Player/index.tsx @@ -4,7 +4,7 @@ import { YStack, useTheme, ZStack, useWindowDimensions, View, getTokenValue } fr import Scrubber from './components/scrubber' import Controls from './components/controls' import Toast from 'react-native-toast-message' -import JellifyToastConfig from '../../constants/toast.config' +import JellifyToastConfig from '../../configs/toast.config' import { useFocusEffect } from '@react-navigation/native' import Footer from './components/footer' import BlurredBackground from './components/blurred-background' diff --git a/src/components/Settings/components/preferences-tab.tsx b/src/components/Settings/components/preferences-tab.tsx index 2d90488b..22c6245b 100644 --- a/src/components/Settings/components/preferences-tab.tsx +++ b/src/components/Settings/components/preferences-tab.tsx @@ -34,9 +34,12 @@ export default function PreferencesTab(): React.JSX.Element { onPress: () => void }) => (