(1) Play whole album when selecting a single track
(2) Create popup window on track long-press in which the track can be added to the end or front of the queue (3) Add Redux counter for added tracks so that the queue is properly updated
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { StackParams } from '../types';
|
||||
import { Text, ScrollView, Dimensions, Button, RefreshControl, StyleSheet } from 'react-native';
|
||||
import { useGetImage } from 'utility/JellyfinApi';
|
||||
import styled, { css } from 'styled-components/native';
|
||||
import { useRoute, RouteProp } from '@react-navigation/native';
|
||||
import { useRoute, RouteProp, useNavigation } from '@react-navigation/native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { differenceInDays } from 'date-fns';
|
||||
@@ -11,10 +11,10 @@ import { useTypedSelector } from 'store';
|
||||
import { fetchTracksByAlbum } from 'store/music/actions';
|
||||
import { ALBUM_CACHE_AMOUNT_OF_DAYS, THEME_COLOR } from 'CONSTANTS';
|
||||
import usePlayAlbum from 'utility/usePlayAlbum';
|
||||
import usePlayTrack from 'utility/usePlayTrack';
|
||||
import TouchableHandler from 'components/TouchableHandler';
|
||||
import useCurrentTrack from 'utility/useCurrentTrack';
|
||||
import { colors } from 'components/Colors';
|
||||
import TrackPlayer from 'react-native-track-player';
|
||||
|
||||
type Route = RouteProp<StackParams, 'Album'>;
|
||||
|
||||
@@ -71,11 +71,26 @@ const Album: React.FC = () => {
|
||||
const getImage = useGetImage();
|
||||
const playAlbum = usePlayAlbum();
|
||||
const currentTrack = useCurrentTrack();
|
||||
const navigation = useNavigation();
|
||||
|
||||
// Setup callbacks
|
||||
const selectAlbum = useCallback(() => { playAlbum(id); }, [playAlbum, id]);
|
||||
const selectTrack = usePlayTrack();
|
||||
const refresh = useCallback(() => { dispatch(fetchTracksByAlbum(id)); }, [id, dispatch]);
|
||||
const selectTrack = useCallback(async (trackId) => {
|
||||
const tracks = await playAlbum(id, false);
|
||||
|
||||
if (tracks) {
|
||||
const track = tracks.find((t) => t.id.startsWith(trackId));
|
||||
|
||||
if (track) {
|
||||
await TrackPlayer.skip(track.id);
|
||||
await TrackPlayer.play();
|
||||
}
|
||||
}
|
||||
}, [playAlbum, id]);
|
||||
const longPressTrack = useCallback((trackId: string) => {
|
||||
navigation.navigate('TrackPopupMenu', { trackId });
|
||||
}, [navigation]);
|
||||
|
||||
// Retrieve album tracks on load
|
||||
useEffect(() => {
|
||||
@@ -101,7 +116,12 @@ const Album: React.FC = () => {
|
||||
<Text style={styles.artist}>{album?.AlbumArtist}</Text>
|
||||
<Button title="Play Album" onPress={selectAlbum} color={THEME_COLOR} />
|
||||
{album?.Tracks?.length ? album.Tracks.map((trackId) =>
|
||||
<TouchableHandler key={trackId} id={trackId} onPress={selectTrack}>
|
||||
<TouchableHandler
|
||||
key={trackId}
|
||||
id={trackId}
|
||||
onPress={selectTrack}
|
||||
onLongPress={longPressTrack}
|
||||
>
|
||||
<TrackContainer isPlaying={currentTrack?.id.startsWith(trackId) || false} style={colors.border}>
|
||||
<Text style={styles.index}>
|
||||
{tracks[trackId]?.IndexNumber}
|
||||
|
||||
@@ -12,8 +12,10 @@ import GearIcon from 'assets/gear.svg';
|
||||
import { THEME_COLOR } from 'CONSTANTS';
|
||||
import { useTypedSelector } from 'store';
|
||||
import Onboarding from './Onboarding';
|
||||
import TrackPopupMenu from './modals/TrackPopupMenu';
|
||||
import { ModalStackParams } from './types';
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
const Stack = createStackNavigator<ModalStackParams>();
|
||||
const Tab = createBottomTabNavigator();
|
||||
|
||||
type Screens = {
|
||||
@@ -84,6 +86,7 @@ export default function Routes() {
|
||||
}}>
|
||||
<Stack.Screen name="Screens" component={Screens} />
|
||||
<Stack.Screen name="SetJellyfinServer" component={SetJellyfinServer} />
|
||||
<Stack.Screen name="TrackPopupMenu" component={TrackPopupMenu} />
|
||||
</Stack.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
59
src/screens/modals/TrackPopupMenu.tsx
Normal file
59
src/screens/modals/TrackPopupMenu.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import Modal from 'components/Modal';
|
||||
import { Text, Button } from 'react-native';
|
||||
import { useNavigation, StackActions, useRoute, RouteProp } from '@react-navigation/native';
|
||||
import { ModalStackParams } from 'screens/types';
|
||||
import { useTypedSelector } from 'store';
|
||||
import { THEME_COLOR } from 'CONSTANTS';
|
||||
import { SubHeader } from 'components/Typography';
|
||||
import styled from 'styled-components/native';
|
||||
import usePlayTrack from 'utility/usePlayTrack';
|
||||
|
||||
type Route = RouteProp<ModalStackParams, 'TrackPopupMenu'>;
|
||||
|
||||
const Container = styled.View`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
const Buttons = styled.View`
|
||||
margin-top: 20px;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
`;
|
||||
|
||||
function TrackPopupMenu() {
|
||||
// Retrieve helpers
|
||||
const { params: { trackId } } = useRoute<Route>();
|
||||
const navigation = useNavigation();
|
||||
const track = useTypedSelector((state) => state.music.tracks.entities[trackId]);
|
||||
const playTrack = usePlayTrack();
|
||||
|
||||
// Set callback to close the modal
|
||||
const closeModal = useCallback(() => {
|
||||
navigation.dispatch(StackActions.popToTop());
|
||||
}, [navigation]);
|
||||
|
||||
const handlePlayNext = useCallback(() => {
|
||||
playTrack(trackId, false, false);
|
||||
closeModal();
|
||||
}, [playTrack, closeModal, trackId]);
|
||||
const handleAddToQueue = useCallback(() => {
|
||||
playTrack(trackId, false, true);
|
||||
closeModal();
|
||||
}, [playTrack, closeModal, trackId]);
|
||||
|
||||
return (
|
||||
<Modal fullSize={false}>
|
||||
<Container>
|
||||
<SubHeader>{track?.Name}</SubHeader>
|
||||
<Text>{track?.Album} - {track?.AlbumArtist}</Text>
|
||||
<Buttons>
|
||||
<Button title="Play Next" color={THEME_COLOR} onPress={handlePlayNext} />
|
||||
<Button title="Add to Queue" color={THEME_COLOR} onPress={handleAddToQueue} />
|
||||
</Buttons>
|
||||
</Container>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default TrackPopupMenu;
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ModalStackParams {
|
||||
SetJellyfinServer: undefined;
|
||||
TrackPopupMenu: { trackId: string };
|
||||
}
|
||||
Reference in New Issue
Block a user