Skip to content

Commit 58a74b0

Browse files
committed
Add: save queue option #86
1 parent 2ec0fca commit 58a74b0

13 files changed

Lines changed: 133 additions & 41 deletions

File tree

App.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ const App = () => {
8585
else global.isSongCaching = settings.isSongCaching
8686
}, [settings.isSongCaching])
8787

88+
React.useEffect(() => {
89+
global.saveQueue = settings.saveQueue
90+
}, [settings.saveQueue])
91+
8892
React.useEffect(() => {
8993
const sysLang = localeLang()
9094

app/components/lists/HorizontalArtists.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import React from 'react';
2-
import { Text, StyleSheet, Pressable } from 'react-native';
3-
import { useNavigation } from '@react-navigation/native';
1+
import React from 'react'
2+
import { Text, StyleSheet, Pressable } from 'react-native'
3+
import { useNavigation } from '@react-navigation/native'
44

5-
import { ConfigContext } from '~/contexts/config';
6-
import { ThemeContext } from '~/contexts/theme';
7-
import { urlCover } from '~/utils/url';
8-
import CustomFlat from '~/components/lists/CustomFlat';
9-
import ImageError from '~/components/ImageError';
10-
import mainStyles from '~/styles/main';
11-
import OptionsArtists from '~/components/options/OptionsArtists';
12-
import size from '~/styles/size';
5+
import { ConfigContext } from '~/contexts/config'
6+
import { ThemeContext } from '~/contexts/theme'
7+
import { urlCover } from '~/utils/url'
8+
import CustomFlat from '~/components/lists/CustomFlat'
9+
import ImageError from '~/components/ImageError'
10+
import mainStyles from '~/styles/main'
11+
import OptionsArtists from '~/components/options/OptionsArtists'
12+
import size from '~/styles/size'
1313

1414
const HorizontalArtists = ({ artists, onPress = () => { } }) => {
15-
const navigation = useNavigation();
15+
const navigation = useNavigation()
1616
const theme = React.useContext(ThemeContext)
1717
const config = React.useContext(ConfigContext)
1818
const [indexOptions, setIndexOptions] = React.useState(-1)
@@ -38,7 +38,7 @@ const HorizontalArtists = ({ artists, onPress = () => { } }) => {
3838
/>
3939
<Text numberOfLines={1} style={{ color: theme.primaryText, fontSize: size.text.medium, marginBottom: 2, width: 100, textAlign: 'center' }}>{item.name}</Text>
4040
</Pressable>
41-
), [theme, config, onPress]);
41+
), [theme, config, onPress])
4242

4343
return (
4444
<>
@@ -70,4 +70,4 @@ const styles = StyleSheet.create({
7070
},
7171
})
7272

73-
export default HorizontalArtists;
73+
export default HorizontalArtists

