Code formatting, translation mistakes, and removal of useless libraries.

This commit is contained in:
Alain Nussbaumer 2022-05-29 18:49:00 +02:00
parent cfa8db7b3f
commit b788273e4c
92 changed files with 2646 additions and 575 deletions

File diff suppressed because one or more lines are too long

View File

@ -39,8 +39,7 @@
"eslint-plugin-vue": "^8.6.0", "eslint-plugin-vue": "^8.6.0",
"prettier": "2.6.2", "prettier": "2.6.2",
"sass": "^1.50.0", "sass": "^1.50.0",
"vite": "^2.9.8", "vite": "^2.9.8"
"vue-cli-plugin-i18n": "~2.3.1"
} }
}, },
"node_modules/@aacassandra/vue3-progressbar": { "node_modules/@aacassandra/vue3-progressbar": {

View File

@ -14,7 +14,6 @@
"@aacassandra/vue3-progressbar": "^1.0.3", "@aacassandra/vue3-progressbar": "^1.0.3",
"@mdi/js": "^6.6.96", "@mdi/js": "^6.6.96",
"@ts-pro/vue-eternal-loading": "^1.2.0", "@ts-pro/vue-eternal-loading": "^1.2.0",
"@vue/cli-shared-utils": "^5.0.4",
"@vueform/slider": "github:chme/slider#faff83ed8a77f2cdbcb7252505ef734301efd139", "@vueform/slider": "github:chme/slider#faff83ed8a77f2cdbcb7252505ef734301efd139",
"axios": "^0.26.1", "axios": "^0.26.1",
"bulma": "^0.9.3", "bulma": "^0.9.3",
@ -35,14 +34,12 @@
}, },
"devDependencies": { "devDependencies": {
"@intlify/vite-plugin-vue-i18n": "^3.4.0", "@intlify/vite-plugin-vue-i18n": "^3.4.0",
"@intlify/vue-i18n-loader": "^3.0.0",
"@vitejs/plugin-vue": "^2.3.1", "@vitejs/plugin-vue": "^2.3.1",
"eslint": "^8.13.0", "eslint": "^8.13.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-vue": "^8.6.0", "eslint-plugin-vue": "^8.6.0",
"prettier": "2.6.2", "prettier": "2.6.2",
"sass": "^1.50.0", "sass": "^1.50.0",
"vite": "^2.9.8", "vite": "^2.9.8"
"vue-cli-plugin-i18n": "~2.3.1"
} }
} }

View File

@ -1,6 +1,9 @@
<template> <template>
<figure> <figure>
<img v-lazy="{ src: artwork_url_with_size, lifecycle: lazy_lifecycle }" @click="$emit('click')" /> <img
v-lazy="{ src: artwork_url_with_size, lifecycle: lazy_lifecycle }"
@click="$emit('click')"
/>
</figure> </figure>
</template> </template>

View File

@ -1,14 +1,30 @@
<template> <template>
<div v-click-away="onClickOutside" class="dropdown" :class="{ 'is-active': is_active }"> <div
v-click-away="onClickOutside"
class="dropdown"
:class="{ 'is-active': is_active }"
>
<div class="dropdown-trigger"> <div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu" @click="is_active = !is_active"> <button
class="button"
aria-haspopup="true"
aria-controls="dropdown-menu"
@click="is_active = !is_active"
>
<span v-text="option.name" /> <span v-text="option.name" />
<mdicon class="icon" name="chevron-down" size="16" /> <mdicon class="icon" name="chevron-down" size="16" />
</button> </button>
</div> </div>
<div id="dropdown-menu" class="dropdown-menu" role="menu"> <div id="dropdown-menu" class="dropdown-menu" role="menu">
<div class="dropdown-content"> <div class="dropdown-content">
<a v-for="option in options" :key="option.id" class="dropdown-item" :class="{ 'is-active': modelValue === option.id }" @click="select(option)" v-text="option.name" /> <a
v-for="o in options"
:key="o.id"
class="dropdown-item"
:class="{ 'is-active': modelValue === o.id }"
@click="select(o)"
v-text="o.name"
/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,13 @@
<template> <template>
<section> <section>
<nav class="buttons is-centered fd-is-square" style="margin-bottom: 16px"> <nav class="buttons is-centered fd-is-square" style="margin-bottom: 16px">
<a v-for="char in filtered_index" :key="char" class="button is-small" @click="nav(char)" v-text="char" /> <a
v-for="char in filtered_index"
:key="char"
class="button is-small"
@click="nav(char)"
v-text="char"
/>
</nav> </nav>
</section> </section>
</template> </template>

View File

@ -1,13 +1,24 @@
<template> <template>
<template v-for="album in albums" :key="album.itemId"> <template v-for="album in albums" :key="album.itemId">
<div v-if="!album.isItem && !hide_group_title" class="mt-6 mb-5 py-2"> <div v-if="!album.isItem && !hide_group_title" class="mt-6 mb-5 py-2">
<span :id="'index_' + album.groupKey" class="tag is-info is-light is-small has-text-weight-bold" v-text="album.groupKey" /> <span
:id="'index_' + album.groupKey"
class="tag is-info is-light is-small has-text-weight-bold"
v-text="album.groupKey"
/>
</div> </div>
<div v-else-if="album.isItem" class="media" @click="open_album(album.item)"> <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"> <div v-if="is_visible_artwork" class="media-left fd-has-action">
<div class="image is-64x64 fd-has-shadow fd-has-action"> <div class="image is-64x64 fd-has-shadow fd-has-action">
<figure> <figure>
<img v-lazy="{ src: artwork_url_with_size(album.item.artwork_url), lifecycle: artwork_options.lazy_lifecycle }" :album="album.item.name" :artist="album.item.artist" /> <img
v-lazy="{
src: artwork_url_with_size(album.item.artwork_url),
lifecycle: artwork_options.lazy_lifecycle
}"
:album="album.item.name"
:artist="album.item.artist"
/>
</figure> </figure>
</div> </div>
</div> </div>
@ -17,7 +28,11 @@
<h2 class="subtitle is-7 has-text-grey"> <h2 class="subtitle is-7 has-text-grey">
<b v-text="album.item.artist" /> <b v-text="album.item.artist" />
</h2> </h2>
<h2 v-if="album.item.date_released && album.item.media_kind === 'music'" class="subtitle is-7 has-text-grey has-text-weight-normal" v-text="$filters.date(album.item.date_released)" /> <h2
v-if="album.item.date_released && album.item.media_kind === 'music'"
class="subtitle is-7 has-text-grey has-text-weight-normal"
v-text="$filters.date(album.item.date_released)"
/>
</div> </div>
</div> </div>
<div class="media-right" style="padding-top: 0.7rem"> <div class="media-right" style="padding-top: 0.7rem">
@ -28,11 +43,27 @@
</div> </div>
</template> </template>
<teleport to="#app"> <teleport to="#app">
<modal-dialog-album :show="show_details_modal" :album="selected_album" :media_kind="media_kind" @remove-podcast="open_remove_podcast_dialog()" @play-count-changed="play_count_changed()" @close="show_details_modal = false" /> <modal-dialog-album
<modal-dialog :show="show_remove_podcast_modal" title="Remove podcast" delete_action="Remove" @close="show_remove_podcast_modal = false" @delete="remove_podcast"> :show="show_details_modal"
:album="selected_album"
:media_kind="media_kind"
@remove-podcast="open_remove_podcast_dialog()"
@play-count-changed="play_count_changed()"
@close="show_details_modal = false"
/>
<modal-dialog
:show="show_remove_podcast_modal"
title="Remove podcast"
delete_action="Remove"
@close="show_remove_podcast_modal = false"
@delete="remove_podcast"
>
<template #modal-content> <template #modal-content>
<p v-text="$t('list.albums.info-1')" /> <p v-text="$t('list.albums.info-1')" />
<p class="is-size-7" v-html="$t('list.albums.info-2', { name: rss_playlist_to_remove.name })" /> <p class="is-size-7">
(<span v-text="$t('list.albums.info-2')" />
<b v-text="rss_playlist_to_remove.name" />)
</p>
</template> </template>
</modal-dialog> </modal-dialog>
</teleport> </teleport>

View File

@ -2,10 +2,18 @@
<template v-for="artist in artists" :key="artist.itemId"> <template v-for="artist in artists" :key="artist.itemId">
<div v-if="!artist.isItem && !hide_group_title" class="mt-6 mb-5 py-2"> <div v-if="!artist.isItem && !hide_group_title" class="mt-6 mb-5 py-2">
<div class="media-content is-clipped"> <div class="media-content is-clipped">
<span :id="'index_' + artist.groupKey" class="tag is-info is-light is-small has-text-weight-bold" v-text="artist.groupKey" /> <span
:id="'index_' + artist.groupKey"
class="tag is-info is-light is-small has-text-weight-bold"
v-text="artist.groupKey"
/>
</div> </div>
</div> </div>
<div v-else-if="artist.isItem" class="media" @click="open_artist(artist.item)"> <div
v-else-if="artist.isItem"
class="media"
@click="open_artist(artist.item)"
>
<div class="media-content fd-has-action is-clipped"> <div class="media-content fd-has-action is-clipped">
<h1 class="title is-6" v-text="artist.item.name" /> <h1 class="title is-6" v-text="artist.item.name" />
</div> </div>
@ -17,7 +25,12 @@
</div> </div>
</template> </template>
<teleport to="#app"> <teleport to="#app">
<modal-dialog-artist :show="show_details_modal" :artist="selected_artist" :media_kind="media_kind" @close="show_details_modal = false" /> <modal-dialog-artist
:show="show_details_modal"
:artist="selected_artist"
:media_kind="media_kind"
@close="show_details_modal = false"
/>
</teleport> </teleport>
</template> </template>

View File

@ -2,10 +2,18 @@
<template v-for="composer in composers" :key="composer.itemId"> <template v-for="composer in composers" :key="composer.itemId">
<div v-if="!composer.isItem && !hide_group_title" class="mt-6 mb-5 py-2"> <div v-if="!composer.isItem && !hide_group_title" class="mt-6 mb-5 py-2">
<div class="media-content is-clipped"> <div class="media-content is-clipped">
<span :id="'index_' + composer.groupKey" class="tag is-info is-light is-small has-text-weight-bold" v-text="composer.groupKey" /> <span
:id="'index_' + composer.groupKey"
class="tag is-info is-light is-small has-text-weight-bold"
v-text="composer.groupKey"
/>
</div> </div>
</div> </div>
<div v-else-if="composer.isItem" class="media" @click="open_composer(composer.item)"> <div
v-else-if="composer.isItem"
class="media"
@click="open_composer(composer.item)"
>
<div class="media-content fd-has-action is-clipped"> <div class="media-content fd-has-action is-clipped">
<h1 class="title is-6" v-text="composer.item.name" /> <h1 class="title is-6" v-text="composer.item.name" />
</div> </div>
@ -17,7 +25,12 @@
</div> </div>
</template> </template>
<teleport to="#app"> <teleport to="#app">
<modal-dialog-composer :show="show_details_modal" :composer="selected_composer" :media_kind="media_kind" @close="show_details_modal = false" /> <modal-dialog-composer
:show="show_details_modal"
:composer="selected_composer"
:media_kind="media_kind"
@close="show_details_modal = false"
/>
</teleport> </teleport>
</template> </template>

View File

@ -1,5 +1,9 @@
<template> <template>
<div v-if="$route.query.directory" class="media" @click="open_parent_directory()"> <div
v-if="$route.query.directory"
class="media"
@click="open_parent_directory()"
>
<figure class="media-left fd-has-action"> <figure class="media-left fd-has-action">
<mdicon class="icon" name="subdirectory-arrow-left" size="16" /> <mdicon class="icon" name="subdirectory-arrow-left" size="16" />
</figure> </figure>
@ -16,7 +20,10 @@
<mdicon class="icon" name="folder" size="16" /> <mdicon class="icon" name="folder" size="16" />
</figure> </figure>
<div class="media-content fd-has-action is-clipped"> <div class="media-content fd-has-action is-clipped">
<h1 class="title is-6" v-text="directory.path.substring(directory.path.lastIndexOf('/') + 1)" /> <h1
class="title is-6"
v-text="directory.path.substring(directory.path.lastIndexOf('/') + 1)"
/>
<h2 class="subtitle is-7 has-text-grey-light" v-text="directory.path" /> <h2 class="subtitle is-7 has-text-grey-light" v-text="directory.path" />
</div> </div>
<div class="media-right"> <div class="media-right">
@ -27,7 +34,11 @@
</div> </div>
</template> </template>
<teleport to="#app"> <teleport to="#app">
<modal-dialog-directory :show="show_details_modal" :directory="selected_directory" @close="show_details_modal = false" /> <modal-dialog-directory
:show="show_details_modal"
:directory="selected_directory"
@close="show_details_modal = false"
/>
</teleport> </teleport>
</template> </template>

View File

@ -2,7 +2,11 @@
<template v-for="genre in genres" :key="genre.itemId"> <template v-for="genre in genres" :key="genre.itemId">
<div v-if="!genre.isItem && !hide_group_title" class="mt-6 mb-5 py-2"> <div v-if="!genre.isItem && !hide_group_title" class="mt-6 mb-5 py-2">
<div class="media-content is-clipped"> <div class="media-content is-clipped">
<span :id="'index_' + genre.groupKey" class="tag is-info is-light is-small has-text-weight-bold" v-text="genre.groupKey" /> <span
:id="'index_' + genre.groupKey"
class="tag is-info is-light is-small has-text-weight-bold"
v-text="genre.groupKey"
/>
</div> </div>
</div> </div>
<div v-else-if="genre.isItem" class="media" @click="open_genre(genre.item)"> <div v-else-if="genre.isItem" class="media" @click="open_genre(genre.item)">
@ -17,7 +21,11 @@
</div> </div>
</template> </template>
<teleport to="#app"> <teleport to="#app">
<modal-dialog-genre :show="show_details_modal" :genre="selected_genre" @close="show_details_modal = false" /> <modal-dialog-genre
:show="show_details_modal"
:genre="selected_genre"
@close="show_details_modal = false"
/>
</teleport> </teleport>
</template> </template>

View File

@ -1,14 +1,40 @@
<template> <template>
<div v-if="is_next || !show_only_next_items" class="media"> <div v-if="is_next || !show_only_next_items" class="media">
<div v-if="edit_mode" class="media-left"> <div v-if="edit_mode" class="media-left">
<mdicon class="icon has-text-grey fd-is-movable handle" name="drag-horizontal" size="16" /> <mdicon
class="icon has-text-grey fd-is-movable handle"
name="drag-horizontal"
size="16"
/>
</div> </div>
<div class="media-content fd-has-action is-clipped" @click="play"> <div class="media-content fd-has-action is-clipped" @click="play">
<h1 class="title is-6" :class="{ 'has-text-primary': item.id === state.item_id, 'has-text-grey-light': !is_next }" v-text="item.title" /> <h1
<h2 class="subtitle is-7" :class="{ 'has-text-primary': item.id === state.item_id, 'has-text-grey-light': !is_next, 'has-text-grey': is_next && item.id !== state.item_id }"> class="title is-6"
:class="{
'has-text-primary': item.id === state.item_id,
'has-text-grey-light': !is_next
}"
v-text="item.title"
/>
<h2
class="subtitle is-7"
:class="{
'has-text-primary': item.id === state.item_id,
'has-text-grey-light': !is_next,
'has-text-grey': is_next && item.id !== state.item_id
}"
>
<b v-text="item.artist" /> <b v-text="item.artist" />
</h2> </h2>
<h2 class="subtitle is-7" :class="{ 'has-text-primary': item.id === state.item_id, 'has-text-grey-light': !is_next, 'has-text-grey': is_next && item.id !== state.item_id }" v-text="item.album" /> <h2
class="subtitle is-7"
:class="{
'has-text-primary': item.id === state.item_id,
'has-text-grey-light': !is_next,
'has-text-grey': is_next && item.id !== state.item_id
}"
v-text="item.album"
/>
</div> </div>
<div class="media-right"> <div class="media-right">
<slot name="actions" /> <slot name="actions" />

View File

@ -1,5 +1,11 @@
<template> <template>
<div v-for="playlist in playlists" :key="playlist.itemId" class="media" :playlist="playlist" @click="open_playlist(playlist.item)"> <div
v-for="playlist in playlists"
:key="playlist.itemId"
class="media"
:playlist="playlist"
@click="open_playlist(playlist.item)"
>
<figure class="media-left fd-has-action"> <figure class="media-left fd-has-action">
<mdicon class="icon" :name="icon_name(playlist.item)" size="16" /> <mdicon class="icon" :name="icon_name(playlist.item)" size="16" />
</figure> </figure>
@ -13,7 +19,11 @@
</div> </div>
</div> </div>
<teleport to="#app"> <teleport to="#app">
<modal-dialog-playlist :show="show_details_modal" :playlist="selected_playlist" @close="show_details_modal = false" /> <modal-dialog-playlist
:show="show_details_modal"
:playlist="selected_playlist"
@close="show_details_modal = false"
/>
</teleport> </teleport>
</template> </template>

View File

@ -1,13 +1,31 @@
<template> <template>
<div v-for="(track, index) in tracks" :id="'index_' + track.title_sort.charAt(0).toUpperCase()" :key="track.id" class="media" :class="{ 'with-progress': show_progress }" @click="play_track(index, track)"> <div
v-for="(track, index) in tracks"
:id="'index_' + track.title_sort.charAt(0).toUpperCase()"
:key="track.id"
class="media"
:class="{ 'with-progress': show_progress }"
@click="play_track(index, track)"
>
<figure v-if="show_icon" class="media-left fd-has-action"> <figure v-if="show_icon" class="media-left fd-has-action">
<mdicon class="icon" name="file-outline" size="16" /> <mdicon class="icon" name="file-outline" size="16" />
</figure> </figure>
<div class="media-content fd-has-action is-clipped"> <div class="media-content fd-has-action is-clipped">
<h1 class="title is-6" :class="{ 'has-text-grey': track.media_kind === 'podcast' && track.play_count > 0 }" v-text="track.title" /> <h1
class="title is-6"
:class="{
'has-text-grey':
track.media_kind === 'podcast' && track.play_count > 0
}"
v-text="track.title"
/>
<h2 class="subtitle is-7 has-text-grey" v-text="track.artist" /> <h2 class="subtitle is-7 has-text-grey" v-text="track.artist" />
<h2 class="subtitle is-7 has-text-grey" v-text="track.album" /> <h2 class="subtitle is-7 has-text-grey" v-text="track.album" />
<progress-bar v-if="show_progress" :max="track.length_ms" :value="track.seek_ms" /> <progress-bar
v-if="show_progress"
:max="track.length_ms"
:value="track.seek_ms"
/>
</div> </div>
<div class="media-right"> <div class="media-right">
<a @click.prevent.stop="open_dialog(track)"> <a @click.prevent.stop="open_dialog(track)">
@ -16,7 +34,12 @@
</div> </div>
</div> </div>
<teleport to="#app"> <teleport to="#app">
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" @play-count-changed="$emit('play-count-changed')" /> <modal-dialog-track
:show="show_details_modal"
:track="selected_track"
@close="show_details_modal = false"
@play-count-changed="$emit('play-count-changed')"
/>
</teleport> </teleport>
</template> </template>

View File

