[web] Refactor modal dialogs

This commit is contained in:
Alain Nussbaumer 2025-02-09 17:52:45 +01:00
parent b9b36855f4
commit e3c8d1fab9
25 changed files with 453 additions and 639 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

@ -44,14 +44,12 @@ export default {
items: { required: true, type: Object },
media_kind: { required: true, type: String }
},
data() {
return {
selected_item: {},
show_details_modal: false
}
},
methods: {
open(item) {
this.$router.push({

View File

@ -11,7 +11,7 @@
<footer v-if="actions.length" class="card-footer">
<a
v-for="action in actions"
:key="action.event"
:key="action.label"
class="card-footer-item"
:class="{ 'is-disabled': action.disabled }"
@click="action.handler"

View File

@ -1,7 +1,11 @@
<template>
<modal-dialog :actions="actions" :show="show" @close="$emit('close')">
<modal-dialog
:actions="actions"
:show="show"
:title="$t('dialog.add.rss.title')"
@close="$emit('close')"
>
<template #content>
<p class="title is-4" v-text="$t('dialog.add.rss.title')" />
<div class="field">
<p class="control has-icons-left">
<input

View File

@ -1,8 +1,12 @@
<template>
<modal-dialog :actions="actions" :show="show" @close="$emit('close')">
<modal-dialog
:actions="actions"
:show="show"
:title="$t('dialog.add.stream.title')"
@close="$emit('close')"
>
<template #content>
<form @submit.prevent="play">
<p class="title is-4" v-text="$t('dialog.add.stream.title')" />
<div class="field">
<p class="control has-icons-left">
<input

View File

@ -1,107 +1,78 @@
<template>
<modal-dialog-playable :item="item" :show="show" @close="$emit('close')">
<template #content>
<div class="title is-4">
<a @click="open" v-text="item.name" />
</div>
<cover-artwork
:url="item.artwork_url"
:artist="item.artist"
:album="item.name"
class="is-normal mb-3"
/>
<div v-if="media_kind_resolved === 'podcast'" class="buttons">
<a
class="button is-small"
@click="mark_played"
v-text="$t('dialog.album.mark-as-played')"
/>
<a
v-if="item.data_kind === 'url'"
class="button is-small"
@click="$emit('remove-podcast')"
v-text="$t('dialog.album.remove-podcast')"
/>
</div>
<div v-if="item.artist" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.album.artist')"
/>
<div class="title is-6">
<a @click="open_artist" v-text="item.artist" />
</div>
</div>
<div v-if="item.date_released" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.album.release-date')"
/>
<div class="title is-6" v-text="$filters.date(item.date_released)" />
</div>
<div v-else-if="item.year" class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.album.year')" />
<div class="title is-6" v-text="item.year" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.album.tracks')"
/>
<div class="title is-6" v-text="item.track_count" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.album.duration')"
/>
<div
class="title is-6"
v-text="$filters.durationInHours(item.length_ms)"
/>
</div>
<div class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.album.type')" />
<div
class="title is-6"
v-text="
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
"
/>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.album.added-on')"
/>
<div class="title is-6" v-text="$filters.datetime(item.time_added)" />
</div>
</template>
</modal-dialog-playable>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
import CoverArtwork from '@/components/CoverArtwork.vue'
import ModalDialogPlayable from '@/components/ModalDialogPlayable.vue'
import webapi from '@/webapi'
export default {
name: 'ModalDialogAlbum',
components: { ModalDialogPlayable, CoverArtwork },
components: { ModalDialogPlayable },
props: {
item: { required: true, type: Object },
media_kind: { default: '', type: String },
show: Boolean
},
emits: ['close', 'remove-podcast', 'play-count-changed'],
data() {
return {
artwork_visible: false
}
},
computed: {
buttons() {
if (this.media_kind_resolved === 'podcast') {
if (item.data_kind === 'url') {
return [
{ label: 'dialog.album.mark-as-played', action: this.mark_played },
{
label: 'dialog.album.remove-podcast',
action: this.remove_podcast
}
]
}
return [
{ label: 'dialog.album.mark-as-played', action: this.mark_played }
]
}
return []
},
media_kind_resolved() {
return this.media_kind || this.item.media_kind
},
playable() {
return {
name: this.item.name,
action: this.open,
image: this.item.artwork_url,
artist: this.item.artist,
album: this.item.name,
properties: [
{
label: 'dialog.album.artist',
value: this.item.artist,
action: this.open_artist
},
{
label: 'dialog.album.release-date',
value: this.$filters.date(this.item.date_released)
},
{ label: 'dialog.album.year', value: this.item.year },
{ label: 'dialog.album.tracks', value: this.item.track_count },
{
label: 'dialog.album.duration',
value: this.$filters.durationInHours(this.item.length_ms)
},
{
label: 'dialog.album.type',
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
},
{
label: 'dialog.album.added-on',
value: this.$filters.datetime(this.item.time_added)
}
]
}
}
},
methods: {
@ -142,6 +113,9 @@ export default {
params: { id: this.item.artist_id }
})
}
},
remove_podcast() {
this.$emit('remove-podcast')
}
}
}

View File

@ -1,55 +1,46 @@
<template>
<modal-dialog-playable :item="item" :show="show" @close="$emit('close')">
<template #content>
<div class="title is-4">
<a @click="open" v-text="item.name" />
</div>
<cover-artwork
:url="artwork_url(item)"
:artist="item.artist"
:album="item.name"
class="is-normal mb-3"
/>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.album.album-artist')"
/>
<div class="title is-6">
<a @click="open_artist" v-text="item.artists[0].name" />
</div>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.album.release-date')"
/>
<div class="title is-6" v-text="$filters.date(item.release_date)" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.album.type')"
/>
<div class="title is-6" v-text="item.album_type" />
</div>
</template>
</modal-dialog-playable>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
import CoverArtwork from '@/components/CoverArtwork.vue'
import ModalDialogPlayable from '@/components/ModalDialogPlayable.vue'
export default {
name: 'ModalDialogAlbumSpotify',
components: { ModalDialogPlayable, CoverArtwork },
components: { ModalDialogPlayable },
props: { item: { required: true, type: Object }, show: Boolean },
emits: ['close'],
computed: {
playable() {
return {
name: this.item.name || '',
image: this.item?.images?.[0]?.url || '',
artist: this.item.artist || '',
album: this.item.name || '',
action: this.open,
properties: [
{
label: 'dialog.spotify.album.album-artist',
value: this.item?.artists?.[0]?.name,
action: this.open_artist
},
{
label: 'dialog.spotify.album.release-date',
value: this.$filters.date(this.item.release_date)
},
{
label: 'dialog.spotify.album.type',
value: this.item.album_type
}
]
}
}
},
methods: {
artwork_url(item) {
return item.images?.[0]?.url || ''
},
open() {
this.$emit('close')
this.$router.push({

View File

@ -1,36 +1,9 @@
<template>
<modal-dialog-playable :item="item" :show="show" @close="$emit('close')">
<template #content>
<div class="title is-4">
<a @click="open" v-text="item.name" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.artist.albums')"
/>
<div class="title is-6" v-text="item.album_count" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.artist.tracks')"
/>
<div class="title is-6" v-text="item.track_count" />
</div>
<div class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.artist.type')" />
<div class="title is-6" v-text="$t(`data.kind.${item.data_kind}`)" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.artist.added-on')"
/>
<div class="title is-6" v-text="$filters.datetime(item.time_added)" />
</div>
</template>
</modal-dialog-playable>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
@ -41,6 +14,26 @@ export default {
components: { ModalDialogPlayable },
props: { item: { required: true, type: Object }, show: Boolean },
emits: ['close'],
computed: {
playable() {
return {
name: this.item.name,
action: this.open,
properties: [
{ label: 'dialog.artist.albums', value: this.item.album_count },
{ label: 'dialog.artist.tracks', value: this.item.track_count },
{
label: 'dialog.artist.type',
value: this.$t(`data.kind.${this.item.data_kind}`)
},
{
label: 'dialog.artist.added-on',
value: this.$filters.datetime(this.item.time_added)
}
]
}
}
},
methods: {
open() {
this.$emit('close')

View File

@ -1,28 +1,9 @@
<template>
<modal-dialog-playable :item="item" :show="show" @close="$emit('close')">
<template #content>
<div class="title is-4">
<a @click="open" v-text="item.name" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.artist.popularity')"
/>
<div
class="title is-6"
v-text="[item.popularity, item.followers.total].join(' / ')"
/>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.artist.genres')"
/>
<div class="title is-6" v-text="item.genres.join(', ')" />
</div>
</template>
</modal-dialog-playable>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
@ -33,6 +14,26 @@ export default {
components: { ModalDialogPlayable },
props: { item: { required: true, type: Object }, show: Boolean },
emits: ['close'],
computed: {
playable() {
return {
name: this.item.name,
action: this.open,
properties: [
{
label: 'dialog.spotify.artist.popularity',
value: [this.item.popularity, this.item.followers?.total].join(
' / '
)
},
{
label: 'dialog.spotify.artist.genres',
value: this.item.genres?.join(', ')
}
]
}
}
},
methods: {
open() {
this.$emit('close')

View File

@ -1,43 +1,9 @@
<template>
<modal-dialog-playable
:expression="expression"
:item="playable"
:show="show"
@close="$emit('close')"
>
<template #content>
<div class="title is-4">
<a @click="open_albums" v-text="item.name" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.composer.albums')"
/>
<div class="title is-6">
<a @click="open_albums" v-text="item.album_count" />
</div>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.composer.tracks')"
/>
<div class="title is-6">
<a @click="open_tracks" v-text="item.track_count" />
</div>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.composer.duration')"
/>
<div
class="title is-6"
v-text="$filters.durationInHours(item.length_ms)"
/>
</div>
</template>
</modal-dialog-playable>
/>
</template>
<script>
@ -49,8 +15,28 @@ export default {
props: { item: { required: true, type: Object }, show: Boolean },
emits: ['close'],
computed: {
expression() {
return `composer is "${this.item.name}" and media_kind is music`
playable() {
return {
action: this.open_albums,
name: this.item.name,
expression: `composer is "${this.item.name}" and media_kind is music`,
properties: [
{
label: 'dialog.composer.albums',
value: this.item.album_count,
action: this.open_albums
},
{
label: 'dialog.composer.tracks',
value: this.item.track_count,
action: this.open_tracks
},
{
label: 'dialog.composer.duration',
value: this.$filters.durationInHours(this.item.length_ms)
}
]
}
}
},
methods: {

View File

@ -1,8 +1,7 @@
<template>
<modal-dialog-playable
:expression="expression"
:item="playable"
:show="show"
:title="item"
@close="$emit('close')"
/>
</template>
@ -16,8 +15,11 @@ export default {
props: { item: { required: true, type: String }, show: Boolean },
emits: ['close'],
computed: {
expression() {
return `path starts with "${this.item}" order by path asc`
playable() {
return {
name: this.item,
expression: `path starts with "${this.item}" order by path asc`
}
}
}
}

View File

@ -1,39 +1,9 @@
<template>
<modal-dialog-playable
:expression="expression"
:item="playable"
:show="show"
@close="$emit('close')"
>
<template #content>
<div class="title is-4">
<a @click="open" v-text="item.name" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.genre.albums')"
/>
<div class="title is-6" v-text="item.album_count" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.genre.tracks')"
/>
<div class="title is-6" v-text="item.track_count" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.genre.duration')"
/>
<div
class="title is-6"
v-text="$filters.durationInHours(item.length_ms)"
/>
</div>
</template>
</modal-dialog-playable>
/>
</template>
<script>
@ -49,8 +19,26 @@ export default {
},
emits: ['close'],
computed: {
expression() {
return `genre is "${this.item.name}" and media_kind is ${this.media_kind}`
playable() {
return {
name: this.item.name,
action: this.open,
expression: `genre is "${this.item.name}" and media_kind is ${this.media_kind}`,
properties: [
{
label: 'dialog.genre.albums',
value: this.item.album_count
},
{
label: 'dialog.genre.tracks',
value: this.item.track_count
},
{
label: 'dialog.genre.duration',
value: this.$filters.durationInHours(this.item.length_ms)
}
]
}
}
},
methods: {

View File

@ -1,26 +1,50 @@
<template>
<modal-dialog :actions="actions" :show="show" @close="$emit('close')">
<template #content>
<slot name="content" />
<div class="title is-4">
<a v-if="item.action" @click="item.action" v-text="item.name"></a>
<span v-else v-text="item.name" />
</div>
<cover-artwork
v-if="item.image"
:url="item.image"
:artist="item.artist"
:album="item.name"
class="is-normal mb-3"
/>
<div v-for="button in buttons" :key="button.label" class="buttons">
<a v-t="button.label" class="button is-small" @click="button.action" />
</div>
<div
v-for="property in item.properties?.filter((p) => p.value)"
:key="property.label"
class="mb-3"
>
<div v-t="property.label" class="is-size-7 is-uppercase" />
<div class="title is-6">
<a
v-if="property.action"
@click="property.action"
v-text="property.value"
/>
<span v-else class="title is-6" v-text="property.value" />
</div>
</div>
</template>
</modal-dialog>
</template>
<script>
import CoverArtwork from '@/components/CoverArtwork.vue'
import ModalDialog from '@/components/ModalDialog.vue'
import webapi from '@/webapi'
export default {
name: 'ModalDialogPlayable',
components: { ModalDialog },
components: { ModalDialog, CoverArtwork },
props: {
expression: { default: '', type: String },
item: {
default() {
return {}
},
type: Object
},
buttons: { default: () => [], type: Array },
item: { required: true, type: Object },
show: Boolean
},
emits: ['close'],
@ -48,26 +72,26 @@ export default {
methods: {
play() {
this.$emit('close')
if (this.expression) {
webapi.player_play_expression(this.expression, false)
if (this.item.expression) {
webapi.player_play_expression(this.item.expression, false)
} else {
webapi.player_play_uri(this.item.uri, false)
webapi.player_play_uri(this.item.uris || this.item.item.uri, false)
}
},
queue_add() {
this.$emit('close')
if (this.expression) {
webapi.queue_expression_add(this.expression)
if (this.item.expression) {
webapi.queue_expression_add(this.item.expression)
} else {
webapi.queue_add(this.item.uri)
webapi.queue_add(this.item.uris || this.item.uri)
}
},
queue_add_next() {
this.$emit('close')
if (this.expression) {
webapi.queue_expression_add_next(this.expression)
if (this.item.expression) {
webapi.queue_expression_add_next(this.item.expression)
} else {
webapi.queue_add_next(this.item.uri)
webapi.queue_add_next(this.item.uris || this.item.uri)
}
}
}

View File

@ -1,41 +1,17 @@
<template>
<modal-dialog :actions="actions" :show="show" @close="$emit('close')">
<template #content>
<div class="title is-4">
<a @click="open" v-text="item.name" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.playlist.path')"
/>
<div class="title is-6" v-text="item.path" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.playlist.type')"
/>
<div class="title is-6" v-text="$t(`playlist.type.${item.type}`)" />
</div>
<div v-if="!item.folder" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.playlist.tracks')"
/>
<div class="title is-6" v-text="item.item_count" />
</div>
</template>
</modal-dialog>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
import ModalDialog from '@/components/ModalDialog.vue'
import webapi from '@/webapi'
import ModalDialogPlayable from '@/components/ModalDialogPlayable.vue'
export default {
name: 'ModalDialogPlaylist',
components: { ModalDialog },
components: { ModalDialogPlayable },
props: {
item: { required: true, type: Object },
show: Boolean,
@ -43,27 +19,20 @@ export default {
},
emits: ['close'],
computed: {
actions() {
if (!this.item.folder) {
return [
playable() {
return {
name: this.item.name,
action: this.open,
uris: this.uris,
properties: [
{ label: 'dialog.playlist.tracks', value: this.item.item_count },
{
label: this.$t('dialog.playlist.add'),
handler: this.queue_add,
icon: 'playlist-plus'
label: 'dialog.playlist.type',
value: this.$t(`playlist.type.${this.item.type}`)
},
{
label: this.$t('dialog.playlist.add-next'),
handler: this.queue_add_next,
icon: 'playlist-play'
},
{
label: this.$t('dialog.playlist.play'),
handler: this.play,
icon: 'play'
}
{ label: 'dialog.playlist.path', value: this.item.path }
]
}
return []
}
},
methods: {
@ -73,18 +42,6 @@ export default {
name: 'playlist',
params: { id: this.item.id }
})
},
play() {
this.$emit('close')
webapi.player_play_uri(this.uris || this.item.uri, false)
},
queue_add() {
this.$emit('close')
webapi.queue_add(this.uris || this.item.uri)
},
queue_add_next() {
this.$emit('close')
webapi.queue_add_next(this.uris || this.item.uri)
}
}
}

View File

@ -1,8 +1,12 @@
<template>
<modal-dialog :actions="actions" :show="show" @close="$emit('close')">
<modal-dialog
:actions="actions"
:show="show"
:title="$t('dialog.playlist.save.title')"
@close="$emit('close')"
>
<template #content>
<form @submit.prevent="save">
<p class="title is-4" v-text="$t('dialog.playlist.save.title')" />
<div class="field">
<p class="control has-icons-left">
<input

View File

@ -1,32 +1,9 @@
<template>
<modal-dialog-playable :item="item" :show="show" @close="$emit('close')">
<template #content>
<div class="title is-4">
<a @click="open" v-text="item.name" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.playlist.owner')"
/>
<div class="title is-6" v-text="item.owner.display_name" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.playlist.tracks')"
/>
<div class="title is-6" v-text="item.tracks.total" />
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.playlist.path')"
/>
<div class="title is-6" v-text="item.uri" />
</div>
</template>
</modal-dialog-playable>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
@ -37,6 +14,25 @@ export default {
components: { ModalDialogPlayable },
props: { item: { required: true, type: Object }, show: Boolean },
emits: ['close'],
computed: {
playable() {
return {
name: this.item.name,
action: this.open,
properties: [
{
label: 'dialog.spotify.playlist.owner',
value: this.item.owner?.display_name
},
{
label: 'dialog.spotify.playlist.tracks',
value: this.item.tracks?.total
},
{ label: 'dialog.spotify.playlist.path', value: this.item.uri }
]
}
}
},
methods: {
open() {
this.$emit('close')

View File

@ -1,7 +1,11 @@
<template>
<modal-dialog :actions="actions" :show="show" @close="$emit('close')">
<modal-dialog
:actions="actions"
:show="show"
:title="$t('dialog.remote-pairing.title')"
@close="$emit('close')"
>
<template #content>
<p class="title is-4" v-text="$t('dialog.remote-pairing.title')" />
<form @submit.prevent="pair">
<label class="label" v-text="pairing.remote" />
<div class="field">

View File

@ -1,156 +1,9 @@
<template>
<modal-dialog-playable :item="item" :show="show" @close="$emit('close')">
<template #content>
<p class="title is-4" v-text="item.title" />
<p class="subtitle" v-text="item.artist" />
<div v-if="item.media_kind === 'podcast'" class="buttons">
<a
v-if="item.play_count > 0"
class="button is-small"
@click="mark_new"
v-text="$t('dialog.track.mark-as-new')"
/>
<a
v-if="item.play_count === 0"
class="button is-small"
@click="mark_played"
v-text="$t('dialog.track.mark-as-played')"
/>
</div>
<div v-if="item.album" class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.album')" />
<div class="title is-6">
<a @click="open_album" v-text="item.album" />
</div>
</div>
<div
v-if="item.album_artist && item.media_kind !== 'audiobook'"
class="mb-3"
>
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.album-artist')"
/>
<div class="title is-6">
<a @click="open_album_artist" v-text="item.album_artist" />
</div>
</div>
<div v-if="item.composer" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.composer')"
/>
<div class="title is-6" v-text="item.composer" />
</div>
<div v-if="item.date_released" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.release-date')"
/>
<div class="title is-6" v-text="$filters.date(item.date_released)" />
</div>
<div v-else-if="item.year" class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.year')" />
<div class="title is-6" v-text="item.year" />
</div>
<div v-if="item.genre" class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.genre')" />
<div class="title is-6">
<a @click="open_genre" v-text="item.genre" />
</div>
</div>
<div v-if="item.disc_number" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.position')"
/>
<div
class="title is-6"
v-text="[item.disc_number, item.track_number].join(' / ')"
/>
</div>
<div v-if="item.length_ms" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.duration')"
/>
<div
class="title is-6"
v-text="$filters.durationInHours(item.length_ms)"
/>
</div>
<div class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.path')" />
<div class="title is-6" v-text="item.path" />
</div>
<div class="mb-3">
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.type')" />
<div
class="title is-6"
v-text="
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
"
/>
</div>
<div v-if="item.samplerate" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.quality')"
/>
<div class="title is-6">
<span v-text="item.type" />
<span
v-if="item.samplerate"
v-text="
$t('dialog.track.samplerate', {
rate: item.samplerate
})
"
/>
<span
v-if="item.channels"
v-text="
$t('dialog.track.channels', {
channels: $filters.channels(item.channels)
})
"
/>
<span
v-if="item.bitrate"
v-text="$t('dialog.track.bitrate', { rate: item.bitrate })"
/>
</div>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.added-on')"
/>
<div class="title is-6" v-text="$filters.datetime(item.time_added)" />
</div>
<div>
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.rating')"
/>
<div
class="title is-6"
v-text="
$t('dialog.track.rating-value', {
rating: Math.floor(item.rating / 10)
})
"
/>
</div>
<div v-if="item.comment" class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.track.comment')"
/>
<div class="title is-6" v-text="item.comment" />
</div>
</template>
</modal-dialog-playable>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
@ -172,6 +25,78 @@ export default {
spotify_track: {}
}
},
computed: {
buttons() {
if (this.item.media_kind === 'podcast') {
if (this.item.play_count > 0) {
return [{ label: 'dialog.track.mark-as-new', action: this.mark_new }]
}
if (this.item.play_count === 0) {
return [
{ label: 'dialog.track.mark-as-played', action: this.mark_played }
]
}
}
return []
},
playable() {
return {
name: this.item.title,
properties: [
{
label: 'dialog.track.album',
value: this.item.album,
action: this.open_album
},
{
label: 'dialog.track.album-artist',
value: this.item.album_artist,
action: this.open_artist
},
{ label: 'dialog.track.composer', value: this.item.composer },
{
label: 'dialog.track.release-date',
value: this.$filters.date(this.item.date_released)
},
{ label: 'dialog.track.year', value: this.item.year },
{ label: 'dialog.track.genre', value: this.item.genre },
{
label: 'dialog.track.position',
value: [this.item.disc_number, this.item.track_number].join(' / ')
},
{
label: 'dialog.track.duration',
value: this.$filters.durationInHours(this.item.length_ms)
},
{
label: 'dialog.track.type',
value: `${this.$t(`media.kind.${this.item.media_kind}`)} - ${this.$t(`data.kind.${this.item.data_kind}`)}`
},
{
label: 'dialog.track.quality',
value: this.$t('dialog.track.quality-value', {
format: this.item.type,
bitrate: this.item.bitrate,
channels: this.$filters.channels(this.item.channels),
samplerate: this.item.samplerate
})
},
{
label: 'dialog.track.added-on',
value: this.$filters.datetime(this.item.time_added)
},
{
label: 'dialog.track.rating',
value: this.$t('dialog.track.rating-value', {
rating: Math.floor(this.item.rating / 10)
})
},
{ label: 'dialog.track.comment', value: this.item.comment },
{ label: 'dialog.track.path', value: this.item.path }
]
}
}
},
watch: {
item() {
if (
@ -234,7 +159,7 @@ export default {
})
}
},
open_album_artist() {
open_artist() {
if (this.item.data_kind === 'spotify') {
this.$router.push({
name: 'music-spotify-artist',

View File

@ -1,65 +1,9 @@
<template>
<modal-dialog-playable :item="item" :show="show" @close="$emit('close')">
<template #content>
<p class="title is-4" v-text="item.name" />
<p class="subtitle" v-text="item.artists[0].name" />
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.track.album')"
/>
<div class="title is-6">
<a @click="open_album" v-text="item.album.name" />
</div>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.track.album-artist')"
/>
<div class="title is-6">
<a @click="open_artist" v-text="item.artists[0].name" />
</div>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.track.release-date')"
/>
<div
class="title is-6"
v-text="$filters.date(item.album.release_date)"
/>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.track.position')"
/>
<div
class="title is-6"
v-text="[item.disc_number, item.track_number].join(' / ')"
/>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.track.duration')"
/>
<div
class="title is-6"
v-text="$filters.durationInHours(item.duration_ms)"
/>
</div>
<div class="mb-3">
<div
class="is-size-7 is-uppercase"
v-text="$t('dialog.spotify.track.path')"
/>
<div class="title is-6" v-text="item.uri" />
</div>
</template>
</modal-dialog-playable>
<modal-dialog-playable
:item="playable"
:show="show"
@close="$emit('close')"
/>
</template>
<script>
@ -70,6 +14,39 @@ export default {
components: { ModalDialogPlayable },
props: { item: { required: true, type: Object }, show: Boolean },
emits: ['close'],
computed: {
playable() {
return {
name: this.item.name,
subtitle: this.item.artists[0].name,
properties: [
{
label: 'dialog.spotify.track.album',
value: this.item.album.name,
action: this.open_album
},
{
label: 'dialog.spotify.track.album-artist',
value: this.item.artists[0].name,
action: this.open_artist
},
{
label: 'dialog.spotify.track.release-date',
value: this.$filters.date(item.album.release_date)
},
{
label: 'dialog.spotify.track.position',
value: [item.disc_number, item.track_number].join(' / ')
},
{
label: 'dialog.spotify.track.duration',
value: this.$filters.durationInHours(item.duration_ms)
},
{ label: 'dialog.spotify.track.path', value: this.item.uri }
]
}
}
},
methods: {
open_album() {
this.$emit('close')

View File

@ -126,8 +126,6 @@
"added-on": "Hinzugefügt am",
"album-artist": "Album-Künstler",
"album": "Album",
"bitrate": " {'|'} {rate} Kb/s",
"channels": " {'|'} {channels}",
"comment": "Kommentar",
"composer": "Komponist",
"duration": "Dauer",
@ -136,11 +134,11 @@
"mark-as-played": "Markiere als gespielt",
"path": "Pfad",
"position": "Disc / Track",
"quality-value": "{format} {'|'} {samplerate} Hz {'|'} {channels} {'|'} {bitrate} kbit/s",
"quality": "Qualität",
"rating-value": "{rating} / 10",
"rating": "Bewertung",
"release-date": "Erscheinungsdatum",
"samplerate": " {'|'} {rate} Hz",
"spotify-album": "Album",
"spotify-artist": "Künstler",
"type": "Art",

View File

@ -126,8 +126,6 @@
"added-on": "Added On",
"album-artist": "Album Artist",
"album": "Album",
"bitrate": " {'|'} {rate} kbit/s",
"channels": " {'|'} {channels}",
"comment": "Comment",
"composer": "Composer",
"duration": "Duration",
@ -136,11 +134,11 @@
"mark-as-played": "Mark as played",
"path": "Path",
"position": "Disc / Track",
"quality-value": "{format} {'|'} {samplerate} Hz {'|'} {channels} {'|'} {bitrate} kbit/s",
"quality": "Quality",
"rating-value": "{rating} / 10",
"rating": "Rating",
"release-date": "Release Date",
"samplerate": " {'|'} {rate} Hz",
"spotify-album": "album",
"spotify-artist": "artist",
"type": "Type",

View File

@ -126,8 +126,6 @@
"added-on": "Ajouté le",
"album-artist": "Artiste de lalbum",
"album": "Album",
"bitrate": " {'|'} {rate} kbit/s",
"channels": " {'|'} {channels}",
"comment": "Commentaire",
"composer": "Compositeur",
"duration": "Durée",
@ -136,11 +134,11 @@
"mark-as-played": "Marquer comme lu",
"path": "Emplacement",
"position": "Disque / Piste",
"quality-value": "{format} {'|'} {samplerate} Hz {'|'} {channels} {'|'} {bitrate} kbit/s",
"quality": "Qualité",
"rating-value": "{rating} / 10",
"rating": "Classement",
"release-date": "Date de sortie",
"samplerate": " {'|'} {rate} Hz",
"spotify-album": "album",
"spotify-artist": "artiste",
"type": "Type",

View File

@ -126,8 +126,6 @@
"added-on": "添加时间",
"album-artist": "专辑艺人",
"album": "专辑",
"bitrate": " {'|'} {rate} kbit/s",
"channels": " {'|'} {channels}",
"comment": "评论",
"composer": "作曲家",
"duration": "时长",
@ -136,11 +134,11 @@
"mark-as-played": "标记为已播放",
"path": "路径",
"position": "盘符 / 曲目",
"quality-value": "{format} {'|'} {samplerate} Hz {'|'} {channels} {'|'} {bitrate} kbit/s",
"quality": "质量",
"rating-value": "{rating} / 10",
"rating": "评级",
"release-date": "发行日期",
"samplerate": " {'|'} {rate} Hz",
"spotify-album": "专辑",
"spotify-artist": "艺人",
"type": "类型",

View File

@ -126,8 +126,6 @@
"added-on": "新增時間",
"album-artist": "專輯藝人",
"album": "專輯",
"bitrate": " {'|'} {rate} kbit/s",
"channels": " {'|'} {channels}",
"comment": "評論",
"composer": "作曲家",
"duration": "時長",
@ -136,11 +134,11 @@
"mark-as-played": "標記為已播放",
"path": "路徑",
"position": "盤符 / 曲目",
"quality-value": "{format} {'|'} {samplerate} Hz {'|'} {channels} {'|'} {bitrate} kbit/s",
"quality": "品質",
"rating-value": "{rating} / 10",
"rating": "評級",
"release-date": "發行日期",
"samplerate": " {'|'} {rate} Hz",
"spotify-album": "專輯",
"spotify-artist": "藝人",
"type": "類型",