Skip to content

Commit 6866bb1

Browse files
committed
Add: cache options (download, play only)
1 parent 4701826 commit 6866bb1

17 files changed

Lines changed: 130 additions & 45 deletions

App.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const App = () => {
4646
.then((settings) => {
4747
setSettings(settings)
4848
})
49+
global.songsDownloading = []
4950
}, [])
5051

5152
React.useEffect(() => {

app/components/options/OptionsAlbum.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ import { useNavigation } from '@react-navigation/native'
44
import { useTranslation } from 'react-i18next'
55

66
import { ConfigContext } from '~/contexts/config'
7-
import { getApi } from '~/utils/api'
8-
import { getApiNetworkFirst } from '~/utils/api'
9-
import { playSong } from '~/utils/player'
7+
import { getApi, getApiNetworkFirst, urlStream } from '~/utils/api'
8+
import { playSong, downloadSong } from '~/utils/player'
109
import { SongDispatchContext } from '~/contexts/song'
10+
import { SettingsContext } from '~/contexts/settings'
1111
import OptionsPopup from '~/components/popup/OptionsPopup'
1212

1313
const OptionsAlbum = ({ album, isOpen, onClose }) => {
1414
const { t } = useTranslation()
15-
const navigation = useNavigation()
1615
const config = React.useContext(ConfigContext)
16+
const navigation = useNavigation()
1717
const refOption = React.useRef()
18+
const settings = React.useContext(SettingsContext)
1819
const songDispatch = React.useContext(SongDispatchContext)
1920

2021
const playSimilarSongs = () => {
@@ -33,7 +34,7 @@ const OptionsAlbum = ({ album, isOpen, onClose }) => {
3334
visible={isOpen}
3435
close={() => {
3536
onClose()
36-
refOption.current.clearVirtualOptions()
37+
refOption.current.clearVirtualOptions()
3738
}}
3839
item={album}
3940
options={[
@@ -42,6 +43,16 @@ const OptionsAlbum = ({ album, isOpen, onClose }) => {
4243
icon: 'play',
4344
onPress: playSimilarSongs
4445
},
46+
{
47+
name: t('Cache all songs'),
48+
icon: 'cloud-download',
49+
onPress: async () => {
50+
refOption.current.close()
51+
for (const song of album.song) {
52+
await downloadSong(urlStream(config, song.id, settings.streamFormat, settings.maxBitRate), song.id)
53+
}
54+
}
55+
},
4556
{
4657
name: t('Go to genre'),
4758
icon: 'tag',

app/components/options/OptionsPlaylist.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ import { useNavigation } from '@react-navigation/native'
44
import { useTranslation } from 'react-i18next'
55

66
import { ConfigContext } from '~/contexts/config'
7-
import { getApi } from '~/utils/api'
7+
import { getApi, urlStream } from '~/utils/api'
8+
import { downloadSong } from '~/utils/player'
9+
import { SettingsContext } from '~/contexts/settings'
810
import OptionsPopup from '~/components/popup/OptionsPopup'
911

1012
const OptionsPlaylist = ({ playlist, open, onClose, onRefresh }) => {
1113
const { t } = useTranslation()
1214
const navigation = useNavigation()
1315
const config = React.useContext(ConfigContext)
1416
const refOption = React.useRef()
17+
const settings = React.useContext(SettingsContext)
1518

1619
if (!playlist) return null
1720
return (
@@ -21,6 +24,16 @@ const OptionsPlaylist = ({ playlist, open, onClose, onRefresh }) => {
2124
close={onClose}
2225
item={playlist}
2326
options={[
27+
{
28+
name: t('Cache all songs'),
29+
icon: 'cloud-download',
30+
onPress: async () => {
31+
refOption.current.close()
32+
for (const song of playlist.entry) {
33+
await downloadSong(urlStream(config, song.id, settings.streamFormat, settings.maxBitRate), song.id)
34+
}
35+
}
36+
},
2437
{
2538
name: t('Edit playlist'),
2639
icon: 'pencil',

app/components/options/OptionsSongsList.js

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,35 @@
1-
import React from 'react';
2-
import { Platform, Share } from 'react-native';
3-
import { useNavigation } from '@react-navigation/native';
4-
import { useTranslation } from 'react-i18next';
5-
6-
import { ConfigContext } from '~/contexts/config';
7-
import { getApi, getApiNetworkFirst, urlStream } from '~/utils/api';
8-
import { playSong, addToQueue } from '~/utils/player';
9-
import { SongContext, SongDispatchContext } from '~/contexts/song';
10-
import { urlCover } from '~/utils/api';
11-
import size from '~/styles/size';
12-
import OptionsPopup from '~/components/popup/OptionsPopup';
13-
import { SettingsContext } from '~/contexts/settings';
1+
import React from 'react'
2+
import { Platform, Share } from 'react-native'
3+
import { useNavigation } from '@react-navigation/native'
4+
import { useTranslation } from 'react-i18next'
5+
6+
import { ConfigContext } from '~/contexts/config'
7+
import { getApi, getApiNetworkFirst, urlStream } from '~/utils/api'
8+
import { isSongCached } from '~/utils/cache'
9+
import { playSong, addToQueue } from '~/utils/player'
10+
import { SettingsContext } from '~/contexts/settings'
11+
import { SongContext, SongDispatchContext } from '~/contexts/song'
12+
import { urlCover } from '~/utils/api'
13+
import OptionsPopup from '~/components/popup/OptionsPopup'
14+
import size from '~/styles/size'
1415

1516
const OptionsSongsList = ({ songs, indexOptions, setIndexOptions, onUpdate = () => { }, idPlaylist = null }) => {
16-
const { t } = useTranslation();
17-
const navigation = useNavigation();
18-
const song = React.useContext(SongContext);
19-
const songDispatch = React.useContext(SongDispatchContext);
20-
const config = React.useContext(ConfigContext);
21-
const settings = React.useContext(SettingsContext);
22-
const refOption = React.useRef();
17+
const { t } = useTranslation()
18+
const navigation = useNavigation()
19+
const song = React.useContext(SongContext)
20+
const songDispatch = React.useContext(SongDispatchContext)
21+
const config = React.useContext(ConfigContext)
22+
const settings = React.useContext(SettingsContext)
23+
const refOption = React.useRef()
24+
const [isCached, setIsCached] = React.useState(false)
25+
26+
React.useEffect(() => {
27+
if (indexOptions < 0) return
28+
isSongCached(config, songs[indexOptions]?.id, settings.streamFormat, settings.maxBitrate)
29+
.then((cached) => {
30+
setIsCached(cached ? true : false)
31+
})
32+
}, [indexOptions])
2333

2434
const playSimilarSongs = () => {
2535
getApiNetworkFirst(config, 'getSimilarSongs', `id=${songs[indexOptions].id}&count=50`)
@@ -56,7 +66,7 @@ const OptionsSongsList = ({ songs, indexOptions, setIndexOptions, onUpdate = ()
5666
borderRadius: size.radius.circle,
5767
onPress: () => {
5868
navigation.navigate('Artist', { id: artist.id, name: artist.name })
59-
refOption.current.close();
69+
refOption.current.close()
6070
}
6171
})
6272

@@ -95,7 +105,7 @@ const OptionsSongsList = ({ songs, indexOptions, setIndexOptions, onUpdate = ()
95105
onPress: () => addToPlaylist(playlist)
96106
}))
97107
]
98-
);
108+
)
99109
})
100110
.catch(() => { })
101111
}
@@ -123,13 +133,13 @@ const OptionsSongsList = ({ songs, indexOptions, setIndexOptions, onUpdate = ()
123133
fetch(urlStream(config, songs[indexOptions].id))
124134
.then((res) => res.blob())
125135
.then((data) => {
126-
const a = document.createElement('a');
127-
a.download = `${songs[indexOptions].artist} - ${songs[indexOptions].title}.mp3`;
128-
a.href = URL.createObjectURL(data);
136+
const a = document.createElement('a')
137+
a.download = `${songs[indexOptions].artist} - ${songs[indexOptions].title}.mp3`
138+
a.href = URL.createObjectURL(data)
129139
a.addEventListener('click', () => {
130-
setTimeout(() => URL.revokeObjectURL(a.href), 1 * 1000);
131-
});
132-
a.click();
140+
setTimeout(() => URL.revokeObjectURL(a.href), 1 * 1000)
141+
})
142+
a.click()
133143
})
134144
.catch(() => { })
135145
}
@@ -146,6 +156,20 @@ const OptionsSongsList = ({ songs, indexOptions, setIndexOptions, onUpdate = ()
146156
refOption.current.close()
147157
}
148158

159+
const playOnlyCached = async () => {
160+
const cachedList = []
161+
let indexPlay = 0
162+
163+
for (let index = 0; index < songs.length; index++) {
164+
const cached = await isSongCached(config, songs[index].id, settings.streamFormat, settings.maxBitrate)
165+
if (index === indexOptions) indexPlay = cachedList.length
166+
if (cached) cachedList.push(songs[index])
167+
}
168+
playSong(config, songDispatch, cachedList, indexPlay)
169+
refOption.current.close()
170+
}
171+
172+
if (indexOptions < 0) return null
149173
return (
150174
<OptionsPopup
151175
ref={refOption}
@@ -161,6 +185,12 @@ const OptionsSongsList = ({ songs, indexOptions, setIndexOptions, onUpdate = ()
161185
icon: 'play',
162186
onPress: playSimilarSongs
163187
},
188+
{
189+
name: t('Play only cached songs'),
190+
icon: 'cloud-download',
191+
onPress: playOnlyCached,
192+
hidden: !isCached
193+
},
164194
{
165195
name: t('Play next'),
166196
icon: 'indent',
@@ -212,7 +242,7 @@ const OptionsSongsList = ({ songs, indexOptions, setIndexOptions, onUpdate = ()
212242
}
213243
},
214244
]} />
215-
);
245+
)
216246
}
217247

218-
export default OptionsSongsList;
248+
export default OptionsSongsList

app/i18next/ca.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"Albums": "Àlbums",
111111
"Artist": "Artista",
112112
"Artists": "Artistes",
113+
"Cache all songs": "Emmagatzema totes les cançons",
113114
"Cache": "Memòria cau",
114115
"Cancel": "Cancel·la",
115116
"Clear": "Neteja",
@@ -132,6 +133,7 @@
132133
"Fresh releases": "Llançaments recents",
133134
"Go to album": "Ves a l’àlbum",
134135
"Go to artist": "Ves a l’artista",
136+
"Go to genre": "Ves al gènere",
135137
"History": "Historial",
136138
"Home page url": "URL de la pàgina d’inici",
137139
"Home": "Inici",

app/i18next/de.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"Albums": "Alben",
111111
"Artist": "Künstler",
112112
"Artists": "Künstler",
113+
"Cache all songs": "Alle Lieder puffern",
113114
"Cache": "Puffer",
114115
"Cancel": "Abbrechen",
115116
"Clear": "Leeren",
@@ -132,6 +133,7 @@
132133
"Fresh releases": "Neue Veröffentlichungen",
133134
"Go to album": "Zum Album",
134135
"Go to artist": "Zum Künstler",
136+
"Go to genre": "Zum Genre",
135137
"History": "Verlauf",
136138
"Home page url": "Startseiten-URL",
137139
"Home": "Start",

app/i18next/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"Albums": "Albums",
111111
"Artist": "Artist",
112112
"Artists": "Artists",
113+
"Cache all songs": "Cache all songs",
113114
"Cache": "Cache",
114115
"Cancel": "Cancel",
115116
"Clear": "Clear",
@@ -132,6 +133,7 @@
132133
"Fresh releases": "Fresh releases",
133134
"Go to album": "Go to album",
134135
"Go to artist": "Go to artist",
136+
"Go to genre": "Go to genre",
135137
"History": "History",
136138
"Home page url": "Home page url",
137139
"Home": "Home",

app/i18next/es.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"Albums": "Álbumes",
111111
"Artist": "Artista",
112112
"Artists": "Artistas",
113+
"Cache all songs": "Emmagatzema totes les cançons",
113114
"Cache": "Caché",
114115
"Cancel": "Cancelar",
115116
"Clear": "Limpiar",
@@ -132,6 +133,7 @@
132133
"Fresh releases": "Novedades",
133134
"Go to album": "Ir al álbum",
134135
"Go to artist": "Ir al artista",
136+
"Go to genre": "Ir al género",
135137
"History": "Historial",
136138
"Home page url": "URL de la página de inicio",
137139
"Home": "Inicio",

app/i18next/fr.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"Albums": "Albums",
111111
"Artist": "Artiste",
112112
"Artists": "Artistes",
113+
"Cache all songs": "Mettre en cache les chansons",
113114
"Cache": "Cache",
114115
"Cancel": "Annuler",
115116
"Clear": "Effacer",
@@ -132,6 +133,7 @@
132133
"Fresh releases": "Sorties récentes",
133134
"Go to album": "Aller à l'album",
134135
"Go to artist": "Aller à l'artiste",
136+
"Go to genre": "Aller au genre",
135137
"History": "Historique",
136138
"Home page url": "Url page d'accueil",
137139
"Home": "Accueil",

app/i18next/gl.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"Albums": "Álbums",
111111
"Artist": "Artista",
112112
"Artists": "Artistas",
113+
"Cache all songs": "Emmagatzema totes les cançons",
113114
"Cache": "Caché",
114115
"Cancel": "Cancelar",
115116
"Clear": "Limpar",
@@ -132,6 +133,7 @@
132133
"Fresh releases": "Novidades",
133134
"Go to album": "Ir o álbum",
134135
"Go to artist": "Ir o artista",
136+
"Go to genre": "Ir o xénero",
135137
"History": "Historial",
136138
"Home page url": "URL da páxina de inicio",
137139
"Home": "Inicio",

0 commit comments

Comments
 (0)