advplyr.audiobookshelf-app/components/modals/PlaybackSpeedModal.vue
2025-03-30 23:26:14 -07:00

121 lines
3.5 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<modals-modal v-model="show" @input="modalInput" :width="200" height="100%">
<template #outer>
<div class="absolute top-8 left-4 z-40">
<p class="text-white text-2xl truncate">{{ $strings.LabelPlaybackSpeed }}</p>
</div>
</template>
<div class="w-full h-full overflow-hidden absolute top-0 left-0 flex items-center justify-center">
<div class="w-full overflow-x-hidden overflow-y-auto bg-primary rounded-lg border border-border" style="max-height: 75%" @click.stop>
<ul class="w-full" role="listbox" aria-labelledby="listbox-label">
<template v-for="rate in rates">
<li :key="rate" class="text-fg select-none relative py-4" :class="rate === selected ? 'bg-bg-hover/50' : ''" role="option" @click="clickedOption(rate)">
<div class="flex items-center justify-center">
<span class="font-normal block truncate text-lg">{{ rate }}x</span>
</div>
</li>
</template>
</ul>
<div class="flex items-center justify-center py-3 border-t border-fg/10">
<button :disabled="!canDecrement" @click="decrement" class="icon-num-btn w-8 h-8 text-fg-muted rounded border border-border flex items-center justify-center">
<span class="material-symbols">remove</span>
</button>
<div class="w-24 text-center">
<p class="text-xl">{{ playbackRate }}<span class="text-lg"></span></p>
</div>
<button :disabled="!canIncrement" @click="increment" class="icon-num-btn w-8 h-8 text-fg-muted rounded border border-border flex items-center justify-center">
<span class="material-symbols">add</span>
</button>
</div>
</div>
</div>
</modals-modal>
</template>
<script>
export default {
props: {
value: Boolean,
playbackRate: Number
},
data() {
return {
currentPlaybackRate: 0,
MIN_SPEED: 0.5,
MAX_SPEED: 10
}
},
watch: {
show(newVal) {
if (newVal) {
this.currentPlaybackRate = this.selected
}
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
selected: {
get() {
return this.playbackRate
},
set(val) {
this.$emit('update:playbackRate', val)
}
},
rates() {
return [0.5, 1, 1.2, 1.5, 1.7, 2, 3]
},
canIncrement() {
return this.playbackRate + 0.1 <= this.MAX_SPEED
},
canDecrement() {
return this.playbackRate - 0.1 >= this.MIN_SPEED
}
},
methods: {
increment() {
if (this.selected + 0.1 > this.MAX_SPEED) return
var newPlaybackRate = this.selected + 0.1
this.selected = Number(newPlaybackRate.toFixed(1))
},
decrement() {
if (this.selected - 0.1 < this.MIN_SPEED) return
var newPlaybackRate = this.selected - 0.1
this.selected = Number(newPlaybackRate.toFixed(1))
},
modalInput(val) {
if (!val) {
if (this.currentPlaybackRate !== this.selected) {
this.$emit('change', this.selected)
}
}
},
clickedOption(rate) {
this.selected = Number(rate)
this.show = false
this.$emit('change', Number(rate))
}
},
mounted() {}
}
</script>
<style>
button.icon-num-btn:disabled {
cursor: not-allowed;
}
button.icon-num-btn:disabled::before {
background-color: rgba(0, 0, 0, 0.2);
}
button.icon-num-btn:disabled span {
color: #777;
}
</style>