Files
App/src/screens/index.tsx
T
Stephen Arg 5fb4eea5f8 Added Genre filtering to the Tracks library view with a multi-select genre picker. (#944)
* These changes include adding an Unplayed filter and also fixing shuffle all to shuffle based on the filtered selection

* Added genre filter and selection page

* Forgot to hit save on this file

* Fixed bug affecting genre filtering

* Shuffle all query now includes the genres

* Fixed trigger to triggerHaptic

* Fixed trigger to triggerHaptic

---------

Co-authored-by: StephenArg <stephen@vody.com>
Co-authored-by: Violet Caulfield <42452695+anultravioletaurora@users.noreply.github.com>
2026-01-30 07:40:04 -06:00

146 lines
3.9 KiB
TypeScript

import Player from './Player'
import Tabs from './Tabs'
import { RootStackParamList } from './types'
import { useTheme, YStack } from 'tamagui'
import Login from './Login'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import Context from './Context'
import { getItemName } from '../utils/formatting/item-names'
import AddToPlaylistSheet from './AddToPlaylist'
import TextTicker from 'react-native-text-ticker'
import { TextTickerConfig } from '../components/Player/component.config'
import { Text } from '../components/Global/helpers/text'
import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models'
import AudioSpecsSheet from './Stats'
import { useApi, useJellifyLibrary } from '../stores'
import DeletePlaylist from './Library/delete-playlist'
import { Platform } from 'react-native'
import { formatArtistNames } from '../utils/formatting/artist-names'
import FiltersSheet from './Filters'
import GenreSelectionScreen from './GenreSelection'
const RootStack = createNativeStackNavigator<RootStackParamList>()
export default function Root(): React.JSX.Element {
const theme = useTheme()
const api = useApi()
const [library] = useJellifyLibrary()
return (
<RootStack.Navigator initialRouteName={api && library ? 'Tabs' : 'Login'}>
<RootStack.Screen
name='Tabs'
component={Tabs}
options={{
headerShown: false,
navigationBarColor: theme.background.val,
gestureEnabled: false,
}}
/>
<RootStack.Screen
name='PlayerRoot'
component={Player}
options={{
// Form Sheet gives swipe to dismiss for Android, but royally fucks up the display on iOS
presentation: Platform.OS === 'android' ? 'formSheet' : 'modal',
sheetAllowedDetents: Platform.OS === 'android' ? [1.0] : undefined,
headerShown: false,
}}
/>
<RootStack.Screen
name='Login'
component={Login}
options={{
headerShown: false,
}}
/>
<RootStack.Screen
name='Context'
component={Context}
options={({ route }) => ({
header: () => ContextSheetHeader(route.params.item),
presentation: 'formSheet',
sheetAllowedDetents: 'fitToContents',
sheetGrabberVisible: true,
})}
/>
<RootStack.Screen
name='AddToPlaylist'
component={AddToPlaylistSheet}
options={{
headerTitle: 'Add to Playlist',
presentation: 'modal',
sheetGrabberVisible: true,
}}
/>
<RootStack.Screen
name='Filters'
component={FiltersSheet}
options={{
headerTitle: 'Filters',
presentation: 'formSheet',
sheetAllowedDetents: 'fitToContents',
sheetGrabberVisible: true,
}}
/>
<RootStack.Screen
name='AudioSpecs'
component={AudioSpecsSheet}
options={({ route }) => ({
header: () => ContextSheetHeader(route.params.item),
presentation: 'formSheet',
sheetAllowedDetents: 'fitToContents',
sheetGrabberVisible: true,
})}
/>
<RootStack.Screen
name='DeletePlaylist'
component={DeletePlaylist}
options={{
title: 'Delete Playlist',
presentation: 'formSheet',
headerShown: false,
sheetGrabberVisible: true,
sheetAllowedDetents: 'fitToContents',
}}
/>
<RootStack.Screen
name='GenreSelection'
component={GenreSelectionScreen}
options={{
headerTitle: 'Select Genres',
presentation: 'modal',
sheetGrabberVisible: true,
}}
/>
</RootStack.Navigator>
)
}
function ContextSheetHeader(item: BaseItemDto): React.JSX.Element {
return (
<YStack gap={'$1'} marginTop={'$4'} alignItems='center'>
<TextTicker {...TextTickerConfig}>
<Text bold fontSize={'$6'}>
{getItemName(item)}
</Text>
</TextTicker>
{(item.ArtistItems?.length ?? 0) > 0 && (
<TextTicker {...TextTickerConfig}>
<Text bold fontSize={'$4'}>
{`${formatArtistNames(item.ArtistItems?.map((artist) => getItemName(artist)) ?? [])}`}
</Text>
</TextTicker>
)}
</YStack>
)
}