@ -12,20 +12,35 @@
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="$emit('close')"> <a class="card-footer-item has-text-dark" @click="$emit('close')">
<mdicon class="icon" name="cancel" size="16" /> <mdicon class="icon" name="cancel" size="16" />
<span class="is-size-7" v-text="close_action ? close_action : t('dialog.cancel')" /> <span
class="is-size-7"
v-text="close_action ? close_action : t('dialog.cancel')"
/>
</a> </a>
<a v-if="delete_action" class="card-footer-item has-background-danger has-text-white has-text-weight-bold" @click="$emit('delete')"> <a
v-if="delete_action"
class="card-footer-item has-background-danger has-text-white has-text-weight-bold"
@click="$emit('delete')"
>
<mdicon class="icon" name="delete" size="16" /> <mdicon class="icon" name="delete" size="16" />
<span class="is-size-7" v-text="delete_action" /> <span class="is-size-7" v-text="delete_action" />
</a> </a>
<a v-if="ok_action" class="card-footer-item has-background-info has-text-white has-text-weight-bold" @click="$emit('ok')"> <a
v-if="ok_action"
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
@click="$emit('ok')"
>
<mdicon class="icon" name="check" size="16" /> <mdicon class="icon" name="check" size="16" />
<span class="is-size-7" v-text="ok_action" /> <span class="is-size-7" v-text="ok_action" />
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -10,7 +10,14 @@
<form @submit.prevent="add_stream"> <form @submit.prevent="add_stream">
<div class="field"> <div class="field">
<p class="control is-expanded has-icons-left"> <p class="control is-expanded has-icons-left">
<input ref="url_field" v-model="url" class="input is-shadowless" type="text" :placeholder="$t('dialog.add.rss.placeholder')" :disabled="loading" /> <input
ref="url_field"
v-model="url"
class="input is-shadowless"
type="text"
:placeholder="$t('dialog.add.rss.placeholder')"
:disabled="loading"
/>
<mdicon class="icon is-left" name="rss" size="16" /> <mdicon class="icon is-left" name="rss" size="16" />
</p> </p>
<p class="help" v-text="$t('dialog.add.rss.help')" /> <p class="help" v-text="$t('dialog.add.rss.help')" />
@ -20,22 +27,35 @@
<footer v-if="loading" class="card-footer"> <footer v-if="loading" class="card-footer">
<a class="card-footer-item button is-loading"> <a class="card-footer-item button is-loading">
<mdicon class="icon" name="web" size="16" /> <mdicon class="icon" name="web" size="16" />
<span class="is-size-7" v-text="$t('dialog.add.rss.processing')" /> <span
class="is-size-7"
v-text="$t('dialog.add.rss.processing')"
/>
</a> </a>
</footer> </footer>
<footer v-else class="card-footer"> <footer v-else class="card-footer">
<a class="card-footer-item has-text-danger" @click="$emit('close')"> <a
class="card-footer-item has-text-danger"
@click="$emit('close')"
>
<mdicon class="icon" name="cancel" size="16" /> <mdicon class="icon" name="cancel" size="16" />
<span class="is-size-7" v-text="$t('dialog.add.rss.cancel')" /> <span class="is-size-7" v-text="$t('dialog.add.rss.cancel')" />
</a> </a>
<a class="card-footer-item has-background-info has-text-white has-text-weight-bold" @click="add_stream"> <a
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
@click="add_stream"
>
<mdicon class="icon" name="playlist-plus" size="16" /> <mdicon class="icon" name="playlist-plus" size="16" />
<span class="is-size-7" v-text="$t('dialog.add.rss.add')" /> <span class="is-size-7" v-text="$t('dialog.add.rss.add')" />
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -10,7 +10,14 @@
<form class="fd-has-margin-bottom" @submit.prevent="play"> <form class="fd-has-margin-bottom" @submit.prevent="play">
<div class="field"> <div class="field">
<p class="control is-expanded has-icons-left"> <p class="control is-expanded has-icons-left">
<input ref="url_field" v-model="url" class="input is-shadowless" type="text" :placeholder="$t('dialog.add.stream.placeholder')" :disabled="loading" /> <input
ref="url_field"
v-model="url"
class="input is-shadowless"
type="text"
:placeholder="$t('dialog.add.stream.placeholder')"
:disabled="loading"
/>
<mdicon class="icon is-left" name="web" size="16" /> <mdicon class="icon is-left" name="web" size="16" />
</p> </p>
</div> </div>
@ -19,26 +26,42 @@
<footer v-if="loading" class="card-footer"> <footer v-if="loading" class="card-footer">
<a class="card-footer-item has-text-dark"> <a class="card-footer-item has-text-dark">
<mdicon class="icon" name="web" size="16" /> <mdicon class="icon" name="web" size="16" />
<span class="is-size-7" v-text="$t('dialog.add.stream.loading')" /> <span
class="is-size-7"
v-text="$t('dialog.add.stream.loading')"
/>
</a> </a>
</footer> </footer>
<footer v-else class="card-footer"> <footer v-else class="card-footer">
<a class="card-footer-item has-text-danger" @click="$emit('close')"> <a
class="card-footer-item has-text-danger"
@click="$emit('close')"
>
<mdicon class="icon" name="cancel" size="16" /> <mdicon class="icon" name="cancel" size="16" />
<span class="is-size-7" v-text="$t('dialog.add.stream.cancel')" /> <span
class="is-size-7"
v-text="$t('dialog.add.stream.cancel')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="add_stream"> <a class="card-footer-item has-text-dark" @click="add_stream">
<mdicon class="icon" name="playlist-plus" size="16" /> <mdicon class="icon" name="playlist-plus" size="16" />
<span class="is-size-7" v-text="$t('dialog.add.stream.add')" /> <span class="is-size-7" v-text="$t('dialog.add.stream.add')" />
</a> </a>
<a class="card-footer-item has-background-info has-text-white has-text-weight-bold" @click="play"> <a
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
@click="play"
>
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
<span class="is-size-7" v-text="$t('dialog.add.stream.play')" /> <span class="is-size-7" v-text="$t('dialog.add.stream.play')" />
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -6,22 +6,49 @@
<div class="modal-content fd-modal-card"> <div class="modal-content fd-modal-card">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<cover-artwork :artwork_url="album.artwork_url" :artist="album.artist" :album="album.name" class="image is-square fd-has-margin-bottom fd-has-shadow" /> <cover-artwork
:artwork_url="album.artwork_url"
:artist="album.artist"
:album="album.name"
class="image is-square fd-has-margin-bottom fd-has-shadow"
/>
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_album" v-text="album.name" /> <a
class="has-text-link"
@click="open_album"
v-text="album.name"
/>
</p> </p>
<div v-if="media_kind_resolved === 'podcast'" class="buttons"> <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
<a class="button is-small" @click="$emit('remove-podcast')" v-text="$t('dialog.album.remove-podcast')" /> class="button is-small"
@click="mark_played"
v-text="$t('dialog.album.mark-as-played')"
/>
<a
class="button is-small"
@click="$emit('remove-podcast')"
v-text="$t('dialog.album.remove-podcast')"
/>
</div> </div>
<div class="content is-small"> <div class="content is-small">
<p v-if="album.artist"> <p v-if="album.artist">
<span class="heading" v-text="$t('dialog.album.artist')" /> <span class="heading" v-text="$t('dialog.album.artist')" />
<a class="title is-6 has-text-link" @click="open_artist" v-text="album.artist" /> <a
class="title is-6 has-text-link"
@click="open_artist"
v-text="album.artist"
/>
</p> </p>
<p v-if="album.date_released"> <p v-if="album.date_released">
<span class="heading" v-text="$t('dialog.album.release-date')" /> <span
<span class="title is-6" v-text="$filters.date(album.date_released)" /> class="heading"
v-text="$t('dialog.album.release-date')"
/>
<span
class="title is-6"
v-text="$filters.date(album.date_released)"
/>
</p> </p>
<p v-else-if="album.year > 0"> <p v-else-if="album.year > 0">
<span class="heading" v-text="$t('dialog.album.year')" /> <span class="heading" v-text="$t('dialog.album.year')" />
@ -33,15 +60,29 @@
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.album.duration')" /> <span class="heading" v-text="$t('dialog.album.duration')" />
<span class="title is-6" v-text="$filters.durationInHours(album.length_ms)" /> <span
class="title is-6"
v-text="$filters.durationInHours(album.length_ms)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.album.type')" /> <span class="heading" v-text="$t('dialog.album.type')" />
<span class="title is-6" v-text="[t('media.kind.' + album.media_kind), t('data.kind.' + album.data_kind)].join(' - ')" /> <span
class="title is-6"
v-text="
[
t('media.kind.' + album.media_kind),
t('data.kind.' + album.data_kind)
].join(' - ')
"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.album.added-on')" /> <span class="heading" v-text="$t('dialog.album.added-on')" />
<span class="title is-6" v-text="$filters.datetime(album.time_added)" /> <span
class="title is-6"
v-text="$filters.datetime(album.time_added)"
/>
</p> </p>
</div> </div>
</div> </div>
@ -61,7 +102,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -7,7 +7,11 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_artist" v-text="artist.name" /> <a
class="has-text-link"
@click="open_artist"
v-text="artist.name"
/>
</p> </p>
<div class="content is-small"> <div class="content is-small">
<p> <p>
@ -20,11 +24,17 @@
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.artist.type')" /> <span class="heading" v-text="$t('dialog.artist.type')" />
<span class="title is-6" v-text="$t('data.kind.' + artist.data_kind)" /> <span
class="title is-6"
v-text="$t('data.kind.' + artist.data_kind)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.artist.added-on')" /> <span class="heading" v-text="$t('dialog.artist.added-on')" />
<span class="title is-6" v-text="$filters.datetime(artist.time_added)" /> <span
class="title is-6"
v-text="$filters.datetime(artist.time_added)"
/>
</p> </p>
</div> </div>
</div> </div>
@ -44,7 +54,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -7,19 +7,34 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_albums" v-text="composer.name" /> <a
class="has-text-link"
@click="open_albums"
v-text="composer.name"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.composer.albums')" /> <span class="heading" v-text="$t('dialog.composer.albums')" />
<a class="has-text-link is-6" @click="open_albums" v-text="composer.album_count" /> <a
class="has-text-link is-6"
@click="open_albums"
v-text="composer.album_count"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.composer.tracks')" /> <span class="heading" v-text="$t('dialog.composer.tracks')" />
<a class="has-text-link is-6" @click="open_tracks" v-text="composer.track_count" /> <a
class="has-text-link is-6"
@click="open_tracks"
v-text="composer.track_count"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.composer.duration')" /> <span class="heading" v-text="$t('dialog.composer.duration')" />
<span class="title is-6" v-text="$filters.durationInHours(composer.length_ms)" /> <span
class="title is-6"
v-text="$filters.durationInHours(composer.length_ms)"
/>
</p> </p>
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
@ -29,7 +44,10 @@
</a> </a>
<a class="card-footer-item has-text-dark" @click="queue_add_next"> <a class="card-footer-item has-text-dark" @click="queue_add_next">
<mdicon class="icon" name="playlist-play" size="16" /> <mdicon class="icon" name="playlist-play" size="16" />
<span class="is-size-7" v-text="$t('dialog.composer.add-next')" /> <span
class="is-size-7"
v-text="$t('dialog.composer.add-next')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
@ -38,7 +56,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -15,7 +15,10 @@
</a> </a>
<a class="card-footer-item has-text-dark" @click="queue_add_next"> <a class="card-footer-item has-text-dark" @click="queue_add_next">
<mdicon class="icon" name="playlist-play" size="16" /> <mdicon class="icon" name="playlist-play" size="16" />
<span class="is-size-7" v-text="$t('dialog.directory.add-next')" /> <span
class="is-size-7"
v-text="$t('dialog.directory.add-next')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
@ -24,7 +27,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -7,7 +7,11 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_genre" v-text="genre.name" /> <a
class="has-text-link"
@click="open_genre"
v-text="genre.name"
/>
</p> </p>
<div class="content is-small"> <div class="content is-small">
<p> <p>
@ -20,7 +24,10 @@
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.genre.duration')" /> <span class="heading" v-text="$t('dialog.genre.duration')" />
<span class="title is-6" v-text="$filters.durationInHours(genre.length_ms)" /> <span
class="title is-6"
v-text="$filters.durationInHours(genre.length_ms)"
/>
</p> </p>
</div> </div>
</div> </div>
@ -40,7 +47,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -7,7 +7,11 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_playlist" v-text="playlist.name" /> <a
class="has-text-link"
@click="open_playlist"
v-text="playlist.name"
/>
</p> </p>
<div class="content is-small"> <div class="content is-small">
<p> <p>
@ -19,7 +23,10 @@
<span class="title is-6" v-text="playlist.type" /> <span class="title is-6" v-text="playlist.type" />
</p> </p>
<p v-if="!playlist.folder"> <p v-if="!playlist.folder">
<span class="heading" v-text="$t('dialog.playlist.track-count')" /> <span
class="heading"
v-text="$t('dialog.playlist.track-count')"
/>
<span class="title is-6" v-text="playlist.item_count" /> <span class="title is-6" v-text="playlist.item_count" />
</p> </p>
</div> </div>
@ -31,7 +38,10 @@
</a> </a>
<a class="card-footer-item has-text-dark" @click="queue_add_next"> <a class="card-footer-item has-text-dark" @click="queue_add_next">
<mdicon class="icon" name="playlist-play" size="16" /> <mdicon class="icon" name="playlist-play" size="16" />
<span class="is-size-7" v-text="$t('dialog.playlist.add-next')" /> <span
class="is-size-7"
v-text="$t('dialog.playlist.add-next')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
@ -40,7 +50,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -10,7 +10,14 @@
<form class="fd-has-margin-bottom" @submit.prevent="save"> <form class="fd-has-margin-bottom" @submit.prevent="save">
<div class="field"> <div class="field">
<p class="control is-expanded has-icons-left"> <p class="control is-expanded has-icons-left">
<input ref="playlist_name_field" v-model="playlist_name" class="input is-shadowless" type="text" placeholder="Playlist name" :disabled="loading" /> <input
ref="playlist_name_field"
v-model="playlist_name"
class="input is-shadowless"
type="text"
placeholder="Playlist name"
:disabled="loading"
/>
<mdicon class="icon is-left" name="file-music" size="16" /> <mdicon class="icon is-left" name="file-music" size="16" />
</p> </p>
</div> </div>
@ -19,22 +26,41 @@
<footer v-if="loading" class="card-footer"> <footer v-if="loading" class="card-footer">
<a class="card-footer-item has-text-dark"> <a class="card-footer-item has-text-dark">
<mdicon class="icon" name="web" size="16" /> <mdicon class="icon" name="web" size="16" />
<span class="is-size-7" v-text="$t('dialog.playlist.save.saving')" /> <span
class="is-size-7"
v-text="$t('dialog.playlist.save.saving')"
/>
</a> </a>
</footer> </footer>
<footer v-else class="card-footer"> <footer v-else class="card-footer">
<a class="card-footer-item has-text-danger" @click="$emit('close')"> <a
class="card-footer-item has-text-danger"
@click="$emit('close')"
>
<mdicon class="icon" name="cancel" size="16" /> <mdicon class="icon" name="cancel" size="16" />
<span class="is-size-7" v-text="$t('dialog.playlist.save.cancel')" /> <span
class="is-size-7"
v-text="$t('dialog.playlist.save.cancel')"
/>
</a> </a>
<a class="card-footer-item has-background-info has-text-white has-text-weight-bold" @click="save"> <a
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
@click="save"
>
<mdicon class="icon" name="content-save" size="16" /> <mdicon class="icon" name="content-save" size="16" />
<span class="is-size-7" v-text="$t('dialog.playlist.save.save')" /> <span
class="is-size-7"
v-text="$t('dialog.playlist.save.save')"
/>
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -10,17 +10,36 @@
<p class="subtitle" v-text="item.artist" /> <p class="subtitle" v-text="item.artist" />
<div class="content is-small"> <div class="content is-small">
<p> <p>
<span class="heading" v-text="$t('dialog.queue-item.album')" /> <span
<a v-if="item.album_id" class="title is-6 has-text-link" @click="open_album" v-text="item.album" /> class="heading"
v-text="$t('dialog.queue-item.album')"
/>
<a
v-if="item.album_id"
class="title is-6 has-text-link"
@click="open_album"
v-text="item.album"
/>
<span v-else class="title is-6" v-text="item.album" /> <span v-else class="title is-6" v-text="item.album" />
</p> </p>
<p v-if="item.album_artist"> <p v-if="item.album_artist">
<span class="heading" v-text="$t('dialog.queue-item.album-artist')" /> <span
<a v-if="item.album_artist_id" class="title is-6 has-text-link" @click="open_album_artist" v-text="item.album_artist" /> class="heading"
v-text="$t('dialog.queue-item.album-artist')"
/>
<a
v-if="item.album_artist_id"
class="title is-6 has-text-link"
@click="open_album_artist"
v-text="item.album_artist"
/>
<span v-else class="title is-6" v-text="item.album_artist" /> <span v-else class="title is-6" v-text="item.album_artist" />
</p> </p>
<p v-if="item.composer"> <p v-if="item.composer">
<span class="heading" v-text="$t('dialog.queue-item.composer')" /> <span
class="heading"
v-text="$t('dialog.queue-item.composer')"
/>
<span class="title is-6" v-text="item.composer" /> <span class="title is-6" v-text="item.composer" />
</p> </p>
<p v-if="item.year > 0"> <p v-if="item.year > 0">
@ -28,16 +47,35 @@
<span class="title is-6" v-text="item.year" /> <span class="title is-6" v-text="item.year" />
</p> </p>
<p v-if="item.genre"> <p v-if="item.genre">
<span class="heading" v-text="$t('dialog.queue-item.genre')" /> <span
<a class="title is-6 has-text-link" @click="open_genre" v-text="item.genre" /> class="heading"
v-text="$t('dialog.queue-item.genre')"
/>
<a
class="title is-6 has-text-link"
@click="open_genre"
v-text="item.genre"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.queue-item.position')" /> <span
<span class="title is-6" v-text="[ item.disc_number, item.track_number ].join(' / ')" /> class="heading"
v-text="$t('dialog.queue-item.position')"
/>
<span
class="title is-6"
v-text="[item.disc_number, item.track_number].join(' / ')"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.queue-item.duration')" /> <span
<span class="title is-6" v-text="$filters.durationInHours(item.length_ms)" /> class="heading"
v-text="$t('dialog.queue-item.duration')"
/>
<span
class="title is-6"
v-text="$filters.durationInHours(item.length_ms)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.queue-item.path')" /> <span class="heading" v-text="$t('dialog.queue-item.path')" />
@ -46,20 +84,53 @@
<p> <p>
<span class="heading" v-text="$t('dialog.queue-item.type')" /> <span class="heading" v-text="$t('dialog.queue-item.type')" />
<span class="title is-6"> <span class="title is-6">
<span v-text="[item.media_kind, item.data_kind].join(' - ')" /> <span
<span v-if="item.data_kind === 'spotify'" class="has-text-weight-normal"> v-text="[item.media_kind, item.data_kind].join(' - ')"
(<a @click="open_spotify_artist" v-text="$t('dialog.queue-item.spotify-artist')" />, />
<a @click="open_spotify_album" v-text="$t('dialog.queue-item.spotify-album')" />) <span
v-if="item.data_kind === 'spotify'"
class="has-text-weight-normal"
>
(<a
@click="open_spotify_artist"
v-text="$t('dialog.queue-item.spotify-artist')"
/>,
<a
@click="open_spotify_album"
v-text="$t('dialog.queue-item.spotify-album')"
/>)
</span> </span>
</span> </span>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.queue-item.quality')" /> <span
class="heading"
v-text="$t('dialog.queue-item.quality')"
/>
<span class="title is-6"> <span class="title is-6">
<span v-text="item.type" /> <span v-text="item.type" />
<span v-if="item.samplerate" v-text="$t('dialog.queue-item.samplerate', { rate: item.samplerate })" /> <span
<span v-if="item.channels" v-text="$t('dialog.queue-item.channels', { channels: $filters.channels(item.channels) })" /> v-if="item.samplerate"
<span v-if="item.bitrate" v-text="$t('dialog.queue-item.bitrate', { rate: item.bitrate })" /> v-text="
$t('dialog.queue-item.samplerate', {
rate: item.samplerate
})
"
/>
<span
v-if="item.channels"
v-text="
$t('dialog.queue-item.channels', {
channels: $filters.channels(item.channels)
})
"
/>
<span
v-if="item.bitrate"
v-text="
$t('dialog.queue-item.bitrate', { rate: item.bitrate })
"
/>
</span> </span>
</p> </p>
</div> </div>
@ -67,7 +138,10 @@
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="remove"> <a class="card-footer-item has-text-dark" @click="remove">
<mdicon class="icon" name="delete" size="16" /> <mdicon class="icon" name="delete" size="16" />
<span class="is-size-7" v-text="$t('dialog.queue-item.remove')" /> <span
class="is-size-7"
v-text="$t('dialog.queue-item.remove')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
@ -76,7 +150,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -6,29 +6,54 @@
<div class="modal-content fd-modal-card"> <div class="modal-content fd-modal-card">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<p class="title is-4" v-text="$t('dialog.remote-pairing.title')" /> <p
class="title is-4"
v-text="$t('dialog.remote-pairing.title')"
/>
<form @submit.prevent="kickoff_pairing"> <form @submit.prevent="kickoff_pairing">
<label class="label" v-text="pairing.remote" /> <label class="label" v-text="pairing.remote" />
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<input ref="pin_field" v-model="pairing_req.pin" class="input" type="text" placeholder="Enter pairing code" /> <input
ref="pin_field"
v-model="pairing_req.pin"
class="input"
type="text"
placeholder="Enter pairing code"
/>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item has-text-danger" @click="$emit('close')"> <a
class="card-footer-item has-text-danger"
@click="$emit('close')"
>
<mdicon class="icon" name="cancel" size="16" /> <mdicon class="icon" name="cancel" size="16" />
<span class="is-size-7" v-text="$t('dialog.remote-pairing.cancel')" /> <span
class="is-size-7"
v-text="$t('dialog.remote-pairing.cancel')"
/>
</a> </a>
<a class="card-footer-item has-background-info has-text-white has-text-weight-bold" @click="kickoff_pairing"> <a
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
@click="kickoff_pairing"
>
<mdicon class="icon" name="cellphone" size="16" /> <mdicon class="icon" name="cellphone" size="16" />
<span class="is-size-7" v-text="$t('dialog.remote-pairing.pair')" /> <span
class="is-size-7"
v-text="$t('dialog.remote-pairing.pair')"
/>
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -9,25 +9,54 @@
<p class="title is-4" v-text="track.title" /> <p class="title is-4" v-text="track.title" />
<p class="subtitle" v-text="track.artist" /> <p class="subtitle" v-text="track.artist" />
<div v-if="track.media_kind === 'podcast'" class="buttons"> <div v-if="track.media_kind === 'podcast'" class="buttons">
<a v-if="track.play_count > 0" class="button is-small" @click="mark_new" v-text="$t('dialog.track.mark-as-new')" /> <a
<a v-if="track.play_count === 0" class="button is-small" @click="mark_played" v-text="$t('dialog.track.mark-as-played')" /> v-if="track.play_count > 0"
class="button is-small"
@click="mark_new"
v-text="$t('dialog.track.mark-as-new')"
/>
<a
v-if="track.play_count === 0"
class="button is-small"
@click="mark_played"
v-text="$t('dialog.track.mark-as-played')"
/>
</div> </div>
<div class="content is-small"> <div class="content is-small">
<p> <p>
<span class="heading" v-text="$t('dialog.track.album')" /> <span class="heading" v-text="$t('dialog.track.album')" />
<a class="title is-6 has-text-link" @click="open_album" v-text="track.album" /> <a
class="title is-6 has-text-link"
@click="open_album"
v-text="track.album"
/>
</p> </p>
<p v-if="track.album_artist && track.media_kind !== 'audiobook'"> <p
<span class="heading" v-text="$t('dialog.track.album-artist')" /> v-if="track.album_artist && track.media_kind !== 'audiobook'"
<a class="title is-6 has-text-link" @click="open_artist" v-text="track.album_artist" /> >
<span
class="heading"
v-text="$t('dialog.track.album-artist')"
/>
<a
class="title is-6 has-text-link"
@click="open_artist"
v-text="track.album_artist"
/>
</p> </p>
<p v-if="track.composer"> <p v-if="track.composer">
<span class="heading" v-text="$t('dialog.track.composer')" /> <span class="heading" v-text="$t('dialog.track.composer')" />
<span class="title is-6" v-text="track.composer" /> <span class="title is-6" v-text="track.composer" />
</p> </p>
<p v-if="track.date_released"> <p v-if="track.date_released">
<span class="heading" v-text="$t('dialog.track.release-date')" /> <span
<span class="title is-6" v-text="$filters.date(track.date_released)" /> class="heading"
v-text="$t('dialog.track.release-date')"
/>
<span
class="title is-6"
v-text="$filters.date(track.date_released)"
/>
</p> </p>
<p v-else-if="track.year > 0"> <p v-else-if="track.year > 0">
<span class="heading" v-text="$t('dialog.track.year')" /> <span class="heading" v-text="$t('dialog.track.year')" />
@ -35,15 +64,25 @@
</p> </p>
<p v-if="track.genre"> <p v-if="track.genre">
<span class="heading" v-text="$t('dialog.track.genre')" /> <span class="heading" v-text="$t('dialog.track.genre')" />
<a class="title is-6 has-text-link" @click="open_genre" v-text="track.genre" /> <a
class="title is-6 has-text-link"
@click="open_genre"
v-text="track.genre"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.track.position')" /> <span class="heading" v-text="$t('dialog.track.position')" />
<span class="title is-6" v-text="[track.disc_number, track.track_number].join(' / ')" /> <span
class="title is-6"
v-text="[track.disc_number, track.track_number].join(' / ')"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.track.duration')" /> <span class="heading" v-text="$t('dialog.track.duration')" />
<span class="title is-6" v-text="$filters.durationInHours(track.length_ms)" /> <span
class="title is-6"
v-text="$filters.durationInHours(track.length_ms)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.track.path')" /> <span class="heading" v-text="$t('dialog.track.path')" />
@ -52,10 +91,21 @@
<p> <p>
<span class="heading" v-text="$t('dialog.track.type')" /> <span class="heading" v-text="$t('dialog.track.type')" />
<span class="title is-6"> <span class="title is-6">
<span v-text="[track.media_kind, track.data_kind].join(' - ')" /> <span
<span v-if="track.data_kind === 'spotify'" class="has-text-weight-normal"> v-text="[track.media_kind, track.data_kind].join(' - ')"
(<a @click="open_spotify_artist" v-text="$t('dialog.track.spotify-artist')" />, />
<a @click="open_spotify_album" v-text="$t('dialog.track.spotify-album')" />) <span
v-if="track.data_kind === 'spotify'"
class="has-text-weight-normal"
>
(<a
@click="open_spotify_artist"
v-text="$t('dialog.track.spotify-artist')"
/>,
<a
@click="open_spotify_album"
v-text="$t('dialog.track.spotify-album')"
/>)
</span> </span>
</span> </span>
</p> </p>
@ -63,18 +113,47 @@
<span class="heading" v-text="$t('dialog.track.quality')" /> <span class="heading" v-text="$t('dialog.track.quality')" />
<span class="title is-6"> <span class="title is-6">
<span v-text="track.type" /> <span v-text="track.type" />
<span v-if="track.samplerate" v-text="$t('dialog.track.samplerate', { rate: track.samplerate })" /> <span
<span v-if="track.channels" v-text="$t('dialog.track.channels', { channels: $filters.channels(track.channels) })" /> v-if="track.samplerate"
<span v-if="track.bitrate" v-text="$t('dialog.track.bitrate', { rate: track.bitrate })" /> v-text="
$t('dialog.track.samplerate', {
rate: track.samplerate
})
"
/>
<span
v-if="track.channels"
v-text="
$t('dialog.track.channels', {
channels: $filters.channels(track.channels)
})
"
/>
<span
v-if="track.bitrate"
v-text="
$t('dialog.track.bitrate', { rate: track.bitrate })
"
/>
</span> </span>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.track.added-on')" /> <span class="heading" v-text="$t('dialog.track.added-on')" />
<span class="title is-6" v-text="$filters.datetime(track.time_added)" /> <span
class="title is-6"
v-text="$filters.datetime(track.time_added)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.track.rating')" /> <span class="heading" v-text="$t('dialog.track.rating')" />
<span class="title is-6" v-text="$t('dialog.track.rating-value', { rating: Math.floor(track.rating / 10) })" /> <span
class="title is-6"
v-text="
$t('dialog.track.rating-value', {
rating: Math.floor(track.rating / 10)
})
"
/>
</p> </p>
<p v-if="track.comment"> <p v-if="track.comment">
<span class="heading" v-text="$t('dialog.track.comment')" /> <span class="heading" v-text="$t('dialog.track.comment')" />
@ -98,7 +177,11 @@
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -1,5 +1,12 @@
<template> <template>
<modal-dialog :show="show" :title="$t('dialog.update.title')" :ok_action="library.updating ? '' : $t('dialog.update.rescan')" :close_action="$t('dialog.update.cancel')" @ok="update_library" @close="close()"> <modal-dialog
:show="show"
:title="$t('dialog.update.title')"
:ok_action="library.updating ? '' : $t('dialog.update.rescan')"
:close_action="$t('dialog.update.cancel')"
@ok="update_library"
@close="close()"
>
<template #modal-content> <template #modal-content>
<div v-if="!library.updating"> <div v-if="!library.updating">
<p class="mb-3" v-text="$t('dialog.update.info')" /> <p class="mb-3" v-text="$t('dialog.update.info')" />
@ -9,15 +16,27 @@
<select v-model="update_dialog_scan_kind"> <select v-model="update_dialog_scan_kind">
<option value="" v-text="$t('dialog.update.all')" /> <option value="" v-text="$t('dialog.update.all')" />
<option value="files" v-text="$t('dialog.update.local')" /> <option value="files" v-text="$t('dialog.update.local')" />
<option v-if="spotify_enabled" value="spotify" v-text="$t('dialog.update.spotify')" /> <option
<option v-if="rss.tracks > 0" value="rss" v-text="$t('dialog.update.feeds')" /> v-if="spotify_enabled"
value="spotify"
v-text="$t('dialog.update.spotify')"
/>
<option
v-if="rss.tracks > 0"
value="rss"
v-text="$t('dialog.update.feeds')"
/>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="checkbox is-size-7 is-small"> <label class="checkbox is-size-7 is-small">
<input v-model="rescan_metadata" type="checkbox" style="margin-right: 5px" /> <input
v-model="rescan_metadata"
type="checkbox"
style="margin-right: 5px"
/>
<span v-text="$t('dialog.update.rescan-metadata')" /> <span v-text="$t('dialog.update.rescan-metadata')" />
</label> </label>
</div> </div>

