getting ready for library

This commit is contained in:
Violet Caulfield
2025-01-15 10:36:08 -06:00
parent 9f94739be8
commit 21e1734768
12 changed files with 173 additions and 62 deletions

View File

@@ -2,7 +2,7 @@ import { ScrollView, useWindowDimensions } from "tamagui";
import { useArtistAlbums } from "../../api/queries/artist";
import { useApiClientContext } from "../jellyfin-api-provider";
import { FlatList } from "react-native";
import { Card } from "../Global/helpers/card";
import { ItemCard } from "../Global/helpers/item-card";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { StackParamList } from "../types";
import { H2 } from "../Global/helpers/text";
@@ -60,7 +60,7 @@ export default function Artist(props: ArtistProps): React.JSX.Element {
numColumns={columns} // TODO: Make this adjustable
renderItem={({ item: album }) => {
return (
<Card
<ItemCard
caption={album.Name}
subCaption={album.ProductionYear?.toString()}
width={(width / 1.1) / columns}

View File

@@ -3,7 +3,10 @@ import Artist from "../component";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { StackParamList } from "../../types";
export function ArtistScreen({ route, navigation } : {
export function ArtistScreen({
route,
navigation
} : {
route: RouteProp<StackParamList, "Artist">,
navigation: NativeStackNavigationProp<StackParamList>
}): React.JSX.Element {

View File

@@ -0,0 +1,62 @@
import { Card, View } from "tamagui";
import { H5, Text } from "./text";
export default function IconCard({
name,
onPress,
caption,
subCaption,
}: {
name: string,
onPress: () => void,
caption?: string | undefined,
subCaption?: string | undefined
}) : React.JSX.Element {
return (
<View
alignItems="center"
margin={5}
>
<Card
elevate
size="$4"
borderRadius={25}
animation="bouncy"
hoverStyle={{ scale: 0.925 }}
pressStyle={{ scale: 0.875 }}
width={150}
height={150}
onPress={onPress}
>
<Card.Header>
</Card.Header>
<Card.Footer padded>
</Card.Footer>
<Card.Background>
</Card.Background>
</Card>
{ caption && (
<View
alignContent="center"
alignItems="center"
>
<H5>
{ caption }
</H5>
{ subCaption && (
<Text
lineBreakStrategyIOS="standard"
numberOfLines={1}
textAlign="center"
>
{ subCaption }
</Text>
)}
</View>
)}
</View>
)
}

View File

@@ -19,7 +19,7 @@ interface CardProps extends TamaguiCardProps {
cornered?: boolean;
}
export function Card(props: CardProps) {
export function ItemCard(props: CardProps) {
const { apiClient } = useApiClientContext();

View File

@@ -1,18 +1,12 @@
import { H3, ScrollView, Separator, XStack, YStack } from "tamagui";
import _ from "lodash";
import RecentlyPlayed from "./helpers/recently-played";
import { useApiClientContext } from "../jellyfin-api-provider";
import RecentArtists from "./helpers/recent-artists";
import { RefreshControl } from "react-native";
import { HomeProvider, useHomeContext } from "./provider";
import { HomeProvider } from "./provider";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { StackParamList, ProvidedHomeProps } from "../types";
import { ArtistScreen } from "../Artist/screens";
import Avatar from "../Global/helpers/avatar";
import { AlbumScreen } from "../Album/screens";
import Playlists from "./helpers/playlists";
import { SafeAreaView } from "react-native-safe-area-context";
import { PlaylistScreen } from "../Playlist/screens";
import { ProvidedHome } from "./screens";
const HomeStack = createNativeStackNavigator<StackParamList>();
@@ -71,44 +65,4 @@ export default function Home(): React.JSX.Element {
</HomeStack.Navigator>
</HomeProvider>
);
}
function ProvidedHome({ route, navigation }: ProvidedHomeProps): React.JSX.Element {
const { user } = useApiClientContext();
const { refreshing: refetching, onRefresh: onRefetch } = useHomeContext()
return (
<SafeAreaView edges={["top", "right", "left"]}>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
refreshControl={
<RefreshControl
refreshing={refetching}
onRefresh={onRefetch}
/>
}>
<YStack alignContent='flex-start'>
<XStack margin={"$2"}>
<H3>{`Hi, ${user!.name}`}</H3>
<YStack />
<Avatar maxHeight={30} itemId={user!.id} />
</XStack>
<Separator marginVertical={"$2"} />
<RecentArtists route={route} navigation={navigation} />
<Separator marginVertical={"$3"} />
<RecentlyPlayed />
<Separator marginVertical={"$3"} />
<Playlists route={route} navigation={navigation}/>
</YStack>
</ScrollView>
</SafeAreaView>
);
}

View File

@@ -1,5 +1,5 @@
import { useUserPlaylists } from "@/api/queries/playlist";
import { Card } from "@/components/Global/helpers/card";
import { ItemCard } from "@/components/Global/helpers/item-card";
import { H2 } from "@/components/Global/helpers/text";
import { useApiClientContext } from "@/components/jellyfin-api-provider";
import { ProvidedHomeProps } from "@/components/types";
@@ -20,7 +20,7 @@ export default function Playlists({ navigation }: ProvidedHomeProps) : React.JSX
data={playlists}
renderItem={({ item: playlist }) => {
return (
<Card
<ItemCard
itemId={playlist.Id!}
caption={playlist.Name ?? "Untitled Playlist"}
onPress={() => {

View File

@@ -4,7 +4,7 @@ import { useHomeContext } from "../provider";
import { H2 } from "../../Global/helpers/text";
import { ProvidedHomeProps } from "../../types";
import { FlatList } from "react-native";
import { Card } from "../../Global/helpers/card";
import { ItemCard } from "../../Global/helpers/item-card";
import { getPrimaryBlurhashFromDto } from "../../../helpers/blurhash";
export default function RecentArtists({ navigation }: ProvidedHomeProps): React.JSX.Element {
@@ -18,7 +18,7 @@ export default function RecentArtists({ navigation }: ProvidedHomeProps): React.
data={recentArtists}
renderItem={({ item: recentArtist}) => {
return (
<Card
<ItemCard
artistName={recentArtist.Name!}
blurhash={getPrimaryBlurhashFromDto(recentArtist)}
itemId={recentArtist.Id!}
@@ -31,7 +31,7 @@ export default function RecentArtists({ navigation }: ProvidedHomeProps): React.
}
)}
}>
</Card>
</ItemCard>
)
}}
/>

View File

@@ -2,7 +2,7 @@ import React from "react";
import { ScrollView, View } from "tamagui";
import { useHomeContext } from "../provider";
import { H2 } from "../../Global/helpers/text";
import { Card } from "../../Global/helpers/card";
import { ItemCard } from "../../Global/helpers/item-card";
import { useApiClientContext } from "../../jellyfin-api-provider";
import { usePlayerContext } from "../../../player/provider";
@@ -18,7 +18,7 @@ export default function RecentlyPlayed(): React.JSX.Element {
<ScrollView horizontal>
{ recentTracks && recentTracks.map((recentlyPlayedTrack, index) => {
return (
<Card
<ItemCard
caption={recentlyPlayedTrack.Name}
subCaption={`${recentlyPlayedTrack.Artists?.join(", ")}`}
cornered

View File

@@ -0,0 +1,51 @@
import { useApiClientContext } from "@/components/jellyfin-api-provider";
import { ProvidedHomeProps } from "@/components/types";
import { ScrollView, RefreshControl } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { YStack, XStack, Separator } from "tamagui";
import Playlists from "../helpers/playlists";
import RecentArtists from "../helpers/recent-artists";
import RecentlyPlayed from "../helpers/recently-played";
import { useHomeContext } from "../provider";
import { H3 } from "@/components/Global/helpers/text";
import Avatar from "@/components/Global/helpers/avatar";
export function ProvidedHome({ route, navigation }: ProvidedHomeProps): React.JSX.Element {
const { user } = useApiClientContext();
const { refreshing: refetching, onRefresh: onRefetch } = useHomeContext()
return (
<SafeAreaView edges={["top", "right", "left"]}>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
refreshControl={
<RefreshControl
refreshing={refetching}
onRefresh={onRefetch}
/>
}>
<YStack alignContent='flex-start'>
<XStack margin={"$2"}>
<H3>{`Hi, ${user!.name}`}</H3>
<YStack />
<Avatar maxHeight={30} itemId={user!.id!} />
</XStack>
<Separator marginVertical={"$2"} />
<RecentArtists route={route} navigation={navigation} />
<Separator marginVertical={"$3"} />
<RecentlyPlayed />
<Separator marginVertical={"$3"} />
<Playlists route={route} navigation={navigation}/>
</YStack>
</ScrollView>
</SafeAreaView>
);
}

View File

@@ -0,0 +1,16 @@
import { StackParamList } from "@/components/types";
interface CategoryRoute {
name: any; // ¯\_(ツ)_/¯
iconName: string;
};
const Categories : CategoryRoute[] = [
{ name: "Artists", iconName: "microphone-variant" },
{ name: "Albums", iconName: "music-box-multiple" },
{ name: "Tracks", iconName: "music-note"},
{ name: "Playlists", iconName: "playlist-music"},
{ name: "Genres", iconName: "guitar-electric"}
];
export default Categories;

View File

@@ -1,9 +1,34 @@
import { FlatList } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import Categories from "./categories";
import IconCard from "@/components/Global/helpers/icon-card";
import { StackParamList } from "@/components/types";
import { RouteProp } from "@react-navigation/native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
export default function LibraryScreen(): React.JSX.Element {
export default function LibraryScreen({
route,
navigation
} : {
route: RouteProp<StackParamList, "Library">,
navigation: NativeStackNavigationProp<StackParamList>
}): React.JSX.Element {
return (
<SafeAreaView>
<FlatList
data={Categories}
numColumns={2}
renderItem={({ index, item }) => {
return (
<IconCard
name={item.iconName}
onPress={() => {
navigation.navigate(item.name)
}}
/>
)
}}
/>
</SafeAreaView>
)
}

View File

@@ -1,6 +1,6 @@
{
"name": "jellify",
"version": "0.0.1",
"version": "0.1.0",
"private": true,
"scripts": {
"android": "react-native run-android",