Split components
All checks were successful
repod / nextcloud (push) Successful in 59s
repod / nodejs (push) Successful in 1m33s

This commit is contained in:
Michel Roux 2023-08-27 22:20:34 +02:00
parent aae108ffc3
commit 351bfd446c
6 changed files with 241 additions and 97 deletions

View File

@ -12,82 +12,38 @@
@timeupdate="currentTime = audio.currentTime" @timeupdate="currentTime = audio.currentTime"
@volumechange="volume = audio.volume" /> @volumechange="volume = audio.volume" />
<NcLoadingIcon v-if="loading" /> <NcLoadingIcon v-if="loading" />
<div v-if="!loading" <ProgressBar v-if="!loading"
class="pointer" :current-time="currentTime"
@click="(event) => audio.fastSeek(event.x * duration / event.target.offsetWidth)"> :duration="duration" />
<NcProgressBar size="medium" :value="currentTime * 100 / duration" />
</div>
<div v-if="!loading" class="player"> <div v-if="!loading" class="player">
<img :src="episode.episodeImage"> <img :src="episode.episodeImage">
<div class="infos"> <Infos />
<a :href="episode.episodeLink" target="_blank"> <Controls :paused="paused" />
<strong>{{ episode.episodeName }}</strong> <Timer class="timer"
</a> :current-time="currentTime"
<router-link :to="$route.params.url"> :duration="duration" />
<i>{{ episode.podcastName }}</i> <Volume class="volume" :volume="volume" />
</router-link>
</div>
<PauseButton v-if="!paused"
class="pointer"
:size="50"
@click="() => audio.pause()" />
<PlayButton v-if="paused"
class="pointer"
:size="50"
@click="() => audio.play()" />
<StopButton class="pointer"
:size="30"
@click="stop" />
<div class="time">
<span class="current">{{ formatTimer(new Date(currentTime*1000)) }}</span>
<span class="divider">/</span>
<span class="length">{{ formatTimer(new Date(duration*1000)) }}</span>
</div>
<div class="volume">
<VolumeHigh v-if="volume > 0.7"
class="pointer"
:size="30"
@click="mute" />
<VolumeLow v-if="volume > 0 && volume <= 0.3"
class="pointer"
:size="30"
@click="mute" />
<VolumeMedium v-if="volume > 0.3 && volume <= 0.7"
class="pointer"
:size="30"
@click="mute" />
<VolumeMute v-if="volume == 0"
class="pointer"
:size="30"
@click="unmute" />
</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { NcLoadingIcon, NcProgressBar } from '@nextcloud/vue' import Controls from './Controls.vue'
import PauseButton from 'vue-material-design-icons/Pause.vue' import Infos from './Infos.vue'
import PlayButton from 'vue-material-design-icons/Play.vue' import { NcLoadingIcon } from '@nextcloud/vue'
import StopButton from 'vue-material-design-icons/Stop.vue' import ProgressBar from './ProgressBar.vue'
import VolumeHigh from 'vue-material-design-icons/VolumeHigh.vue' import Timer from './Timer.vue'
import VolumeLow from 'vue-material-design-icons/VolumeLow.vue' import Volume from './Volume.vue'
import VolumeMedium from 'vue-material-design-icons/VolumeMedium.vue'
import VolumeMute from 'vue-material-design-icons/VolumeMute.vue'
import { formatTimer } from '../../utils/time.js'
export default { export default {
name: 'Bar', name: 'Bar',
components: { components: {
Controls,
Infos,
NcLoadingIcon, NcLoadingIcon,
NcProgressBar, ProgressBar,
PauseButton, Timer,
PlayButton, Volume,
StopButton,
VolumeHigh,
VolumeLow,
VolumeMedium,
VolumeMute,
}, },
data() { data() {
return { return {
@ -96,7 +52,6 @@ export default {
loading: true, loading: true,
paused: true, paused: true,
volume: 1, volume: 1,
volumeMuted: 0,
} }
}, },
computed: { computed: {
@ -107,19 +62,6 @@ export default {
return this.$store.state.player.episode return this.$store.state.player.episode
}, },
}, },
methods: {
formatTimer,
mute() {
this.volumeMuted = this.audio.volume
this.audio.volume = 0
},
stop() {
this.$store.commit('player/play', null)
},
unmute() {
this.audio.volume = this.volumeMuted
},
},
} }
</script> </script>
@ -134,13 +76,6 @@ export default {
z-index: 2000; z-index: 2000;
} }
.infos {
display: flex;
flex-direction: column;
justify-content: center;
width: 45%;
}
.player { .player {
display: flex; display: flex;
gap: 1rem; gap: 1rem;
@ -148,18 +83,7 @@ export default {
justify-content: space-between; justify-content: space-between;
} }
.pointer { .timer {
cursor: pointer;
}
.time, .volume {
align-items: center;
display: flex;
gap: 5px;
justify-content: center;
}
.time {
width: 25%; width: 25%;
} }

View File

@ -0,0 +1,41 @@
<template>
<fragment>
<PauseButton v-if="!paused"
class="pointer"
:size="50"
@click="() => audio.pause()" />
<PlayButton v-if="paused"
class="pointer"
:size="50"
@click="() => audio.play()" />
<StopButton class="pointer"
:size="30"
@click="$store.commit('player/play', null)" />
</fragment>
</template>
<script>
import PauseButton from 'vue-material-design-icons/Pause.vue'
import PlayButton from 'vue-material-design-icons/Play.vue'
import StopButton from 'vue-material-design-icons/Stop.vue'
export default {
name: 'Controls',
components: {
PauseButton,
PlayButton,
StopButton,
},
props: {
paused: {
type: Boolean,
required: true,
},
},
computed: {
audio() {
return document.getElementById('audio-player')
},
},
}
</script>

View File

@ -0,0 +1,30 @@
<template>
<div>
<a :href="episode.episodeLink" target="_blank">
<strong>{{ episode.episodeName }}</strong>
</a>
<router-link :to="$route.params.url">
<i>{{ episode.podcastName }}</i>
</router-link>
</div>
</template>
<script>
export default {
name: 'Infos',
computed: {
episode() {
return this.$store.state.player.episode
},
},
}
</script>
<style scoped>
div {
display: flex;
flex-direction: column;
justify-content: center;
width: 45%;
}
</style>

View File

@ -0,0 +1,37 @@
<template>
<div @click="(event) => audio.fastSeek(event.x * duration / event.target.offsetWidth)">
<NcProgressBar size="medium" :value="currentTime * 100 / duration" />
</div>
</template>
<script>
import { NcProgressBar } from '@nextcloud/vue'
export default {
name: 'ProgressBar',
components: {
NcProgressBar,
},
props: {
currentTime: {
type: Number,
required: true,
},
duration: {
type: Number,
required: true,
},
},
computed: {
audio() {
return document.getElementById('audio-player')
},
},
}
</script>
<style scoped>
div {
cursor: pointer;
}
</style>

View File

@ -0,0 +1,37 @@
<template>
<div>
<span>{{ formatTimer(new Date(currentTime*1000)) }}</span>
<span>/</span>
<span>{{ formatTimer(new Date(duration*1000)) }}</span>
</div>
</template>
<script>
import { formatTimer } from '../../utils/time.js'
export default {
name: 'Timer',
props: {
currentTime: {
type: Number,
required: true,
},
duration: {
type: Number,
required: true,
},
},
methods: {
formatTimer,
},
}
</script>
<style scoped>
div {
align-items: center;
display: flex;
gap: 5px;
justify-content: center;
}
</style>

View File

@ -0,0 +1,75 @@
<template>
<div>
<VolumeHigh v-if="volume > 0.7"
class="pointer"
:size="30"
@click="mute" />
<VolumeLow v-if="volume > 0 && volume <= 0.3"
class="pointer"
:size="30"
@click="mute" />
<VolumeMedium v-if="volume > 0.3 && volume <= 0.7"
class="pointer"
:size="30"
@click="mute" />
<VolumeMute v-if="volume == 0"
class="pointer"
:size="30"
@click="unmute" />
</div>
</template>
<script>
import VolumeHigh from 'vue-material-design-icons/VolumeHigh.vue'
import VolumeLow from 'vue-material-design-icons/VolumeLow.vue'
import VolumeMedium from 'vue-material-design-icons/VolumeMedium.vue'
import VolumeMute from 'vue-material-design-icons/VolumeMute.vue'
export default {
name: 'Volume',
components: {
VolumeHigh,
VolumeLow,
VolumeMedium,
VolumeMute,
},
props: {
volume: {
type: Number,
required: true,
},
},
data() {
return {
volumeMuted: 0,
}
},
computed: {
audio() {
return document.getElementById('audio-player')
},
},
methods: {
mute() {
this.volumeMuted = this.audio.volume
this.audio.volume = 0
},
unmute() {
this.audio.volume = this.volumeMuted
},
},
}
</script>
<style scoped>
div {
align-items: center;
display: flex;
gap: 5px;
justify-content: center;
}
.pointer {
cursor: pointer;
}
</style>