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
1516const 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
0 commit comments