app/components/lists/HorizontalList.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ThemeContext } from '~/contexts/theme'
1010
import { SettingsContext, homeSections } from '~/contexts/settings'
1111
import { ConfigContext } from '~/contexts/config'
1212
import { UpdateApiContext, isUpdatable } from '~/contexts/updateApi'
13+
import HorizontalQueue from '~/components/lists/HorizontalQueue'
1314
import HorizontalAlbums from '~/components/lists/HorizontalAlbums'
1415
import HorizontalArtists from '~/components/lists/HorizontalArtists'
1516
import HorizontalGenres from '~/components/lists/HorizontalGenres'
@@ -109,6 +110,7 @@ const HorizontalList = ({ refresh, id, enable }) => {
109110
/>
110111
}
111112
</Pressable>
113+
{section.type === 'queue' && <HorizontalQueue current={list.current} queue={list.entry} />}
112114
{section.type === 'album' && <HorizontalAlbums albums={list} />}
113115
{section.type === 'album_star' && <HorizontalAlbums albums={list} />}
114116
{section.type === 'artist' && <HorizontalArtists artists={list} />}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React from 'react'
2+
import { View, Text, Pressable } from 'react-native'
3+
4+
import { ConfigContext } from '~/contexts/config'
5+
import { ThemeContext } from '~/contexts/theme'
6+
import { urlCover } from '~/utils/url'
7+
import { playSong } from '~/utils/player'
8+
import { SongDispatchContext } from '~/contexts/song'
9+
import ImageError from '~/components/ImageError'
10+
import mainStyles from '~/styles/main'
11+
import size from '~/styles/size'
12+
13+
const HorizontalQueue = ({ current, queue }) => {
14+
const theme = React.useContext(ThemeContext)
15+
const config = React.useContext(ConfigContext)
16+
const songDispatch = React.useContext(SongDispatchContext)
17+
const [currentTrack, setCurrentTrack] = React.useState(null)
18+
19+
React.useEffect(() => {
20+
setCurrentTrack(queue?.find(item => current === item.id) || null)
21+
}, [queue, current])
22+
23+
if (!queue?.length || !currentTrack) return null
24+
return (
25+
<Pressable
26+
onPress={() => playSong(config, songDispatch, queue, queue.findIndex(item => current === item.id))}
27+
style={{
28+
marginHorizontal: 20,
29+
flexDirection: 'row',
30+
alignItems: 'center',
31+
gap: 10,
32+
}}
33+
>
34+
<ImageError
35+
source={{ uri: urlCover(config, currentTrack) }}
36+
style={{ height: size.image.medium, width: size.image.medium, borderRadius: 5 }}
37+
/>
38+
<View style={{ flex: 1, gap: 5 }}>
39+
<Text style={mainStyles.mediumText(theme.primaryText)} numberOfLines={1}>
40+
{currentTrack.title}
41+
</Text>
42+
<Text style={mainStyles.smallText(theme.secondaryText)} numberOfLines={1}>
43+
{currentTrack.artist}
44+
</Text>
45+
</View>
46+
<Text style={mainStyles.smallText(theme.secondaryText)}>+ {queue.length - 1}</Text>
47+
</Pressable>
48+
)
49+
}
50+
51+
export default HorizontalQueue