View File

@ -1,52 +1,129 @@
<template> <template>
<nav class="fd-bottom-navbar navbar is-white is-fixed-bottom" :style="zindex" :class="{ 'is-transparent': is_now_playing_page, 'is-dark': !is_now_playing_page }" role="navigation" aria-label="player controls"> <nav
class="fd-bottom-navbar navbar is-white is-fixed-bottom"
:style="zindex"
:class="{
'is-transparent': is_now_playing_page,
'is-dark': !is_now_playing_page
}"
role="navigation"
aria-label="player controls"
>
<div class="navbar-brand fd-expanded"> <div class="navbar-brand fd-expanded">
<!-- Link to queue --> <!-- Link to queue -->
<navbar-item-link to="/" exact> <navbar-item-link to="/" exact>
<mdicon class="icon" name="playlist-play" size="24" /> <mdicon class="icon" name="playlist-play" size="24" />
</navbar-item-link> </navbar-item-link>
<!-- Now playing artist/title (not visible on "now playing" page) --> <!-- Now playing artist/title (not visible on "now playing" page) -->
<router-link v-if="!is_now_playing_page" to="/now-playing" class="navbar-item is-expanded is-clipped" active-class="is-active" exact> <router-link
v-if="!is_now_playing_page"
to="/now-playing"
class="navbar-item is-expanded is-clipped"
active-class="is-active"
exact
>
<div class="is-clipped"> <div class="is-clipped">
<p class="is-size-7 fd-is-text-clipped"> <p class="is-size-7 fd-is-text-clipped">
<strong v-text="now_playing.title" /> <strong v-text="now_playing.title" />
<br /> <br />
<span v-text="now_playing.artist" /> <span v-text="now_playing.artist" />
<span v-if="now_playing.data_kind === 'url'" v-text="$t('navigation.now-playing', { album: now_playing.album })" /> <span
v-if="now_playing.data_kind === 'url'"
v-text="
$t('navigation.now-playing', { album: now_playing.album })
"
/>
</p> </p>
</div> </div>
</router-link> </router-link>
<!-- Skip previous (not visible on "now playing" page) --> <!-- Skip previous (not visible on "now playing" page) -->
<player-button-previous v-if="is_now_playing_page" class="navbar-item fd-margin-left-auto" :icon_size="24" /> <player-button-previous
<player-button-seek-back v-if="is_now_playing_page" :seek_ms="10000" class="navbar-item" :icon_size="24" /> v-if="is_now_playing_page"
class="navbar-item fd-margin-left-auto"
:icon_size="24"
/>
<player-button-seek-back
v-if="is_now_playing_page"
:seek_ms="10000"
class="navbar-item"
:icon_size="24"
/>
<!-- Play/pause --> <!-- Play/pause -->
<player-button-play-pause class="navbar-item" :icon_size="36" show_disabled_message /> <player-button-play-pause
<player-button-seek-forward v-if="is_now_playing_page" :seek_ms="30000" class="navbar-item" :icon_size="24" /> class="navbar-item"
:icon_size="36"
show_disabled_message
/>
<player-button-seek-forward
v-if="is_now_playing_page"
:seek_ms="30000"
class="navbar-item"
:icon_size="24"
/>
<!-- Skip next (not visible on "now playing" page) --> <!-- Skip next (not visible on "now playing" page) -->
<player-button-next v-if="is_now_playing_page" class="navbar-item" :icon_size="24" /> <player-button-next
v-if="is_now_playing_page"
class="navbar-item"
:icon_size="24"
/>
<!-- Player menu button (only visible on mobile and tablet) --> <!-- Player menu button (only visible on mobile and tablet) -->
<a class="navbar-item fd-margin-left-auto is-hidden-desktop" @click="show_player_menu = !show_player_menu"> <a
<mdicon class="icon" :name="show_player_menu ? 'chevron-down' : 'chevron-up'" size="18" /> class="navbar-item fd-margin-left-auto is-hidden-desktop"
@click="show_player_menu = !show_player_menu"
>
<mdicon
class="icon"
:name="show_player_menu ? 'chevron-down' : 'chevron-up'"
size="18"
/>
</a> </a>
<!-- Player menu dropup menu (only visible on desktop) --> <!-- Player menu dropup menu (only visible on desktop) -->
<div class="navbar-item has-dropdown has-dropdown-up fd-margin-left-auto is-hidden-touch" :class="{ 'is-active': show_player_menu }"> <div
<a class="navbar-link is-arrowless" @click="show_player_menu = !show_player_menu"> class="navbar-item has-dropdown has-dropdown-up fd-margin-left-auto is-hidden-touch"
<mdicon class="icon" :name="show_player_menu ? 'chevron-down' : 'chevron-up'" size="18" /> :class="{ 'is-active': show_player_menu }"
>
<a
class="navbar-link is-arrowless"
@click="show_player_menu = !show_player_menu"
>
<mdicon
class="icon"
:name="show_player_menu ? 'chevron-down' : 'chevron-up'"
size="18"
/>
</a> </a>
<div class="navbar-dropdown is-right is-boxed" style="margin-right: 6px; margin-bottom: 6px; border-radius: 6px"> <div
class="navbar-dropdown is-right is-boxed"
style="margin-right: 6px; margin-bottom: 6px; border-radius: 6px"
>
<div class="navbar-item"> <div class="navbar-item">
<!-- Outputs: master volume --> <!-- Outputs: master volume -->
<div class="level is-mobile"> <div class="level is-mobile">
<div class="level-left fd-expanded"> <div class="level-left fd-expanded">
<div class="level-item" style="flex-grow: 0"> <div class="level-item" style="flex-grow: 0">
<a class="button is-white is-small" @click="toggle_mute_volume"> <a
<mdicon class="icon" :name="player.volume > 0 ? 'volume-high' : 'volume-off'" size="18" /> class="button is-white is-small"
@click="toggle_mute_volume"
>
<mdicon
class="icon"
:name="player.volume > 0 ? 'volume-high' : 'volume-off'"
size="18"
/>
</a> </a>
</div> </div>
<div class="level-item fd-expanded"> <div class="level-item fd-expanded">
<div class="fd-expanded"> <div class="fd-expanded">
<p class="heading" v-text="$t('navigation.volume')" /> <p class="heading" v-text="$t('navigation.volume')" />
<Slider v-model="player.volume" :min="0" :max="100" :step="1" :tooltips="false" :classes="{ target: 'slider' }" @change="set_volume" /> <Slider
v-model="player.volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:classes="{ target: 'slider' }"
@change="set_volume"
/>
</div> </div>
</div> </div>
</div> </div>
@ -54,28 +131,63 @@
</div> </div>
<!-- Outputs: master volume --> <!-- Outputs: master volume -->
<hr class="fd-navbar-divider" /> <hr class="fd-navbar-divider" />
<navbar-item-output v-for="output in outputs" :key="output.id" :output="output" /> <navbar-item-output
v-for="output in outputs"
:key="output.id"
:output="output"
/>
<!-- Outputs: stream volume --> <!-- Outputs: stream volume -->
<hr class="fd-navbar-divider" /> <hr class="fd-navbar-divider" />
<div class="navbar-item"> <div class="navbar-item">
<div class="level is-mobile"> <div class="level is-mobile">
<div class="level-left fd-expanded"> <div class="level-left fd-expanded">
<div class="level-item" style="flex-grow: 0"> <div class="level-item" style="flex-grow: 0">
<a class="button is-white is-small" :class="{ 'is-loading': loading }"> <a
<span class="icon fd-has-action" :class="{ 'has-text-grey-light': !playing && !loading, 'is-loading': loading }" @click="togglePlay"> class="button is-white is-small"
:class="{ 'is-loading': loading }"
>
<span
class="icon fd-has-action"
:class="{
'has-text-grey-light': !playing && !loading,
'is-loading': loading
}"
@click="togglePlay"
>
<mdicon name="broadcast" size="18" /> <mdicon name="broadcast" size="18" />
</span> </span>
</a> </a>
</div> </div>
<div class="level-item fd-expanded"> <div class="level-item fd-expanded">
<div class="fd-expanded"> <div class="fd-expanded">
<p class="heading" :class="{ 'has-text-grey-light': !playing }"> <p
class="heading"
:class="{ 'has-text-grey-light': !playing }"
>
<span v-text="$t('navigation.stream')" /> <span v-text="$t('navigation.stream')" />
<a href="stream.mp3" style="margin-left: 5px" target="_blank"> <a
<mdicon class="icon" name="open-in-new" size="16" style="vertical-align: middle" /> href="stream.mp3"
style="margin-left: 5px"
target="_blank"
>
<mdicon
class="icon"
name="open-in-new"
size="16"
style="vertical-align: middle"
/>
</a> </a>
</p> </p>
<Slider v-model="stream_volume" :min="0" :max="100" :step="1" :tooltips="false" :disabled="!playing" :classes="{ target: 'slider' }" @change="set_stream_volume" /> <Slider
v-model="stream_volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:disabled="!playing"
:classes="{ target: 'slider' }"
@change="set_stream_volume"
/>
</div> </div>
</div> </div>
</div> </div>
@ -98,7 +210,10 @@
</div> </div>
</div> </div>
<!-- Player menu (only visible on mobile and tablet) --> <!-- Player menu (only visible on mobile and tablet) -->
<div class="navbar-menu is-hidden-desktop" :class="{ 'is-active': show_player_menu }"> <div
class="navbar-menu is-hidden-desktop"
:class="{ 'is-active': show_player_menu }"
>
<div class="navbar-start" /> <div class="navbar-start" />
<div class="navbar-end"> <div class="navbar-end">
<!-- Repeat/shuffle/consume --> <!-- Repeat/shuffle/consume -->
@ -116,41 +231,88 @@
<div class="level-left fd-expanded"> <div class="level-left fd-expanded">
<div class="level-item" style="flex-grow: 0"> <div class="level-item" style="flex-grow: 0">
<a class="button is-white is-small" @click="toggle_mute_volume"> <a class="button is-white is-small" @click="toggle_mute_volume">
<mdicon class="icon" :name="player.volume > 0 ? 'volume-high' : 'volume-off'" size="18" /> <mdicon
class="icon"
:name="player.volume > 0 ? 'volume-high' : 'volume-off'"
size="18"
/>
</a> </a>
</div> </div>
<div class="level-item fd-expanded"> <div class="level-item fd-expanded">
<div class="fd-expanded"> <div class="fd-expanded">
<p class="heading" v-text="$t('navigation.volume')" /> <p class="heading" v-text="$t('navigation.volume')" />
<Slider v-model="player.volume" :min="0" :max="100" :step="1" :tooltips="false" :classes="{ target: 'slider' }" @change="set_volume" /> <Slider
v-model="player.volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:classes="{ target: 'slider' }"
@change="set_volume"
/>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Outputs: speaker volumes --> <!-- Outputs: speaker volumes -->
<navbar-item-output v-for="output in outputs" :key="output.id" :output="output" /> <navbar-item-output
v-for="output in outputs"
:key="output.id"
:output="output"
/>
<!-- Outputs: stream volume --> <!-- Outputs: stream volume -->
<hr class="fd-navbar-divider" /> <hr class="fd-navbar-divider" />
<div class="navbar-item fd-has-margin-bottom"> <div class="navbar-item fd-has-margin-bottom">
<div class="level is-mobile"> <div class="level is-mobile">
<div class="level-left fd-expanded"> <div class="level-left fd-expanded">
<div class="level-item" style="flex-grow: 0"> <div class="level-item" style="flex-grow: 0">
<a class="button is-white is-small" :class="{ 'is-loading': loading }"> <a
<span class="icon fd-has-action" :class="{ 'has-text-grey-light': !playing && !loading, 'is-loading': loading }" @click="togglePlay"> class="button is-white is-small"
:class="{ 'is-loading': loading }"
>
<span
class="icon fd-has-action"
:class="{
'has-text-grey-light': !playing && !loading,
'is-loading': loading
}"
@click="togglePlay"
>
<mdicon name="broadcast" size="16" /> <mdicon name="broadcast" size="16" />
</span> </span>
</a> </a>
</div> </div>
<div class="level-item fd-expanded"> <div class="level-item fd-expanded">
<div class="fd-expanded"> <div class="fd-expanded">
<p class="heading" :class="{ 'has-text-grey-light': !playing }"> <p
class="heading"
:class="{ 'has-text-grey-light': !playing }"
>
<span v-text="$t('navigation.stream')" /> <span v-text="$t('navigation.stream')" />
<a href="stream.mp3" style="margin-left: 5px" target="_blank"> <a
<mdicon class="icon" name="open-in-new" size="16" style="vertical-align: middle" /> href="stream.mp3"
style="margin-left: 5px"
target="_blank"
>
<mdicon
class="icon"
name="open-in-new"
size="16"
style="vertical-align: middle"
/>
</a> </a>
</p> </p>
<Slider v-model="stream_volume" :min="0" :max="100" :step="1" :tooltips="false" :disabled="!playing" :classes="{ target: 'slider' }" @change="set_stream_volume" /> <Slider
v-model="stream_volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:disabled="!playing"
:classes="{ target: 'slider' }"
@change="set_stream_volume"
/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,5 +1,10 @@
<template> <template>
<a class="navbar-item" :class="{ 'is-active': is_active }" :href="full_path()" @click.stop.prevent="open_link()"> <a
class="navbar-item"
:class="{ 'is-active': is_active }"
:href="full_path()"
@click.stop.prevent="open_link()"
>
<slot /> <slot />
</a> </a>
</template> </template>

View File

@ -4,15 +4,32 @@
<div class="level-left fd-expanded"> <div class="level-left fd-expanded">
<div class="level-item" style="flex-grow: 0"> <div class="level-item" style="flex-grow: 0">
<a class="button is-white is-small"> <a class="button is-white is-small">
<span class="icon fd-has-action" :class="{ 'has-text-grey-light': !output.selected }" @click="set_enabled"> <span
class="icon fd-has-action"
:class="{ 'has-text-grey-light': !output.selected }"
@click="set_enabled"
>
<mdicon :name="type_class" size="18" :title="output.type" /> <mdicon :name="type_class" size="18" :title="output.type" />
</span> </span>
</a> </a>
</div> </div>
<div class="level-item fd-expanded"> <div class="level-item fd-expanded">
<div class="fd-expanded"> <div class="fd-expanded">
<p class="heading" :class="{ 'has-text-grey-light': !output.selected }" v-text="output.name" /> <p
<Slider v-model="volume" :min="0" :max="100" :step="1" :tooltips="false" :disabled="!output.selected" :classes="{ target: 'slider' }" @change="set_volume" /> class="heading"
:class="{ 'has-text-grey-light': !output.selected }"
v-text="output.name"
/>
<Slider
v-model="volume"
:min="0"
:max="100"
:step="1"
:tooltips="false"
:disabled="!output.selected"
:classes="{ target: 'slider' }"
@change="set_volume"
/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,5 +1,10 @@
<template> <template>
<nav class="fd-top-navbar navbar is-light is-fixed-top" :style="zindex" role="navigation" aria-label="main navigation"> <nav
class="fd-top-navbar navbar is-light is-fixed-top"
:style="zindex"
role="navigation"
aria-label="main navigation"
>
<div class="navbar-brand"> <div class="navbar-brand">
<navbar-item-link v-if="is_visible_playlists" to="/playlists"> <navbar-item-link v-if="is_visible_playlists" to="/playlists">
<mdicon class="icon" name="music-box-multiple" size="16" /> <mdicon class="icon" name="music-box-multiple" size="16" />
@ -22,7 +27,11 @@
<navbar-item-link v-if="is_visible_search" to="/search"> <navbar-item-link v-if="is_visible_search" to="/search">
<mdicon class="icon" name="magnify" size="16" /> <mdicon class="icon" name="magnify" size="16" />
</navbar-item-link> </navbar-item-link>
<div class="navbar-burger" :class="{ 'is-active': show_burger_menu }" @click="show_burger_menu = !show_burger_menu"> <div
class="navbar-burger"
:class="{ 'is-active': show_burger_menu }"
@click="show_burger_menu = !show_burger_menu"
>
<span /> <span />
<span /> <span />
<span /> <span />
@ -32,10 +41,17 @@
<div class="navbar-start" /> <div class="navbar-start" />
<div class="navbar-end"> <div class="navbar-end">
<!-- Burger menu entries --> <!-- Burger menu entries -->
<div class="navbar-item has-dropdown is-hoverable" :class="{ 'is-active': show_settings_menu }" @click="on_click_outside_settings"> <div
class="navbar-item has-dropdown is-hoverable"
:class="{ 'is-active': show_settings_menu }"
@click="on_click_outside_settings"
>
<a class="navbar-link is-arrowless"> <a class="navbar-link is-arrowless">
<mdicon class="icon is-hidden-touch" name="menu" size="24" /> <mdicon class="icon is-hidden-touch" name="menu" size="24" />
<span class="is-hidden-desktop has-text-weight-bold" v-text="$t('navigation.title')" /> <span
class="is-hidden-desktop has-text-weight-bold"
v-text="$t('navigation.title')"
/>
</a> </a>
<div class="navbar-dropdown is-right"> <div class="navbar-dropdown is-right">
<navbar-item-link to="/playlists"> <navbar-item-link to="/playlists">
@ -47,16 +63,28 @@
<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 class="fd-navbar-item-level2" v-text="$t('navigation.artists')" /> <span
class="fd-navbar-item-level2"
v-text="$t('navigation.artists')"
/>
</navbar-item-link> </navbar-item-link>
<navbar-item-link to="/music/albums"> <navbar-item-link to="/music/albums">
<span class="fd-navbar-item-level2" v-text="$t('navigation.albums')" /> <span
class="fd-navbar-item-level2"
v-text="$t('navigation.albums')"
/>
</navbar-item-link> </navbar-item-link>
<navbar-item-link to="/music/genres"> <navbar-item-link to="/music/genres">
<span class="fd-navbar-item-level2" v-text="$t('navigation.genres')" /> <span
class="fd-navbar-item-level2"
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 class="fd-navbar-item-level2" v-text="$t('navigation.spotify')" /> <span
class="fd-navbar-item-level2"
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="podcast" size="16" /> <mdicon class="icon" name="podcast" size="16" />
@ -79,15 +107,30 @@
<b v-text="$t('navigation.search')" /> <b v-text="$t('navigation.search')" />
</navbar-item-link> </navbar-item-link>
<hr class="fd-navbar-divider" /> <hr class="fd-navbar-divider" />
<navbar-item-link to="/settings/webinterface" v-text="$t('navigation.settings')" /> <navbar-item-link
<a class="navbar-item" @click.stop.prevent="open_update_dialog()" v-text="$t('navigation.update-library')" /> to="/settings/webinterface"
v-text="$t('navigation.settings')"
/>
<a
class="navbar-item"
@click.stop.prevent="open_update_dialog()"
v-text="$t('navigation.update-library')"
/>
<navbar-item-link to="/about" v-text="$t('navigation.about')" /> <navbar-item-link to="/about" v-text="$t('navigation.about')" />
<div class="navbar-item is-hidden-desktop" style="margin-bottom: 2.5rem" /> <div
class="navbar-item is-hidden-desktop"
style="margin-bottom: 2.5rem"
/>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div v-show="show_settings_menu" class="is-overlay" style="z-index: 10; width: 100vw; height: 100vh" @click="show_settings_menu = false" /> <div
v-show="show_settings_menu"
class="is-overlay"
style="z-index: 10; width: 100vw; height: 100vh"
@click="show_settings_menu = false"
/>
</nav> </nav>
</template> </template>

