[web] Improve user interaction with sliders for output volume and music progress bar #1620

The sliders for output volume and the music slider have been optimised and simplified (one library less) to ensure easier user interaction.
This commit is contained in:
Alain Nussbaumer 2023-06-21 15:14:17 +02:00
parent b7a52d1761
commit eeb4d328c8
15 changed files with 249 additions and 241 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,6 @@
"@aacassandra/vue3-progressbar": "^1.0.3",
"@mdi/js": "^6.7.96",
"@ts-pro/vue-eternal-loading": "^1.2.0",
"@vueform/slider": "github:chme/slider#faff83ed8a77f2cdbcb7252505ef734301efd139",
"axios": "^1.4.0",
"bulma": "^0.9.4",
"bulma-switch": "^2.0.4",
@ -36,7 +35,7 @@
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-vue": "^9.14.1",
"prettier": "^2.8.8",
"sass": "^1.62.1",
"sass": "^1.63.5",
"vite": "^2.9.16"
}
},
@ -50,9 +49,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.22.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz",
"integrity": "sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
"integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
"bin": {
"parser": "bin/babel-parser.js"
},
@ -124,9 +123,9 @@
}
},
"node_modules/@eslint/js": {
"version": "8.42.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz",
"integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==",
"version": "8.43.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
"integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -481,16 +480,10 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/@vueform/slider": {
"version": "2.0.9",
"resolved": "git+ssh://git@github.com/chme/slider.git#faff83ed8a77f2cdbcb7252505ef734301efd139",
"integrity": "sha512-IfGEwBS5hwptmLbcnjrhDB7olw8mhCbQFDYv24bfYK/LVJo8pueumd7qsO9qlwfyezgnBdp1/CGBm+Wrh1oYdA==",
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
"integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@ -745,9 +738,9 @@
"dev": true
},
"node_modules/core-js": {
"version": "3.30.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz",
"integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==",
"version": "3.31.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.0.tgz",
"integrity": "sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@ -1197,15 +1190,15 @@
}
},
"node_modules/eslint": {
"version": "8.42.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz",
"integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==",
"version": "8.43.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
"integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.4.0",
"@eslint/eslintrc": "^2.0.3",
"@eslint/js": "8.42.0",
"@eslint/js": "8.43.0",
"@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
@ -1265,9 +1258,9 @@
}
},
"node_modules/eslint-plugin-vue": {
"version": "9.14.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.14.1.tgz",
"integrity": "sha512-LQazDB1qkNEKejLe/b5a9VfEbtbczcOaui5lQ4Qw0tbRBbQYREyxxOV5BQgNDTqGPs9pxqiEpbMi9ywuIaF7vw==",
"version": "9.15.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.15.0.tgz",
"integrity": "sha512-XYzpK6e2REli100+6iCeBA69v6Sm0D/yK2FZP+fCeNt0yH/m82qZQq+ztseyV0JsKdhFysuSEzeE1yCmSC92BA==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.3.0",
@ -2399,9 +2392,9 @@
}
},
"node_modules/sass": {
"version": "1.62.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz",
"integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==",
"version": "1.63.5",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.63.5.tgz",
"integrity": "sha512-Q6c5gs482oezdAp+0fWF9cRisvpy7yfYb64knID0OE8AnMgtkluRPfpGMFjeD4/+M4+6QpJZCU6JRSxbjiktkg==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
@ -2416,9 +2409,9 @@
}
},
"node_modules/semver": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@ -2645,9 +2638,9 @@
}
},
"node_modules/vue-eslint-parser": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.0.tgz",
"integrity": "sha512-48IxT9d0+wArT1+3wNIy0tascRoywqSUe2E1YalIC1L8jsUGe5aJQItWfRok7DVFGz3UYvzEI7n5wiTXsCMAcQ==",
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz",
"integrity": "sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==",
"dev": true,
"dependencies": {
"debug": "^4.3.4",

View File

@ -6,7 +6,7 @@
"build": "vite build --base='./'",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src",
"dev": "vite",
"format": "prettier . --write",
"format": "prettier . --write",
"i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\"",
"preview": "vite preview"
},
@ -14,7 +14,6 @@
"@aacassandra/vue3-progressbar": "^1.0.3",
"@mdi/js": "^6.7.96",
"@ts-pro/vue-eternal-loading": "^1.2.0",
"@vueform/slider": "github:chme/slider#faff83ed8a77f2cdbcb7252505ef734301efd139",
"axios": "^1.4.0",
"bulma": "^0.9.4",
"bulma-switch": "^2.0.4",
@ -39,7 +38,7 @@
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-vue": "^9.14.1",
"prettier": "^2.8.8",
"sass": "^1.62.1",
"sass": "^1.63.5",
"vite": "^2.9.16"
}
}

