[web] Create a slider component

As a component, the slider is easier to maintain.
This commit is contained in:
Alain Nussbaumer 2023-07-05 22:24:50 +02:00
parent 4cddfa4dfc
commit 583b676489
5 changed files with 72 additions and 82 deletions

View File

@ -0,0 +1,29 @@
<template>
<input
:value="value"
:disabled="disabled"
class="slider"
:class="{ 'is-inactive': disabled }"
:max="max"
type="range"
:style="{
'--ratio': ratio,
'--cursor': $filters.cursor(cursor)
}"
@input="$emit('update:value', $event.target.value)"
/>
</template>
<script>
export default {
name: 'ControlSlider',
props: ['value', 'max', 'disabled', 'cursor'],
emits: ['update:value'],
computed: {
ratio() {
return this.value / this.max
}
}
}
</script>

View File

@ -112,12 +112,9 @@
<div class="level-item"> <div class="level-item">
<div> <div>
<p class="heading" v-text="$t('navigation.volume')" /> <p class="heading" v-text="$t('navigation.volume')" />
<input <control-slider
v-model="player.volume" v-model:value="player.volume"
class="slider" :max="100"
max="100"
type="range"
:style="{ '--ratio': player.volume / 100 }"
@change="change_volume" @change="change_volume"
/> />
</div> </div>
@ -163,17 +160,11 @@
/> />
</a> </a>
</div> </div>
<input <control-slider
v-model="stream_volume" v-model:value="stream_volume"
:disabled="!playing" :disabled="!playing"
class="slider" :max="100"
:class="{ 'is-inactive': !playing }" :cursor="cursor"
max="100"
type="range"
:style="{
'--ratio': stream_volume / 100,
'--cursor': $filters.cursor(cursor)
}"
@change="change_stream_volume" @change="change_stream_volume"
/> />
</div> </div>
@ -229,12 +220,9 @@
<div class="level-item"> <div class="level-item">
<div class="is-flex-grow-1"> <div class="is-flex-grow-1">
<p class="heading" v-text="$t('navigation.volume')" /> <p class="heading" v-text="$t('navigation.volume')" />
<input <control-slider
v-model="player.volume" v-model:value="player.volume"
class="slider" :max="100"
max="100"
type="range"
:style="{ '--ratio': player.volume / 100 }"
@change="change_volume" @change="change_volume"
/> />
</div> </div>
@ -279,17 +267,11 @@
/> />
</a> </a>
</div> </div>
<input <control-slider
v-model="stream_volume" v-model:value="stream_volume"
:disabled="!playing" :disabled="!playing"
class="slider" :max="100"
:class="{ 'is-inactive': !playing }" :cursor="cursor"
max="100"
type="range"
:style="{
'--ratio': stream_volume / 100,
'--cursor': $filters.cursor(cursor)
}"
@change="change_stream_volume" @change="change_stream_volume"
/> />
</div> </div>
@ -303,8 +285,9 @@
</template> </template>
<script> <script>
import webapi from '@/webapi' import * as types from '@/store/mutation_types'
import _audio from '@/audio' import _audio from '@/audio'
import ControlSlider from '@/components/ControlSlider.vue'
import { mdiCancel } from '@mdi/js' import { mdiCancel } from '@mdi/js'
import NavbarItemLink from './NavbarItemLink.vue' import NavbarItemLink from './NavbarItemLink.vue'
import NavbarItemOutput from './NavbarItemOutput.vue' import NavbarItemOutput from './NavbarItemOutput.vue'
@ -316,11 +299,12 @@ import PlayerButtonConsume from '@/components/PlayerButtonConsume.vue'
import PlayerButtonRepeat from '@/components/PlayerButtonRepeat.vue' import PlayerButtonRepeat from '@/components/PlayerButtonRepeat.vue'
import PlayerButtonSeekBack from '@/components/PlayerButtonSeekBack.vue' import PlayerButtonSeekBack from '@/components/PlayerButtonSeekBack.vue'
import PlayerButtonSeekForward from '@/components/PlayerButtonSeekForward.vue' import PlayerButtonSeekForward from '@/components/PlayerButtonSeekForward.vue'
import * as types from '@/store/mutation_types' import webapi from '@/webapi'
export default { export default {
name: 'NavbarBottom', name: 'NavbarBottom',
components: { components: {
ControlSlider,
NavbarItemLink, NavbarItemLink,
NavbarItemOutput, NavbarItemOutput,
PlayerButtonPlayPause, PlayerButtonPlayPause,

View File

@ -23,17 +23,11 @@
:class="{ 'has-text-grey-light': !output.selected }" :class="{ 'has-text-grey-light': !output.selected }"
v-text="output.name" v-text="output.name"
/> />
<input <control-slider
v-model="volume" v-model:value="volume"
:disabled="!output.selected" :disabled="!output.selected"
class="slider" :max="100"
:class="{ 'is-inactive': !output.selected }" :cursor="cursor"
max="100"
type="range"
:style="{
'--ratio': volume / 100,
'--cursor': $filters.cursor(cursor)
}"
@change="change_volume" @change="change_volume"
/> />
</div> </div>
@ -44,14 +38,16 @@
</template> </template>
<script> <script>
import ControlSlider from '@/components/ControlSlider.vue'
import { mdiCancel } from '@mdi/js' import { mdiCancel } from '@mdi/js'
import webapi from '@/webapi' import webapi from '@/webapi'
export default { export default {
name: 'NavbarItemOutput', name: 'NavbarItemOutput',
props: ['output'], props: ['output'],
components: {
ControlSlider
},
data() { data() {
return { return {
volume: this.output.selected ? this.output.volume : 0, volume: this.output.selected ? this.output.volume : 0,

View File

@ -63,28 +63,16 @@
<b v-text="$t('navigation.music')" /> <b v-text="$t('navigation.music')" />
</navbar-item-link> </navbar-item-link>
<navbar-item-link to="/music/artists"> <navbar-item-link to="/music/artists">
<span <span class="pl-5" v-text="$t('navigation.artists')" />
class="pl-5"
v-text="$t('navigation.artists')"
/>
</navbar-item-link> </navbar-item-link>
<navbar-item-link to="/music/albums"> <navbar-item-link to="/music/albums">
<span <span class="pl-5" v-text="$t('navigation.albums')" />
class="pl-5"
v-text="$t('navigation.albums')"
/>
</navbar-item-link> </navbar-item-link>
<navbar-item-link to="/music/genres"> <navbar-item-link to="/music/genres">
<span <span class="pl-5" v-text="$t('navigation.genres')" />
class="pl-5"
v-text="$t('navigation.genres')"
/>
</navbar-item-link> </navbar-item-link>
<navbar-item-link v-if="spotify_enabled" to="/music/spotify"> <navbar-item-link v-if="spotify_enabled" to="/music/spotify">
<span <span class="pl-5" v-text="$t('navigation.spotify')" />
class="pl-5"
v-text="$t('navigation.spotify')"
/>
</navbar-item-link> </navbar-item-link>
<navbar-item-link to="/podcasts"> <navbar-item-link to="/podcasts">
<mdicon class="icon" name="microphone" size="16" /> <mdicon class="icon" name="microphone" size="16" />
@ -132,8 +120,8 @@
</template> </template>
<script> <script>
import NavbarItemLink from './NavbarItemLink.vue'
import * as types from '@/store/mutation_types' import * as types from '@/store/mutation_types'
import NavbarItemLink from './NavbarItemLink.vue'
export default { export default {
name: 'NavbarTop', name: 'NavbarTop',

View File

@ -9,17 +9,12 @@
class="is-clickable fd-has-shadow fd-cover-big-image" class="is-clickable fd-has-shadow fd-cover-big-image"
@click="open_dialog(track)" @click="open_dialog(track)"
/> />
<input <control-slider
v-model.number="track_progress" v-model:value="track_progress"
:max="track_progress_max" class="mt-5"
type="range"
class="slider mt-5"
:class="{ 'is-inactive': is_live }"
:style="{
'--ratio': track_progress_ratio,
'--cursor': $filters.cursor(cursor)
}"
:disabled="is_live" :disabled="is_live"
:max="track_progress_max"
:cursor="cursor"
@change="seek" @change="seek"
@mousedown="start_dragging" @mousedown="start_dragging"
@mouseup="end_dragging" @mouseup="end_dragging"
@ -58,19 +53,21 @@
</template> </template>
<script> <script>
import * as types from '@/store/mutation_types'
import ControlSlider from '@/components/ControlSlider.vue'
import CoverArtwork from '@/components/CoverArtwork.vue' import CoverArtwork from '@/components/CoverArtwork.vue'
import { mdiCancel } from '@mdi/js' import { mdiCancel } from '@mdi/js'
import ModalDialogQueueItem from '@/components/ModalDialogQueueItem.vue' import ModalDialogQueueItem from '@/components/ModalDialogQueueItem.vue'
import webapi from '@/webapi' import webapi from '@/webapi'
import * as types from '@/store/mutation_types'
const INTERVAL = 1000 const INTERVAL = 1000
export default { export default {
name: 'PageNowPlaying', name: 'PageNowPlaying',
components: { components: {
ModalDialogQueueItem, ControlSlider,
CoverArtwork CoverArtwork,
ModalDialogQueueItem
}, },
data() { data() {
@ -79,8 +76,8 @@ export default {
INTERVAL, INTERVAL,
interval_id: 0, interval_id: 0,
is_dragged: false, is_dragged: false,
show_details_modal: false, selected_item: {},
selected_item: {} show_details_modal: false
} }
}, },
@ -98,10 +95,6 @@ export default {
} }
}, },
track_progress_ratio() {
return this.track_progress / this.track_progress_max
},
player() { player() {
return this.$store.state.player return this.$store.state.player
}, },