[web-src] Show album cover artwork in album page

This commit is contained in:
chme 2020-05-16 06:14:21 +02:00
parent a2ec7ee28f
commit d2b5e82837
8 changed files with 671 additions and 935 deletions

1442
web-src/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "forked-daapd-web", "name": "forked-daapd-web",
"version": "0.7.1", "version": "0.7.2",
"private": true, "private": true,
"description": "forked-daapd web interface", "description": "forked-daapd web interface",
"author": "chme <christian.meffert@googlemail.com>", "author": "chme <christian.meffert@googlemail.com>",
@ -15,11 +15,11 @@
"bulma": "^0.8.2", "bulma": "^0.8.2",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"mdi": "^2.2.43", "mdi": "^2.2.43",
"moment": "^2.24.0", "moment": "^2.25.3",
"moment-duration-format": "^2.3.2", "moment-duration-format": "^2.3.2",
"npm": "^6.14.4", "npm": "^6.14.5",
"reconnectingwebsocket": "^1.0.0", "reconnectingwebsocket": "^1.0.0",
"spotify-web-api-js": "^1.2.0", "spotify-web-api-js": "^1.4.0",
"string-to-color": "^2.1.3", "string-to-color": "^2.1.3",
"v-click-outside": "^3.0.1", "v-click-outside": "^3.0.1",
"vue": "^2.6.11", "vue": "^2.6.11",
@ -27,8 +27,9 @@
"vue-progressbar": "^0.7.5", "vue-progressbar": "^0.7.5",
"vue-range-slider": "^0.6.0", "vue-range-slider": "^0.6.0",
"vue-router": "^3.1.6", "vue-router": "^3.1.6",
"vue-tiny-lazyload-img": "^0.1.0",
"vuedraggable": "^2.23.2", "vuedraggable": "^2.23.2",
"vuex": "^3.1.3" "vuex": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.3.1", "@vue/cli-plugin-babel": "^4.3.1",
@ -42,6 +43,8 @@
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1", "eslint-plugin-standard": "^4.0.1",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11" "vue-template-compiler": "^2.6.11"
}, },
"license": "GPL-2.0" "license": "GPL-2.0"

View File

@ -1,15 +1,9 @@
<template> <template>
<figure> <figure>
<img <img v-lazyload
v-show="artwork_visible"
:src="artwork_url_with_size"
@load="artwork_loaded"
@error="artwork_error"
@click="$emit('click')">
<img
v-show="!artwork_visible"
:src="dataURI" :src="dataURI"
:alt="alt_text" :data-src="artwork_url_with_size"
:data-err="dataURI"
@click="$emit('click')"> @click="$emit('click')">
</figure> </figure>
</template> </template>
@ -30,9 +24,7 @@ export default {
height: 600, height: 600,
font_family: 'sans-serif', font_family: 'sans-serif',
font_size: 200, font_size: 200,
font_weight: 600, font_weight: 600
artwork_visible: false
} }
}, },
@ -95,16 +87,6 @@ export default {
dataURI () { dataURI () {
return this.svg.render(this.rendererParams) return this.svg.render(this.rendererParams)
} }
},
methods: {
artwork_loaded: function () {
this.artwork_visible = true
},
artwork_error: function () {
this.artwork_visible = false
}
} }
} }
</script> </script>

View File

@ -1,10 +1,13 @@
<template functional> <template functional>
<div class="media" :id="'index_' + props.album.name_sort.charAt(0).toUpperCase()"> <div class="media" :id="'index_' + props.album.name_sort.charAt(0).toUpperCase()">
<slot name="artwork"></slot>
<div class="media-content fd-has-action is-clipped" @click="listeners.click"> <div class="media-content fd-has-action is-clipped" @click="listeners.click">
<h1 class="title is-6">{{ props.album.name }}</h1> <div style="margin-top:0.7rem;">
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.album.artist }}</b></h2> <h1 class="title is-6">{{ props.album.name }}</h1>
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.album.artist }}</b></h2>
</div>
</div> </div>
<div class="media-right"> <div class="media-right" style="padding-top:0.7rem;">
<slot name="actions"></slot> <slot name="actions"></slot>
</div> </div>
</div> </div>

View File