View File

@ -3,7 +3,7 @@
<navbar-top />
<vue-progress-bar class="fd-progress-bar" />
<router-view v-slot="{ Component }">
<component :is="Component" class="fd-page" />
<component :is="Component" />
</router-view>
<modal-dialog-remote-pairing

View File

@ -115,14 +115,13 @@
<div class="level-item fd-expanded">
<div class="fd-expanded">
<p class="heading" v-text="$t('navigation.volume')" />
<Slider
<input
v-model="player.volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:classes="{ target: 'slider' }"
@change="set_volume"
class="slider"
max="100"
type="range"
:style="{ '--ratio': player.volume / 100 }"
@change="change_volume"
/>
</div>
</div>
@ -175,15 +174,15 @@
/></span>
</a>
</p>
<Slider
<input
v-model="stream_volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:disabled="!playing"
:classes="{ target: 'slider' }"
@change="set_stream_volume"
class="slider"
:class="{ 'is-inactive': !playing }"
max="100"
type="range"
:style="{ '--ratio': stream_volume / 100 }"
@change="change_stream_volume"
/>
</div>
</div>
@ -238,14 +237,13 @@
<div class="level-item fd-expanded">
<div class="fd-expanded">
<p class="heading" v-text="$t('navigation.volume')" />
<Slider
<input
v-model="player.volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:classes="{ target: 'slider' }"
@change="set_volume"
class="slider"
max="100"
type="range"
:style="{ '--ratio': player.volume / 100 }"
@change="change_volume"
/>
</div>
</div>
@ -260,7 +258,7 @@
/>
<!-- Outputs: stream volume -->
<hr class="fd-navbar-divider" />
<div class="navbar-item fd-has-margin-bottom">
<div class="navbar-item mb-5">
<div class="level is-mobile">
<div class="level-left fd-expanded">
<div class="level-item" style="flex-grow: 0">
@ -298,15 +296,15 @@
/></span>
</a>
</p>
<Slider
<input
v-model="stream_volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:disabled="!playing"
:classes="{ target: 'slider' }"
@change="set_stream_volume"
class="slider"
:class="{ 'is-inactive': !playing }"
max="100"
type="range"
:style="{ '--ratio': stream_volume / 100 }"
@change="change_stream_volume"
/>
</div>
</div>
@ -331,7 +329,6 @@ import PlayerButtonConsume from '@/components/PlayerButtonConsume.vue'
import PlayerButtonRepeat from '@/components/PlayerButtonRepeat.vue'
import PlayerButtonSeekBack from '@/components/PlayerButtonSeekBack.vue'
import PlayerButtonSeekForward from '@/components/PlayerButtonSeekForward.vue'
import Slider from '@vueform/slider'
import * as types from '@/store/mutation_types'
export default {
@ -339,7 +336,6 @@ export default {
components: {
NavbarItemLink,
NavbarItemOutput,
Slider,
PlayerButtonPlayPause,
PlayerButtonNext,
PlayerButtonPrevious,
@ -382,9 +378,6 @@ export default {
return ''
},
state() {
return this.$store.state.player
},
now_playing() {
return this.$store.getters.now_playing
},
@ -427,16 +420,13 @@ export default {
this.show_outputs_menu = false
},
set_volume(newVolume) {
webapi.player_volume(newVolume)
change_volume() {
webapi.player_volume(this.player.volume)
},
toggle_mute_volume() {
if (this.player.volume > 0) {
this.set_volume(0)
} else {
this.set_volume(this.old_volume)
}
this.player.volume = this.player.volume > 0 ? 0 : this.old_volume
this.change_volume()
},
setupAudio() {
@ -492,8 +482,8 @@ export default {
return this.playChannel()
},
set_stream_volume(newVolume) {
this.stream_volume = newVolume
change_stream_volume() {
console.log(this.stream_volume)
_audio.setVolume(this.stream_volume / 100)
}
}

View File

@ -19,15 +19,15 @@
:class="{ 'has-text-grey-light': !output.selected }"
v-text="output.name"
/>
<Slider
<input
v-model="volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:disabled="!output.selected"
:classes="{ target: 'slider' }"
@change="set_volume"
class="slider"
:class="{ 'is-inactive': !output.selected }"
max="100"
type="range"
:style="{ '--ratio': volume / 100 }"
@change="change_volume"
/>
</div>
</div>
@ -37,17 +37,19 @@
</template>
<script>
import Slider from '@vueform/slider'
import webapi from '@/webapi'
export default {
name: 'NavbarItemOutput',
components: {
Slider
},
props: ['output'],
data() {
return {
volume: this.output.selected ? this.output.volume : 0
}
},
computed: {
type_class() {
if (this.output.type.startsWith('AirPlay')) {
@ -59,20 +61,18 @@ export default {
} else {
return 'server'
}
},
}
},
volume() {
return this.output.selected ? this.output.volume : 0
watch: {
output() {
this.volume = this.output.volume
}
},
methods: {
play_next() {
webapi.player_next()
},
set_volume(newVolume) {
webapi.player_output_volume(this.output.id, newVolume)
change_volume() {
webapi.player_output_volume(this.output.id, this.volume)
},
set_enabled() {

View File

@ -12,7 +12,6 @@ import { icons } from './icons'
import App from './App.vue'
import './mystyles.scss'
import '@vueform/slider/themes/default.css'
const app = createApp(App)
.use(store)

View File

@ -3,40 +3,6 @@
@import 'bulma/bulma.sass';
@import 'bulma-switch';
/* Volume slider */
.slider {
min-width: 250px;
width: 100%;
margin-top: 16px;
margin-bottom: 16px;
--slider-height: 4px;
--slider-connect-bg: #{$dark};
--slider-tooltip-bg: #{$dark};
--slider-handle-ring-color: #3b82f630;
--slider-handle-shadow: 0.5px 0.5px 0.5px 0.5px rgba(0, 0, 0, 0.32);
--slider-handle-shadow-active: 0.5px 0.5px 0.5px 0.5px rgba(0, 0, 0, 0.42);
}
/* Now playing progress bar */
.seek-slider {
min-width: 250px;
max-width: 500px;
width: 100% !important;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
margin: 0 auto 16px auto;
--slider-height: 4px;
--slider-connect-bg: #{$primary};
--slider-tooltip-bg: #{$primary};
--slider-handle-bg: #{$primary};
--slider-handle-border: 0;
--slider-handle-width: 10px;
--slider-handle-height: 10px;
--slider-handle-radius: 9999px;
--slider-handle-shadow: 0.5px 0.5px 0.5px 0.5px rgba(0, 0, 0, 0.32);
--slider-handle-shadow-active: 0.5px 0.5px 0.5px 0.5px rgba(0, 0, 0, 0.42);
--slider-handle-ring-width: 3px;
}
.progress-bar {
background-color: $info;
border-radius: 9999px;
@ -299,3 +265,67 @@ hr.fd-navbar-divider {
.hero-body {
padding: 1.5rem !important;
}
/* Slider */
@mixin thumb {
-webkit-appearance: none;
width: var(--th);
height: var(--th);
border-radius: 50%;
background: $dark;
border: none;
}
@mixin track {
height: calc(var(--sh));
border-radius: calc(var(--sh) / 2);
background: linear-gradient(90deg, $dark var(--sx), $grey-light var(--sx));
}
input[type='range'].slider {
--sh: 0.5rem;
--th: calc(var(--sh) * 1.5);
--sx: calc(var(--th) / 2 + (var(--ratio) * (100% - var(--th))));
-webkit-appearance: none;
min-width: 250px;
width: 100% !important;
cursor: grab;
&:active {
cursor: grabbing;
}
&::-webkit-slider-thumb {
@include thumb;
margin-top: calc((var(--th) - var(--sh)) / -2);
}
&::-moz-range-thumb {
@include thumb;
}
&::-webkit-slider-runnable-track {
@include track;
}
&::-moz-range-track {
@include track;
}
&.is-inactive {
&::-webkit-slider-thumb {
background-color: $grey-light;
}
&::-webkit-slider-runnable-track {
background: linear-gradient(
90deg,
$grey-light var(--sx),
$light var(--sx)
);
}
&::-moz-range-thumb {
background-color: $grey-light;
}
&::-moz-range-track {
background: linear-gradient(
90deg,
$grey-light var(--sx),
$light var(--sx)
);
}
}
}

View File

@ -1,6 +1,6 @@
<template>
<div>
<section class="section">
<section class="section fd-page">
<div class="container">
<div class="columns is-centered">
<div class="column is-four-fifths has-text-centered-mobile">

View File

@ -1,69 +1,54 @@
<template>
<section>
<div v-if="now_playing.id > 0" class="fd-is-fullheight">
<cover-artwork
:artwork_url="now_playing.artwork_url"
:artist="now_playing.artist"
:album="now_playing.album"
class="is-clickable fd-has-shadow fd-is-expanded fd-cover fd-cover-big-image"
@click="open_dialog(now_playing)"
/>
<div class="fd-has-padding-left-right">
<div class="container has-text-centered">
<p class="control has-text-centered fd-progress-now-playing">
<slider
ref="slider"
v-model="item_progress_ms"
:min="0"
:max="state.item_length_ms"
:step="1000"
:tooltips="false"
:disabled="state.state === 'stop'"
:classes="{ target: 'seek-slider' }"
@change="seek"
@start="start_dragging"
@end="end_dragging"
/>
</p>
<p class="content">
<span
v-text="
[
$filters.durationInHours(item_progress_ms),
$filters.durationInHours(now_playing.length_ms)
].join(' / ')
"
/>
</p>
</div>
</div>
<div class="fd-has-padding-left-right">
<div class="container has-text-centered fd-has-margin-top">
<h1 class="title is-5" v-text="now_playing.title" />
<h2 class="title is-6" v-text="now_playing.artist" />
<h2
v-if="composer"
class="subtitle is-6 has-text-grey has-text-weight-bold"
v-text="composer"
<div class="hero is-fullheight">
<div v-if="track.id > 0" class="hero-body">
<div class="container has-text-centered" style="max-width: 500px">
<cover-artwork
:artwork_url="track.artwork_url"
:artist="track.artist"
:album="track.album"
class="is-clickable fd-has-shadow fd-cover-big-image"
@click="open_dialog(track)"
/>
<input
v-model.number="item_progress_ms"
:step="1000"
:max="is_live ? 1000 : track.length_ms"
type="range"
class="slider mt-5"
:style="{ '--ratio': progress }"
@change="seek"
@touchstart="start_dragging"
@touchend="end_dragging"
/>
<div class="is-flex is-justify-content-space-between">
<p
class="subtitle is-7"
v-text="$filters.durationInHours(item_progress_ms)"
/>
<h3 class="subtitle is-6" v-text="now_playing.album" />
<h3
v-if="filepath"
class="subtitle is-6 has-text-grey"
v-text="filepath"
<p
class="subtitle is-7"
v-text="$filters.durationInHours(track.length_ms)"
/>
</div>
<h1 class="title is-5" v-text="track.title" />
<h2 class="title is-6" v-text="track.artist" />
<h2
v-if="composer"
class="subtitle is-6 has-text-grey has-text-weight-bold"
v-text="composer"
/>
<h3 class="subtitle is-6" v-text="track.album" />
<h3
v-if="filepath"
class="subtitle is-6 has-text-grey"
v-text="filepath"
/>
</div>
</div>
<div v-else class="fd-is-fullheight">
<div
class="fd-is-expanded fd-has-padding-left-right"
style="flex-direction: column"
>
<div class="content has-text-centered">
<h1 class="title is-5" v-text="$t('page.now-playing.title')" />
<p v-text="$t('page.now-playing.info')" />
</div>
<div v-else class="hero-body">
<div class="container has-text-centered">
<p class="title is-5" v-text="$t('page.now-playing.title')" />
<p class="subtitle" v-text="$t('page.now-playing.info')" />
</div>
</div>
<modal-dialog-queue-item
@ -71,12 +56,11 @@
:item="selected_item"
@close="show_details_modal = false"
/>
</section>
</div>
</template>
<script>
import ModalDialogQueueItem from '@/components/ModalDialogQueueItem.vue'
import Slider from '@vueform/slider'
import CoverArtwork from '@/components/CoverArtwork.vue'
import webapi from '@/webapi'
import * as types from '@/store/mutation_types'
@ -85,7 +69,6 @@ export default {
name: 'PageNowPlaying',
components: {
ModalDialogQueueItem,
Slider,
CoverArtwork
},
@ -101,11 +84,19 @@ export default {
},
computed: {
state() {
progress() {
return this.is_live ? 2 : this.item_progress_ms / this.track.length_ms
},
is_live() {
return this.track.length_ms == 0
},
player() {
return this.$store.state.player
},
now_playing() {
track() {
return this.$store.getters.now_playing
},
@ -121,16 +112,16 @@ export default {
if (this.settings_option_show_composer_now_playing) {
if (
!this.settings_option_show_composer_for_genre ||
(this.now_playing.genre &&
(this.track.genre &&
this.settings_option_show_composer_for_genre
.toLowerCase()
.split(',')
.findIndex(
(elem) =>
this.now_playing.genre.toLowerCase().indexOf(elem.trim()) >= 0
this.track.genre.toLowerCase().indexOf(elem.trim()) >= 0
) >= 0)
) {
return this.now_playing.composer
return this.track.composer
}
}
return null
@ -142,32 +133,30 @@ export default {
filepath() {
if (this.settings_option_show_filepath_now_playing) {
return this.now_playing.path
return this.track.path
}
return null
}
},
watch: {
state() {
player() {
if (this.interval_id > 0) {
window.clearTimeout(this.interval_id)
this.interval_id = 0
}
this.item_progress_ms = this.state.item_progress_ms
if (this.state.state === 'play') {
this.item_progress_ms = this.player.item_progress_ms
if (this.player.state === 'play') {
this.interval_id = window.setInterval(this.tick, 1000)
}
}
},
mounted() {},
created() {
this.item_progress_ms = this.state.item_progress_ms
this.item_progress_ms = this.player.item_progress_ms
webapi.player_status().then(({ data }) => {
this.$store.commit(types.UPDATE_PLAYER_STATUS, data)
if (this.state.state === 'play') {
if (this.player.state === 'play') {
this.interval_id = window.setInterval(this.tick, 1000)
}
})
@ -183,7 +172,13 @@ export default {
methods: {
tick() {
if (!this.is_dragged) {
this.item_progress_ms += 1000
if (this.is_live) {
this.item_progress_ms += 1000
} else if (this.item_progress_ms + 1000 > this.track.length_ms) {
this.item_progress_ms = this.track.length_ms
} else {
this.item_progress_ms += 1000
}
}
},
@ -195,10 +190,12 @@ export default {
this.is_dragged = false
},
seek(newPosition) {
webapi.player_seek_to_pos(newPosition).catch(() => {
this.item_progress_ms = this.state.item_progress_ms
})
seek() {
if (!this.is_live) {
webapi.player_seek_to_pos(this.item_progress_ms).catch(() => {
this.item_progress_ms = this.player.item_progress_ms
})
}
},
open_dialog(item) {

View File

@ -1,7 +1,7 @@
<template>
<div>
<!-- Search field + recent searches -->
<section class="section pb-0">
<section class="section fd-page pb-0">
<div class="container">
<div class="columns is-centered">
<div class="column is-four-fifths">

View File

@ -1,7 +1,7 @@
<template>
<div>
<!-- Search field + recent searches -->
<section class="section pb-0">
<section class="section pb-0 fd-page">
<div class="container">
<div class="columns is-centered">
<div class="column is-four-fifths">

View File

@ -1,5 +1,5 @@
<template>
<section class="section fd-content">
<section class="section fd-page fd-content">
<div class="container">
<div class="columns is-centered">
<div class="column is-four-fifths">

View File

@ -1,6 +1,6 @@
<template>
<div>
<section class="hero is-light is-bold fd-content">
<section class="hero is-light is-bold fd-page fd-content">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">