app/contexts/settings.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export const defaultSettings = {
3333
// Home Settings
3434
homeOrderV2: [
3535
{ id: 'week-activity', enable: false },
36+
{ id: 'last-queue', enable: false },
3637
{ id: 'favorited-artist', enable: true },
3738
{ id: 'genre', enable: false },
3839
{ id: 'radio', enable: false },
@@ -55,6 +56,7 @@ export const defaultSettings = {
5556
cacheNextSong: 5,
5657
showCache: true,
5758
// Player settings
59+
saveQueue: false,
5860
streamFormat: 'raw',
5961
maxBitRate: 0,
6062
playSeedFirst: false,
@@ -76,6 +78,16 @@ export const homeSections = [
7678
query: '',
7779
getInfo: () => { },
7880
},
81+
{
82+
icon: 'list',
83+
id: 'last-queue',
84+
title: 'Last queue',
85+
type: 'queue',
86+
isShowAll: false,
87+
path: 'getPlayQueue',
88+
query: '',
89+
getInfo: (json, setList) => setList(json?.playQueue),
90+
},
7991
{
8092
icon: 'user',
8193
id: 'favorited-artist',

app/i18next/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
},
99
"homeSection": {
1010
"Week Activity": "Week Activity",
11+
"Last queue": "Last queue",
1112
"Favorited Artist": "Favorited Artist",
1213
"Genre": "Genre",
1314
"Radio": "Radio",

app/screens/Settings/Home.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import React from 'react';
2-
import { Text, View, ScrollView } from 'react-native';
3-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
4-
import { useTranslation } from 'react-i18next';
1+
import React from 'react'
2+
import { Text, View, ScrollView } from 'react-native'
3+
import { useSafeAreaInsets } from 'react-native-safe-area-context'
4+
import { useTranslation } from 'react-i18next'
55

6-
import { SettingsContext, SetSettingsContext } from '~/contexts/settings';
7-
import { ThemeContext } from '~/contexts/theme';
8-
import ButtonSwitch from '~/components/settings/ButtonSwitch';
9-
import Header from '~/components/Header';
10-
import HomeOrder from '~/components/settings/HomeOrder';
11-
import OptionInput from '~/components/settings/OptionInput';
12-
import mainStyles from '~/styles/main';
13-
import settingStyles from '~/styles/settings';
6+
import { SettingsContext, SetSettingsContext } from '~/contexts/settings'
7+
import { ThemeContext } from '~/contexts/theme'
8+
import ButtonSwitch from '~/components/settings/ButtonSwitch'
9+
import Header from '~/components/Header'
10+
import HomeOrder from '~/components/settings/HomeOrder'
11+
import OptionInput from '~/components/settings/OptionInput'
12+
import mainStyles from '~/styles/main'
13+
import settingStyles from '~/styles/settings'
1414

1515
const HomeSettings = () => {
16-
const { t } = useTranslation();
16+
const { t } = useTranslation()
1717
const insets = useSafeAreaInsets()
1818
const theme = React.useContext(ThemeContext)
1919
const settings = React.useContext(SettingsContext)
@@ -91,4 +91,4 @@ const HomeSettings = () => {
9191
)
9292
}
9393

94-
export default HomeSettings;
94+
export default HomeSettings

app/screens/Settings/Player.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react'
22
import { View, Text, ScrollView } from 'react-native'
33
import { useSafeAreaInsets } from 'react-native-safe-area-context'
4-
import { useTranslation } from 'react-i18next';
4+
import { useTranslation } from 'react-i18next'
55

66
import { SettingsContext } from '~/contexts/settings'
77
import { SetSettingsContext } from '~/contexts/settings'
@@ -93,6 +93,15 @@ const PlayerSettings = () => {
9393
isLast
9494
/>
9595
</View>
96+
<Text style={settingStyles.titleContainer(theme)}>{t('settings.player.Save queue')}</Text>
97+
<View style={settingStyles.optionsContainer(theme)}>
98+
<ButtonSwitch
99+
title={t('settings.player.Save queue')}
100+
value={settings.saveQueue}
101+
onPress={() => setSettings({ ...settings, saveQueue: !settings.saveQueue })}
102+
isLast
103+
/>
104+
</View>
96105
</View>
97106
</ScrollView>
98107
)

app/styles/main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { StyleSheet } from "react-native";
2-
import size from "~/styles/size";
1+
import { StyleSheet } from "react-native"
2+
import size from "~/styles/size"
33

44
export default StyleSheet.create({
55
mainContainer: (theme) => ({

app/utils/player.native.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import TrackPlayer, { AppKilledPlaybackBehavior, Capability, RepeatMode, State, useProgress, Event, useTrackPlayerEvents } from 'react-native-track-player';
2-
import * as FileSystem from 'expo-file-system';
3-
import AsyncStorage from '@react-native-async-storage/async-storage';
1+
import TrackPlayer, { AppKilledPlaybackBehavior, Capability, RepeatMode, State, useProgress, Event, useTrackPlayerEvents } from 'react-native-track-player'
2+
import * as FileSystem from 'expo-file-system'
3+
import AsyncStorage from '@react-native-async-storage/async-storage'
44

5-
import { urlCover, urlStream } from '~/utils/url';
6-
import { isSongCached, getPathSong } from '~/utils/cache';
7-
import { nextRandomIndex, prevRandomIndex } from '~/utils/tools';
8-
import logger from '~/utils/logger';
5+
import { urlCover, urlStream } from '~/utils/url'
6+
import { isSongCached, getPathSong } from '~/utils/cache'
7+
import { nextRandomIndex, prevRandomIndex, saveQueue } from '~/utils/tools'
8+
import logger from '~/utils/logger'
99

1010
export const initService = async () => {
11-
TrackPlayer.registerPlaybackService(() => require('~/services/servicePlayback'));
11+
TrackPlayer.registerPlaybackService(() => require('~/services/servicePlayback'))
1212
}
1313

1414
export const initPlayer = async (songDispatch) => {
@@ -186,6 +186,7 @@ export const playSong = async (config, songDispatch, queue, index) => {
186186
loadSong(config, queue, index)
187187
songDispatch({ type: 'setQueue', queue, index })
188188
setRepeat(songDispatch, 'next')
189+
saveQueue(config, queue, index)
189190
}
190191

191192
export const secondToTime = (second) => {

0 commit comments

Comments
 (0)