Forked from
funkwhale / funkwhale
7971 commits behind the upstream repository.
-
Eliot Berriot authoredEliot Berriot authored
Player.vue 5.94 KiB
<template>
<div class="player">
<div v-if="queue.currentTrack" class="track-area ui items">
<div class="ui inverted item">
<div class="ui tiny image">
<img v-if="queue.currentTrack.album.cover" :src="Track.getCover(queue.currentTrack)">
<img v-else src="../../assets/audio/default-cover.png">
</div>
<div class="middle aligned content">
<router-link class="small header discrete link track" :to="{name: 'library.track', params: {id: queue.currentTrack.id }}">
{{ queue.currentTrack.title }}
</router-link>
<div class="meta">
<router-link class="artist" :to="{name: 'library.artist', params: {id: queue.currentTrack.artist.id }}">
{{ queue.currentTrack.artist.name }}
</router-link> /
<router-link class="album" :to="{name: 'library.album', params: {id: queue.currentTrack.album.id }}">
{{ queue.currentTrack.album.title }}
</router-link>
</div>
<div class="description">
<track-favorite-icon :track="queue.currentTrack"></track-favorite-icon>
</div>
</div>
</div>
</div>
<div class="progress-area" v-if="queue.currentTrack">
<div class="ui grid">
<div class="left floated four wide column">
<p class="timer start" @click="queue.audio.setTime(0)">{{queue.audio.state.currentTimeFormat}}</p>
</div>
<div class="right floated four wide column">
<p class="timer total">{{queue.audio.state.durationTimerFormat}}</p>
</div>
</div>
<div ref="progress" class="ui small orange inverted progress" @click="touchProgress">
<div class="bar" :data-percent="queue.audio.state.progress" :style="{ 'width': queue.audio.state.progress + '%' }"></div>
</div>
</div>
<div class="controls ui grid">
<div class="volume-control four wide center aligned column">
<input type="range" step="0.05" min="0" max="1" v-model="sliderVolume" />
<i title="Unmute" @click="queue.setVolume(1)" v-if="currentVolume === 0" class="volume off secondary icon"></i>
<i title="Mute" @click="queue.setVolume(0)" v-else-if="currentVolume < 0.5" class="volume down secondary icon"></i>
<i title="Mute" @click="queue.setVolume(0)" v-else class="volume up secondary icon"></i>
</div>
<div class="eight wide center aligned column">
<i title="Previous track" @click="queue.previous()" :class="['ui', {'disabled': !hasPrevious}, 'step', 'backward', 'big', 'icon']" :disabled="!hasPrevious"></i>
<i title="Play track" v-if="!queue.audio.state.playing" :class="['ui', 'play', {'disabled': !queue.currentTrack}, 'big', 'icon']" @click="pauseOrPlay"></i>
<i title="Pause track" v-else :class="['ui', 'pause', {'disabled': !queue.currentTrack}, 'big', 'icon']" @click="pauseOrPlay"></i>
<i title="Next track" @click="queue.next()" :class="['ui', 'step', 'forward', {'disabled': !hasNext}, 'big', 'icon']" :disabled="!hasNext"></i>
</div>
<div class="four wide center aligned column">
<i title="Clear your queue" @click="queue.clean()" :class="['ui', 'trash', 'secondary', {'disabled': queue.tracks.length === 0}, 'icon']" :disabled="queue.tracks.length === 0"></i>
</div>
</div>
<GlobalEvents
@keydown.space.prevent="pauseOrPlay"
@keydown.ctrl.left.prevent="queue.previous"
@keydown.ctrl.right.prevent="queue.next"
@keydown.ctrl.down.prevent="queue.incrementVolume(-0.1)"
@keydown.ctrl.up.prevent="queue.incrementVolume(0.1)"
/>
</div>
</template>
<script>
import GlobalEvents from 'vue-global-events'
import queue from '@/audio/queue'
import Track from '@/audio/track'
import TrackFavoriteIcon from '@/components/favorites/TrackFavoriteIcon'
import radios from '@/radios'
export default {
name: 'player',
components: {
TrackFavoriteIcon,
GlobalEvents
},
data () {
return {
sliderVolume: this.currentVolume,
queue: queue,
Track: Track,
radios
}
},
mounted () {
// we trigger the watcher explicitely it does not work otherwise
this.sliderVolume = this.currentVolume
},
methods: {
pauseOrPlay () {
if (this.queue.audio.state.playing) {
this.queue.audio.pause()
} else {
this.queue.audio.play()
}
},
touchProgress (e) {
let time
let target = this.$refs.progress
time = e.layerX / target.offsetWidth * this.queue.audio.state.duration
this.queue.audio.setTime(time)
}
},
computed: {
hasPrevious () {
return this.queue.currentIndex > 0
},
hasNext () {
return this.queue.currentIndex < this.queue.tracks.length - 1
},
currentVolume () {
return this.queue.audio.state.volume
}
},
watch: {
currentVolume (newValue) {
this.sliderVolume = newValue
},
sliderVolume (newValue) {
this.queue.setVolume(parseFloat(newValue))
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.ui.progress {
margin: 0.5rem 0 1rem;
}
.progress {
cursor: pointer;
.bar {
min-width: 0 !important;
}
}
.ui.inverted.item > .content > .description {
color: rgba(255, 255, 255, 0.9) !important;
}
.ui.item {
.meta {
font-size: 90%;
line-height: 1.2
}
}
.timer.total {
text-align: right;
}
.timer.start {
cursor: pointer
}
.track-area {
.header, .meta, .artist, .album {
color: white !important;
}
}
.controls .icon.big {
cursor: pointer;
font-size: 2em !important;
}
.controls .icon {
cursor: pointer;
vertical-align: middle;
}
.secondary.icon {
font-size: 1.5em;
}
.progress-area .actions {
text-align: center;
}
.volume-control {
position: relative;
.icon {
margin: 0;
}
[type="range"] {
max-width: 75%;
position: absolute;
bottom: 5px;
left: 10%;
cursor: pointer;
}
}
.ui.feed.icon {
margin: 0;
}
</style>