View File

@ -2,7 +2,15 @@
<section v-if="notifications.length > 0" class="fd-notifications"> <section v-if="notifications.length > 0" class="fd-notifications">
<div class="columns is-centered"> <div class="columns is-centered">
<div class="column is-half"> <div class="column is-half">
<div v-for="notification in notifications" :key="notification.id" class="notification has-shadow" :class="[ 'notification', notification.type ? `is-${notification.type}` : '' ]"> <div
v-for="notification in notifications"
:key="notification.id"
class="notification has-shadow"
:class="[
'notification',
notification.type ? `is-${notification.type}` : ''
]"
>
<button class="delete" @click="remove(notification)" /> <button class="delete" @click="remove(notification)" />
<span v-text="notification.text" /> <span v-text="notification.text" />
</div> </div>

View File

@ -1,5 +1,9 @@
<template> <template>
<div v-if="width > 0" class="progress-bar mt-2" :style="{ width: width_percent }" /> <div
v-if="width > 0"
class="progress-bar mt-2"
:style="{ width: width_percent }"
/>
</template> </template>
<script> <script>

View File

@ -1,9 +1,19 @@
<template> <template>
<div class="field"> <div class="field">
<label class="switch"> <label class="switch">
<input ref="setting" type="checkbox" :checked="value" style="margin-right: 5px" @change="set_update_timer"/> <input
ref="setting"
type="checkbox"
:checked="value"
style="margin-right: 5px"
@change="set_update_timer"
/>
<slot name="label" /> <slot name="label" />
<i class="is-size-7" :class="{ 'has-text-info': is_success, 'has-text-danger': is_error }" v-text="info" /> <i
class="is-size-7"
:class="{ 'has-text-info': is_success, 'has-text-danger': is_error }"
v-text="info"
/>
</label> </label>
<p v-if="$slots['info']" class="help"> <p v-if="$slots['info']" class="help">
<slot name="info" /> <slot name="info" />

View File

@ -3,10 +3,23 @@
<div class="field"> <div class="field">
<label class="label has-text-weight-normal"> <label class="label has-text-weight-normal">
<slot name="label" /> <slot name="label" />
<i class="is-size-7" :class="{ 'has-text-info': is_success, 'has-text-danger': is_error }" v-text="info" /> <i
class="is-size-7"
:class="{ 'has-text-info': is_success, 'has-text-danger': is_error }"
v-text="info"
/>
</label> </label>
<div class="control"> <div class="control">
<input ref="setting" class="input" type="number" min="0" style="width: 10em" :placeholder="placeholder" :value="value" @input="set_update_timer" /> <input
ref="setting"
class="input"
type="number"
min="0"
style="width: 10em"
:placeholder="placeholder"
:value="value"
@input="set_update_timer"
/>
</div> </div>
<p v-if="$slots['info']" class="help"> <p v-if="$slots['info']" class="help">
<slot name="info" /> <slot name="info" />

View File

@ -3,10 +3,21 @@
<div class="field"> <div class="field">
<label class="label has-text-weight-normal"> <label class="label has-text-weight-normal">
<slot name="label" /> <slot name="label" />
<i class="is-size-7" :class="{ 'has-text-info': is_success, 'has-text-danger': is_error }" v-text="info" /> <i
class="is-size-7"
:class="{ 'has-text-info': is_success, 'has-text-danger': is_error }"
v-text="info"
/>
</label> </label>
<div class="control"> <div class="control">
<input ref="setting" class="input" type="text" :placeholder="placeholder" :value="value" @input="set_update_timer" /> <input
ref="setting"
class="input"
type="text"
:placeholder="placeholder"
:value="value"
@input="set_update_timer"
/>
</div> </div>
<p v-if="$slots['info']" class="help"> <p v-if="$slots['info']" class="help">
<slot name="info" /> <slot name="info" />

View File

@ -8,7 +8,12 @@
<h2 class="subtitle is-7 has-text-grey"> <h2 class="subtitle is-7 has-text-grey">
<b v-text="album.artists[0].name" /> <b v-text="album.artists[0].name" />
</h2> </h2>
<h2 class="subtitle is-7 has-text-grey has-text-weight-normal" v-text="[album.album_type, $filters.date(album.release_date)].join(', ')" /> <h2
class="subtitle is-7 has-text-grey has-text-weight-normal"
v-text="
[album.album_type, $filters.date(album.release_date)].join(', ')
"
/>
</div> </div>
<div class="media-right"> <div class="media-right">
<slot name="actions" /> <slot name="actions" />

View File

@ -1,13 +1,30 @@
<template> <template>
<div class="media"> <div class="media">
<div class="media-content fd-has-action is-clipped" @click="play"> <div class="media-content fd-has-action is-clipped" @click="play">
<h1 class="title is-6" :class="{ 'has-text-grey-light': track.is_playable === false }" v-text="track.name" /> <h1
<h2 class="subtitle is-7" :class="{ 'has-text-grey': track.is_playable, 'has-text-grey-light': track.is_playable === false }"> class="title is-6"
:class="{ 'has-text-grey-light': track.is_playable === false }"
v-text="track.name"
/>
<h2
class="subtitle is-7"
:class="{
'has-text-grey': track.is_playable,
'has-text-grey-light': track.is_playable === false
}"
>
<b v-text="track.artists[0].name" /> <b v-text="track.artists[0].name" />
</h2> </h2>
<h2 v-if="track.is_playable === false" class="subtitle is-7"> <h2 v-if="track.is_playable === false" class="subtitle is-7">
(<span v-text="$t('list.spotify.not-playable-track')" /> (<span v-text="$t('list.spotify.not-playable-track')" />
<span v-if="track.restrictions && track.restrictions.reason" v-text="$t('list.spotify.restriction-reason', { reason: track.restrictions.reason })" />) <span
v-if="track.restrictions && track.restrictions.reason"
v-text="
$t('list.spotify.restriction-reason', {
reason: track.restrictions.reason
})
"
/>)
</h2> </h2>
</div> </div>
<div class="media-right"> <div class="media-right">

View File

@ -6,23 +6,51 @@
<div class="modal-content fd-modal-card"> <div class="modal-content fd-modal-card">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<figure v-show="artwork_visible" class="image is-square fd-has-margin-bottom"> <figure
<img :src="artwork_url" class="fd-has-shadow" @load="artwork_loaded" @error="artwork_error" /> v-show="artwork_visible"
class="image is-square fd-has-margin-bottom"
>
<img
:src="artwork_url"
class="fd-has-shadow"
@load="artwork_loaded"
@error="artwork_error"
/>
</figure> </figure>
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_album" v-text="album.name" /> <a
class="has-text-link"
@click="open_album"
v-text="album.name"
/>
</p> </p>
<div class="content is-small"> <div class="content is-small">
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.album.album-artist')" /> <span
<a class="title is-6 has-text-link" @click="open_artist" v-text="album.artists[0].name" /> class="heading"
v-text="$t('dialog.spotify.album.album-artist')"
/>
<a
class="title is-6 has-text-link"
@click="open_artist"
v-text="album.artists[0].name"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.album.release-date')" /> <span
<span class="title is-6" v-text="$filters.date(album.release_date)" /> class="heading"
v-text="$t('dialog.spotify.album.release-date')"
/>
<span
class="title is-6"
v-text="$filters.date(album.release_date)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.album.type')" /> <span
class="heading"
v-text="$t('dialog.spotify.album.type')"
/>
<span class="title is-6" v-text="album.album_type" /> <span class="title is-6" v-text="album.album_type" />
</p> </p>
</div> </div>
@ -30,20 +58,33 @@
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add"> <a class="card-footer-item has-text-dark" @click="queue_add">
<mdicon class="icon" name="playlist-plus" size="16" /> <mdicon class="icon" name="playlist-plus" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.album.add')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.album.add')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="queue_add_next"> <a class="card-footer-item has-text-dark" @click="queue_add_next">
<mdicon class="icon" name="playlist-play" size="16" /> <mdicon class="icon" name="playlist-play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.album.add-next')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.album.add-next')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.album.play')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.album.play')"
/>
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -7,15 +7,30 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_artist" v-text="artist.name" /> <a
class="has-text-link"
@click="open_artist"
v-text="artist.name"
/>
</p> </p>
<div class="content is-small"> <div class="content is-small">
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.artist.popularity')" /> <span
<span class="title is-6" v-text="[artist.popularity, artist.followers.total].join(' / ')" /> class="heading"
v-text="$t('dialog.spotify.artist.popularity')"
/>
<span
class="title is-6"
v-text="
[artist.popularity, artist.followers.total].join(' / ')
"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.artist.genres')" /> <span
class="heading"
v-text="$t('dialog.spotify.artist.genres')"
/>
<span class="title is-6" v-text="artist.genres.join(', ')" /> <span class="title is-6" v-text="artist.genres.join(', ')" />
</p> </p>
</div> </div>
@ -23,20 +38,33 @@
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add"> <a class="card-footer-item has-text-dark" @click="queue_add">
<mdicon class="icon" name="playlist-plus" size="16" /> <mdicon class="icon" name="playlist-plus" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.artist.add')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.artist.add')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="queue_add_next"> <a class="card-footer-item has-text-dark" @click="queue_add_next">
<mdicon class="icon" name="playlist-play" size="16" /> <mdicon class="icon" name="playlist-play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.artist.add-next')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.artist.add-next')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.artist.play')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.artist.play')"
/>
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -7,19 +7,35 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<p class="title is-4"> <p class="title is-4">
<a class="has-text-link" @click="open_playlist" v-text="playlist.name" /> <a
class="has-text-link"
@click="open_playlist"
v-text="playlist.name"
/>
</p> </p>
<div class="content is-small"> <div class="content is-small">
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.playlist.owner')" /> <span
<span class="title is-6" v-text="playlist.owner.display_name" /> class="heading"
v-text="$t('dialog.spotify.playlist.owner')"
/>
<span
class="title is-6"
v-text="playlist.owner.display_name"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.playlist.tracks')" /> <span
class="heading"
v-text="$t('dialog.spotify.playlist.tracks')"
/>
<span class="title is-6" v-text="playlist.tracks.total" /> <span class="title is-6" v-text="playlist.tracks.total" />
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.playlist.path')" /> <span
class="heading"
v-text="$t('dialog.spotify.playlist.path')"
/>
<span class="title is-6" v-text="playlist.uri" /> <span class="title is-6" v-text="playlist.uri" />
</p> </p>
</div> </div>
@ -27,20 +43,33 @@
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add"> <a class="card-footer-item has-text-dark" @click="queue_add">
<mdicon class="icon" name="playlist-plus" size="16" /> <mdicon class="icon" name="playlist-plus" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.playlist.add')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.playlist.add')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="queue_add_next"> <a class="card-footer-item has-text-dark" @click="queue_add_next">
<mdicon class="icon" name="playlist-play" size="16" /> <mdicon class="icon" name="playlist-play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.playlist.add-next')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.playlist.add-next')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.playlist.play')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.playlist.play')"
/>
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -10,27 +10,62 @@
<p class="subtitle" v-text="track.artists[0].name" /> <p class="subtitle" v-text="track.artists[0].name" />
<div class="content is-small"> <div class="content is-small">
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.track.album')" /> <span
<a class="title is-6 has-text-link" @click="open_album" v-text="album.name" /> class="heading"
v-text="$t('dialog.spotify.track.album')"
/>
<a
class="title is-6 has-text-link"
@click="open_album"
v-text="album.name"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.track.album-artist')" /> <span
<a class="title is-6 has-text-link" @click="open_artist" v-text="album.artists[0].name" /> class="heading"
v-text="$t('dialog.spotify.track.album-artist')"
/>
<a
class="title is-6 has-text-link"
@click="open_artist"
v-text="album.artists[0].name"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.track.release-date')" /> <span
<span class="title is-6" v-text="$filters.date(album.release_date)" /> class="heading"
v-text="$t('dialog.spotify.track.release-date')"
/>
<span
class="title is-6"
v-text="$filters.date(album.release_date)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.track.position')" /> <span
<span class="title is-6" v-text="[ track.disc_number, track.track_number ].join(' / ')" /> class="heading"
v-text="$t('dialog.spotify.track.position')"
/>
<span
class="title is-6"
v-text="[track.disc_number, track.track_number].join(' / ')"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.track.duration')" /> <span
<span class="title is-6" v-text="$filters.durationInHours(track.duration_ms)" /> class="heading"
v-text="$t('dialog.spotify.track.duration')"
/>
<span
class="title is-6"
v-text="$filters.durationInHours(track.duration_ms)"
/>
</p> </p>
<p> <p>
<span class="heading" v-text="$t('dialog.spotify.track.path')" /> <span
class="heading"
v-text="$t('dialog.spotify.track.path')"
/>
<span class="title is-6" v-text="track.uri" /> <span class="title is-6" v-text="track.uri" />
</p> </p>
</div> </div>
@ -38,20 +73,33 @@
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item has-text-dark" @click="queue_add"> <a class="card-footer-item has-text-dark" @click="queue_add">
<mdicon class="icon" name="playlist-plus" size="16" /> <mdicon class="icon" name="playlist-plus" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.track.add')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.track.add')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="queue_add_next"> <a class="card-footer-item has-text-dark" @click="queue_add_next">
<mdicon class="icon" name="playlist-play" size="16" /> <mdicon class="icon" name="playlist-play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.track.add-next')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.track.add-next')"
/>
</a> </a>
<a class="card-footer-item has-text-dark" @click="play"> <a class="card-footer-item has-text-dark" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
<span class="is-size-7" v-text="$t('dialog.spotify.track.play')" /> <span
class="is-size-7"
v-text="$t('dialog.spotify.track.play')"
/>
</a> </a>
</footer> </footer>
</div> </div>
</div> </div>
<button class="modal-close is-large" aria-label="close" @click="$emit('close')" /> <button
class="modal-close is-large"
aria-label="close"
@click="$emit('close')"
/>
</div> </div>
</transition> </transition>
</div> </div>

View File

@ -5,15 +5,27 @@
<div class="column is-four-fifths"> <div class="column is-four-fifths">
<div class="tabs is-centered is-small"> <div class="tabs is-centered is-small">
<ul> <ul>
<router-link v-slot="{ navigate, isActive }" to="/audiobooks/artists" custom> <router-link
v-slot="{ navigate, isActive }"
to="/audiobooks/artists"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="account-music" size="16" /> <mdicon
class="icon is-small"
name="account-music"
size="16"
/>
<span v-text="$t('tabs.audiobooks.authors')" /> <span v-text="$t('tabs.audiobooks.authors')" />
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/audiobooks/albums" custom> <router-link
v-slot="{ navigate, isActive }"
to="/audiobooks/albums"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="album" size="16" /> <mdicon class="icon is-small" name="album" size="16" />

View File

@ -5,7 +5,11 @@
<div class="column is-four-fifths"> <div class="column is-four-fifths">
<div class="tabs is-centered is-small"> <div class="tabs is-centered is-small">
<ul> <ul>
<router-link v-slot="{ navigate, isActive }" to="/music/browse" custom> <router-link
v-slot="{ navigate, isActive }"
to="/music/browse"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="web" size="16" /> <mdicon class="icon is-small" name="web" size="16" />
@ -13,15 +17,27 @@
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/music/artists" custom> <router-link
v-slot="{ navigate, isActive }"
to="/music/artists"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="account-music" size="16" /> <mdicon
class="icon is-small"
name="account-music"
size="16"
/>
<span v-text="$t('page.settings.tabs.music.artists')" /> <span v-text="$t('page.settings.tabs.music.artists')" />
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/music/albums" custom> <router-link
v-slot="{ navigate, isActive }"
to="/music/albums"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="album" size="16" /> <mdicon class="icon is-small" name="album" size="16" />
@ -29,7 +45,11 @@
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/music/genres" custom> <router-link
v-slot="{ navigate, isActive }"
to="/music/genres"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="speaker" size="16" /> <mdicon class="icon is-small" name="speaker" size="16" />
@ -37,15 +57,28 @@
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/music/composers" custom> <router-link
v-slot="{ navigate, isActive }"
to="/music/composers"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="book-open-page-variant" size="16" /> <mdicon
class="icon is-small"
name="book-open-page-variant"
size="16"
/>
<span v-text="$t('page.settings.tabs.music.composers')" /> <span v-text="$t('page.settings.tabs.music.composers')" />
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-if="spotify_enabled" v-slot="{ navigate, isActive }" to="/music/spotify" custom> <router-link
v-if="spotify_enabled"
v-slot="{ navigate, isActive }"
to="/music/spotify"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<mdicon class="icon is-small" name="spotify" size="16" /> <mdicon class="icon is-small" name="spotify" size="16" />

View File

@ -5,13 +5,21 @@
<div class="column is-four-fifths"> <div class="column is-four-fifths">
<div class="tabs is-centered is-small is-toggle is-toggle-rounded"> <div class="tabs is-centered is-small is-toggle is-toggle-rounded">
<ul> <ul>
<li :class="{ 'is-active': $store.state.search_path === '/search/library' }"> <li
:class="{
'is-active': $store.state.search_path === '/search/library'
}"
>
<a @click="search_library"> <a @click="search_library">
<mdicon class="icon is-small" name="bookshelf" size="16" /> <mdicon class="icon is-small" name="bookshelf" size="16" />
<span v-text="$t('tabs.search.library')" /> <span v-text="$t('tabs.search.library')" />
</a> </a>
</li> </li>
<li :class="{ 'is-active': $store.state.search_path === '/search/spotify' }"> <li
:class="{
'is-active': $store.state.search_path === '/search/spotify'
}"
>
<a @click="search_spotify"> <a @click="search_spotify">
<mdicon class="icon is-small" name="spotify" size="16" /> <mdicon class="icon is-small" name="spotify" size="16" />
<span v-text="$t('tabs.search.spotify')" /> <span v-text="$t('tabs.search.spotify')" />

View File

@ -5,31 +5,53 @@
<div class="column is-four-fifths"> <div class="column is-four-fifths">
<div class="tabs is-centered is-small"> <div class="tabs is-centered is-small">
<ul> <ul>
<router-link v-slot="{ navigate, isActive }" to="/settings/webinterface" custom> <router-link
v-slot="{ navigate, isActive }"
to="/settings/webinterface"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<span v-text="$t('page.settings.tabs.settings.general')" /> <span v-text="$t('page.settings.tabs.settings.general')" />
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/settings/remotes-outputs" custom> <router-link
v-slot="{ navigate, isActive }"
to="/settings/remotes-outputs"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<span v-text="$t('page.settings.tabs.settings.remotes-and-outputs')" /> <span
v-text="
$t('page.settings.tabs.settings.remotes-and-outputs')
"
/>
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/settings/artwork" custom> <router-link
v-slot="{ navigate, isActive }"
to="/settings/artwork"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<span v-text="$t('page.settings.tabs.settings.artwork')" /> <span v-text="$t('page.settings.tabs.settings.artwork')" />
</a> </a>
</li> </li>
</router-link> </router-link>
<router-link v-slot="{ navigate, isActive }" to="/settings/online-services" custom> <router-link
v-slot="{ navigate, isActive }"
to="/settings/online-services"
custom
>
<li :class="{ 'is-active': isActive }"> <li :class="{ 'is-active': isActive }">
<a @click="navigate" @keypress.enter="navigate"> <a @click="navigate" @keypress.enter="navigate">
<span v-text="$t('page.settings.tabs.settings.online-services')" /> <span
v-text="$t('page.settings.tabs.settings.online-services')"
/>
</a> </a>
</li> </li>
</router-link> </router-link>

View File

