aboutsummaryrefslogtreecommitdiffstats
path: root/apps/Youtube/components/App.js
diff options
context:
space:
mode:
authorGravatar piotrruss <mail@pruss.it> 2021-09-12 23:11:25 +0200
committerGravatar piotrruss <mail@pruss.it> 2021-09-12 23:11:25 +0200
commit16dab011c575eaf96630cab406ec2d8086403d0b (patch)
treeaf53af45b8cb52317cef3d4d59216b1c58d8d8ff /apps/Youtube/components/App.js
parentd79f4c0bf3dae76eaae0d36469f5b279272d6944 (diff)
downloadmy_apps-16dab011c575eaf96630cab406ec2d8086403d0b.tar.gz
my_apps-16dab011c575eaf96630cab406ec2d8086403d0b.tar.bz2
my_apps-16dab011c575eaf96630cab406ec2d8086403d0b.zip
added youtube & player apps
Diffstat (limited to 'apps/Youtube/components/App.js')
-rw-r--r--apps/Youtube/components/App.js126
1 files changed, 126 insertions, 0 deletions
diff --git a/apps/Youtube/components/App.js b/apps/Youtube/components/App.js
new file mode 100644
index 0000000..d902346
--- /dev/null
+++ b/apps/Youtube/components/App.js
@@ -0,0 +1,126 @@
+import styles from '../styles/Youtube.module.scss'
+import { useState } from 'react'
+import fetchJson from 'helpers/fetchJson'
+import useApps from 'hooks/useApps'
+import useSettings from 'hooks/useSettings'
+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 App = () => {
+ const { apps, setApps } = useApps()
+ const [results, setResults] = useState()
+ const [searching, setSearching] = useState(false)
+ const [sending, setSending] = useState(false)
+ const [enqueue, setEnqueue] = useState(false)
+ const [type, setType] = useState('youtube_videos')
+ const { t } = useSettings()
+
+ const handleSearch = async e => {
+ e.preventDefault()
+ e.stopPropagation()
+ setSearching(true)
+ const quote = e.currentTarget.quote.value
+
+ const results = await fetchJson('/api/youtube/search', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ quote })
+ })
+
+ results?.videos && setResults(results.videos)
+ setSearching(false)
+ }
+
+ const handlePlay = async url => {
+ setSending(true)
+ const data = await fetchJson('/api/youtube/player', {
+ 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
+ }
+
+ 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 })
+
+ setSending(false)
+ }
+
+ return (
+ <>
+ <div className='window__submenu'>
+ <div>
+ {[
+ 'youtube_videos',
+ 'youtube_music',
+ 'youtube_live',
+ 'youtube_channels',
+ 'youtube_playlists'
+ ].map(y => (
+ <div
+ className={y === type ? 'active' : ''}
+ onClick={() => { setType(y); setResults() }}
+ key={y}
+ >
+ {t(y)}
+ </div>
+ ))}
+ <span />
+ <div
+ className={enqueue ? '' : 'off'}
+ onClick={() => { setEnqueue(e => !e) }}
+ >
+ {t('youtube_enqueue')}
+ </div>
+ </div>
+ </div>
+ <div className={styles.results}>
+ <form onSubmit={handleSearch}>
+ <input type='text' name='quote' />
+ <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>
+ )
+ }
+ </div>
+ </div>
+ </>
+ )
+}
+
+export default App