diff options
Diffstat (limited to 'apps/Youtube')
-rw-r--r-- | apps/Youtube/components/App.js | 128 |
1 files changed, 69 insertions, 59 deletions
diff --git a/apps/Youtube/components/App.js b/apps/Youtube/components/App.js index d902346..6130473 100644 --- a/apps/Youtube/components/App.js +++ b/apps/Youtube/components/App.js @@ -7,56 +7,64 @@ import { open } from 'helpers/windowActions' import appList from 'configs/appList' import Splash from 'components/Splash' -const time = t => new Date(t * 1000).toISOString().substr(11, 8) +const time = t => t ? new Date(t * 1000).toISOString().substr(11, 8) : '-' const App = () => { const { apps, setApps } = useApps() const [results, setResults] = useState() - const [searching, setSearching] = useState(false) - const [sending, setSending] = useState(false) + const [loading, setLoading] = useState(false) const [enqueue, setEnqueue] = useState(false) - const [type, setType] = useState('youtube_videos') + const [type, setType] = useState('yt_video') const { t } = useSettings() - const handleSearch = async e => { + const handleSearch = e => { e.preventDefault() e.stopPropagation() - setSearching(true) - const quote = e.currentTarget.quote.value + setLoading(true) + const quote = [ + e.currentTarget.quote.value, + { type: type === 'yt_music' ? 'music' : type.split('_')[1] } + ] - const results = await fetchJson('/api/youtube/search', { + fetchJson('/api/youtube/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ quote }) }) - - results?.videos && setResults(results.videos) - setSearching(false) + .then(results => { + if (type === 'yt_live') { + results?.streams && setResults(results.streams) + } else if (type === 'yt_playlist') { + results?.playlists && setResults(results.playlists) + } else { + results?.videos && setResults(results.videos) + } + }) + .catch(() => { console.log('Could not fetch results') }) + .finally(() => { setLoading(false) }) } - const handlePlay = async url => { - setSending(true) - const data = await fetchJson('/api/youtube/player', { + const fetchPlaylist = (id) => fetchJson( + '/api/youtube/playlist', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url }) - }) - - const list = { - items: [{ - id: data.videoDetails.videoId, - title: data.videoDetails.title, - type: 'youtube-video', - sources: data.formats.filter(v => v.hasAudio).sort((a, b) => a.bitrate > b.bitrate) - }], - enqueue + body: JSON.stringify({ id }) } + ) - apps && apps.length > 0 && apps.some(a => a && a.name === 'Player') - ? setApps(prev => prev.map(a => a.name === 'Player' ? { ...a, props: { list } } : a)) - : open({ appName: 'Player', ...appList.Player }, setApps, { list }) + const handlePlay = async (e, title, id) => { + e.stopPropagation() + setLoading(true) + const items = type === 'yt_playlist' + ? await fetchPlaylist(id) + .then(data => data.items.map(i => ({ title: i.title, id: i.id, type: i.isLive ? 'yt_live' : 'yt_video' }))) + .catch(() => { console.log('Could not fetch playlist') }) + : [{ title, id, type }] - setSending(false) + apps && apps.length > 0 && apps.some(a => a && a.name === 'Player') + ? setApps(prev => prev.map(a => a.name === 'Player' ? { ...a, props: { list: { items, enqueue } } } : a)) + : open({ appName: 'Player', ...appList.Player }, setApps, { list: { items, enqueue } }) + setLoading(false) } return ( @@ -64,11 +72,9 @@ const App = () => { <div className='window__submenu'> <div> {[ - 'youtube_videos', - 'youtube_music', - 'youtube_live', - 'youtube_channels', - 'youtube_playlists' + 'yt_video', + 'yt_live', + 'yt_playlist' ].map(y => ( <div className={y === type ? 'active' : ''} @@ -83,7 +89,7 @@ const App = () => { className={enqueue ? '' : 'off'} onClick={() => { setEnqueue(e => !e) }} > - {t('youtube_enqueue')} + {t('yt_enqueue')} </div> </div> </div> @@ -93,30 +99,34 @@ const App = () => { <input type='submit' className='window__button' value={t('search')} /> </form> <div className='window__scroll'> - { - searching - ? ( - <Splash /> - ) - : ( - <ul> - { - results && results.length > 0 && results.map(r => ( - <li key={r.id} onClick={() => handlePlay(r.link)}> - <img loading='lazy' src={r.thumbnail} width={96} height={72} /> - <p>{time(r.duration)}</p> - <div> - <p>{r.title}</p> - <p>Views: {r.views}, uploaded: {r.uploaded || '-'}</p> - <p>{r.channel?.name}</p> - </div> - </li> - )) - } - {sending && <Splash fixed />} - </ul> - ) - } + <ul> + { + results && results.length > 0 && results.map(r => ( + <li + key={r.id} + onClick={e => handlePlay(e, r.title, r.id)} + > + <img loading='lazy' src={r.thumbnail} width={96} height={72} /> + {r.duration && <p>{time(r.duration)}</p>} + <div> + <p>{r.title}</p> + <p>{r.views + ? r.views + ' ' + t('yt_views') + : r.watching + ? r.watching + ' ' + t('yt_watching') + : r.videoCount + ? r.videoCount + t('yt_video_count') + : '-'} + {(r.views || r.watching) && r.uploaded && ', '} + {r.uploaded || ''} + </p> + <p>{r.channel?.name}</p> + </div> + </li> + )) + } + </ul> + {loading && <Splash fixed />} </div> </div> </> |