@ -5,6 +5,7 @@ import {
mdiBookOpenPageVariant, mdiBookOpenPageVariant,
mdiBookOpenVariant, mdiBookOpenVariant,
mdiBookshelf, mdiBookshelf,
mdiBroadcast,
mdiCancel, mdiCancel,
mdiCast, mdiCast,
mdiCastVariant, mdiCastVariant,
@ -24,19 +25,18 @@ import {
mdiFire, mdiFire,
mdiFolder, mdiFolder,
mdiFolderOpen, mdiFolderOpen,
mdiOpenInNew,
mdiMagnify, mdiMagnify,
mdiMenu, mdiMenu,
mdiPodcast,
mdiMusic, mdiMusic,
mdiMusicBoxMultiple, mdiMusicBoxMultiple,
mdiOpenInNew,
mdiPause, mdiPause,
mdiPencil, mdiPencil,
mdiPipe, mdiPipe,
mdiPlay, mdiPlay,
mdiPlaylistPlay, mdiPlaylistPlay,
mdiPlaylistPlus, mdiPlaylistPlus,
mdiBroadcast, mdiPodcast,
mdiRadioTower, mdiRadioTower,
mdiRefresh, mdiRefresh,
mdiRepeat, mdiRepeat,
@ -65,6 +65,7 @@ export const icons = {
mdiBookOpenPageVariant, mdiBookOpenPageVariant,
mdiBookOpenVariant, mdiBookOpenVariant,
mdiBookshelf, mdiBookshelf,
mdiBroadcast,
mdiCancel, mdiCancel,
mdiCast, mdiCast,
mdiCastVariant, mdiCastVariant,
@ -84,19 +85,18 @@ export const icons = {
mdiFire, mdiFire,
mdiFolder, mdiFolder,
mdiFolderOpen, mdiFolderOpen,
mdiOpenInNew,
mdiMagnify, mdiMagnify,
mdiMenu, mdiMenu,
mdiPodcast,
mdiMusic, mdiMusic,
mdiMusicBoxMultiple, mdiMusicBoxMultiple,
mdiOpenInNew,
mdiPause, mdiPause,
mdiPencil, mdiPencil,
mdiPipe, mdiPipe,
mdiPlay, mdiPlay,
mdiPlaylistPlay, mdiPlaylistPlay,
mdiPlaylistPlus, mdiPlaylistPlus,
mdiBroadcast, mdiPodcast,
mdiRadioTower, mdiRadioTower,
mdiRefresh, mdiRefresh,
mdiRepeat, mdiRepeat,

View File

@ -191,7 +191,7 @@
"list": { "list": {
"albums": { "albums": {
"info-1": "Permanently remove this podcast from your library?", "info-1": "Permanently remove this podcast from your library?",
"info-2": "(This will also remove the RSS playlist <b>{name}</b>).", "info-2": "This will also remove the RSS playlist ",
"notification": "Podcast cannot be removed. Probably it was not added as an RSS playlist." "notification": "Podcast cannot be removed. Probably it was not added as an RSS playlist."
}, },
"spotify": { "spotify": {
@ -201,10 +201,10 @@
}, },
"media": { "media": {
"kind": { "kind": {
"album":"Album", "album": "Album",
"audiobook": "Audiobook", "audiobook": "Audiobook",
"music":"Music", "music": "Music",
"podcast":"Podcast" "podcast": "Podcast"
} }
}, },
"navigation": { "navigation": {
@ -241,7 +241,7 @@
"updated-on": "{time} ago", "updated-on": "{time} ago",
"updated": "Updated", "updated": "Updated",
"uptime": "Uptime", "uptime": "Uptime",
"version": "<b>OwnTone</b> - version {version}" "version": "Version {version}"
}, },
"album": { "album": {
"shuffle": "Shuffle", "shuffle": "Shuffle",
@ -279,7 +279,7 @@
"title": "Sort by", "title": "Sort by",
"name": "Name", "name": "Name",
"recently-added": "Rencently added" "recently-added": "Rencently added"
} , },
"hide-singles-help": "If active, hides artists that only appear on singles or playlists.", "hide-singles-help": "If active, hides artists that only appear on singles or playlists.",
"hide-singles": "Hide singles", "hide-singles": "Hide singles",
"hide-spotify-help": "If active, hides artists that only appear in your Spotify library.", "hide-spotify-help": "If active, hides artists that only appear in your Spotify library.",
@ -421,7 +421,7 @@
}, },
"devices": { "devices": {
"no-active-pairing": "No active pairing request.", "no-active-pairing": "No active pairing request.",
"pairing-request": "Remote pairing request from <b>{remote}</b>", "pairing-request": "Remote pairing request from ",
"pairing": "Remote Pairing", "pairing": "Remote Pairing",
"send": "Send", "send": "Send",
"speaker-pairing-info": "If your speaker requires pairing then activate it below and enter the PIN that it displays.", "speaker-pairing-info": "If your speaker requires pairing then activate it below and enter the PIN that it displays.",
@ -545,5 +545,10 @@
"queue-saved": "Queue saved to playlist {name}", "queue-saved": "Queue saved to playlist {name}",
"appended-tracks": "{count} tracks appended to the queue", "appended-tracks": "{count} tracks appended to the queue",
"empty-queue": "Queue is empty" "empty-queue": "Queue is empty"
},
"group-by-list": {
"today": "Today",
"last-week": "Last week",
"last-month": "Last month"
} }
} }

View File

@ -14,7 +14,7 @@
"add": "Ajouter", "add": "Ajouter",
"cancel": "Annuler", "cancel": "Annuler",
"help": "Lajout dun podcast inclut la création dune liste de lecture RSS, qui permettra à OwnTone de gérer labonnement au podcast.", "help": "Lajout dun podcast inclut la création dune liste de lecture RSS, qui permettra à OwnTone de gérer labonnement au podcast.",
"placeholder": "https://url-vers-le-flux-rss", "placeholder": "https://url-du-flux-rss",
"processing": "Traitement en cours…", "processing": "Traitement en cours…",
"title": "Ajouter lURL du flux RSS du podcast" "title": "Ajouter lURL du flux RSS du podcast"
}, },
@ -22,7 +22,7 @@
"add": "Ajouter", "add": "Ajouter",
"cancel": "Annuler", "cancel": "Annuler",
"loading": "Chargement…", "loading": "Chargement…",
"placeholder": "https://url-to-stream", "placeholder": "https://url-du-flux",
"play": "Lire", "play": "Lire",
"title": "Ajouter lURL du flux" "title": "Ajouter lURL du flux"
} }
@ -33,7 +33,7 @@
"added-on": "Ajouté le", "added-on": "Ajouté le",
"artiste": "Album artist", "artiste": "Album artist",
"duration": "Durée", "duration": "Durée",
"mark-as-played": "Mark as played", "mark-as-played": "Marquer comme lu",
"play": "Lire", "play": "Lire",
"release-date": "Date de sortie", "release-date": "Date de sortie",
"remove-podcast": "Supprimer le podcast", "remove-podcast": "Supprimer le podcast",
@ -106,7 +106,7 @@
"remote-pairing": { "remote-pairing": {
"cancel": "Annuler", "cancel": "Annuler",
"pair": "Jumeler la télécommande", "pair": "Jumeler la télécommande",
"title": "Demande de jumelage de la télécommande" "title": "Demande de jumelage de télécommande"
}, },
"spotify": { "spotify": {
"album": { "album": {
@ -192,11 +192,11 @@
"albums": { "albums": {
"info-1": "Supprimer définitivement ce podcast de votre bibliothèque ?", "info-1": "Supprimer définitivement ce podcast de votre bibliothèque ?",
"info-2": "Cela supprimera également la liste de lecture RSS ", "info-2": "Cela supprimera également la liste de lecture RSS ",
"notification": "Le podcast ne peut être supprimé. Il navait probablement pas été ajouté comme une liste de lecture RSS.", "notification": "Le podcast ne peut être supprimé. Il navait probablement pas été ajouté comme une liste de lecture RSS."
}, },
"spotify": { "spotify": {
"not-playable-track": "La piste ne peut pas être lue", "not-playable-track": "La piste ne peut pas être lue",
"restriction-reason": ", raison de la restriction : {reason}", "restriction-reason": ", raison de la restriction : {reason}"
} }
}, },
"media": { "media": {
@ -241,7 +241,7 @@
"updated-on": "il y a {time}", "updated-on": "il y a {time}",
"updated": "Mis à jour", "updated": "Mis à jour",
"uptime": "Temps de fonctionnement", "uptime": "Temps de fonctionnement",
"version": "<b>OwnTone</b> - version {version}" "name": "Version {version}"
}, },
"album": { "album": {
"shuffle": "Lecture aléatoire", "shuffle": "Lecture aléatoire",
@ -279,7 +279,7 @@
"title": "Trier par", "title": "Trier par",
"name": "Nom", "name": "Nom",
"recently-added": "Ajouts récents" "recently-added": "Ajouts récents"
} , },
"hide-singles-help": "Si actif, masque les artistes qui napparaissent que dans des singles ou des listes de lecture.", "hide-singles-help": "Si actif, masque les artistes qui napparaissent que dans des singles ou des listes de lecture.",
"hide-singles": "Masquer les singles", "hide-singles": "Masquer les singles",
"hide-spotify-help": "Si actif, masque les artistes qui napparaissent que dans votre bibliothèque Spotify.", "hide-spotify-help": "Si actif, masque les artistes qui napparaissent que dans votre bibliothèque Spotify.",
@ -363,7 +363,7 @@
"play": "Lire", "play": "Lire",
"remove-error": "Le podcast ne peut pas être supprimé. Il na probablement pas été ajouté en tant que liste de lecture RSS.", "remove-error": "Le podcast ne peut pas être supprimé. Il na probablement pas été ajouté en tant que liste de lecture RSS.",
"remove-info-1": "Supprimer ce podcast de manière permanente de la bibliothèque ?", "remove-info-1": "Supprimer ce podcast de manière permanente de la bibliothèque ?",
"remove-info-2": "(Cela supprimera également la liste de lecture RSS <b>{name}</b>).", "remove-info-2": "Cela supprimera également la liste de lecture RSS ",
"track-count": "{count} pistes" "track-count": "{count} pistes"
}, },
"podcasts": { "podcasts": {
@ -421,11 +421,11 @@
}, },
"devices": { "devices": {
"no-active-pairing": "Aucune demande de jumelage active.", "no-active-pairing": "Aucune demande de jumelage active.",
"pairing-request": "Demande de jumelage de la télécommande <b>{remote}</b>", "pairing-request": "Demande de jumelage de télécommande ",
"pairing": "Jumelage de la télécommande", "pairing": "Jumelage de télécommande",
"send": "Envoyer", "send": "Envoyer",
"speaker-pairing-info": "Si votre enceinte nécessite un jumelage, activez-le ci-dessous et entrez le code PIN quil affiche.", "speaker-pairing-info": "Si votre enceinte nécessite un jumelage, activez-la ci-dessous et entrez le code PIN quelle affiche.",
"speaker-pairing": "Jumelage de lenceinte et vérification de lappareil", "speaker-pairing": "Jumelage denceinte et vérification dappareil",
"verification-code": "Code de vérification", "verification-code": "Code de vérification",
"verify": "Vérifier" "verify": "Vérifier"
}, },
@ -451,7 +451,7 @@
"show-composer-genres": "Afficher le compositeur uniquement pour les genres listés", "show-composer-genres": "Afficher le compositeur uniquement pour les genres listés",
"show-composer-info": "Si actif, le compositeur de la piste en cours de lecture est affiché sur la page \"lecture en cours\"", "show-composer-info": "Si actif, le compositeur de la piste en cours de lecture est affiché sur la page \"lecture en cours\"",
"show-composer": "Afficher le compositeur", "show-composer": "Afficher le compositeur",
"show-coverart": "Afficher les illustration dans la liste dalbums", "show-coverart": "Afficher les illustration dans la liste dalbums"
}, },
"services": { "services": {
"lastfm": { "lastfm": {
@ -536,7 +536,7 @@
}, },
"setting": { "setting": {
"not-saved": " (erreur à lenregistrement du réglage)", "not-saved": " (erreur à lenregistrement du réglage)",
"saved": " (réglage enregistré)", "saved": " (réglage enregistré)"
}, },
"server": { "server": {
"connection-failed": "Échec de connexion au serveur", "connection-failed": "Échec de connexion au serveur",
@ -545,5 +545,10 @@
"queue-saved": "La file dattente enregistrée dans la liste de lecture {name}", "queue-saved": "La file dattente enregistrée dans la liste de lecture {name}",
"appended-tracks": "{count} pistes ajoutées à la file dattente", "appended-tracks": "{count} pistes ajoutées à la file dattente",
"empty-queue": "La file dattente est vide" "empty-queue": "La file dattente est vide"
},
"group-by-list": {
"today": "Aujourdhui",
"last-week": "La semaine dernière",
"last-month": "Le mois dernier"
} }
} }

View File

@ -4,7 +4,6 @@
<div class="container"> <div class="container">
<div class="columns is-centered"> <div class="columns is-centered">
<div class="column is-four-fifths has-text-centered-mobile"> <div class="column is-four-fifths has-text-centered-mobile">
<p class="heading" v-html="$t('page.about.version', {version: config.version})" />
<h1 class="title is-4" v-text="config.library_name" /> <h1 class="title is-4" v-text="config.library_name" />
</div> </div>
</div> </div>
@ -25,43 +24,78 @@
<!-- Right side --> <!-- Right side -->
<div class="level-right"> <div class="level-right">
<div v-if="library.updating"> <div v-if="library.updating">
<a class="button is-small is-loading" v-text="$t('page.about.update')" /> <a
class="button is-small is-loading"
v-text="$t('page.about.update')"
/>
</div> </div>
<div v-else> <div v-else>
<a class="button is-small" @click="showUpdateDialog()" v-text="$t('page.about.update')" /> <a
class="button is-small"
@click="showUpdateDialog()"
v-text="$t('page.about.update')"
/>
</div> </div>
</div> </div>
</nav> </nav>
<table class="table"> <table class="table">
<tbody> <tbody>
<tr> <tr>
<th v-text="$t('page.about.artists')" /> <th class="has-text-left" v-text="$t('page.about.artists')" />
<td class="has-text-right" v-text="$filters.number(library.artists)" /> <td
class="has-text-right"
v-text="$filters.number(library.artists)"
/>
</tr> </tr>
<tr> <tr>
<th v-text="$t('page.about.albums')" /> <th class="has-text-left" v-text="$t('page.about.albums')" />
<td class="has-text-right" v-text="$filters.number(library.albums)" /> <td
class="has-text-right"
v-text="$filters.number(library.albums)"
/>
</tr> </tr>
<tr> <tr>
<th v-text="$t('page.about.tracks')" /> <th class="has-text-left" v-text="$t('page.about.tracks')" />
<td class="has-text-right" v-text="$filters.number(library.songs)" /> <td
class="has-text-right"
v-text="$filters.number(library.songs)"
/>
</tr> </tr>
<tr> <tr>
<th v-text="$t('page.about.total-playtime')" /> <th class="has-text-left" v-text="$t('page.about.total-playtime')" />
<td class="has-text-right" v-text="$filters.durationInDays(library.db_playtime * 1000)" /> <td
class="has-text-right"
v-text="
$filters.durationInDays(library.db_playtime * 1000)
"
/>
</tr> </tr>
<tr> <tr>
<th v-text="$t('page.about.updated')" /> <th class="has-text-left" v-text="$t('page.about.updated')" />
<td class="has-text-right"> <td class="has-text-right">
<span v-text="$t('page.about.updated-on', { time: $filters.timeFromNow(library.updated_at) })" /> <span
(<span class="has-text-grey" v-text="$filters.datetime(library.updated_at)" />) v-text="
$t('page.about.updated-on', {
time: $filters.timeFromNow(library.updated_at)
})
"
/>
(<span
class="has-text-grey"
v-text="$filters.datetime(library.updated_at)"
/>)
</td> </td>
</tr> </tr>
<tr> <tr>
<th v-text="$t('page.about.uptime')" /> <th class="has-text-left" v-text="$t('page.about.uptime')" />
<td class="has-text-right"> <td class="has-text-right">
<span v-text="$filters.timeFromNow(library.started_at, true)" /> <span
(<span class="has-text-grey" v-text="$filters.datetime(library.started_at)" />) v-text="$filters.timeFromNow(library.started_at, true)"
/>
(<span
class="has-text-grey"
v-text="$filters.datetime(library.started_at)"
/>)
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -76,7 +110,15 @@
<div class="columns is-centered"> <div class="columns is-centered">
<div class="column is-four-fifths"> <div class="column is-four-fifths">
<div class="content has-text-centered-mobile"> <div class="content has-text-centered-mobile">
<p class="is-size-7" v-text="$t('page.about.compiled-with', { options: config.buildoptions.join(', ') })" /> <p class="is-size-7" v-text="$t('page.about.version', { version: config.version })" />
<p
class="is-size-7"
v-text="
$t('page.about.compiled-with', {
options: config.buildoptions.join(', ')
})
"
/>
<p class="is-size-7" v-html="$t('page.about.built-with')" /> <p class="is-size-7" v-html="$t('page.about.built-with')" />
</div> </div>
</div> </div>

View File

@ -10,20 +10,35 @@
<mdicon class="icon" name="shuffle" size="16" /> <mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.album.shuffle')" /> <span v-text="$t('page.album.shuffle')" />
</a> </a>
<a class="button is-small is-light is-rounded" @click="show_album_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_album_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
</div> </div>
</template> </template>
<template #heading-right> <template #heading-right>
<p class="image is-square fd-has-shadow fd-has-action"> <p class="image is-square fd-has-shadow fd-has-action">
<cover-artwork :artwork_url="album.artwork_url" :artist="album.artist" :album="album.name" @click="show_album_details_modal = true" /> <cover-artwork
:artwork_url="album.artwork_url"
:artist="album.artist"
:album="album.name"
@click="show_album_details_modal = true"
/>
</p> </p>
</template> </template>
<template #content> <template #content>
<p class="heading is-7 has-text-centered-mobile fd-has-margin-top" v-text="$t('page.album.track-count', {count: album.track_count})" /> <p
class="heading is-7 has-text-centered-mobile fd-has-margin-top"
v-text="$t('page.album.track-count', { count: album.track_count })"
/>
<list-tracks :tracks="tracks" :uris="album.uri" /> <list-tracks :tracks="tracks" :uris="album.uri" />
<modal-dialog-album :show="show_album_details_modal" :album="album" @close="show_album_details_modal = false" /> <modal-dialog-album
:show="show_album_details_modal"
:album="album"
@close="show_album_details_modal = false"
/>
</template> </template>
</content-with-hero> </content-with-hero>
</template> </template>

View File

@ -6,31 +6,63 @@
<index-button-list :index="albums.indexList" /> <index-button-list :index="albums.indexList" />
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
<p class="heading" style="margin-bottom: 24px" v-text="$t('page.albums.filter')" /> <p
class="heading"
style="margin-bottom: 24px"
v-text="$t('page.albums.filter')"
/>
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<input id="switchHideSingles" v-model="hide_singles" type="checkbox" name="switchHideSingles" class="switch" /> <input
<label for="switchHideSingles" v-text="$t('page.albums.hide-singles')" /> id="switchHideSingles"
v-model="hide_singles"
type="checkbox"
name="switchHideSingles"
class="switch"
/>
<label
for="switchHideSingles"
v-text="$t('page.albums.hide-singles')"
/>
</div> </div>
<p class="help" v-text="$t('page.albums.hide-singles-help')" /> <p class="help" v-text="$t('page.albums.hide-singles-help')" />
</div> </div>
<div v-if="spotify_enabled" class="field"> <div v-if="spotify_enabled" class="field">
<div class="control"> <div class="control">
<input id="switchHideSpotify" v-model="hide_spotify" type="checkbox" name="switchHideSpotify" class="switch" /> <input
<label for="switchHideSpotify" v-text="$t('page.albums.hide-spotify')" /> id="switchHideSpotify"
v-model="hide_spotify"
type="checkbox"
name="switchHideSpotify"
class="switch"
/>
<label
for="switchHideSpotify"
v-text="$t('page.albums.hide-spotify')"
/>
</div> </div>
<p class="help" v-text="$t('page.albums.hide-spotify-help')" /> <p class="help" v-text="$t('page.albums.hide-spotify-help')" />
</div> </div>
</div> </div>
<div class="column"> <div class="column">
<p class="heading" style="margin-bottom: 24px" v-text="$t('page.albums.sort-by.title')" /> <p
<dropdown-menu v-model="selected_groupby_option_id" :options="groupby_options" /> class="heading"
style="margin-bottom: 24px"
v-text="$t('page.albums.sort-by.title')"
/>
<dropdown-menu
v-model="selected_groupby_option_id"
:options="groupby_options"
/>
</div> </div>
</div> </div>
</template> </template>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.albums.title')" /> <p class="title is-4" v-text="$t('page.albums.title')" />
<p class="heading" v-text="$t('page.albums.count', { count: albums.count })" /> <p
class="heading"
v-text="$t('page.albums.count', { count: albums.count })"
/>
</template> </template>
<template #heading-right /> <template #heading-right />
<template #content> <template #content>

View File

@ -3,17 +3,27 @@
<template #options> <template #options>
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
<p class="heading" style="margin-bottom: 24px" v-text="$t('page.artist.sort-by.title')" /> <p
<dropdown-menu v-model="selected_groupby_option_id" :options="groupby_options"/> class="heading"
style="margin-bottom: 24px"
v-text="$t('page.artist.sort-by.title')"
/>
<dropdown-menu
v-model="selected_groupby_option_id"
:options="groupby_options"
/>
</div> </div>
</div> </div>
</template> </template>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="artist.name" /> <p class="title is-4" v-text="artist.name" />
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_artist_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_artist_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -24,11 +34,21 @@
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile"> <p class="heading has-text-centered-mobile">
<span v-text="$t('page.artist.album-count', { count: artist.album_count })" /> <span
<a class="has-text-link" @click="open_tracks" v-text="$t('page.artist.track-count', { count: artist.track_count })" /> v-text="$t('page.artist.album-count', { count: artist.album_count })"
/>
<a
class="has-text-link"
@click="open_tracks"
v-text="$t('page.artist.track-count', { count: artist.track_count })"
/>
</p> </p>
<list-albums :albums="albums" :hide_group_title="true" /> <list-albums :albums="albums" :hide_group_title="true" />
<modal-dialog-artist :show="show_artist_details_modal" :artist="artist" @close="show_artist_details_modal = false" /> <modal-dialog-artist
:show="show_artist_details_modal"
:artist="artist"
@close="show_artist_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>

View File

@ -9,7 +9,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_artist_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_artist_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -20,10 +23,23 @@
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile"> <p class="heading has-text-centered-mobile">
<a class="has-text-link" @click="open_artist" v-text="$t('page.artist.track-count', { albums: artist.album_count, tracks: artist.track_count})" /> <a
class="has-text-link"
@click="open_artist"
v-text="
$t('page.artist.track-count', {
albums: artist.album_count,
tracks: artist.track_count
})
"
/>
</p> </p>
<list-tracks :tracks="tracks.items" :uris="track_uris" /> <list-tracks :tracks="tracks.items" :uris="track_uris" />
<modal-dialog-artist :show="show_artist_details_modal" :artist="artist" @close="show_artist_details_modal = false" /> <modal-dialog-artist
:show="show_artist_details_modal"
:artist="artist"
@close="show_artist_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -6,31 +6,63 @@
<index-button-list :index="artists.indexList" /> <index-button-list :index="artists.indexList" />
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
<p class="heading" style="margin-bottom: 24px" v-text="$t('page.artists.filter')" /> <p
class="heading"
style="margin-bottom: 24px"
v-text="$t('page.artists.filter')"
/>
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<input id="switchHideSingles" v-model="hide_singles" type="checkbox" name="switchHideSingles" class="switch" /> <input
<label for="switchHideSingles" v-text="$t('page.artists.hide-singles')" /> id="switchHideSingles"
v-model="hide_singles"
type="checkbox"
name="switchHideSingles"
class="switch"
/>
<label
for="switchHideSingles"
v-text="$t('page.artists.hide-singles')"
/>
</div> </div>
<p class="help" v-text="$t('page.artists.hide-singles-help')" /> <p class="help" v-text="$t('page.artists.hide-singles-help')" />
</div> </div>
<div v-if="spotify_enabled" class="field"> <div v-if="spotify_enabled" class="field">
<div class="control"> <div class="control">
<input id="switchHideSpotify" v-model="hide_spotify" type="checkbox" name="switchHideSpotify" class="switch" /> <input
<label for="switchHideSpotify" v-text="$t('page.artists.hide-spotify')" /> id="switchHideSpotify"
v-model="hide_spotify"
type="checkbox"
name="switchHideSpotify"
class="switch"
/>
<label
for="switchHideSpotify"
v-text="$t('page.artists.hide-spotify')"
/>
</div> </div>
<p class="help" v-text="$t('page.artists.hide-spotify-help')" /> <p class="help" v-text="$t('page.artists.hide-spotify-help')" />
</div> </div>
</div> </div>
<div class="column"> <div class="column">
<p class="heading" style="margin-bottom: 24px" v-text="$t('page.artists.sort-by.title')" /> <p
<dropdown-menu v-model="selected_groupby_option_id" :options="groupby_options" /> class="heading"
style="margin-bottom: 24px"
v-text="$t('page.artists.sort-by.title')"
/>
<dropdown-menu
v-model="selected_groupby_option_id"
:options="groupby_options"
/>
</div> </div>
</div> </div>
</template> </template>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.artists.title')" /> <p class="title is-4" v-text="$t('page.artists.title')" />
<p class="heading" v-text="$t('page.artists.count', { count: artists.count })" /> <p
class="heading"
v-text="$t('page.artists.count', { count: artists.count })"
/>
</template> </template>
<template #heading-right /> <template #heading-right />
<template #content> <template #content>

