wip remove yt-player

This commit is contained in:
wryk 2020-01-18 17:42:44 +01:00
parent 92e0bbc74a
commit 601652709a
6 changed files with 249 additions and 116 deletions

13
package-lock.json generated
View File

@ -4547,11 +4547,6 @@
"resolved": "https://registry.npmjs.org/little-ds-toolkit/-/little-ds-toolkit-1.1.1.tgz",
"integrity": "sha512-Zl5flhnd5W6nhRCyoL1bNlU8M5CWFp6SItMmK4pj39LKgzQD7LGg591OJ0jwDKat7mjHvJVkOyJT+BXOQH4iXw=="
},
"load-script2": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/load-script2/-/load-script2-2.0.4.tgz",
"integrity": "sha512-WzZ2Df8QvWwGdjcJ7BYqcaojHGBC+Dg3oFsBg8gyz/mGyjCduBKdja+HkRo7BHoqt8sV5oil1Bc6Eyq6e40jfg=="
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@ -7536,14 +7531,6 @@
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
},
"yt-player": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/yt-player/-/yt-player-3.4.3.tgz",
"integrity": "sha512-Ke5oM+qW8CR6aaK40mTxBff3hS4DXjyfmFkjg3eoaGt8fWQGyKFOFIpZqzNTR5c7Lu+xAG9SIvxCvbBPhCBbPg==",
"requires": {
"load-script2": "^2.0.1"
}
}
}
}

View File

