repod/src/store/player.ts

115 lines
2.8 KiB
TypeScript

import type { EpisodeActionInterface, EpisodeInterface } from '../utils/types'
import axios from '@nextcloud/axios'
import { defineStore } from 'pinia'
import { formatEpisodeTimestamp } from '../utils/time'
import { generateUrl } from '@nextcloud/router'
const audio = new Audio()
export const usePlayer = defineStore('player', {
state: () => ({
currentTime: null as number | null,
duration: null as number | null,
episode: null as EpisodeInterface | null,
loaded: false,
paused: true,
podcastUrl: null as string | null,
volume: 1,
rate: 1,
started: 0,
}),
actions: {
init() {
audio.ondurationchange = () => (this.duration = audio.duration)
audio.onended = () => this.stop()
audio.onloadeddata = () => (this.loaded = true)
audio.onpause = () => this.pause()
audio.onplay = () => this.play()
audio.onratechange = () => (this.rate = audio.playbackRate)
audio.onseeked = () => (this.currentTime = audio.currentTime)
audio.ontimeupdate = () => (this.currentTime = audio.currentTime)
audio.onvolumechange = () => (this.volume = audio.volume)
},
async load(episode: EpisodeInterface | null, podcastUrl?: string) {
this.episode = episode
this.podcastUrl = podcastUrl || null
if (this.episode?.url) {
audio.src = this.episode.url
audio.load()
try {
const action = await axios.get<EpisodeActionInterface>(
generateUrl('/apps/repod/episodes/action?url={url}', {
url: this.episode.url,
}),
)
this.episode.action = action.data
} catch {}
if (
this.episode.action &&
this.episode.action.position < this.episode.action.total
) {
audio.currentTime = this.episode.action.position
this.started = audio.currentTime
}
audio.play()
} else {
this.loaded = false
this.podcastUrl = null
audio.src = ''
}
},
pause() {
audio.pause()
this.paused = true
this.time()
},
play() {
audio.play()
this.paused = false
this.started = audio.currentTime
},
seek(currentTime: number) {
audio.currentTime = currentTime
this.time()
},
stop() {
this.pause()
this.episode = null
},
time() {
if (!this.podcastUrl || !this.episode?.url) {
return
}
this.episode = {
...this.episode,
action: {
podcast: this.podcastUrl,
episode: this.episode.url,
guid: this.episode.guid,
action: 'play',
timestamp: formatEpisodeTimestamp(new Date()),
started: Math.round(this.started),
position: Math.round(audio.currentTime),
total: Math.round(audio.duration),
},
}
axios.post(generateUrl('/apps/gpoddersync/episode_action/create'), [
this.episode.action,
])
},
setVolume(volume: number) {
audio.volume = volume
},
setRate(rate: number) {
audio.playbackRate = rate
},
},
})