View File

@ -10,20 +10,38 @@
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
<span v-text="$t('page.audiobooks.album.play')" /> <span v-text="$t('page.audiobooks.album.play')" />
</a> </a>
<a class="button is-small is-light is-rounded" @click="show_album_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_album_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
</div> </div>
</template> </template>
<template #heading-right> <template #heading-right>
<p class="image is-square fd-has-shadow fd-has-action"> <p class="image is-square fd-has-shadow fd-has-action">
<cover-artwork :artwork_url="album.artwork_url" :artist="album.artist" :album="album.name" @click="show_album_details_modal = true" /> <cover-artwork
:artwork_url="album.artwork_url"
:artist="album.artist"
:album="album.name"
@click="show_album_details_modal = true"
/>
</p> </p>
</template> </template>
<template #content> <template #content>
<p class="heading is-7 has-text-centered-mobile fd-has-margin-top" v-text="$t('page.audiobooks.album.track-count', { count: album.track_count })" /> <p
class="heading is-7 has-text-centered-mobile fd-has-margin-top"
v-text="
$t('page.audiobooks.album.track-count', { count: album.track_count })
"
/>
<list-tracks :tracks="tracks" :uris="album.uri" /> <list-tracks :tracks="tracks" :uris="album.uri" />
<modal-dialog-album :show="show_album_details_modal" :album="album" :media_kind="'audiobook'" @close="show_album_details_modal = false" /> <modal-dialog-album
:show="show_album_details_modal"
:album="album"
:media_kind="'audiobook'"
@close="show_album_details_modal = false"
/>
</template> </template>
</content-with-hero> </content-with-hero>
</template> </template>

View File

@ -7,7 +7,10 @@
</template> </template>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.audiobooks.albums.title')" /> <p class="title is-4" v-text="$t('page.audiobooks.albums.title')" />
<p class="heading" v-text="$t('page.audiobooks.albums.count', { count: albums.count })" /> <p
class="heading"
v-text="$t('page.audiobooks.albums.count', { count: albums.count })"
/>
</template> </template>
<template #content> <template #content>
<list-albums :albums="albums" /> <list-albums :albums="albums" />

View File

@ -5,7 +5,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_artist_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_artist_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -15,9 +18,20 @@
</div> </div>
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile" v-text="$t('page.audiobooks.artist.album-count', { count: artist.album_count })" /> <p
class="heading has-text-centered-mobile"
v-text="
$t('page.audiobooks.artist.album-count', {
count: artist.album_count
})
"
/>
<list-albums :albums="albums" /> <list-albums :albums="albums" />
<modal-dialog-artist :show="show_artist_details_modal" :artist="artist" @close="show_artist_details_modal = false" /> <modal-dialog-artist
:show="show_artist_details_modal"
:artist="artist"
@close="show_artist_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>

View File

@ -7,7 +7,10 @@
</template> </template>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.audiobooks.artists.title')" /> <p class="title is-4" v-text="$t('page.audiobooks.artists.title')" />
<p class="heading" v-text="$t('page.audiobooks.artists.count', { count: tists.count })" /> <p
class="heading"
v-text="$t('page.audiobooks.artists.count', { count: tists.count })"
/>
</template> </template>
<template #heading-right /> <template #heading-right />
<template #content> <template #content>

View File

@ -5,7 +5,7 @@
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.browse.recently-added.title')" /> <p class="title is-4" v-text="$t('page.browse.recently-added.title')" />
<p class="heading" v-text="$t('page.browse.albums')"/> <p class="heading" v-text="$t('page.browse.albums')" />
</template> </template>
<template #content> <template #content>
<list-albums :albums="recently_added" /> <list-albums :albums="recently_added" />
@ -13,7 +13,11 @@
<template #footer> <template #footer>
<nav class="level"> <nav class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_browse('recently_added')" v-text="$t('page.browse.show-more')" /> <a
class="button is-light is-small is-rounded"
@click="open_browse('recently_added')"
v-text="$t('page.browse.show-more')"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -21,7 +25,10 @@
<!-- Recently played --> <!-- Recently played -->
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.browse.recently-played.title')" /> <p
class="title is-4"
v-text="$t('page.browse.recently-played.title')"
/>
<p class="heading" v-text="$t('page.browse.tracks')" /> <p class="heading" v-text="$t('page.browse.tracks')" />
</template> </template>
<template #content> <template #content>
@ -30,7 +37,11 @@
<template #footer> <template #footer>
<nav class="level"> <nav class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_browse('recently_played')" v-text="$t('page.browse.show-more')" /> <a
class="button is-light is-small is-rounded"
@click="open_browse('recently_played')"
v-text="$t('page.browse.show-more')"
/>
</p> </p>
</nav> </nav>
</template> </template>

View File

@ -3,8 +3,8 @@
<tabs-music /> <tabs-music />
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.browse.recently.added.title')" /> <p class="title is-4" v-text="$t('page.browse.recently-added.title')" />
<p class="heading" v-text="$t('page.browse.recently.added.albums')" /> <p class="heading" v-text="$t('page.browse.recently-added.albums')" />
</template> </template>
<template #content> <template #content>
<list-albums :albums="recently_added" /> <list-albums :albums="recently_added" />

View File

@ -3,7 +3,10 @@
<tabs-music /> <tabs-music />
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.browse.recently.played.title')" /> <p
class="title is-4"
v-text="$t('page.browse.recently.played.title')"
/>
<p class="heading" v-text="$t('page.browse.recently.played.tracks')" /> <p class="heading" v-text="$t('page.browse.recently.played.tracks')" />
</template> </template>
<template #content> <template #content>

View File

@ -6,7 +6,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_composer_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_composer_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -17,11 +20,25 @@
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile"> <p class="heading has-text-centered-mobile">
<span v-text="$t('page.composer.album-count', { count: composer.album_count })" /> <span
<a class="has-text-link" @click="open_tracks" v-text="$t('page.composer.track-count', { count: composer.track_count })" /> v-text="
$t('page.composer.album-count', { count: composer.album_count })
"
/>
<a
class="has-text-link"
@click="open_tracks"
v-text="
$t('page.composer.track-count', { count: composer.track_count })
"
/>
</p> </p>
<list-albums :albums="albums_list" :hide_group_title="true" /> <list-albums :albums="albums_list" :hide_group_title="true" />
<modal-dialog-composer :show="show_composer_details_modal" :composer="composer" @close="show_composer_details_modal = false" /> <modal-dialog-composer
:show="show_composer_details_modal"
:composer="composer"
@close="show_composer_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -6,7 +6,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_composer_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_composer_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -17,11 +20,27 @@
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile"> <p class="heading has-text-centered-mobile">
<a class="has-text-link" @click="open_albums" v-text="$t('page.composer.tracks.album-count', { count: composer.album_count })" /> <a
<span v-text="$t('page.composer.track-count', {count: composer.track_count })" /> class="has-text-link"
@click="open_albums"
v-text="
$t('page.composer.tracks.album-count', {
count: composer.album_count
})
"
/>
<span
v-text="
$t('page.composer.track-count', { count: composer.track_count })
"
/>
</p> </p>
<list-tracks :tracks="tracks.items" :expression="play_expression" /> <list-tracks :tracks="tracks.items" :expression="play_expression" />
<modal-dialog-composer :show="show_composer_details_modal" :composer="composer" @close="show_composer_details_modal = false" /> <modal-dialog-composer
:show="show_composer_details_modal"
:composer="composer"
@close="show_composer_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -7,7 +7,10 @@
</template> </template>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.composers.title')" /> <p class="title is-4" v-text="$t('page.composers.title')" />
<p class="heading" v-text="$t('page.composers.count', { count: composers.total })" /> <p
class="heading"
v-text="$t('page.composers.count', { count: composers.total })"
/>
</template> </template>
<template #content> <template #content>
<list-composers :composers="composers" /> <list-composers :composers="composers" />

View File

@ -7,8 +7,11 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="open_directory_dialog({ path: current_directory })"> <a
<mdicon class="icon" name="dots-horizontal" size="16"/> class="button is-small is-light is-rounded"
@click="open_directory_dialog({ path: current_directory })"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<mdicon class="icon" name="play" size="16" /> <mdicon class="icon" name="play" size="16" />
@ -19,8 +22,16 @@
<template #content> <template #content>
<list-directories :directories="files.directories" /> <list-directories :directories="files.directories" />
<list-playlists :playlists="files.playlists.items" /> <list-playlists :playlists="files.playlists.items" />
<list-tracks :tracks="files.tracks.items" :expression="play_expression" :show_icon="true" /> <list-tracks
<modal-dialog-directory :show="show_directory_details_modal" :directory="selected_directory" @close="show_directory_details_modal = false" /> :tracks="files.tracks.items"
:expression="play_expression"
:show_icon="true"
/>
<modal-dialog-directory
:show="show_directory_details_modal"
:directory="selected_directory"
@close="show_directory_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -9,8 +9,11 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_genre_details_modal = true"> <a
<mdicon class="icon" name="dots-horizontal" size="16"/> class="button is-small is-light is-rounded"
@click="show_genre_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" /> <mdicon class="icon" name="shuffle" size="16" />
@ -20,11 +23,21 @@
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile"> <p class="heading has-text-centered-mobile">
<span v-text="$t('page.genre.album-count', { count: genre.album_count })" /> <span
<a class="has-text-link" @click="open_tracks" v-text="$t('page.genre.track-count', { count: genre.track_count })" /> v-text="$t('page.genre.album-count', { count: genre.album_count })"
/>
<a
class="has-text-link"
@click="open_tracks"
v-text="$t('page.genre.track-count', { count: genre.track_count })"
/>
</p> </p>
<list-albums :albums="albums_list" /> <list-albums :albums="albums_list" />
<modal-dialog-genre :show="show_genre_details_modal" :genre="genre" @close="show_genre_details_modal = false" /> <modal-dialog-genre
:show="show_genre_details_modal"
:genre="genre"
@close="show_genre_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -9,8 +9,11 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_genre_details_modal = true"> <a
<mdicon class="icon" name="dots-horizontal" size="16"/> class="button is-small is-light is-rounded"
@click="show_genre_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" /> <mdicon class="icon" name="shuffle" size="16" />
@ -20,11 +23,23 @@
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile"> <p class="heading has-text-centered-mobile">
<a class="has-text-link" @click="open_genre" v-text="$t('page.genre.tracks.album-count', { count: genre.album_count })" /> <a
<span v-text="$t('page.genre.tracks.count', { count: genre.track_count })" /> class="has-text-link"
@click="open_genre"
v-text="
$t('page.genre.tracks.album-count', { count: genre.album_count })
"
/>
<span
v-text="$t('page.genre.tracks.count', { count: genre.track_count })"
/>
</p> </p>
<list-tracks :tracks="tracks.items" :expression="expression" /> <list-tracks :tracks="tracks.items" :expression="expression" />
<modal-dialog-genre :show="show_genre_details_modal" :genre="genre" @close="show_genre_details_modal = false" /> <modal-dialog-genre
:show="show_genre_details_modal"
:genre="genre"
@close="show_genre_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -7,7 +7,10 @@
</template> </template>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.genres.title')" /> <p class="title is-4" v-text="$t('page.genres.title')" />
<p class="heading" v-text="$t('page.genres.count', { count: genres.total })" /> <p
class="heading"
v-text="$t('page.genres.count', { count: genres.total })"
/>
</template> </template>
<template #content> <template #content>
<list-genres :genres="genres" /> <list-genres :genres="genres" />

View File

@ -2,15 +2,40 @@
<section> <section>
<div v-if="now_playing.id > 0" class="fd-is-fullheight"> <div v-if="now_playing.id > 0" class="fd-is-fullheight">
<div class="fd-is-expanded"> <div class="fd-is-expanded">
<cover-artwork :artwork_url="now_playing.artwork_url" :artist="now_playing.artist" :album="now_playing.album" class="fd-cover-image fd-has-action" @click="open_dialog(now_playing)" /> <cover-artwork
:artwork_url="now_playing.artwork_url"
:artist="now_playing.artist"
:album="now_playing.album"
class="fd-cover-image fd-has-action"
@click="open_dialog(now_playing)"
/>
</div> </div>
<div class="fd-has-padding-left-right"> <div class="fd-has-padding-left-right">
<div class="container has-text-centered"> <div class="container has-text-centered">
<p class="control has-text-centered fd-progress-now-playing"> <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" /> <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>
<p class="content"> <p class="content">
<span v-text="[$filters.durationInHours(item_progress_ms), $filters.durationInHours(now_playing.length_ms)].join(' / ')" /> <span
v-text="
[
$filters.durationInHours(item_progress_ms),
$filters.durationInHours(now_playing.length_ms)
].join(' / ')
"
/>
</p> </p>
</div> </div>
</div> </div>
@ -18,20 +43,31 @@
<div class="container has-text-centered fd-has-margin-top"> <div class="container has-text-centered fd-has-margin-top">
<h1 class="title is-5" v-text="now_playing.title" /> <h1 class="title is-5" v-text="now_playing.title" />
<h2 class="title is-6" v-text="now_playing.artist" /> <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" /> <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="now_playing.album" /> <h3 class="subtitle is-6" v-text="now_playing.album" />
</div> </div>
</div> </div>
</div> </div>
<div v-else class="fd-is-fullheight"> <div v-else class="fd-is-fullheight">
<div class="fd-is-expanded fd-has-padding-left-right" style="flex-direction: column"> <div
class="fd-is-expanded fd-has-padding-left-right"
style="flex-direction: column"
>
<div class="content has-text-centered"> <div class="content has-text-centered">
<h1 class="title is-5" v-text="$('page.now-playing.title')" /> <h1 class="title is-5" v-text="$('page.now-playing.title')" />
<p v-text="$('page.now-playing.info')" /> <p v-text="$('page.now-playing.info')" />
</div> </div>
</div> </div>
</div> </div>
<modal-dialog-queue-item :show="show_details_modal" :item="selected_item" @close="show_details_modal = false" /> <modal-dialog-queue-item
:show="show_details_modal"
:item="selected_item"
@close="show_details_modal = false"
/>
</section> </section>
</template> </template>

View File

@ -5,7 +5,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_playlist_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_playlist_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -15,9 +18,17 @@
</div> </div>
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile" v-text="$t('page.playlist.length', { length: tracks.length })" /> <p
class="heading has-text-centered-mobile"
v-text="$t('page.playlist.length', { length: tracks.length })"
/>
<list-tracks :tracks="tracks" :uris="uris" /> <list-tracks :tracks="tracks" :uris="uris" />
<modal-dialog-playlist :show="show_playlist_details_modal" :playlist="playlist" :uris="uris" @close="show_playlist_details_modal = false" /> <modal-dialog-playlist
:show="show_playlist_details_modal"
:playlist="playlist"
:uris="uris"
@close="show_playlist_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>

View File

@ -2,7 +2,10 @@
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="playlist.name" /> <p class="title is-4" v-text="playlist.name" />
<p class="heading" v-text="$t('page.playlists.count', { count: playlists.count })" /> <p
class="heading"
v-text="$t('page.playlists.count', { count: playlists.count })"
/>
</template> </template>
<template #content> <template #content>
<list-playlists :playlists="playlists" /> <list-playlists :playlists="playlists" />

View File

@ -5,7 +5,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_album_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_album_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -15,10 +18,31 @@
</div> </div>
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile" v-text="$t('page.podcast.track-count', { count: album.track_count })" /> <p
<list-tracks :tracks="tracks" :show_progress="true" @play-count-changed="reload_tracks" /> class="heading has-text-centered-mobile"
<modal-dialog-album :show="show_album_details_modal" :album="album" :media_kind="'podcast'" :new_tracks="new_tracks" @close="show_album_details_modal = false" @play-count-changed="reload_tracks" @remove-podcast="open_remove_podcast_dialog" /> v-text="$t('page.podcast.track-count', { count: album.track_count })"
<modal-dialog :show="show_remove_podcast_modal" title="Remove podcast" delete_action="Remove" @close="show_remove_podcast_modal = false" @delete="remove_podcast"> />
<list-tracks
:tracks="tracks"
:show_progress="true"
@play-count-changed="reload_tracks"
/>
<modal-dialog-album
:show="show_album_details_modal"
:album="album"
:media_kind="'podcast'"
:new_tracks="new_tracks"
@close="show_album_details_modal = false"
@play-count-changed="reload_tracks"
@remove-podcast="open_remove_podcast_dialog"
/>
<modal-dialog
:show="show_remove_podcast_modal"
title="Remove podcast"
delete_action="Remove"
@close="show_remove_podcast_modal = false"
@delete="remove_podcast"
>
<template #modal-content> <template #modal-content>
<p v-text="$t('page.podcast.remove-info-1')" /> <p v-text="$t('page.podcast.remove-info-1')" />
<p class="is-size-7"> <p class="is-size-7">

View File

@ -13,13 +13,20 @@
</div> </div>
</template> </template>
<template #content> <template #content>
<list-tracks :tracks="new_episodes.items" :show_progress="true" @play-count-changed="reload_new_episodes" /> <list-tracks
:tracks="new_episodes.items"
:show_progress="true"
@play-count-changed="reload_new_episodes"
/>
</template> </template>
</content-with-heading> </content-with-heading>
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.podcasts.title')" /> <p class="title is-4" v-text="$t('page.podcasts.title')" />
<p class="heading" v-text="$t('page.podcasts.count', { count: albums.total })" /> <p
class="heading"
v-text="$t('page.podcasts.count', { count: albums.total })"
/>
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
@ -34,8 +41,16 @@
</div> </div>
</template> </template>
<template #content> <template #content>
<list-albums :albums="albums" @play-count-changed="reload_new_episodes()" @podcast-deleted="reload_podcasts()" /> <list-albums
<modal-dialog-add-rss :show="show_url_modal" @close="show_url_modal = false" @podcast-added="reload_podcasts()" /> :albums="albums"
@play-count-changed="reload_new_episodes()"
@podcast-deleted="reload_podcasts()"
/>
<modal-dialog-add-rss
:show="show_url_modal"
@close="show_url_modal = false"
@podcast-added="reload_podcasts()"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -2,11 +2,18 @@
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.queue.title')" /> <p class="title is-4" v-text="$t('page.queue.title')" />
<p class="heading" v-text="$t('page.queue.count', { count: queue.count })" /> <p
class="heading"
v-text="$t('page.queue.count', { count: queue.count })"
/>
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small" :class="{ 'is-info': show_only_next_items }" @click="update_show_next_items"> <a
class="button is-small"
:class="{ 'is-info': show_only_next_items }"
@click="update_show_next_items"
>
<mdicon class="icon" name="arrow-collapse-down" size="16" /> <mdicon class="icon" name="arrow-collapse-down" size="16" />
<span v-text="$t('page.queue.hide-previous')" /> <span v-text="$t('page.queue.hide-previous')" />
</a> </a>
@ -14,7 +21,11 @@
<mdicon class="icon" name="web" size="16" /> <mdicon class="icon" name="web" size="16" />
<span v-text="$t('page.queue.add-stream')" /> <span v-text="$t('page.queue.add-stream')" />
</a> </a>
<a class="button is-small" :class="{ 'is-info': edit_mode }" @click="edit_mode = !edit_mode"> <a
class="button is-small"
:class="{ 'is-info': edit_mode }"
@click="edit_mode = !edit_mode"
>
<mdicon class="icon" name="pencil" size="16" /> <mdicon class="icon" name="pencil" size="16" />
<span v-text="$t('page.queue.edit')" /> <span v-text="$t('page.queue.edit')" />
</a> </a>
@ -22,30 +33,64 @@
<mdicon class="icon" name="delete-empty" size="16" /> <mdicon class="icon" name="delete-empty" size="16" />
<span v-text="$t('page.queue.clear')" /> <span v-text="$t('page.queue.clear')" />
</a> </a>
<a v-if="is_queue_save_allowed" class="button is-small" :disabled="queue_items.length === 0" @click="save_dialog"> <a
v-if="is_queue_save_allowed"
class="button is-small"
:disabled="queue_items.length === 0"
@click="save_dialog"
>
<mdicon class="icon" name="content-save" size="16" /> <mdicon class="icon" name="content-save" size="16" />
<span v-text="$t('page.queue.save')" /> <span v-text="$t('page.queue.save')" />
</a> </a>
</div> </div>
</template> </template>
<template #content> <template #content>
<draggable v-model="queue_items" handle=".handle" item-key="id" @end="move_item"> <draggable
v-model="queue_items"
handle=".handle"
item-key="id"
@end="move_item"
>
<template #item="{ element, index }"> <template #item="{ element, index }">
<list-item-queue-item :item="element" :position="index" :current_position="current_position" :show_only_next_items="show_only_next_items" :edit_mode="edit_mode"> <list-item-queue-item
:item="element"
:position="index"
:current_position="current_position"
:show_only_next_items="show_only_next_items"
:edit_mode="edit_mode"
>
<template #actions> <template #actions>
<a v-if="!edit_mode" @click.prevent.stop="open_dialog(element)"> <a v-if="!edit_mode" @click.prevent.stop="open_dialog(element)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16"/> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
<a v-if="element.id !== state.item_id && edit_mode" @click.prevent.stop="remove(element)"> <a
<mdicon class="icon has-text-grey" name="delete" size="18"/> v-if="element.id !== state.item_id && edit_mode"
@click.prevent.stop="remove(element)"
>
<mdicon class="icon has-text-grey" name="delete" size="18" />
</a> </a>
</template> </template>
</list-item-queue-item> </list-item-queue-item>
</template> </template>
</draggable> </draggable>
<modal-dialog-queue-item :show="show_details_modal" :item="selected_item" @close="show_details_modal = false" /> <modal-dialog-queue-item
<modal-dialog-add-url-stream :show="show_url_modal" @close="show_url_modal = false" /> :show="show_details_modal"
<modal-dialog-playlist-save v-if="is_queue_save_allowed" :show="show_pls_save_modal" @close="show_pls_save_modal = false" /> :item="selected_item"
@close="show_details_modal = false"
/>
<modal-dialog-add-url-stream
:show="show_url_modal"
@close="show_url_modal = false"
/>
<modal-dialog-playlist-save
v-if="is_queue_save_allowed"
:show="show_pls_save_modal"
@close="show_pls_save_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>

View File

@ -5,7 +5,10 @@
<p class="title is-4" v-text="$t('page.radio.title')" /> <p class="title is-4" v-text="$t('page.radio.title')" />
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile" v-text="$t('page.radio.count', { count: tracks.total })" /> <p
class="heading has-text-centered-mobile"
v-text="$t('page.radio.count', { count: tracks.total })"
/>
<list-tracks :tracks="tracks.items" /> <list-tracks :tracks="tracks.items" />
</template> </template>
</content-with-heading> </content-with-heading>

View File