@ -22,8 +22,7 @@
"@babel/runtime-corejs3": "^7.7.7",
"date-fns": "^2.9.0",
"get-urls": "^9.2.0",
"iter-tools": "^7.0.0-rc.0",
"yt-player": "^3.4.3"
"iter-tools": "^7.0.0-rc.0"
},
"browserslist": [
"last 1 chrome versions"

View File

@ -1,10 +1,21 @@
<div>
<div class="embed-container" class:hidden={!loaded}>
<div bind:this={element}></div>
<YoutubePlayer
id={$current ? $current.data.id : null}
paused={$paused}
muted={$muted}
volume={$volume}
bind:ready
bind:ended
bind:currentTime
bind:duration
bind:seek={seek}>
</YoutubePlayer>
<div class="embed-container" class:hidden={!ready}>
<div class="embed-overlay" on:click={() => $paused = !$paused}></div>
</div>
{#if !loaded}
{#if !ready}
LOADING TRACK
{/if}
@ -15,120 +26,30 @@
min="0"
max={duration}
value={currentTime}
on:input={ (e) => updatePlayerCurrentTime(e.target.value) }
on:mousedown={() => { if (player && !$paused) player.pause() }}
on:mouseup={() => { if (player && !$paused) player.play() }}>
on:input={(e) => seek(e.target.value, false)}
on:change={(e) => seek(e.target.value, true)}>
{durationText}
{/if}
</div>
<script>
import { onMount, onDestroy } from 'svelte'
import { get } from 'svelte/store'
import YoutubePlayer from 'yt-player'
import YoutubePlayer from '/components/YoutubePlayer'
import { secondsToElapsedTime } from '/util.js'
import { paused, muted, volume, current, selectNext, loading } from '/store.js'
let element
let player
let ready = null
let ended = null
let currentTime = null
let duration = null
let loaded = false
let currentTimeText = null
let durationText = null
let seek = null
$: currentTimeText = currentTime !== null ? secondsToElapsedTime(currentTime) : null
$: durationText = duration !== null ? secondsToElapsedTime(duration) : null
$: updatePlayerVideoId($current)
$: updatePlayerPaused($paused)
$: updatePlayerMuted($muted)
$: updatePlayerVolume($volume)
const updateViewerDurationCallback = () => {
if (player) {
duration = player.getDuration()
currentTime = player.getCurrentTime()
$loading = false
}
$: if (ended) {
selectNext()
}
const updatePlayerVideoId = ($current) => {
if (player && $current) {
duration = null
currentTime = null
$loading = true
loaded = false
player.off('playing', updateViewerDurationCallback)
player.load($current.data.id, !$paused)
}
}
const updatePlayerPaused = (paused) => {
if (player) paused ? player.pause() : player.play()
}
const updatePlayerMuted = (muted) => {
if (player) muted ? player.mute() : player.unMute()
}
const updatePlayerVolume = (volume) => {
if (player) player.setVolume(volume)
}
const updatePlayerCurrentTime = (seconds) => {
if (player) player.seek(seconds)
}
onMount(() => {
player = new YoutubePlayer(element, {
width: 300,
height: 300,
autoplay: !$paused,
controls: false,
keyboard: false,
fullscreen: false,
modestBranding: true,
related: false
})
updatePlayerPaused($paused)
updatePlayerMuted($muted)
updatePlayerVolume($volume)
player.on('unstarted', () => {
loaded = true
player.once('playing', updateViewerDurationCallback)
})
player.on('timeupdate', (time) => {
currentTime = time
})
player.on('ended', () => {
selectNext()
})
player.on('unplayable', (...args) => {
console.log('unplayable', ...args)
selectNext()
})
player.on('error', (...args) => {
console.log('error', ...args)
selectNext()
})
})
onDestroy(() => {
if (player) {
player.destroy()
}
})
</script>
<style>

View File

@ -0,0 +1,134 @@
<div bind:this={element}></div>
<script>
import { onMount, onDestroy } from 'svelte'
import { loadIframeApi, STATUS } from '/youtube.js'
import { queue } from '/util.js'
let element
let player
// output props
export let ready = false
export let ended = false
export let duration = null
export let currentTime = null
// input props
export let id
export let paused
export let muted
export let volume
$: load(id)
$: setPaused(paused)
$: setMuted(muted)
$: setVolume(volume)
const { enqueue, run } = queue()
export const load = (id) => enqueue((player) => {
ready = false
ended = false
currentTime = null
duration = null
if (paused) {
player.cueVideoById(id)
} else {
player.loadVideoById(id)
}
})
const setPaused = paused => enqueue(player => {
if (paused) {
if (player.getPlayerState() === STATUS.PLAYING) {
player.pauseVideo()
}
} else {
if (player.getPlayerState() !== STATUS.PLAYING) {
player.playVideo()
}
}
})
const setMuted = muted => enqueue(player => {
if (muted) {
if (!player.isMuted()) {
player.mute()
}
} else {
if (player.isMuted()) {
player.unMute()
}
}
})
const setVolume = volume => enqueue(player => {
player.setVolume(volume)
})
export const seek = (seconds, allowSeekAhead) => enqueue((player) => {
player.seekTo(seconds, allowSeekAhead)
// currentTime = player.getCurrentTime()
})
onMount(() => {
loadIframeApi().then(api => {
element.id = Math.random().toString(16).slice(2, 8)
const onReady = (event) => {
run(event.target)
setInterval(() => {
currentTime = event.target.getCurrentTime()
}, 1000)
}
const onStateChange = (event) => {
console.log('stateChange', event)
switch (event.data) {
case STATUS.CUED:
ready = true
break
case STATUS.PLAYING:
duration = event.target.getDuration()
break
case STATUS.ENDED:
ended = true
break
}
}
const onError = () => {
console.log('error', event)
}
player = new api.Player(element.id, {
playerVars: {
autoplay: 0,
controls: 0,
enablejsapi: 1,
modestbranding: 1,
rel: 0
},
events: {
onReady,
onStateChange,
onError
}
})
})
})
onDestroy(() => {
if (player) {
player.destroy()
}
})
</script>

View File

@ -2,6 +2,34 @@ import { writable } from 'svelte/store'
import getUrls from 'get-urls'
import { execPipe, asyncFilter, asyncMap } from 'iter-tools'
export const tap = f => x => {
f(x)
return x
}
export const queue = () => {
const deferred = defer()
let promise = deferred.promise
const enqueue = f => {
promise = promise.then(tap(f))
}
return { enqueue, run: deferred.resolve }
}
export const defer = () => {
let resolve
let reject
const promise = new Promise((res, rej) => {
resolve = res
reject = rej
})
return { resolve, reject, promise }
}
export const writableLocalStorage = (key, value) => {
const item = JSON.parse(localStorage.getItem(key))
const store = writable(item === null ? value : item)

64
src/youtube.js Normal file
View File

@ -0,0 +1,64 @@
const IFRAME_API_URL = 'https://www.youtube.com/iframe_api'
export const STATUS = {
UNSTARTED: -1,
ENDED: 0,
PLAYING: 1,
PAUSED: 2,
BUFFERING: 3,
CUED: 5
}
const loadScript = (attributes) => {
return new Promise((resolve, reject) => {
if (!attributes.hasOwnProperty('src')) {
throw new Error('src is required')
}
// const scripts = Array.from(document.getElementsByTagName('script'))
// .filter(script => script.src === attribute.src)
// if (scripts.length) {
// if (scripts.some(script => script.readyState.complete)) {
// }
// } else {
// }
const script = document.createElement('script')
for (const [name, value] of Object.entries(attributes)) {
script[name] = value
}
script.onload = (e) => {
script.onload = script.onerror = null
resolve(e.target)
}
script.onerror = (e) => {
script.onload = script.onerror = null
reject(e)
}
document.head.appendChild(script)
})
}
export const loadIframeApi = async () => {
return new Promise((resolve, reject) => {
if (window.YT && typeof window.YT.Player === 'function') {
resolve(window.YT)
} else {
const previousInitializer = window.onYouTubeIframeAPIReady
window.onYouTubeIframeAPIReady = () => {
window.onYouTubeIframeAPIReady = previousInitializer
resolve(window.YT)
}
loadScript({ src: IFRAME_API_URL })
}
})
}