@ -7,14 +7,14 @@ import store from './store'
import './filter' import './filter'
import './progress' import './progress'
import vClickOutside from 'v-click-outside' import vClickOutside from 'v-click-outside'
import 'bulma/css/bulma.css' import VueTinyLazyloadImg from 'vue-tiny-lazyload-img'
import 'mdi/css/materialdesignicons.css' import 'mdi/css/materialdesignicons.css'
import 'vue-range-slider/dist/vue-range-slider.css' import 'vue-range-slider/dist/vue-range-slider.css'
import './mystyles.css' import './mystyles.scss'
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.use(vClickOutside) Vue.use(vClickOutside)
Vue.use(VueTinyLazyloadImg)
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({

View File

@ -1,4 +1,7 @@
@import 'bulma';
.slider { .slider {
min-width: 250px; min-width: 250px;
width: 100%; width: 100%;
@ -246,4 +249,32 @@ hr.fd-navbar-divider {
.fd-bottom-navbar .navbar-menu { .fd-bottom-navbar .navbar-menu {
max-height: calc(100vh - 3.25rem - 3.25rem - 1rem); max-height: calc(100vh - 3.25rem - 3.25rem - 1rem);
overflow: scroll; overflow: scroll;
}
.buttons {
@include mobile {
&.fd-is-centered-mobile {
justify-content: center;
&:not(.has-addons) {
.button:not(.is-fullwidth) {
margin-left: 0.25rem;
margin-right: 0.25rem;
}
}
}
}
}
.column {
&.fd-has-cover {
max-height: 256px;
max-width: 256px;
@include mobile {
margin: auto;
}
@include from($tablet) {
margin: auto 0 auto auto;
}
}
} }

View File

@ -1,21 +1,29 @@
<template> <template>
<content-with-heading> <content-with-hero>
<template slot="heading-left"> <template slot="heading-left">
<div class="title is-4">{{ album.name }}</div> <h1 class="title is-4 fd-has-margin-top">{{ album.name }}</h1>
<a class="title is-4 has-text-link has-text-weight-normal" @click="open_artist">{{ album.artist }}</a> <h2 class="subtitle is-4 has-text-link has-text-weight-normal"><a class="has-text-link" @click="open_artist">{{ album.artist }}</a></h2>
</template> <p class="heading has-text-centered-mobile">{{ album.track_count }} tracks</p>
<template slot="heading-right">
<div class="buttons is-centered"> <div class="buttons fd-is-centered-mobile fd-has-margin-top">
<a class="button is-small is-light is-rounded" @click="show_album_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span> <span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span>
</a> </a>
<a class="button is-small is-light is-rounded" @click="show_album_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
</div> </div>
</template> </template>
<template slot="heading-right">
<p class="image is-square fd-has-shadow">
<cover-artwork
:artwork_url="album.artwork_url"
:artist="album.artist"
:album="album.name"
class="" />
</p>
</template>
<template slot="content"> <template slot="content">
<p class="heading has-text-centered-mobile">{{ album.track_count }} tracks</p>
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" @click="play_track(index)"> <list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" @click="play_track(index)">
<template slot="actions"> <template slot="actions">
<a @click="open_dialog(track)"> <a @click="open_dialog(track)">
@ -26,15 +34,16 @@
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" /> <modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
<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-heading> </content-with-hero>
</template> </template>
<script> <script>
import { LoadDataBeforeEnterMixin } from './mixin' import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading' import ContentWithHero from '@/templates/ContentWithHero'
import ListItemTrack from '@/components/ListItemTrack' import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack' import ModalDialogTrack from '@/components/ModalDialogTrack'
import ModalDialogAlbum from '@/components/ModalDialogAlbum' import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import CoverArtwork from '@/components/CoverArtwork'
import webapi from '@/webapi' import webapi from '@/webapi'
const albumData = { const albumData = {
@ -54,7 +63,7 @@ const albumData = {
export default { export default {
name: 'PageAlbum', name: 'PageAlbum',
mixins: [LoadDataBeforeEnterMixin(albumData)], mixins: [LoadDataBeforeEnterMixin(albumData)],
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack, ModalDialogAlbum }, components: { ContentWithHero, ListItemTrack, ModalDialogTrack, ModalDialogAlbum, CoverArtwork },
data () { data () {
return { return {

View File

@ -0,0 +1,44 @@
<template>
<div>
<section class="hero is-light is-bold fd-content">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-four-fifths">
<div class="columns" style="flex-direction: row-reverse;">
<div class="column fd-has-cover">
<!-- Slot heading right -->
<slot name="heading-right"></slot>
</div>
<div class="column is-three-fifths has-text-centered-mobile">
<!-- Slot heading left -->
<slot name="heading-left"></slot>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="section fd-content">
<div class="container">
<div class="columns is-centered">
<div class="column is-four-fifths">
<!-- Slot content -->
<slot name="content"></slot>
<div style="margin-top: 16px;">
<!-- Slot footer -->
<slot name="footer"></slot>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
</script>
<style>
</style>