@ -8,7 +8,14 @@
<form @submit.prevent="new_search"> <form @submit.prevent="new_search">
<div class="field"> <div class="field">
<p class="control is-expanded has-icons-left"> <p class="control is-expanded has-icons-left">
<input ref="search_field" v-model="search_query" class="input is-rounded is-shadowless" type="text" placeholder="Search" autocomplete="off" /> <input
ref="search_field"
v-model="search_query"
class="input is-rounded is-shadowless"
type="text"
placeholder="Search"
autocomplete="off"
/>
<mdicon class="icon is-left" name="magnify" size="16" /> <mdicon class="icon is-left" name="magnify" size="16" />
</p> </p>
<p class="help has-text-centered"> <p class="help has-text-centered">
@ -17,7 +24,13 @@
</div> </div>
</form> </form>
<div class="tags" style="margin-top: 16px"> <div class="tags" style="margin-top: 16px">
<a v-for="recent_search in recent_searches" :key="recent_search" class="tag" @click="open_recent_search(recent_search)" v-text="recent_search" /> <a
v-for="recent_search in recent_searches"
:key="recent_search"
class="tag"
@click="open_recent_search(recent_search)"
v-text="recent_search"
/>
</div> </div>
</div> </div>
</div> </div>
@ -35,7 +48,15 @@
<template #footer> <template #footer>
<nav v-if="show_all_tracks_button" class="level"> <nav v-if="show_all_tracks_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_tracks" v-text="$t('page.search.show.tracks', { count: tracks.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_tracks"
v-text="
$t('page.search.show.tracks', {
count: tracks.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -56,7 +77,15 @@
<template #footer> <template #footer>
<nav v-if="show_all_artists_button" class="level"> <nav v-if="show_all_artists_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_artists" v-text="$t('page.search.show.artists', { count:artists.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_artists"
v-text="
$t('page.search.show.artists', {
count: artists.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -77,7 +106,15 @@
<template #footer> <template #footer>
<nav v-if="show_all_albums_button" class="level"> <nav v-if="show_all_albums_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_albums" v-text="$t('page.search.show-albums', { count: albums.total.toLocaleString()})" /> <a
class="button is-light is-small is-rounded"
@click="open_search_albums"
v-text="
$t('page.search.show-albums', {
count: albums.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -98,7 +135,15 @@
<template #footer> <template #footer>
<nav v-if="show_all_composers_button" class="level"> <nav v-if="show_all_composers_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_composers" v-text="$t('page.search.show.composers', { count: composers.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_composers"
v-text="
$t('page.search.show.composers', {
count: composers.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -119,7 +164,15 @@
<template #footer> <template #footer>
<nav v-if="show_all_playlists_button" class="level"> <nav v-if="show_all_playlists_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_playlists" v-text="$t('page.search.show.playlists', { count: playlists.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_playlists"
v-text="
$t('page.search.show.playlists', {
count: playlists.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -140,7 +193,15 @@
<template #footer> <template #footer>
<nav v-if="show_all_podcasts_button" class="level"> <nav v-if="show_all_podcasts_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_podcasts" v-text="$t('page.search.show.podcasts', { count: podcasts.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_podcasts"
v-text="
$t('page.search.show.podcasts', {
count: podcasts.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -162,7 +223,15 @@
<template #footer> <template #footer>
<nav v-if="show_all_audiobooks_button" class="level"> <nav v-if="show_all_audiobooks_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_audiobooks" v-text="$t('page.search.show.audiobooks', { count: audiobooks.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_audiobooks"
v-text="
$t('page.search.show.audiobooks', {
count: audiobooks.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>

View File

@ -6,9 +6,19 @@
<div class="title is-4" v-text="$t('page.settings.artwork.artwork')" /> <div class="title is-4" v-text="$t('page.settings.artwork.artwork')" />
</template> </template>
<template #content> <template #content>
<div class="content" v-text="$t('page.settings.artwork.explanation-1')" /> <div
<div class="content" v-text="$t('page.settings.artwork.explanation-2')" /> class="content"
<settings-checkbox v-if="spotify.libspotify_logged_in" category_name="artwork" option_name="use_artwork_source_spotify"> v-text="$t('page.settings.artwork.explanation-1')"
/>
<div
class="content"
v-text="$t('page.settings.artwork.explanation-2')"
/>
<settings-checkbox
v-if="spotify.libspotify_logged_in"
category_name="artwork"
option_name="use_artwork_source_spotify"
>
<template #label> <template #label>
<span v-text="$t('page.settings.artwork.spotify')" /> <span v-text="$t('page.settings.artwork.spotify')" />
<a href="https://www.spotify.com/" target="_blank"> <a href="https://www.spotify.com/" target="_blank">
@ -16,7 +26,10 @@
</a> </a>
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="artwork" option_name="use_artwork_source_discogs"> <settings-checkbox
category_name="artwork"
option_name="use_artwork_source_discogs"
>
<template #label> <template #label>
<span v-text="$t('page.settings.artwork.discogs')" /> <span v-text="$t('page.settings.artwork.discogs')" />
<a href="https://www.discogs.com/" target="_blank"> <a href="https://www.discogs.com/" target="_blank">
@ -24,7 +37,10 @@
</a> </a>
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="artwork" option_name="use_artwork_source_coverartarchive"> <settings-checkbox
category_name="artwork"
option_name="use_artwork_source_coverartarchive"
>
<template #label> <template #label>
<span v-text="$t('page.settings.artwork.coverartarchive')" /> <span v-text="$t('page.settings.artwork.coverartarchive')" />
<a href="https://coverartarchive.org/" target="_blank"> <a href="https://coverartarchive.org/" target="_blank">

View File

@ -3,7 +3,10 @@
<tabs-settings /> <tabs-settings />
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.services.spotify.title')" /> <div
class="title is-4"
v-text="$t('page.settings.services.spotify.title')"
/>
</template> </template>
<template #content> <template #content>
<div v-if="!spotify.spotify_installed" class="notification is-size-7"> <div v-if="!spotify.spotify_installed" class="notification is-size-7">
@ -12,7 +15,10 @@
<div v-if="spotify.spotify_installed"> <div v-if="spotify.spotify_installed">
<div class="notification is-size-7"> <div class="notification is-size-7">
<b v-text="$t('page.settings.services.spotify.requirements')" /> <b v-text="$t('page.settings.services.spotify.requirements')" />
<span v-if="use_libspotity" v-text="$t('page.settings.services.spotify.help')" /> <span
v-if="use_libspotity"
v-text="$t('page.settings.services.spotify.help')"
/>
</div> </div>
<div v-if="use_libspotity"> <div v-if="use_libspotity">
<p class="content"> <p class="content">
@ -23,27 +29,55 @@
<span v-text="$t('page.settings.services.spotify.logged-as')" /> <span v-text="$t('page.settings.services.spotify.logged-as')" />
<b><code v-text="spotify.libspotify_user" /></b> <b><code v-text="spotify.libspotify_user" /></b>
</p> </p>
<form v-if="spotify.spotify_installed && !spotify.libspotify_logged_in" @submit.prevent="login_libspotify"> <form
v-if="spotify.spotify_installed && !spotify.libspotify_logged_in"
@submit.prevent="login_libspotify"
>
<div class="field is-grouped"> <div class="field is-grouped">
<div class="control is-expanded"> <div class="control is-expanded">
<input v-model="libspotify.user" class="input" type="text" placeholder="Username" /> <input
v-model="libspotify.user"
class="input"
type="text"
placeholder="Username"
/>
<p class="help is-danger" v-text="libspotify.errors.user" /> <p class="help is-danger" v-text="libspotify.errors.user" />
</div> </div>
<div class="control is-expanded"> <div class="control is-expanded">
<input v-model="libspotify.password" class="input" type="password" placeholder="Password" /> <input
<p class="help is-danger" v-text="libspotify.errors.password" /> v-model="libspotify.password"
class="input"
type="password"
placeholder="Password"
/>
<p
class="help is-danger"
v-text="libspotify.errors.password"
/>
</div> </div>
<div class="control"> <div class="control">
<button class="button is-info" v-text="$t('page.settings.services.login')" /> <button
class="button is-info"
v-text="$t('page.settings.services.login')"
/>
</div> </div>
</div> </div>
</form> </form>
<p class="help is-danger" v-text="libspotify.errors.error" /> <p class="help is-danger" v-text="libspotify.errors.error" />
<p class="help" v-text="$t('page.settings.services.spotify.help-1')" /> <p
<p class="help" v-text="$t('page.settings.services.spotify.help-2')" /> class="help"
v-text="$t('page.settings.services.spotify.help-1')"
/>
<p
class="help"
v-text="$t('page.settings.services.spotify.help-2')"
/>
</div> </div>
<div class="fd-has-margin-top"> <div class="fd-has-margin-top">
<p class="content" v-html="$t('page.settings.services.spotify.grant-access')" /> <p
class="content"
v-html="$t('page.settings.services.spotify.grant-access')"
/>
<p v-if="spotify.webapi_token_valid"> <p v-if="spotify.webapi_token_valid">
<span v-text="$t('page.settings.services.spotify.user')" /> <span v-text="$t('page.settings.services.spotify.user')" />
<code v-text="spotify.webapi_user" /> <code v-text="spotify.webapi_user" />
@ -54,16 +88,32 @@
</p> </p>
<div class="field fd-has-margin-top"> <div class="field fd-has-margin-top">
<div class="control"> <div class="control">
<a class="button" :class="{ 'is-info': !spotify.webapi_token_valid || spotify_missing_scope.length > 0 }" :href="spotify.oauth_uri" v-text="$t('page.settings.services.spotify.authorize')" /> <a
class="button"
:class="{
'is-info':
!spotify.webapi_token_valid ||
spotify_missing_scope.length > 0
}"
:href="spotify.oauth_uri"
v-text="$t('page.settings.services.spotify.authorize')"
/>
</div> </div>
</div> </div>
<p class="help"> <p class="help">
<span v-text="$t('page.settings.services.spotify.scopes')" /> <span v-text="$t('page.settings.services.spotify.scopes')" />
<code v-text="spotify_required_scope.join()" /> <code v-text="spotify_required_scope.join()" />
</p> </p>
<div v-if="spotify.webapi_token_valid" class="field fd-has-margin-top"> <div
v-if="spotify.webapi_token_valid"
class="field fd-has-margin-top"
>
<div class="control"> <div class="control">
<a class="button is-danger" @click="logout_spotify" v-text="$t('page.settings.services.logout')" /> <a
class="button is-danger"
@click="logout_spotify"
v-text="$t('page.settings.services.logout')"
/>
</div> </div>
</div> </div>
</div> </div>
@ -72,34 +122,64 @@
</content-with-heading> </content-with-heading>
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.services.lastfm.title')" /> <div
class="title is-4"
v-text="$t('page.settings.services.lastfm.title')"
/>
</template> </template>
<template #content> <template #content>
<div v-if="!lastfm.enabled" class="notification is-size-7"> <div v-if="!lastfm.enabled" class="notification is-size-7">
<p v-text="$t('page.settings.services.lastfm.no-support')" /> <p v-text="$t('page.settings.services.lastfm.no-support')" />
</div> </div>
<div v-if="lastfm.enabled"> <div v-if="lastfm.enabled">
<p class="content" v-html="$t('page.settings.services.lastfm.grant-access')" /> <p
class="content"
v-html="$t('page.settings.services.lastfm.grant-access')"
/>
<div v-if="lastfm.scrobbling_enabled"> <div v-if="lastfm.scrobbling_enabled">
<a class="button" @click="logoutLastfm" v-text="$t('page.settings.services.lastfm.stop-scrobbling')" /> <a
class="button"
@click="logoutLastfm"
v-text="$t('page.settings.services.lastfm.stop-scrobbling')"
/>
</div> </div>
<div v-if="!lastfm.scrobbling_enabled"> <div v-if="!lastfm.scrobbling_enabled">
<form @submit.prevent="login_lastfm"> <form @submit.prevent="login_lastfm">
<div class="field is-grouped"> <div class="field is-grouped">
<div class="control is-expanded"> <div class="control is-expanded">
<input v-model="lastfm_login.user" class="input" type="text" placeholder="Username" /> <input
v-model="lastfm_login.user"
class="input"
type="text"
placeholder="Username"
/>
<p class="help is-danger" v-text="lastfm_login.errors.user" /> <p class="help is-danger" v-text="lastfm_login.errors.user" />
</div> </div>
<div class="control is-expanded"> <div class="control is-expanded">
<input v-model="lastfm_login.password" class="input" type="password" placeholder="Password" /> <input
<p class="help is-danger" v-text="lastfm_login.errors.password" /> v-model="lastfm_login.password"
class="input"
type="password"
placeholder="Password"
/>
<p
class="help is-danger"
v-text="lastfm_login.errors.password"
/>
</div> </div>
<div class="control"> <div class="control">
<button class="button is-info" type="submit" v-text="$t('page.settings.services.login')" /> <button
class="button is-info"
type="submit"
v-text="$t('page.settings.services.login')"
/>
</div> </div>
</div> </div>
<p class="help is-danger" v-text="lastfm_login.errors.error" /> <p class="help is-danger" v-text="lastfm_login.errors.error" />
<p class="help" v-text="$t('page.settings.services.lastfm.info')" /> <p
class="help"
v-text="$t('page.settings.services.lastfm.info')"
/>
</form> </form>
</div> </div>
</div> </div>

View File

@ -9,13 +9,25 @@
<!-- Paring request active --> <!-- Paring request active -->
<div v-if="pairing.active" class="notification"> <div v-if="pairing.active" class="notification">
<form @submit.prevent="kickoff_pairing"> <form @submit.prevent="kickoff_pairing">
<label class="label has-text-weight-normal" v-html="$t('page.settings.devices.pairing-request', { remote: pairing.remote})" /> <label class="label has-text-weight-normal">
<span v-text="$t('page.settings.devices.pairing-request')" />
<b v-text="pairing.remote" />
</label>
<div class="field is-grouped"> <div class="field is-grouped">
<div class="control"> <div class="control">
<input v-model="pairing_req.pin" class="input" type="text" placeholder="Enter pairing code" /> <input
v-model="pairing_req.pin"
class="input"
type="text"
placeholder="Enter pairing code"
/>
</div> </div>
<div class="control"> <div class="control">
<button class="button is-info" type="submit" v-text="$t('page.settings.devices.send')" /> <button
class="button is-info"
type="submit"
v-text="$t('page.settings.devices.send')"
/>
</div> </div>
</div> </div>
</form> </form>
@ -28,26 +40,50 @@
</content-with-heading> </content-with-heading>
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.devices.speaker-pairing')" /> <div
class="title is-4"
v-text="$t('page.settings.devices.speaker-pairing')"
/>
</template> </template>
<template #content> <template #content>
<p class="content" v-text="$t('page.settings.devices.speaker-pairing-info')" /> <p
class="content"
v-text="$t('page.settings.devices.speaker-pairing-info')"
/>
<div v-for="output in outputs" :key="output.id"> <div v-for="output in outputs" :key="output.id">
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<label class="checkbox"> <label class="checkbox">
<input v-model="output.selected" type="checkbox" style="margin-right: 5px" @change="output_toggle(output.id)"/> <input
v-model="output.selected"
type="checkbox"
style="margin-right: 5px"
@change="output_toggle(output.id)"
/>
<span v-text="output.name" /> <span v-text="output.name" />
</label> </label>
</div> </div>
</div> </div>
<form v-if="output.needs_auth_key" class="fd-has-margin-bottom" @submit.prevent="kickoff_verification(output.id)"> <form
v-if="output.needs_auth_key"
class="fd-has-margin-bottom"
@submit.prevent="kickoff_verification(output.id)"
>
<div class="field is-grouped"> <div class="field is-grouped">
<div class="control"> <div class="control">
<input v-model="verification_req.pin" class="input" type="text" :placeholder="$t('page.settings.devices.verification-code')" /> <input
v-model="verification_req.pin"
class="input"
type="text"
:placeholder="$t('page.settings.devices.verification-code')"
/>
</div> </div>
<div class="control"> <div class="control">
<button class="button is-info" type="submit" v-text="$t('page.settings.devices.verify')" /> <button
class="button is-info"
type="submit"
v-text="$t('page.settings.devices.verify')"
/>
</div> </div>
</div> </div>
</form> </form>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="fd-page-with-tabs"> <div class="fd-page-with-tabs">
<tabs-settings /> <tabs-settings />
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.general.language')" /> <div class="title is-4" v-text="$t('page.settings.general.language')" />
</template> </template>
@ -11,42 +11,72 @@
</content-with-heading> </content-with-heading>
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.general.navigation-items')" /> <div
class="title is-4"
v-text="$t('page.settings.general.navigation-items')"
/>
</template> </template>
<template #content> <template #content>
<p class="content" v-text="$t('page.settings.general.navigation-item-selection')" /> <p
<div class="notification is-size-7" v-text="$t('page.settings.general.navigation-item-selection-info')" /> class="content"
<settings-checkbox category_name="webinterface" option_name="show_menu_item_playlists"> v-text="$t('page.settings.general.navigation-item-selection')"
/>
<div
class="notification is-size-7"
v-text="$t('page.settings.general.navigation-item-selection-info')"
/>
<settings-checkbox
category_name="webinterface"
option_name="show_menu_item_playlists"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.playlists')" /> <span v-text="$t('page.settings.general.playlists')" />
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="webinterface" option_name="show_menu_item_music"> <settings-checkbox
category_name="webinterface"
option_name="show_menu_item_music"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.music')" /> <span v-text="$t('page.settings.general.music')" />
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="webinterface" option_name="show_menu_item_podcasts"> <settings-checkbox
category_name="webinterface"
option_name="show_menu_item_podcasts"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.podcasts')" /> <span v-text="$t('page.settings.general.podcasts')" />
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="webinterface" option_name="show_menu_item_audiobooks"> <settings-checkbox
category_name="webinterface"
option_name="show_menu_item_audiobooks"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.audiobooks')" /> <span v-text="$t('page.settings.general.audiobooks')" />
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="webinterface" option_name="show_menu_item_radio"> <settings-checkbox
category_name="webinterface"
option_name="show_menu_item_radio"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.radio')" /> <span v-text="$t('page.settings.general.radio')" />
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="webinterface" option_name="show_menu_item_files"> <settings-checkbox
category_name="webinterface"
option_name="show_menu_item_files"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.files')" /> <span v-text="$t('page.settings.general.files')" />
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-checkbox category_name="webinterface" option_name="show_menu_item_search"> <settings-checkbox
category_name="webinterface"
option_name="show_menu_item_search"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.search')" /> <span v-text="$t('page.settings.general.search')" />
</template> </template>
@ -55,10 +85,16 @@
</content-with-heading> </content-with-heading>
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.general.album-lists')" /> <div
class="title is-4"
v-text="$t('page.settings.general.album-lists')"
/>
</template> </template>
<template #content> <template #content>
<settings-checkbox category_name="webinterface" option_name="show_cover_artwork_in_album_lists"> <settings-checkbox
category_name="webinterface"
option_name="show_cover_artwork_in_album_lists"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.show-coverart')" /> <span v-text="$t('page.settings.general.show-coverart')" />
</template> </template>
@ -67,10 +103,16 @@
</content-with-heading> </content-with-heading>
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.general.now-playing-page')" /> <div
class="title is-4"
v-text="$t('page.settings.general.now-playing-page')"
/>
</template> </template>
<template #content> <template #content>
<settings-checkbox category_name="webinterface" option_name="show_composer_now_playing"> <settings-checkbox
category_name="webinterface"
option_name="show_composer_now_playing"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.show-composer')" /> <span v-text="$t('page.settings.general.show-composer')" />
</template> </template>
@ -78,26 +120,48 @@
<span v-text="$t('page.settings.general.show-composer-info')" /> <span v-text="$t('page.settings.general.show-composer-info')" />
</template> </template>
</settings-checkbox> </settings-checkbox>
<settings-textfield category_name="webinterface" option_name="show_composer_for_genre" :disabled="!settings_option_show_composer_now_playing" placeholder="Genres"> <settings-textfield
category_name="webinterface"
option_name="show_composer_for_genre"
:disabled="!settings_option_show_composer_now_playing"
placeholder="Genres"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.show-composer-genres')" /> <span v-text="$t('page.settings.general.show-composer-genres')" />
</template> </template>
<template #info> <template #info>
<p class="help" v-text="$t('page.settings.general.show-composer-genres-info-1')" /> <p
<p class="help" v-text="$t('page.settings.general.show-composer-genres-info-2')" /> class="help"
<p class="help" v-text="$t('page.settings.general.show-composer-genres-info-3')" /> v-text="$t('page.settings.general.show-composer-genres-info-1')"
/>
<p
class="help"
v-text="$t('page.settings.general.show-composer-genres-info-2')"
/>
<p
class="help"
v-text="$t('page.settings.general.show-composer-genres-info-3')"
/>
</template> </template>
</settings-textfield> </settings-textfield>
</template> </template>
</content-with-heading> </content-with-heading>
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<div class="title is-4" v-text="$t('page.settings.general.recently-added-page')" /> <div
class="title is-4"
v-text="$t('page.settings.general.recently-added-page')"
/>
</template> </template>
<template #content> <template #content>
<settings-intfield category_name="webinterface" option_name="recently_added_limit"> <settings-intfield
category_name="webinterface"
option_name="recently_added_limit"
>
<template #label> <template #label>
<span v-text="$t('page.settings.general.recently-added-page-info')" /> <span
v-text="$t('page.settings.general.recently-added-page-info')"
/>
</template> </template>
</settings-intfield> </settings-intfield>
</template> </template>

View File

@ -3,34 +3,67 @@
<template #heading-left> <template #heading-left>
<h1 class="title is-5" v-text="album.name" /> <h1 class="title is-5" v-text="album.name" />
<h2 class="subtitle is-6 has-text-link has-text-weight-normal"> <h2 class="subtitle is-6 has-text-link has-text-weight-normal">
<a class="has-text-link" @click="open_artist" v-text="album.artists[0].name" /> <a
class="has-text-link"
@click="open_artist"
v-text="album.artists[0].name"
/>
</h2> </h2>
<div class="buttons fd-is-centered-mobile fd-has-margin-top"> <div class="buttons fd-is-centered-mobile fd-has-margin-top">
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<mdicon class="icon" name="shuffle" size="16" /> <mdicon class="icon" name="shuffle" size="16" />
<span v-text="$t('page.spotify.album.shuffle')" /> <span v-text="$t('page.spotify.album.shuffle')" />
</a> </a>
<a class="button is-small is-light is-rounded" @click="show_album_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_album_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
</div> </div>
</template> </template>
<template #heading-right> <template #heading-right>
<p class="image is-square fd-has-shadow fd-has-action"> <p class="image is-square fd-has-shadow fd-has-action">
<cover-artwork :artwork_url="artwork_url" :artist="album.artist" :album="album.name" @click="show_album_details_modal = true" /> <cover-artwork
:artwork_url="artwork_url"
:artist="album.artist"
:album="album.name"
@click="show_album_details_modal = true"
/>
</p> </p>
</template> </template>
<template #content> <template #content>
<p class="heading is-7 has-text-centered-mobile fd-has-margin-top" v-text="$t('page.spotify.album.track-count', { count: album.tracks.total })" /> <p
<spotify-list-item-track v-for="(track, index) in album.tracks.items" :key="track.id" :track="track" :position="index" :album="album" :context_uri="album.uri"> class="heading is-7 has-text-centered-mobile fd-has-margin-top"
v-text="
$t('page.spotify.album.track-count', { count: album.tracks.total })
"
/>
<spotify-list-item-track
v-for="(track, index) in album.tracks.items"
:key="track.id"
:track="track"
:position="index"
:album="album"
:context_uri="album.uri"
>
<template #actions> <template #actions>
<a @click.prevent.stop="open_track_dialog(track)"> <a @click.prevent.stop="open_track_dialog(track)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon class="icon has-text-dark" name="dots-vertical" size="16" />
</a> </a>
</template> </template>
</spotify-list-item-track> </spotify-list-item-track>
<spotify-modal-dialog-track :show="show_track_details_modal" :track="selected_track" :album="album" @close="show_track_details_modal = false" /> <spotify-modal-dialog-track
<spotify-modal-dialog-album :show="show_album_details_modal" :album="album" @close="show_album_details_modal = false" /> :show="show_track_details_modal"
:track="selected_track"
:album="album"
@close="show_track_details_modal = false"
/>
<spotify-modal-dialog-album
:show="show_album_details_modal"
:album="album"
@close="show_album_details_modal = false"
/>
</template> </template>
</content-with-hero> </content-with-hero>
</template> </template>

View File

@ -5,7 +5,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_artist_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_artist_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -15,11 +18,25 @@
</div> </div>
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile" v-text="$t('page.spotify.artist.album-count', { count: total })" /> <p
<spotify-list-item-album v-for="album in albums" :key="album.id" :album="album" @click="open_album(album)"> class="heading has-text-centered-mobile"
v-text="$t('page.spotify.artist.album-count', { count: total })"
/>
<spotify-list-item-album
v-for="album in albums"
:key="album.id"
:album="album"
@click="open_album(album)"
>
<template v-if="is_visible_artwork" #artwork> <template v-if="is_visible_artwork" #artwork>
<p class="image is-64x64 fd-has-shadow fd-has-action"> <p class="image is-64x64 fd-has-shadow fd-has-action">
<cover-artwork :artwork_url="artwork_url(album)" :artist="album.artist" :album="album.name" :maxwidth="64" :maxheight="64" /> <cover-artwork
:artwork_url="artwork_url(album)"
:artist="album.artist"
:album="album.name"
:maxwidth="64"
:maxheight="64"
/>
</p> </p>
</template> </template>
<template #actions> <template #actions>
@ -31,8 +48,16 @@
<VueEternalLoading v-if="offset < total" :load="load_next"> <VueEternalLoading v-if="offset < total" :load="load_next">
<template #no-more> . </template> <template #no-more> . </template>
</VueEternalLoading> </VueEternalLoading>
<spotify-modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" /> <spotify-modal-dialog-album
<spotify-modal-dialog-artist :show="show_artist_details_modal" :artist="artist" @close="show_artist_details_modal = false" /> :show="show_details_modal"
:album="selected_album"
@close="show_details_modal = false"
/>
<spotify-modal-dialog-artist
:show="show_artist_details_modal"
:artist="artist"
@close="show_artist_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>

View File

@ -7,24 +7,47 @@
<p class="title is-4" v-text="$t('page.spotify.browse.new-releases')" /> <p class="title is-4" v-text="$t('page.spotify.browse.new-releases')" />
</template> </template>
<template #content> <template #content>
<spotify-list-item-album v-for="album in new_releases" :key="album.id" :album="album" @click="open_album(album)"> <spotify-list-item-album
v-for="album in new_releases"
:key="album.id"
:album="album"
@click="open_album(album)"
>
<template v-if="is_visible_artwork" #artwork> <template v-if="is_visible_artwork" #artwork>
<p class="image is-64x64 fd-has-shadow fd-has-action"> <p class="image is-64x64 fd-has-shadow fd-has-action">
<cover-artwork :artwork_url="artwork_url(album)" :artist="album.artist" :album="album.name" :maxwidth="64" :maxheight="64" /> <cover-artwork
:artwork_url="artwork_url(album)"
:artist="album.artist"
:album="album.name"
:maxwidth="64"
:maxheight="64"
/>
</p> </p>
</template> </template>
<template #actions> <template #actions>
<a @click.prevent.stop="open_album_dialog(album)"> <a @click.prevent.stop="open_album_dialog(album)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-album> </spotify-list-item-album>
<spotify-modal-dialog-album :show="show_album_details_modal" :album="selected_album" @close="show_album_details_modal = false" /> <spotify-modal-dialog-album
:show="show_album_details_modal"
:album="selected_album"
@close="show_album_details_modal = false"
/>
</template> </template>
<template #footer> <template #footer>
<nav class="level"> <nav class="level">
<p class="level-item"> <p class="level-item">
<router-link to="/music/spotify/new-releases" class="button is-light is-small is-rounded" v-text="$t('page.spotify.browse.show-more')" /> <router-link
to="/music/spotify/new-releases"
class="button is-light is-small is-rounded"
v-text="$t('page.spotify.browse.show-more')"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -32,22 +55,41 @@
<!-- Featured Playlists --> <!-- Featured Playlists -->
<content-with-heading> <content-with-heading>
<template #heading-left> <template #heading-left>
<p class="title is-4" v-text="$t('page.spotify.browse.featured-playlists')" /> <p
class="title is-4"
v-text="$t('page.spotify.browse.featured-playlists')"
/>
</template> </template>
<template #content> <template #content>
<spotify-list-item-playlist v-for="playlist in featured_playlists" :key="playlist.id" :playlist="playlist"> <spotify-list-item-playlist
v-for="playlist in featured_playlists"
:key="playlist.id"
:playlist="playlist"
>
<template #actions> <template #actions>
<a @click.prevent.stop="open_playlist_dialog(playlist)"> <a @click.prevent.stop="open_playlist_dialog(playlist)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-playlist> </spotify-list-item-playlist>
<spotify-modal-dialog-playlist :show="show_playlist_details_modal" :playlist="selected_playlist" @close="show_playlist_details_modal = false" /> <spotify-modal-dialog-playlist
:show="show_playlist_details_modal"
:playlist="selected_playlist"
@close="show_playlist_details_modal = false"
/>
</template> </template>
<template #footer> <template #footer>
<nav class="level"> <nav class="level">
<p class="level-item"> <p class="level-item">
<router-link to="/music/spotify/featured-playlists" class="button is-light is-small is-rounded" v-text="$t('page.spotify.browse.show-more')" /> <router-link
to="/music/spotify/featured-playlists"
class="button is-light is-small is-rounded"
v-text="$t('page.spotify.browse.show-more')"
/>
</p> </p>
</nav> </nav>
</template> </template>

View File

@ -6,14 +6,26 @@
<p class="title is-4">Featured Playlists</p> <p class="title is-4">Featured Playlists</p>
</template> </template>
<template #content> <template #content>
<spotify-list-item-playlist v-for="playlist in featured_playlists" :key="playlist.id" :playlist="playlist"> <spotify-list-item-playlist
v-for="playlist in featured_playlists"
:key="playlist.id"
:playlist="playlist"
>
<template #actions> <template #actions>
<a @click.prevent.stop="open_playlist_dialog(playlist)"> <a @click.prevent.stop="open_playlist_dialog(playlist)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-playlist> </spotify-list-item-playlist>
<spotify-modal-dialog-playlist :show="show_playlist_details_modal" :playlist="selected_playlist" @close="show_playlist_details_modal = false" /> <spotify-modal-dialog-playlist
:show="show_playlist_details_modal"
:playlist="selected_playlist"
@close="show_playlist_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -6,19 +6,38 @@
<p class="title is-4">New Releases</p> <p class="title is-4">New Releases</p>
</template> </template>
<template #content> <template #content>
<spotify-list-item-album v-for="album in new_releases" :key="album.id" :album="album" @click="open_album(album)"> <spotify-list-item-album
v-for="album in new_releases"
:key="album.id"
:album="album"
@click="open_album(album)"
>
<template v-if="is_visible_artwork" #artwork> <template v-if="is_visible_artwork" #artwork>
<p class="image is-64x64 fd-has-shadow fd-has-action"> <p class="image is-64x64 fd-has-shadow fd-has-action">
<cover-artwork :artwork_url="artwork_url(album)" :artist="album.artist" :album="album.name" :maxwidth="64" :maxheight="64" /> <cover-artwork
:artwork_url="artwork_url(album)"
:artist="album.artist"
:album="album.name"
:maxwidth="64"
:maxheight="64"
/>
</p> </p>
</template> </template>
<template #actions> <template #actions>
<a @click.prevent.stop="open_album_dialog(album)"> <a @click.prevent.stop="open_album_dialog(album)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-album> </spotify-list-item-album>
<spotify-modal-dialog-album :show="show_album_details_modal" :album="selected_album" @close="show_album_details_modal = false" /> <spotify-modal-dialog-album
:show="show_album_details_modal"
:album="selected_album"
@close="show_album_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -5,7 +5,10 @@
</template> </template>
<template #heading-right> <template #heading-right>
<div class="buttons is-centered"> <div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_playlist_details_modal = true"> <a
class="button is-small is-light is-rounded"
@click="show_playlist_details_modal = true"
>
<mdicon class="icon" name="dots-horizontal" size="16" /> <mdicon class="icon" name="dots-horizontal" size="16" />
</a> </a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
@ -15,8 +18,20 @@
</div> </div>
</template> </template>
<template #content> <template #content>
<p class="heading has-text-centered-mobile" v-text="$t('page.spotify.playlist.count', {count: playlist.tracks.total})" /> <p
<spotify-list-item-track v-for="(item, index) in tracks" :key="item.track.id" :track="item.track" :album="item.track.album" :position="index" :context_uri="playlist.uri"> class="heading has-text-centered-mobile"
v-text="
$t('page.spotify.playlist.count', { count: playlist.tracks.total })
"
/>
<spotify-list-item-track
v-for="(item, index) in tracks"
:key="item.track.id"
:track="item.track"
:album="item.track.album"
:position="index"
:context_uri="playlist.uri"
>
<template #actions> <template #actions>
<a @click.prevent.stop="open_track_dialog(item.track)"> <a @click.prevent.stop="open_track_dialog(item.track)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon class="icon has-text-dark" name="dots-vertical" size="16" />
@ -26,8 +41,17 @@
<VueEternalLoading v-if="offset < total" :load="load_next"> <VueEternalLoading v-if="offset < total" :load="load_next">
<template #no-more> . </template> <template #no-more> . </template>
</VueEternalLoading> </VueEternalLoading>
<spotify-modal-dialog-track :show="show_track_details_modal" :track="selected_track" :album="selected_track.album" @close="show_track_details_modal = false" /> <spotify-modal-dialog-track
<spotify-modal-dialog-playlist :show="show_playlist_details_modal" :playlist="playlist" @close="show_playlist_details_modal = false" /> :show="show_track_details_modal"
:track="selected_track"
:album="selected_track.album"
@close="show_track_details_modal = false"
/>
<spotify-modal-dialog-playlist
:show="show_playlist_details_modal"
:playlist="playlist"
@close="show_playlist_details_modal = false"
/>
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>

View File

@ -8,13 +8,26 @@
<form @submit.prevent="new_search"> <form @submit.prevent="new_search">
<div class="field"> <div class="field">
<p class="control is-expanded has-icons-left"> <p class="control is-expanded has-icons-left">
<input ref="search_field" v-model="search_query" class="input is-rounded is-shadowless" type="text" placeholder="Search" autocomplete="off" /> <input
ref="search_field"
v-model="search_query"
class="input is-rounded is-shadowless"
type="text"
placeholder="Search"
autocomplete="off"
/>
<mdicon class="icon is-left" name="magnify" size="16" /> <mdicon class="icon is-left" name="magnify" size="16" />
</p> </p>
</div> </div>
</form> </form>
<div class="tags" style="margin-top: 16px"> <div class="tags" style="margin-top: 16px">
<a v-for="recent_search in recent_searches" :key="recent_search" class="tag" @click="open_recent_search(recent_search)" v-text="recent_search" /> <a
v-for="recent_search in recent_searches"
:key="recent_search"
class="tag"
@click="open_recent_search(recent_search)"
v-text="recent_search"
/>
</div> </div>
</div> </div>
</div> </div>
@ -27,22 +40,49 @@
<p class="title is-4" v-text="$t('page.spotify.search.tracks')" /> <p class="title is-4" v-text="$t('page.spotify.search.tracks')" />
</template> </template>
<template #content> <template #content>
<spotify-list-item-track v-for="track in tracks.items" :key="track.id" :track="track" :album="track.album" :position="0" :context_uri="track.uri"> <spotify-list-item-track
v-for="track in tracks.items"
:key="track.id"
:track="track"
:album="track.album"
:position="0"
:context_uri="track.uri"
>
<template #actions> <template #actions>
<a @click.prevent.stop="open_track_dialog(track)"> <a @click.prevent.stop="open_track_dialog(track)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-track> </spotify-list-item-track>
<VueEternalLoading v-if="query.type === 'track'" :load="search_tracks_next"> <VueEternalLoading
v-if="query.type === 'track'"
:load="search_tracks_next"
>
<template #no-more> . </template> <template #no-more> . </template>
</VueEternalLoading> </VueEternalLoading>
<spotify-modal-dialog-track :show="show_track_details_modal" :track="selected_track" :album="selected_track.album" @close="show_track_details_modal = false" /> <spotify-modal-dialog-track
:show="show_track_details_modal"
:track="selected_track"
:album="selected_track.album"
@close="show_track_details_modal = false"
/>
</template> </template>
<template #footer> <template #footer>
<nav v-if="show_all_tracks_button" class="level"> <nav v-if="show_all_tracks_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_tracks" v-text="$t('page.spotify.search.show-all-tracks', { count: tracks.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_tracks"
v-text="
$t('page.spotify.search.show-all-tracks', {
count: tracks.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -58,22 +98,45 @@
<p class="title is-4" v-text="$t('page.spotify.search.artists')" /> <p class="title is-4" v-text="$t('page.spotify.search.artists')" />
</template> </template>
<template #content> <template #content>
<spotify-list-item-artist v-for="artist in artists.items" :key="artist.id" :artist="artist"> <spotify-list-item-artist
v-for="artist in artists.items"
:key="artist.id"
:artist="artist"
>
<template #actions> <template #actions>
<a @click.prevent.stop="open_artist_dialog(artist)"> <a @click.prevent.stop="open_artist_dialog(artist)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-artist> </spotify-list-item-artist>
<VueEternalLoading v-if="query.type === 'artist'" :load="search_artists_next"> <VueEternalLoading
v-if="query.type === 'artist'"
:load="search_artists_next"
>
<template #no-more> . </template> <template #no-more> . </template>
</VueEternalLoading> </VueEternalLoading>
<spotify-modal-dialog-artist :show="show_artist_details_modal" :artist="selected_artist" @close="show_artist_details_modal = false" /> <spotify-modal-dialog-artist
:show="show_artist_details_modal"
:artist="selected_artist"
@close="show_artist_details_modal = false"
/>
</template> </template>
<template #footer> <template #footer>
<nav v-if="show_all_artists_button" class="level"> <nav v-if="show_all_artists_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_artists" v-text="$t('page.spotify.search.show-all-artists', { count: artists.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_artists"
v-text="
$t('page.spotify.search.show-all-artists', {
count: artists.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -89,27 +152,57 @@
<p class="title is-4" v-text="$t('page.spotify.search.albums')" /> <p class="title is-4" v-text="$t('page.spotify.search.albums')" />
</template> </template>
<template #content> <template #content>
<spotify-list-item-album v-for="album in albums.items" :key="album.id" :album="album" @click="open_album(album)"> <spotify-list-item-album
v-for="album in albums.items"
:key="album.id"
:album="album"
@click="open_album(album)"
>
<template v-if="is_visible_artwork" #artwork> <template v-if="is_visible_artwork" #artwork>
<p class="image is-64x64 fd-has-shadow fd-has-action"> <p class="image is-64x64 fd-has-shadow fd-has-action">
<cover-artwork :artwork_url="artwork_url(album)" :artist="album.artist" :album="album.name" :maxwidth="64" :maxheight="64" /> <cover-artwork
:artwork_url="artwork_url(album)"
:artist="album.artist"
:album="album.name"
:maxwidth="64"
:maxheight="64"
/>
</p> </p>
</template> </template>
<template #actions> <template #actions>
<a @click.prevent.stop="open_album_dialog(album)"> <a @click.prevent.stop="open_album_dialog(album)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-album> </spotify-list-item-album>
<VueEternalLoading v-if="query.type === 'album'" :load="search_albums_next"> <VueEternalLoading
v-if="query.type === 'album'"
:load="search_albums_next"
>
<template #no-more> . </template> <template #no-more> . </template>
</VueEternalLoading> </VueEternalLoading>
<spotify-modal-dialog-album :show="show_album_details_modal" :album="selected_album" @close="show_album_details_modal = false" /> <spotify-modal-dialog-album
:show="show_album_details_modal"
:album="selected_album"
@close="show_album_details_modal = false"
/>
</template> </template>
<template #footer> <template #footer>
<nav v-if="show_all_albums_button" class="level"> <nav v-if="show_all_albums_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_albums" v-text="$t('page.spotify.search.show-all-albums', { count: albums.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_albums"
v-text="
$t('page.spotify.search.show-all-albums', {
count: albums.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>
@ -125,22 +218,45 @@
<p class="title is-4" v-text="$t('page.spotify.search.playlists')" /> <p class="title is-4" v-text="$t('page.spotify.search.playlists')" />
</template> </template>
<template #content> <template #content>
<spotify-list-item-playlist v-for="playlist in playlists.items" :key="playlist.id" :playlist="playlist"> <spotify-list-item-playlist
v-for="playlist in playlists.items"
:key="playlist.id"
:playlist="playlist"
>
<template #actions> <template #actions>
<a @click.prevent.stop="open_playlist_dialog(playlist)"> <a @click.prevent.stop="open_playlist_dialog(playlist)">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" /> <mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/>
</a> </a>
</template> </template>
</spotify-list-item-playlist> </spotify-list-item-playlist>
<VueEternalLoading v-if="query.type === 'playlist'" :load="search_playlists_next"> <VueEternalLoading
v-if="query.type === 'playlist'"
:load="search_playlists_next"
>
<template #no-more> . </template> <template #no-more> . </template>
</VueEternalLoading> </VueEternalLoading>
<spotify-modal-dialog-playlist :show="show_playlist_details_modal" :playlist="selected_playlist" @close="show_playlist_details_modal = false" /> <spotify-modal-dialog-playlist
:show="show_playlist_details_modal"
:playlist="selected_playlist"
@close="show_playlist_details_modal = false"
/>
</template> </template>
<template #footer> <template #footer>
<nav v-if="show_all_playlists_button" class="level"> <nav v-if="show_all_playlists_button" class="level">
<p class="level-item"> <p class="level-item">
<a class="button is-light is-small is-rounded" @click="open_search_playlists" v-text="$t('page.spotify.search.show-all-playlists', { count: playlists.total.toLocaleString() })" /> <a
class="button is-light is-small is-rounded"
@click="open_search_playlists"
v-text="
$t('page.spotify.search.show-all-playlists', {
count: playlists.total.toLocaleString()
})
"
/>
</p> </p>
</nav> </nav>
</template> </template>

View File

@ -6,11 +6,22 @@
<section v-if="$slots['options']"> <section v-if="$slots['options']">
<div ref="options_ref" style="height: 1px" /> <div ref="options_ref" style="height: 1px" />
<slot name="options" /> <slot name="options" />
<nav class="buttons is-centered" style="margin-bottom: 6px; margin-top: 16px"> <nav
<a v-if="!options_visible" class="button is-small is-white" @click="scroll_to_top"> class="buttons is-centered"
style="margin-bottom: 6px; margin-top: 16px"
>
<a
v-if="!options_visible"
class="button is-small is-white"
@click="scroll_to_top"
>
<mdicon class="icon is-small" name="chevron-down" size="16" /> <mdicon class="icon is-small" name="chevron-down" size="16" />
</a> </a>
<a v-else class="button is-small is-white" @click="scroll_to_content"> <a
v-else
class="button is-small is-white"
@click="scroll_to_content"
>
<mdicon class="icon is-small" name="chevron-up" size="16" /> <mdicon class="icon is-small" name="chevron-up" size="16" />
</a> </a>
</nav> </nav>

View File

@ -10,7 +10,10 @@
<!-- Slot heading right --> <!-- Slot heading right -->
<slot name="heading-right" /> <slot name="heading-right" />
</div> </div>
<div class="column is-three-fifths has-text-centered-mobile" style="margin: auto 0"> <div
class="column is-three-fifths has-text-centered-mobile"
style="margin: auto 0"
>
<!-- Slot heading left --> <!-- Slot heading left -->
<slot name="heading-left" /> <slot name="heading-left" />
</div> </div>

View File

@ -8,7 +8,11 @@ axios.interceptors.response.use(
function (error) { function (error) {
if (error.request.status && error.request.responseURL) { if (error.request.status && error.request.responseURL) {
store.dispatch('add_notification', { store.dispatch('add_notification', {
text: this.$t('server.request-failed', { status: error.request.status, cause: error.request.statusText, url: error.request.responseURL }), text: this.$t('server.request-failed', {
status: error.request.status,
cause: error.request.statusText,
url: error.request.responseURL
}),
type: 'danger' type: 'danger'
}) })
} }
@ -94,7 +98,9 @@ export default {
.post('./api/queue/items/add?uris=' + uri + '&position=' + position) .post('./api/queue/items/add?uris=' + uri + '&position=' + position)
.then((response) => { .then((response) => {
store.dispatch('add_notification', { store.dispatch('add_notification', {
text: this.$t('server.appended-tracks', { count: response.data.count }), text: this.$t('server.appended-tracks', {
count: response.data.count
}),
type: 'info', type: 'info',
timeout: 2000 timeout: 2000
}) })
@ -110,7 +116,9 @@ export default {
.post('./api/queue/items/add', undefined, { params: options }) .post('./api/queue/items/add', undefined, { params: options })
.then((response) => { .then((response) => {
store.dispatch('add_notification', { store.dispatch('add_notification', {
text: this.$t('server.appended-tracks', { count: response.data.count }), text: this.$t('server.appended-tracks', {
count: response.data.count
}),
type: 'info', type: 'info',
timeout: 2000 timeout: 2000
}) })
@ -130,7 +138,9 @@ export default {
.post('./api/queue/items/add', undefined, { params: options }) .post('./api/queue/items/add', undefined, { params: options })
.then((response) => { .then((response) => {
store.dispatch('add_notification', { store.dispatch('add_notification', {
text: this.$t('server.appended-tracks', { count: response.data.count }), text: this.$t('server.appended-tracks', {
count: response.data.count
}),
type: 'info', type: 'info',
timeout: 2000 timeout: 2000
}) })