Merge pull request #980 from chme/web_next

Player web interface fixes
This commit is contained in:
Christian Meffert 2020-05-04 20:09:10 +02:00 committed by GitHub
commit 77165d834c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 105 additions and 40 deletions

View File

@ -1,2 +1,2 @@
.fd-notifications{position:fixed;bottom:60px;z-index:20000;width:100%}.fd-notifications .notification{margin-bottom:10px;margin-left:24px;margin-right:24px;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.slider{min-width:250px;width:100%}.range-slider-fill{background-color:#363636}.track-progress{margin:0;padding:0;min-width:250px;width:100%}.track-progress .range-slider-knob{visibility:hidden}.track-progress .range-slider-fill{background-color:#3273dc;height:2px}.track-progress .range-slider-rail{background-color:#fff}.media.with-progress h2:last-of-type{margin-bottom:6px}.media.with-progress{margin-top:0}a.navbar-item{outline:0;line-height:1.5;padding:.5rem 1rem}.fd-expanded{flex-grow:1;flex-shrink:1}.fd-margin-left-auto{margin-left:auto}.fd-has-action{cursor:pointer}.fd-is-movable{cursor:move}.fd-has-margin-top{margin-top:24px}.fd-has-margin-bottom{margin-bottom:24px}.fd-remove-padding-bottom{padding-bottom:0}.fd-has-padding-left-right{padding-left:24px;padding-right:24px}.fd-is-square .button{height:27px;width:27px}.fd-is-text-clipped{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fd-tabs-section{padding-bottom:3px;padding-top:3px;background:#fff;top:3.25rem;z-index:20;position:fixed;width:100%}section.fd-tabs-section+section.fd-content{margin-top:24px}.fd-progress-bar{top:52px!important}.fd-has-shadow{box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.fd-is-fullheight{height:calc(100vh - 6.5rem);display:flex;flex-direction:column;justify-content:center}.fd-is-fullheight .fd-is-expanded{max-height:calc(100vh - 25rem);padding:1.5rem;overflow:hidden;flex-grow:1;flex-shrink:1}.fd-cover-image{height:100%}.fd-cover-image img{width:100%;height:100%;object-fit:contain;object-position:bottom;-webkit-filter:drop-shadow(0 0 1px rgba(0,0,0,.3)) drop-shadow(0 0 10px rgba(0,0,0,.3));filter:drop-shadow(0 0 1px rgba(0,0,0,.3)) drop-shadow(0 0 10px rgba(0,0,0,.3))}.sortable-chosen .media-right{visibility:hidden}.sortable-ghost h1,.sortable-ghost h2{color:#ff3860!important}.media:first-of-type{padding-top:17px;margin-top:16px}.fade-enter-active,.fade-leave-active{transition:opacity .4s}.fade-enter,.fade-leave-to{opacity:0}.seek-slider{min-width:250px;max-width:500px;width:100%!important}.seek-slider .range-slider-fill{background-color:#00d1b2;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.seek-slider .range-slider-knob{width:10px;height:10px;background-color:#00d1b2;border-color:#00d1b2}.title:not(.is-spaced)+.subtitle,.title:not(.is-spaced)+.subtitle+.subtitle{margin-top:-1.3rem!important}.fd-modal-card{overflow:visible}.fd-modal-card .card-content{max-height:calc(100vh - 200px);overflow:auto}.fd-modal-card .card{margin-left:16px;margin-right:16px}.dropdown-item a{display:block}.dropdown-item:hover{background-color:#f5f5f5} .fd-notifications{position:fixed;bottom:60px;z-index:20000;width:100%}.fd-notifications .notification{margin-bottom:10px;margin-left:24px;margin-right:24px;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.slider{min-width:250px;width:100%}.range-slider-fill{background-color:#363636}.track-progress{margin:0;padding:0;min-width:250px;width:100%}.track-progress .range-slider-knob{visibility:hidden}.track-progress .range-slider-fill{background-color:#3273dc;height:2px}.track-progress .range-slider-rail{background-color:#fff}.media.with-progress h2:last-of-type{margin-bottom:6px}.media.with-progress{margin-top:0}a.navbar-item{outline:0;line-height:1.5;padding:.5rem 1rem}.fd-expanded{flex-grow:1;flex-shrink:1}.fd-margin-left-auto{margin-left:auto}.fd-has-action{cursor:pointer}.fd-is-movable{cursor:move}.fd-has-margin-top{margin-top:24px}.fd-has-margin-bottom{margin-bottom:24px}.fd-remove-padding-bottom{padding-bottom:0}.fd-has-padding-left-right{padding-left:24px;padding-right:24px}.fd-is-square .button{height:27px;width:27px}.fd-is-text-clipped{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fd-tabs-section{padding-bottom:3px;padding-top:3px;background:#fff;top:3.25rem;z-index:20;position:fixed;width:100%}section.fd-tabs-section+section.fd-content{margin-top:24px}.fd-progress-bar{top:52px!important}.fd-has-shadow{box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.fd-is-fullheight{height:calc(100vh - 6.5rem);display:flex;flex-direction:column;justify-content:center}.fd-is-fullheight .fd-is-expanded{max-height:calc(100vh - 25rem);padding:1.5rem}.fd-cover-image,.fd-is-fullheight .fd-is-expanded{overflow:hidden;flex-grow:1;flex-shrink:1;display:flex}.fd-cover-image,.fd-cover-image img{min-width:0;min-height:0}.fd-cover-image img{object-fit:contain;object-position:center bottom;-webkit-filter:drop-shadow(0 0 1px rgba(0,0,0,.3)) drop-shadow(0 0 10px rgba(0,0,0,.3));filter:drop-shadow(0 0 1px rgba(0,0,0,.3)) drop-shadow(0 0 10px rgba(0,0,0,.3));flex-grow:1;flex-shrink:1;height:unset;width:unset;max-width:unset;max-height:unset;overflow:hidden}.sortable-chosen .media-right{visibility:hidden}.sortable-ghost h1,.sortable-ghost h2{color:#ff3860!important}.media:first-of-type{padding-top:17px;margin-top:16px}.fade-enter-active,.fade-leave-active{transition:opacity .4s}.fade-enter,.fade-leave-to{opacity:0}.seek-slider{min-width:250px;max-width:500px;width:100%!important}.seek-slider .range-slider-fill{background-color:#00d1b2;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.seek-slider .range-slider-knob{width:10px;height:10px;background-color:#00d1b2;border-color:#00d1b2}.title:not(.is-spaced)+.subtitle,.title:not(.is-spaced)+.subtitle+.subtitle{margin-top:-1.3rem!important}.fd-modal-card{overflow:visible}.fd-modal-card .card-content{max-height:calc(100vh - 200px);overflow:auto}.fd-modal-card .card{margin-left:16px;margin-right:16px}.dropdown-item a{display:block}.dropdown-item:hover{background-color:#f5f5f5}.navbar-item .fd-navbar-item-level2{padding-left:1.5rem}hr.fd-navbar-divider{margin:12px 0}@media only screen and (min-width:1024px){.navbar-dropdown{max-height:calc(100vh - 8.5rem);overflow:auto}}.fd-bottom-navbar .navbar-menu{max-height:calc(100vh - 7.5rem);overflow:scroll}
/*# sourceMappingURL=app.css.map */ /*# sourceMappingURL=app.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
web-src/.env.development Normal file
View File

@ -0,0 +1,2 @@
VUE_APP_JSON_API_SERVER='http://localhost:3689'
VUE_APP_WEBSOCKET_SERVER='ws://localhost:3688'

View File

@ -1,6 +1,6 @@
{ {
"name": "forked-daapd-web", "name": "forked-daapd-web",
"version": "0.7.0", "version": "0.7.1",
"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>",

View File

@ -111,8 +111,14 @@ export default {
protocol = 'wss://' protocol = 'wss://'
} }
var wsUrl = protocol + window.location.hostname + ':' + vm.$store.state.config.websocket_port
if (process.env.NODE_ENV === 'development' && process.env.VUE_APP_WEBSOCKET_SERVER) {
// If we are running in the development server, use the websocket url configured in .env.development
wsUrl = process.env.VUE_APP_WEBSOCKET_SERVER
}
var socket = new ReconnectingWebSocket( var socket = new ReconnectingWebSocket(
protocol + window.location.hostname + ':' + vm.$store.state.config.websocket_port, wsUrl,
'notify', 'notify',
{ reconnectInterval: 3000 } { reconnectInterval: 3000 }
) )

View File

@ -1,5 +1,5 @@
<template> <template>
<nav class="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 -->
@ -68,11 +68,11 @@
</div> </div>
<!-- Outputs: master volume --> <!-- Outputs: master volume -->
<hr class="navbar-divider"> <hr class="fd-navbar-divider">
<navbar-item-output v-for="output in outputs" :key="output.id" :output="output"></navbar-item-output> <navbar-item-output v-for="output in outputs" :key="output.id" :output="output"></navbar-item-output>
<!-- Outputs: stream volume --> <!-- Outputs: stream volume -->
<hr class="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">
@ -98,7 +98,7 @@
</div> </div>
<!-- Playback controls --> <!-- Playback controls -->
<hr class="navbar-divider"> <hr class="fd-navbar-divider">
<div class="navbar-item"> <div class="navbar-item">
<div class="level is-mobile fd-expanded"> <div class="level is-mobile fd-expanded">
<div class="level-item"> <div class="level-item">
@ -115,8 +115,7 @@
</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" style="max-height: calc(100vh - 3.25rem); overflow: scroll" <div class="navbar-menu is-hidden-desktop" :class="{ 'is-active': show_player_menu }">
:class="{ 'is-active': show_player_menu }">
<div class="navbar-start"> <div class="navbar-start">
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
@ -129,7 +128,7 @@
</div> </div>
</div> </div>
<hr style="margin: 12px 0;"> <hr class="fd-navbar-divider">
<!-- Outputs: master volume --> <!-- Outputs: master volume -->
<div class="navbar-item"> <div class="navbar-item">
@ -161,7 +160,7 @@
<navbar-item-output v-for="output in outputs" :key="output.id" :output="output"></navbar-item-output> <navbar-item-output v-for="output in outputs" :key="output.id" :output="output"></navbar-item-output>
<!-- Outputs: stream volume --> <!-- Outputs: stream volume -->
<hr class="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">

View File

@ -3,7 +3,13 @@
<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"><span class="icon fd-has-action" :class="{ 'has-text-grey-light': !output.selected }" v-on:click="set_enabled"><i class="mdi mdi-18px" v-bind:class="type_class"></i></span></a> <a class="button is-white is-small">
<span class="icon fd-has-action"
:class="{ 'has-text-grey-light': !output.selected }"
v-on:click="set_enabled">
<i class="mdi mdi-18px" :class="type_class"></i>
</span>
</a>
</div> </div>
<div class="level-item fd-expanded"> <div class="level-item fd-expanded">
<div class="fd-expanded"> <div class="fd-expanded">
@ -38,6 +44,8 @@ export default {
type_class () { type_class () {
if (this.output.type === 'AirPlay') { if (this.output.type === 'AirPlay') {
return 'mdi-airplay' return 'mdi-airplay'
} else if (this.output.type === 'Chromecast') {
return 'mdi-cast'
} else if (this.output.type === 'fifo') { } else if (this.output.type === 'fifo') {
return 'mdi-pipe' return 'mdi-pipe'
} else { } else {

View File

@ -1,5 +1,5 @@
<template> <template>
<nav class="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 to="/playlists"> <navbar-item-link to="/playlists">
<span class="icon"><i class="mdi mdi-library-music"></i></span> <span class="icon"><i class="mdi mdi-library-music"></i></span>
@ -46,20 +46,23 @@
<navbar-item-link to="/playlists"><span class="icon"><i class="mdi mdi-library-music"></i></span> <b>Playlists</b></navbar-item-link> <navbar-item-link to="/playlists"><span class="icon"><i class="mdi mdi-library-music"></i></span> <b>Playlists</b></navbar-item-link>
<navbar-item-link to="/music" exact><span class="icon"><i class="mdi mdi-music"></i></span> <b>Music</b></navbar-item-link> <navbar-item-link to="/music" exact><span class="icon"><i class="mdi mdi-music"></i></span> <b>Music</b></navbar-item-link>
<navbar-item-link to="/music/artists"><span style="padding-left: 1.5rem;">Artists</span></navbar-item-link> <navbar-item-link to="/music/artists"><span class="fd-navbar-item-level2">Artists</span></navbar-item-link>
<navbar-item-link to="/music/albums"><span style="padding-left: 1.5rem;">Albums</span></navbar-item-link> <navbar-item-link to="/music/albums"><span class="fd-navbar-item-level2">Albums</span></navbar-item-link>
<navbar-item-link to="/music/genres"><span style="padding-left: 1.5rem;">Genres</span></navbar-item-link> <navbar-item-link to="/music/genres"><span class="fd-navbar-item-level2">Genres</span></navbar-item-link>
<navbar-item-link to="/music/spotify" v-if="spotify_enabled"><span style="padding-left: 1.5rem;">Spotify</span></navbar-item-link> <navbar-item-link to="/music/spotify" v-if="spotify_enabled"><span class="fd-navbar-item-level2">Spotify</span></navbar-item-link>
<navbar-item-link to="/podcasts"><span class="icon"><i class="mdi mdi-microphone"></i></span> <b>Podcasts</b></navbar-item-link> <navbar-item-link to="/podcasts"><span class="icon"><i class="mdi mdi-microphone"></i></span> <b>Podcasts</b></navbar-item-link>
<navbar-item-link to="/audiobooks"><span class="icon"><i class="mdi mdi-book-open-variant"></i></span> <b>Audiobooks</b></navbar-item-link> <navbar-item-link to="/audiobooks"><span class="icon"><i class="mdi mdi-book-open-variant"></i></span> <b>Audiobooks</b></navbar-item-link>
<navbar-item-link to="/files"><span class="icon"><i class="mdi mdi-folder-open"></i></span> <b>Files</b></navbar-item-link> <navbar-item-link to="/files"><span class="icon"><i class="mdi mdi-folder-open"></i></span> <b>Files</b></navbar-item-link>
<navbar-item-link to="/search"><span class="icon"><i class="mdi mdi-magnify"></i></span> <b>Search</b></navbar-item-link> <navbar-item-link to="/search"><span class="icon"><i class="mdi mdi-magnify"></i></span> <b>Search</b></navbar-item-link>
<hr style="margin: 12px 0;"> <hr class="fd-navbar-divider">
<a class="navbar-item" href="/admin.html">Admin</a> <a class="navbar-item" href="/admin.html">Admin</a>
<hr style="margin: 12px 0;"> <hr class="fd-navbar-divider">
<navbar-item-link to="/settings/webinterface">Settings</navbar-item-link> <navbar-item-link to="/settings/webinterface">Settings</navbar-item-link>
<navbar-item-link to="/about">About</navbar-item-link> <navbar-item-link to="/about">About</navbar-item-link>
<div class="navbar-item is-hidden-desktop" style="margin-bottom: 2.5rem;"></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -122,18 +122,42 @@ section.fd-tabs-section + section.fd-content {
overflow: hidden; overflow: hidden;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
/* Use flex box to properly size children */
display: flex;
} }
.fd-cover-image { .fd-cover-image {
height: 100%; display: flex;
flex-grow: 1;
flex-shrink: 1;
/* Allow flex item to shrink smaller than its content size: https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size */
min-width: 0;
min-height: 0;
overflow: hidden;
} }
.fd-cover-image img { .fd-cover-image img {
width: 100%; /* Use object-fit to properly size the cover artwork: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit */
height: 100%;
object-fit: contain; object-fit: contain;
object-position: bottom; object-position: center bottom;
filter: drop-shadow(0px 0px 1px rgba(0,0,0,.3)) drop-shadow(0px 0px 10px rgba(0,0,0,.3)); filter: drop-shadow(0px 0px 1px rgba(0,0,0,.3)) drop-shadow(0px 0px 10px rgba(0,0,0,.3));
/* Allow flex item to grow/shrink to fill the whole container size */
flex-grow: 1;
flex-shrink: 1;
/* Unset height/width to allow flex sizing */
height: unset;
width: unset;
max-width: unset;
max-height: unset;
/* Allow flex item to shrink smaller than its content size: https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size */
min-width: 0;
min-height: 0;
overflow: hidden;
} }
@ -202,3 +226,24 @@ section.fd-tabs-section + section.fd-content {
.dropdown-item:hover { .dropdown-item:hover {
background-color: hsl(0, 0%, 96%) background-color: hsl(0, 0%, 96%)
} }
.navbar-item .fd-navbar-item-level2 {
padding-left: 1.5rem;
}
hr.fd-navbar-divider {
margin: 12px 0;
}
/* Show scrollbar for navbar menu in desktop mode if content exceeds the screen size */
@media only screen and (min-width: 1024px) {
.navbar-dropdown {
max-height: calc(100vh - 3.25rem - 3.25rem - 2rem);
overflow: auto;
}
}
/* Limit the size of the bottom navbar menu to not be displayed behind the Safari browser menu on iOS */
.fd-bottom-navbar .navbar-menu {
max-height: calc(100vh - 3.25rem - 3.25rem - 1rem);
overflow: scroll;
}

View File

@ -43,16 +43,18 @@
</div> </div>
</div> </div>
</div> </div>
<div v-else class="fd-is-fullheight" style="justify-content: center;"> <div v-else class="fd-is-fullheight">
<div class="fd-is-expanded fd-has-padding-left-right has-text-centered"> <div class="fd-is-expanded fd-has-padding-left-right" style="flex-direction: column;">
<div class="content has-text-centered">
<h1 class="title is-5"> <h1 class="title is-5">
You play queue is empty Your play queue is empty
</h1> </h1>
<p class="content"> <p>
Add some tracks by browsing your library Add some tracks by browsing your library
</p> </p>
</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

@ -15,7 +15,7 @@
</p> </p>
<p>In addition to that, you can enable fetching artwork from the following artwork providers:</p> <p>In addition to that, you can enable fetching artwork from the following artwork providers:</p>
</div> </div>
<settings-checkbox category_name="artwork" option_name="use_artwork_source_spotify" v-if="spotify.enabled"> <settings-checkbox category_name="artwork" option_name="use_artwork_source_spotify" v-if="spotify.libspotify_logged_in">
<template slot="label"> Spotify</template> <template slot="label"> Spotify</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">

View File

@ -24,13 +24,13 @@ module.exports = {
// localhost:3689 // localhost:3689
proxy: { proxy: {
'/api': { '/api': {
target: 'http://localhost:3689' target: process.env.VUE_APP_JSON_API_SERVER
}, },
'/artwork': { '/artwork': {
target: 'http://localhost:3689' target: process.env.VUE_APP_JSON_API_SERVER
}, },
'/stream.mp3': { '/stream.mp3': {
target: 'http://localhost:3689' target: process.env.VUE_APP_JSON_API_SERVER
} }
} }
} }