mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
commit
b3a661cae8
@ -25,7 +25,6 @@ htdocsassetsdir = $(datadir)/owntone/htdocs/assets
|
||||
dist_htdocsassets_DATA = \
|
||||
assets/index.css \
|
||||
assets/index.js \
|
||||
assets/vendor.js \
|
||||
assets/materialdesignicons-webfont.svg \
|
||||
assets/materialdesignicons-webfont.ttf \
|
||||
assets/materialdesignicons-webfont.woff2 \
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -17,7 +17,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>OwnTone</title>
|
||||
<script type="module" crossorigin src="/assets/index.js"></script>
|
||||
<link rel="modulepreload" href="/assets/vendor.js">
|
||||
<link rel="stylesheet" href="/assets/index.css">
|
||||
</head>
|
||||
<body>
|
||||
|
963
web-src/package-lock.json
generated
963
web-src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,17 +12,16 @@
|
||||
"dependencies": {
|
||||
"@aacassandra/vue3-progressbar": "^1.0.3",
|
||||
"@ts-pro/vue-eternal-loading": "^1.2.0",
|
||||
"@vueform/slider": "^2.0.9",
|
||||
"@vueform/slider": "github:chme/slider#faff83ed8a77f2cdbcb7252505ef734301efd139",
|
||||
"axios": "^0.26.1",
|
||||
"bulma": "^0.9.3",
|
||||
"bulma-switch": "^2.0.4",
|
||||
"luxon": "^2.3.1",
|
||||
"mdi": "^2.2.43",
|
||||
"moment": "^2.29.1",
|
||||
"moment-duration-format": "^2.3.2",
|
||||
"reconnectingwebsocket": "^1.0.0",
|
||||
"spotify-web-api-js": "^1.5.2",
|
||||
"string-to-color": "^2.2.2",
|
||||
"vue": "^3.2.31",
|
||||
"vue": "^3.2.33",
|
||||
"vue-router": "^4.0.14",
|
||||
"vue-scrollto": "^2.20.0",
|
||||
"vue3-click-away": "^1.2.4",
|
||||
@ -31,12 +30,12 @@
|
||||
"vuex": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^2.2.4",
|
||||
"eslint": "^8.11.0",
|
||||
"@vitejs/plugin-vue": "^2.3.1",
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-vue": "^8.5.0",
|
||||
"prettier": "2.6.0",
|
||||
"sass": "^1.49.9",
|
||||
"vite": "^2.8.6"
|
||||
"eslint-plugin-vue": "^8.6.0",
|
||||
"prettier": "2.6.2",
|
||||
"sass": "^1.50.0",
|
||||
"vite": "^2.9.5"
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ import ModalDialogUpdate from '@/components/ModalDialogUpdate.vue'
|
||||
import webapi from '@/webapi'
|
||||
import * as types from '@/store/mutation_types'
|
||||
import ReconnectingWebSocket from 'reconnectingwebsocket'
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
@ -90,7 +89,6 @@ export default {
|
||||
},
|
||||
|
||||
created: function () {
|
||||
moment.locale(navigator.language)
|
||||
this.connect()
|
||||
|
||||
// Start the progress bar on app start
|
||||
|
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div v-else-if="album.isItem" class="media" @click="open_album(album.item)">
|
||||
<div v-if="is_visible_artwork" class="media-left fd-has-action">
|
||||
<p class="image is-64x64 fd-has-shadow fd-has-action">
|
||||
<div class="image is-64x64 fd-has-shadow fd-has-action">
|
||||
<figure>
|
||||
<img
|
||||
v-lazy="{
|
||||
@ -20,7 +20,7 @@
|
||||
:artist="album.item.artist"
|
||||
/>
|
||||
</figure>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-content fd-has-action is-clipped">
|
||||
<div style="margin-top: 0.7rem">
|
||||
@ -34,7 +34,7 @@
|
||||
v-if="album.item.date_released && album.item.media_kind === 'music'"
|
||||
class="subtitle is-7 has-text-grey has-text-weight-normal"
|
||||
>
|
||||
{{ $filters.time(album.item.date_released, 'L') }}
|
||||
{{ $filters.date(album.item.date_released) }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@
|
||||
<p v-if="album.date_released">
|
||||
<span class="heading">Release date</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.time(album.date_released, 'L')
|
||||
$filters.date(album.date_released)
|
||||
}}</span>
|
||||
</p>
|
||||
<p v-else-if="album.year > 0">
|
||||
@ -49,7 +49,7 @@
|
||||
<p>
|
||||
<span class="heading">Length</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.duration(album.length_ms)
|
||||
$filters.durationInHours(album.length_ms)
|
||||
}}</span>
|
||||
</p>
|
||||
<p>
|
||||
@ -61,7 +61,7 @@
|
||||
<p>
|
||||
<span class="heading">Added at</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.time(album.time_added, 'L LT')
|
||||
$filters.datetime(album.time_added)
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -27,7 +27,7 @@
|
||||
<p>
|
||||
<span class="heading">Added at</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.time(artist.time_added, 'L LT')
|
||||
$filters.datetime(artist.time_added)
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -23,6 +23,12 @@
|
||||
composer.track_count
|
||||
}}</a>
|
||||
</p>
|
||||
<p>
|
||||
<span class="heading">Length</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.durationInHours(composer.length_ms)
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<footer class="card-footer">
|
||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||
|
@ -11,6 +11,22 @@
|
||||
genre.name
|
||||
}}</a>
|
||||
</p>
|
||||
<div class="content is-small">
|
||||
<p>
|
||||
<span class="heading">Albums</span>
|
||||
<span class="title is-6">{{ genre.album_count }}</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="heading">Tracks</span>
|
||||
<span class="title is-6">{{ genre.track_count }}</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="heading">Length</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.durationInHours(genre.length_ms)
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer">
|
||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||
|
@ -56,7 +56,7 @@
|
||||
<p>
|
||||
<span class="heading">Length</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.duration(item.length_ms)
|
||||
$filters.durationInHours(item.length_ms)
|
||||
}}</span>
|
||||
</p>
|
||||
<p>
|
||||
|
@ -48,7 +48,7 @@
|
||||
<p v-if="track.date_released">
|
||||
<span class="heading">Release date</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.time(track.date_released, 'L')
|
||||
$filters.date(track.date_released)
|
||||
}}</span>
|
||||
</p>
|
||||
<p v-else-if="track.year > 0">
|
||||
@ -70,7 +70,7 @@
|
||||
<p>
|
||||
<span class="heading">Length</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.duration(track.length_ms)
|
||||
$filters.durationInHours(track.length_ms)
|
||||
}}</span>
|
||||
</p>
|
||||
<p>
|
||||
@ -107,7 +107,7 @@
|
||||
<p>
|
||||
<span class="heading">Added at</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.time(track.time_added, 'L LT')
|
||||
$filters.datetime(track.time_added)
|
||||
}}</span>
|
||||
</p>
|
||||
<p>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<b>{{ album.artists[0].name }}</b>
|
||||
</h2>
|
||||
<h2 class="subtitle is-7 has-text-grey has-text-weight-normal">
|
||||
({{ album.album_type }}, {{ $filters.time(album.release_date, 'L') }})
|
||||
({{ album.album_type }}, {{ $filters.date(album.release_date) }})
|
||||
</h2>
|
||||
</div>
|
||||
<div class="media-right">
|
||||
|
@ -32,7 +32,7 @@
|
||||
<p>
|
||||
<span class="heading">Release date</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.time(album.release_date, 'L')
|
||||
$filters.date(album.release_date)
|
||||
}}</span>
|
||||
</p>
|
||||
<p>
|
||||
|
@ -28,7 +28,7 @@
|
||||
<p>
|
||||
<span class="heading">Release date</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.time(album.release_date, 'L')
|
||||
$filters.date(album.release_date)
|
||||
}}</span>
|
||||
</p>
|
||||
<p>
|
||||
@ -40,7 +40,7 @@
|
||||
<p>
|
||||
<span class="heading">Length</span>
|
||||
<span class="title is-6">{{
|
||||
$filters.duration(track.duration_ms)
|
||||
$filters.durationInHours(track.duration_ms)
|
||||
}}</span>
|
||||
</p>
|
||||
<p>
|
||||
|
@ -1,25 +1,47 @@
|
||||
import moment from 'moment'
|
||||
import momentDurationFormatSetup from 'moment-duration-format'
|
||||
|
||||
momentDurationFormatSetup(moment)
|
||||
import { DateTime, Duration } from 'luxon'
|
||||
|
||||
export const filters = {
|
||||
duration: function (value, format) {
|
||||
if (format) {
|
||||
return moment.duration(value).format(format)
|
||||
durationInHours: function (value_ms) {
|
||||
const seconds = Math.floor(value_ms / 1000)
|
||||
if (seconds > 3600) {
|
||||
return Duration.fromObject({ seconds: seconds })
|
||||
.shiftTo('hours', 'minutes', 'seconds')
|
||||
.toFormat('hh:mm:ss')
|
||||
}
|
||||
return moment.duration(value).format('hh:*mm:ss')
|
||||
return Duration.fromObject({ seconds: seconds })
|
||||
.shiftTo('minutes', 'seconds')
|
||||
.toFormat('mm:ss')
|
||||
},
|
||||
|
||||
time: function (value, format) {
|
||||
if (format) {
|
||||
return moment(value).format(format)
|
||||
durationInDays: function (value_ms) {
|
||||
const minutes = Math.floor(value_ms / 60000)
|
||||
if (minutes > 1440) {
|
||||
// 60 * 24
|
||||
return Duration.fromObject({ minutes: minutes })
|
||||
.shiftTo('days', 'hours', 'minutes')
|
||||
.toHuman()
|
||||
} else if (minutes > 60) {
|
||||
return Duration.fromObject({ minutes: minutes })
|
||||
.shiftTo('hours', 'minutes')
|
||||
.toHuman()
|
||||
}
|
||||
return moment(value).format()
|
||||
return Duration.fromObject({ minutes: minutes })
|
||||
.shiftTo('minutes')
|
||||
.toHuman()
|
||||
},
|
||||
|
||||
timeFromNow: function (value, withoutSuffix) {
|
||||
return moment(value).fromNow(withoutSuffix)
|
||||
date: function (value) {
|
||||
return DateTime.fromISO(value).toLocaleString(DateTime.DATE_FULL)
|
||||
},
|
||||
|
||||
datetime: function (value) {
|
||||
return DateTime.fromISO(value).toLocaleString(DateTime.DATETIME_MED)
|
||||
},
|
||||
|
||||
timeFromNow: function (value) {
|
||||
var diff = DateTime.now().diff(DateTime.fromISO(value))
|
||||
|
||||
return this.durationInDays(diff.as('milliseconds'))
|
||||
},
|
||||
|
||||
number: function (value) {
|
||||
|
@ -132,10 +132,12 @@ section.hero + section.fd-content {
|
||||
|
||||
.fd-page {
|
||||
margin-top: 3.25rem;
|
||||
margin-bottom: 3.25rem;
|
||||
}
|
||||
|
||||
.fd-page-with-tabs {
|
||||
margin-top: 6.25rem !important;
|
||||
margin-bottom: 3.25rem;
|
||||
}
|
||||
|
||||
/* Set minimum height to hide "option" section */
|
||||
|
@ -61,20 +61,15 @@
|
||||
<tr>
|
||||
<th>Total playtime</th>
|
||||
<td class="has-text-right">
|
||||
{{
|
||||
$filters.duration(
|
||||
library.db_playtime * 1000,
|
||||
'y [years], d [days], h [hours], m [minutes]'
|
||||
)
|
||||
}}
|
||||
{{ $filters.durationInDays(library.db_playtime * 1000) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Library updated</th>
|
||||
<td class="has-text-right">
|
||||
{{ $filters.timeFromNow(library.updated_at) }}
|
||||
{{ $filters.timeFromNow(library.updated_at) }} ago
|
||||
<span class="has-text-grey"
|
||||
>({{ $filters.time(library.updated_at, 'lll') }})</span
|
||||
>({{ $filters.datetime(library.updated_at) }})</span
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
@ -83,7 +78,7 @@
|
||||
<td class="has-text-right">
|
||||
{{ $filters.timeFromNow(library.started_at, true) }}
|
||||
<span class="has-text-grey"
|
||||
>({{ $filters.time(library.started_at, 'll') }})</span
|
||||
>({{ $filters.datetime(library.started_at) }})</span
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<content-with-heading>
|
||||
<template #heading-left>
|
||||
<p class="title is-4">
|
||||
{{ name }}
|
||||
{{ composer.name }}
|
||||
</p>
|
||||
</template>
|
||||
<template #heading-right>
|
||||
@ -24,14 +24,16 @@
|
||||
</template>
|
||||
<template #content>
|
||||
<p class="heading has-text-centered-mobile">
|
||||
{{ albums_list.total }} albums |
|
||||
<a class="has-text-link" @click="open_tracks">tracks</a>
|
||||
{{ composer.album_count }} albums |
|
||||
<a class="has-text-link" @click="open_tracks"
|
||||
>{{ composer.track_count }} tracks</a
|
||||
>
|
||||
</p>
|
||||
<list-albums :albums="albums_list" :hide_group_title="true" />
|
||||
|
||||
<modal-dialog-composer
|
||||
:show="show_composer_details_modal"
|
||||
:composer="{ name: name }"
|
||||
:composer="composer"
|
||||
@close="show_composer_details_modal = false"
|
||||
/>
|
||||
</template>
|
||||
@ -48,12 +50,15 @@ import { GroupByList } from '@/lib/GroupByList'
|
||||
|
||||
const dataObject = {
|
||||
load: function (to) {
|
||||
return webapi.library_composer(to.params.composer)
|
||||
return Promise.all([
|
||||
webapi.library_composer(to.params.composer),
|
||||
webapi.library_composer_albums(to.params.composer)
|
||||
])
|
||||
},
|
||||
|
||||
set: function (vm, response) {
|
||||
vm.name = vm.$route.params.composer
|
||||
vm.albums_list = new GroupByList(response.data.albums)
|
||||
vm.composer = response[0].data
|
||||
vm.albums_list = new GroupByList(response[1].data.albums)
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +85,7 @@ export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
name: '',
|
||||
composer: {},
|
||||
albums_list: new GroupByList(),
|
||||
show_composer_details_modal: false
|
||||
}
|
||||
@ -90,13 +95,13 @@ export default {
|
||||
open_tracks: function () {
|
||||
this.$router.push({
|
||||
name: 'ComposerTracks',
|
||||
params: { composer: this.name }
|
||||
params: { composer: this.composer.name }
|
||||
})
|
||||
},
|
||||
|
||||
play: function () {
|
||||
webapi.player_play_expression(
|
||||
'composer is "' + this.name + '" and media_kind is music',
|
||||
'composer is "' + this.composer.name + '" and media_kind is music',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<content-with-heading>
|
||||
<template #heading-left>
|
||||
<p class="title is-4">
|
||||
{{ composer }}
|
||||
{{ composer.name }}
|
||||
</p>
|
||||
</template>
|
||||
<template #heading-right>
|
||||
@ -24,13 +24,15 @@
|
||||
</template>
|
||||
<template #content>
|
||||
<p class="heading has-text-centered-mobile">
|
||||
<a class="has-text-link" @click="open_albums">albums</a> |
|
||||
{{ tracks.total }} tracks
|
||||
<a class="has-text-link" @click="open_albums"
|
||||
>{{ composer.album_count }} albums</a
|
||||
>
|
||||
| {{ composer.track_count }} tracks
|
||||
</p>
|
||||
<list-tracks :tracks="tracks.items" :expression="play_expression" />
|
||||
<modal-dialog-composer
|
||||
:show="show_composer_details_modal"
|
||||
:composer="{ name: composer }"
|
||||
:composer="composer"
|
||||
@close="show_composer_details_modal = false"
|
||||
/>
|
||||
</template>
|
||||
@ -46,12 +48,15 @@ import webapi from '@/webapi'
|
||||
|
||||
const dataObject = {
|
||||
load: function (to) {
|
||||
return webapi.library_composer_tracks(to.params.composer)
|
||||
return Promise.all([
|
||||
webapi.library_composer(to.params.composer),
|
||||
webapi.library_composer_tracks(to.params.composer)
|
||||
])
|
||||
},
|
||||
|
||||
set: function (vm, response) {
|
||||
vm.composer = vm.$route.params.composer
|
||||
vm.tracks = response.data.tracks
|
||||
vm.composer = response[0].data
|
||||
vm.tracks = response[1].data.tracks
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +84,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
tracks: { items: [] },
|
||||
composer: '',
|
||||
composer: {},
|
||||
|
||||
show_composer_details_modal: false
|
||||
}
|
||||
@ -87,7 +92,7 @@ export default {
|
||||
|
||||
computed: {
|
||||
play_expression() {
|
||||
return 'composer is "' + this.composer + '" and media_kind is music'
|
||||
return 'composer is "' + this.composer.name + '" and media_kind is music'
|
||||
}
|
||||
},
|
||||
|
||||
@ -96,7 +101,7 @@ export default {
|
||||
this.show_details_modal = false
|
||||
this.$router.push({
|
||||
name: 'ComposerAlbums',
|
||||
params: { composer: this.composer }
|
||||
params: { composer: this.composer.name }
|
||||
})
|
||||
},
|
||||
|
||||
|
@ -27,7 +27,7 @@ import { byName, GroupByList } from '@/lib/GroupByList'
|
||||
|
||||
const dataObject = {
|
||||
load: function (to) {
|
||||
return webapi.library_composers()
|
||||
return webapi.library_composers('music')
|
||||
},
|
||||
|
||||
set: function (vm, response) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
</template>
|
||||
<template #heading-left>
|
||||
<p class="title is-4">
|
||||
{{ name }}
|
||||
{{ genre.name }}
|
||||
</p>
|
||||
</template>
|
||||
<template #heading-right>
|
||||
@ -27,13 +27,15 @@
|
||||
</template>
|
||||
<template #content>
|
||||
<p class="heading has-text-centered-mobile">
|
||||
{{ albums_list.total }} albums |
|
||||
<a class="has-text-link" @click="open_tracks">tracks</a>
|
||||
{{ genre.album_count }} albums |
|
||||
<a class="has-text-link" @click="open_tracks"
|
||||
>{{ genre.track_count }} tracks</a
|
||||
>
|
||||
</p>
|
||||
<list-albums :albums="albums_list" />
|
||||
<modal-dialog-genre
|
||||
:show="show_genre_details_modal"
|
||||
:genre="{ name: name }"
|
||||
:genre="genre"
|
||||
@close="show_genre_details_modal = false"
|
||||
/>
|
||||
</template>
|
||||
@ -51,12 +53,15 @@ import { bySortName, GroupByList } from '@/lib/GroupByList'
|
||||
|
||||
const dataObject = {
|
||||
load: function (to) {
|
||||
return webapi.library_genre(to.params.genre)
|
||||
return Promise.all([
|
||||
webapi.library_genre(to.params.genre),
|
||||
webapi.library_genre_albums(to.params.genre)
|
||||
])
|
||||
},
|
||||
|
||||
set: function (vm, response) {
|
||||
vm.name = vm.$route.params.genre
|
||||
vm.albums_list = new GroupByList(response.data.albums)
|
||||
vm.genre = response[0].data
|
||||
vm.albums_list = new GroupByList(response[1].data.albums)
|
||||
vm.albums_list.group(bySortName('name_sort'))
|
||||
}
|
||||
}
|
||||
@ -89,7 +94,7 @@ export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
name: '',
|
||||
genre: {},
|
||||
albums_list: new GroupByList(),
|
||||
|
||||
show_genre_details_modal: false
|
||||
@ -99,12 +104,15 @@ export default {
|
||||
methods: {
|
||||
open_tracks: function () {
|
||||
this.show_details_modal = false
|
||||
this.$router.push({ name: 'GenreTracks', params: { genre: this.name } })
|
||||
this.$router.push({
|
||||
name: 'GenreTracks',
|
||||
params: { genre: this.genre.name }
|
||||
})
|
||||
},
|
||||
|
||||
play: function () {
|
||||
webapi.player_play_expression(
|
||||
'genre is "' + this.name + '" and media_kind is music',
|
||||
'genre is "' + this.genre.name + '" and media_kind is music',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
</template>
|
||||
<template #heading-left>
|
||||
<p class="title is-4">
|
||||
{{ genre }}
|
||||
{{ genre.name }}
|
||||
</p>
|
||||
</template>
|
||||
<template #heading-right>
|
||||
@ -27,13 +27,15 @@
|
||||
</template>
|
||||
<template #content>
|
||||
<p class="heading has-text-centered-mobile">
|
||||
<a class="has-text-link" @click="open_genre">albums</a> |
|
||||
{{ tracks.total }} tracks
|
||||
<a class="has-text-link" @click="open_genre"
|
||||
>{{ genre.album_count }} albums</a
|
||||
>
|
||||
| {{ genre.track_count }} tracks
|
||||
</p>
|
||||
<list-tracks :tracks="tracks.items" :expression="expression" />
|
||||
<modal-dialog-genre
|
||||
:show="show_genre_details_modal"
|
||||
:genre="{ name: genre }"
|
||||
:genre="genre"
|
||||
@close="show_genre_details_modal = false"
|
||||
/>
|
||||
</template>
|
||||
@ -50,12 +52,15 @@ import webapi from '@/webapi'
|
||||
|
||||
const dataObject = {
|
||||
load: function (to) {
|
||||
return webapi.library_genre_tracks(to.params.genre)
|
||||
return Promise.all([
|
||||
webapi.library_genre(to.params.genre),
|
||||
webapi.library_genre_tracks(to.params.genre)
|
||||
])
|
||||
},
|
||||
|
||||
set: function (vm, response) {
|
||||
vm.genre = vm.$route.params.genre
|
||||
vm.tracks = response.data.tracks
|
||||
vm.genre = response[0].data
|
||||
vm.tracks = response[1].data.tracks
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,14 +107,14 @@ export default {
|
||||
},
|
||||
|
||||
expression() {
|
||||
return 'genre is "' + this.genre + '" and media_kind is music'
|
||||
return 'genre is "' + this.genre.name + '" and media_kind is music'
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
open_genre: function () {
|
||||
this.show_details_modal = false
|
||||
this.$router.push({ name: 'Genre', params: { genre: this.genre } })
|
||||
this.$router.push({ name: 'Genre', params: { genre: this.genre.name } })
|
||||
},
|
||||
|
||||
play: function () {
|
||||
|
@ -27,7 +27,7 @@ import { byName, GroupByList } from '@/lib/GroupByList'
|
||||
|
||||
const dataObject = {
|
||||
load: function (to) {
|
||||
return webapi.library_genres()
|
||||
return webapi.library_genres('music')
|
||||
},
|
||||
|
||||
set: function (vm, response) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
<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"
|
||||
@ -22,6 +23,8 @@
|
||||
:disabled="state.state === 'stop'"
|
||||
:classes="{ target: 'seek-slider' }"
|
||||
@change="seek"
|
||||
@start="start_dragging"
|
||||
@end="end_dragging"
|
||||
/>
|
||||
<!--range-slider
|
||||
class="seek-slider fd-has-action"
|
||||
@ -35,8 +38,8 @@
|
||||
</p>
|
||||
<p class="content">
|
||||
<span
|
||||
>{{ $filters.duration(item_progress_ms) }} /
|
||||
{{ $filters.duration(now_playing.length_ms) }}</span
|
||||
>{{ $filters.durationInHours(item_progress_ms) }} /
|
||||
{{ $filters.durationInHours(now_playing.length_ms) }}</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
@ -101,6 +104,7 @@ export default {
|
||||
return {
|
||||
item_progress_ms: 0,
|
||||
interval_id: 0,
|
||||
is_dragged: false,
|
||||
|
||||
show_details_modal: false,
|
||||
selected_item: {}
|
||||
@ -157,6 +161,10 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
mounted: function () {
|
||||
console.log(this.$refs.slider)
|
||||
},
|
||||
|
||||
created() {
|
||||
this.item_progress_ms = this.state.item_progress_ms
|
||||
webapi.player_status().then(({ data }) => {
|
||||
@ -176,7 +184,19 @@ export default {
|
||||
|
||||
methods: {
|
||||
tick: function () {
|
||||
this.item_progress_ms += 1000
|
||||
if (!this.is_dragged) {
|
||||
this.item_progress_ms += 1000
|
||||
}
|
||||
},
|
||||
|
||||
start_dragging: function () {
|
||||
console.log('@start')
|
||||
this.is_dragged = true
|
||||
},
|
||||
|
||||
end_dragging: function () {
|
||||
console.log('@end')
|
||||
this.is_dragged = false
|
||||
},
|
||||
|
||||
seek: function (newPosition) {
|
||||
|
@ -50,7 +50,7 @@
|
||||
:context_uri="album.uri"
|
||||
>
|
||||
<template #actions>
|
||||
<a @click="open_track_dialog(track)">
|
||||
<a @click.prevent.stop="open_track_dialog(track)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
|
@ -26,7 +26,7 @@
|
||||
</p>
|
||||
</template>
|
||||
<template #actions>
|
||||
<a @click="open_album_dialog(album)">
|
||||
<a @click.prevent.stop="open_album_dialog(album)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
@ -65,7 +65,7 @@
|
||||
:playlist="playlist"
|
||||
>
|
||||
<template #actions>
|
||||
<a @click="open_playlist_dialog(playlist)">
|
||||
<a @click.prevent.stop="open_playlist_dialog(playlist)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
|
@ -13,7 +13,7 @@
|
||||
:playlist="playlist"
|
||||
>
|
||||
<template #actions>
|
||||
<a @click="open_playlist_dialog(playlist)">
|
||||
<a @click.prevent.stop="open_playlist_dialog(playlist)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
|
@ -25,7 +25,7 @@
|
||||
</p>
|
||||
</template>
|
||||
<template #actions>
|
||||
<a @click="open_album_dialog(album)">
|
||||
<a @click.prevent.stop="open_album_dialog(album)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
|
@ -34,7 +34,7 @@
|
||||
:context_uri="playlist.uri"
|
||||
>
|
||||
<template #actions>
|
||||
<a @click="open_track_dialog(item.track)">
|
||||
<a @click.prevent.stop="open_track_dialog(item.track)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
|
@ -53,7 +53,7 @@
|
||||
:context_uri="track.uri"
|
||||
>
|
||||
<template #actions>
|
||||
<a @click="open_track_dialog(track)">
|
||||
<a @click.prevent.stop="open_track_dialog(track)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
@ -103,7 +103,7 @@
|
||||
:artist="artist"
|
||||
>
|
||||
<template #actions>
|
||||
<a @click="open_artist_dialog(artist)">
|
||||
<a @click.prevent.stop="open_artist_dialog(artist)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
@ -164,7 +164,7 @@
|
||||
</p>
|
||||
</template>
|
||||
<template #actions>
|
||||
<a @click="open_album_dialog(album)">
|
||||
<a @click.prevent.stop="open_album_dialog(album)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
@ -213,7 +213,7 @@
|
||||
:playlist="playlist"
|
||||
>
|
||||
<template #actions>
|
||||
<a @click="open_playlist_dialog(playlist)">
|
||||
<a @click.prevent.stop="open_playlist_dialog(playlist)">
|
||||
<span class="icon has-text-dark"
|
||||
><i class="mdi mdi-dots-vertical mdi-18px"
|
||||
/></span>
|
||||
|
@ -292,15 +292,20 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
library_genres() {
|
||||
return axios.get('./api/library/genres')
|
||||
library_genres(media_kind = undefined) {
|
||||
return axios.get('./api/library/genres', {
|
||||
params: { media_kind: media_kind }
|
||||
})
|
||||
},
|
||||
|
||||
library_genre(genre) {
|
||||
return axios.get(`./api/library/genres/${encodeURIComponent(genre)}`)
|
||||
},
|
||||
|
||||
library_genre_albums(genre) {
|
||||
const genreParams = {
|
||||
type: 'albums',
|
||||
media_kind: 'music',
|
||||
expression: 'genre is "' + genre + '"'
|
||||
expression: `genre is "${genre}" and media_kind is music`
|
||||
}
|
||||
return axios.get('./api/search', {
|
||||
params: genreParams
|
||||
@ -310,8 +315,7 @@ export default {
|
||||
library_genre_tracks(genre) {
|
||||
const genreParams = {
|
||||
type: 'tracks',
|
||||
media_kind: 'music',
|
||||
expression: 'genre is "' + genre + '"'
|
||||
expression: `genre is "${genre}" and media_kind is music`
|
||||
}
|
||||
return axios.get('./api/search', {
|
||||
params: genreParams
|
||||
@ -329,15 +333,20 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
library_composers() {
|
||||
return axios.get('./api/library/composers')
|
||||
library_composers(media_kind = undefined) {
|
||||
return axios.get('./api/library/composers', {
|
||||
params: { media_kind: media_kind }
|
||||
})
|
||||
},
|
||||
|
||||
library_composer(composer) {
|
||||
return axios.get(`./api/library/composers/${encodeURIComponent(composer)}`)
|
||||
},
|
||||
|
||||
library_composer_albums(composer) {
|
||||
const params = {
|
||||
type: 'albums',
|
||||
media_kind: 'music',
|
||||
expression: 'composer is "' + composer + '"'
|
||||
expression: `composer is "${composer}" and media_kind is music`
|
||||
}
|
||||
return axios.get('./api/search', {
|
||||
params: params
|
||||
@ -347,8 +356,7 @@ export default {
|
||||
library_composer_tracks(composer) {
|
||||
const params = {
|
||||
type: 'tracks',
|
||||
media_kind: 'music',
|
||||
expression: 'composer is "' + composer + '"'
|
||||
expression: `composer is "${composer}" and media_kind is music`
|
||||
}
|
||||
return axios.get('./api/search', {
|
||||
params: params
|
||||
|
Loading…
Reference in New Issue
Block a user