improvements to library-songs
This commit is contained in:
parent
a373cb196b
commit
70f02d38e0
7 changed files with 235 additions and 88 deletions
7
index.js
7
index.js
|
@ -22,6 +22,13 @@ const configDefaults = {
|
|||
"followedArtists": [],
|
||||
"favoriteItems": []
|
||||
},
|
||||
"libraryPrefs": {
|
||||
"songs": {
|
||||
"sort": "name",
|
||||
"sortOrder": "asc",
|
||||
"size": "normal"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"quality": "990",
|
||||
"seamless_audio": true,
|
||||
|
|
|
@ -658,7 +658,7 @@ const app = new Vue({
|
|||
})
|
||||
},
|
||||
select_hasMediaItem(id) {
|
||||
let found = this.selectedMediaItems.find(item => item.guid == id)
|
||||
let found = this.selectedMediaItems.find(item => item.id == id)
|
||||
if (found) {
|
||||
return true
|
||||
} else {
|
||||
|
@ -1306,13 +1306,14 @@ const app = new Vue({
|
|||
},
|
||||
searchLibrarySongs() {
|
||||
let self = this
|
||||
let prefs = this.cfg.libraryPrefs.songs
|
||||
|
||||
function sortSongs() {
|
||||
// sort this.library.songs.displayListing by song.attributes[self.library.songs.sorting] in descending or ascending order based on alphabetical order and numeric order
|
||||
// check if song.attributes[self.library.songs.sorting] is a number and if so, sort by number if not, sort by alphabetical order ignoring case
|
||||
self.library.songs.displayListing.sort((a, b) => {
|
||||
let aa = a.attributes[self.library.songs.sorting]
|
||||
let bb = b.attributes[self.library.songs.sorting]
|
||||
let aa = a.attributes[prefs.sort]
|
||||
let bb = b.attributes[prefs.sort]
|
||||
if (self.library.songs.sorting == "genre") {
|
||||
aa = a.attributes.genreNames[0]
|
||||
bb = b.attributes.genreNames[0]
|
||||
|
@ -1323,13 +1324,13 @@ const app = new Vue({
|
|||
if (bb == null) {
|
||||
bb = ""
|
||||
}
|
||||
if (self.library.songs.sortOrder == "asc") {
|
||||
if (prefs.sortOrder == "asc") {
|
||||
if (aa.toString().match(/^\d+$/) && bb.toString().match(/^\d+$/)) {
|
||||
return aa - bb
|
||||
} else {
|
||||
return aa.toString().toLowerCase().localeCompare(bb.toString().toLowerCase())
|
||||
}
|
||||
} else if (self.library.songs.sortOrder == "desc") {
|
||||
} else if (prefs.sortOrder == "desc") {
|
||||
if (aa.toString().match(/^\d+$/) && bb.toString().match(/^\d+$/)) {
|
||||
return bb - aa
|
||||
} else {
|
||||
|
@ -1551,7 +1552,6 @@ const app = new Vue({
|
|||
this.library.songs.downloadState = 1
|
||||
this.library.downloadNotification.show = true
|
||||
this.library.downloadNotification.message = "Updating library songs..."
|
||||
|
||||
function downloadChunk() {
|
||||
const params = {
|
||||
"include[library-songs]": "catalog,artists,albums",
|
||||
|
@ -3077,6 +3077,41 @@ const app = new Vue({
|
|||
}
|
||||
})
|
||||
|
||||
Vue.component('animated-number', {
|
||||
|
||||
template:"<div style='display: inline-block;'>{{ displayNumber }}</div>",
|
||||
props: {'number': { default:0 }},
|
||||
|
||||
data () {
|
||||
return {
|
||||
displayNumber:0,
|
||||
interval:false
|
||||
}
|
||||
},
|
||||
|
||||
ready () {
|
||||
this.displayNumber = this.number ? this.number : 0;
|
||||
},
|
||||
|
||||
watch: {
|
||||
number () {
|
||||
clearInterval(this.interval);
|
||||
|
||||
if(this.number == this.displayNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.interval = window.setInterval(() => {
|
||||
if(this.displayNumber != this.number) {
|
||||
var change = (this.number - this.displayNumber) / 10;
|
||||
change = change >= 0 ? Math.ceil(change) : Math.floor(change);
|
||||
this.displayNumber = this.displayNumber + change;
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('sidebar-library-item', {
|
||||
template: '#sidebar-library-item',
|
||||
props: {
|
||||
|
|
|
@ -496,6 +496,19 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
background: rgb(0 0 0 / 15%);
|
||||
flex-direction: column;
|
||||
padding: 20px 0px;
|
||||
|
||||
&.libraryNotification {
|
||||
flex-direction: row;
|
||||
padding: 0px;
|
||||
.message {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.spinner {
|
||||
width: 46px;
|
||||
height: 30px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-sidebar-content {
|
||||
|
@ -1843,26 +1856,31 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
|
||||
.md-select {
|
||||
padding: 5px 10px;
|
||||
font-size: 1em;
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(200, 200, 200, 0.1);
|
||||
font-family: inherit;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgb(100 100 100 / 35%);
|
||||
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3), 0px 1px 1px rgba(0, 0, 0, 0.4);
|
||||
background: #363636;
|
||||
color: #eee;
|
||||
}
|
||||
font-size: 14px;
|
||||
background: rgba(100, 100, 100, 0.25);
|
||||
color: #c8c8c8;
|
||||
font-weight: 500;
|
||||
|
||||
.md-select:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.md-select > option {
|
||||
option {
|
||||
font-size: 1em;
|
||||
font-family: inherit;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
optgroup {
|
||||
background: #2c2c2c;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: solid 1px var(--selected);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-playlist {
|
||||
.folder-button-active {
|
||||
background: rgb(255 255 255 / 12%);
|
||||
|
@ -2238,6 +2256,27 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
}
|
||||
|
||||
// Library - Songs page
|
||||
.library-page {
|
||||
padding: 0px;
|
||||
.library-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-bottom: 1px solid rgba(200, 200, 200, 0.05);
|
||||
z-index: 6;
|
||||
background: black;
|
||||
padding: 0px 2em;
|
||||
backdrop-filter: blur(32px);
|
||||
background: rgba(24, 24, 24, 0.15);
|
||||
top: var(--navigationBarHeight);
|
||||
}
|
||||
|
||||
.well {
|
||||
margin: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Album / Playlist Page */
|
||||
.playlist-page {
|
||||
--bgColor: transparent;
|
||||
|
@ -2835,11 +2874,11 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
|
||||
.info-rect {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
|
@ -2848,7 +2887,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
.subtitle {
|
||||
width: 90%;
|
||||
font-size: 12px;
|
||||
font-size: .8em;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
@ -2870,21 +2909,18 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.content-rating {
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
border-radius: 3px;
|
||||
background: rgb(200 200 200 / 15%);
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 auto;
|
||||
font-weight: 500;
|
||||
color: #ccc;
|
||||
.explicit-icon {
|
||||
background-image: url("./assets/explicit.svg");
|
||||
height: 12px;
|
||||
width: 36px;
|
||||
filter: contrast(0);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.isLibrary {
|
||||
flex: 0 0 auto;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
button {
|
||||
appearance: none;
|
||||
border: 0px;
|
||||
|
@ -2913,6 +2949,19 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
box-shadow: var(--mediaItemShadow);
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
// list item compact
|
||||
&.compact {
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
.artwork {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-rect {
|
||||
padding-left: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* mediaitem-hrect */
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
:data-guid="guid"
|
||||
:data-islibrary="this.item.attributes.playParams.isLibrary ?? false"
|
||||
class="cd-mediaitem-list-item"
|
||||
:class="{'mediaitem-selected': app.select_hasMediaItem(guid)}">
|
||||
:class="[{'mediaitem-selected': app.select_hasMediaItem(item.id)}, addClasses]">
|
||||
<template v-if="isVisible">
|
||||
<div class="isLibrary" v-if="showLibraryStatus == true">
|
||||
<button @click="addToLibrary()"
|
||||
|
@ -44,9 +44,7 @@
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-rating" v-if="item.attributes.contentRating" @dblclick="app.routeView(item)">
|
||||
{{ item.attributes.contentRating }}
|
||||
</div>
|
||||
<div class="explicit-icon" v-if="item.attributes && item.attributes.contentRating == 'explicit'"></div>
|
||||
<template v-if="showMetaData == true" @dblclick="app.routeView(item)">
|
||||
<div class="metainfo">
|
||||
{{ item.attributes.releaseDate ? new Date(item.attributes.releaseDate).toLocaleDateString()
|
||||
|
@ -72,7 +70,8 @@
|
|||
addedToLibrary: false,
|
||||
guid: this.uuidv4(),
|
||||
app: this.$root,
|
||||
displayDuration: true
|
||||
displayDuration: true,
|
||||
addClasses: {}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
@ -84,14 +83,25 @@
|
|||
'show-meta-data': {type: Boolean, default: false},
|
||||
'show-duration': {type: Boolean, default: true},
|
||||
'contextExt': {type: Object, required: false},
|
||||
'class-list': {type: String, required: false, default: ""},
|
||||
},
|
||||
mounted() {
|
||||
let duration = this.item.attributes.durationInMillis ?? 0
|
||||
if (duration == 0 || !this.showDuration) {
|
||||
this.displayDuration = false
|
||||
}
|
||||
this.getClasses()
|
||||
},
|
||||
methods: {
|
||||
getClasses() {
|
||||
if(this.classList) {
|
||||
this.addClasses = {}
|
||||
let classList = this.classList.split(' ')
|
||||
for(let i = 0; i < classList.length; i++) {
|
||||
this.addClasses[classList[i]] = true
|
||||
}
|
||||
}
|
||||
},
|
||||
dragStart(evt) {
|
||||
evt.dataTransfer.setData('text/plain', JSON.stringify({
|
||||
type: this.item.attributes.playParams.kind ?? this.item.type,
|
||||
|
|
|
@ -269,14 +269,8 @@
|
|||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-sidebar-notification" v-if="library.downloadNotification.show">
|
||||
<div>{{ library.downloadNotification.message }}</div>
|
||||
<div>{{ library.downloadNotification.progress }} / {{ library.downloadNotification.total }}
|
||||
</div>
|
||||
<div style="width: 100%">
|
||||
<progress style="width: 80%;" :value="library.downloadNotification.progress"
|
||||
:max="library.downloadNotification.total"></progress>
|
||||
</div>
|
||||
<div class="app-sidebar-notification libraryNotification" v-if="library.downloadNotification.show">
|
||||
<div class="message">{{ library.downloadNotification.message }} ({{ library.downloadNotification.progress }} / {{ library.downloadNotification.total }})</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app-content">
|
||||
|
@ -427,7 +421,9 @@
|
|||
</transition>
|
||||
<!-- Library - Songs -->
|
||||
<transition name="wpfade" v-on:enter="getLibrarySongsFull()">
|
||||
<%- include('pages/library-songs') %>
|
||||
<template v-if="page == 'library-songs'">
|
||||
<cider-library-songs :data="library.songs"></cider-library-songs>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Library - Albums -->
|
||||
<transition name="wpfade" v-on:enter="getLibraryAlbumsFull(null, 1); searchLibraryAlbums(1);">
|
||||
|
@ -528,6 +524,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Library - Songs -->
|
||||
<%- include('pages/library-songs') %>
|
||||
|
||||
<!-- Media Item Artwork-->
|
||||
<%- include("components/mediaitem-artwork"); %>
|
||||
<!-- Browse -->
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
<template v-if="page == 'library-songs'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0;">
|
||||
<h1 class="header-text">Songs</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button v-if="library.songs.downloadState == 2" @click="getLibrarySongsFull(true)" class="reload-btn"><%- include('../svg/redo.svg') %></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/x-template" id="cider-library-songs">
|
||||
<div class="content-inner library-page">
|
||||
<div class="library-header">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0;">
|
||||
|
@ -16,31 +11,70 @@
|
|||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="searchLibrarySongs"
|
||||
@input="$root.searchLibrarySongs"
|
||||
v-model="library.songs.search" class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.songs.sorting" @change="searchLibrarySongs()">
|
||||
<select class="md-select" v-model="prefs.sort" @change="$root.searchLibrarySongs()">
|
||||
<optgroup label="Sort By">
|
||||
<option v-for="(sort, index) in library.songs.sortingOptions" :value="index">{{ sort }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.songs.sortOrder" @change="searchLibrarySongs()">
|
||||
<select class="md-select" v-model="prefs.sortOrder" @change="$root.searchLibrarySongs()">
|
||||
<optgroup label="Sort Order">
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="prefs.size" @change="$root.searchLibrarySongs()">
|
||||
<optgroup label="Size">
|
||||
<option value="normal">Normal</option>
|
||||
<option value="compact">Compact</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<button v-if="library.songs.downloadState == 2" @click="$root.getLibrarySongsFull(true)" class="reload-btn"><%- include('../svg/redo.svg') %></button>
|
||||
<button v-else class="reload-btn" style="opacity: 0.8;pointer-events: none">
|
||||
<div class="spinner"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="library.songs.downloadState == 3">Library contains no songs.</div>
|
||||
<div class="well" :key="1" v-if="prefs.size == 'compact'">
|
||||
<mediaitem-list-item class-list="compact" :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
|
||||
</div>
|
||||
<div class="well" :key="2" v-else>
|
||||
<mediaitem-list-item :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-library-songs', {
|
||||
template: '#cider-library-songs',
|
||||
data: function () {
|
||||
return {
|
||||
library: this.$root.library,
|
||||
mediaItemSize: "compact",
|
||||
prefs: this.$root.cfg.libraryPrefs.songs
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sayHello: function () {
|
||||
alert('Hello world!');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
13
src/renderer/views/svg/in-library.svg
Normal file
13
src/renderer/views/svg/in-library.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 214 214" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-79.4309,9.53659)">
|
||||
<path d="M250.163,76.146C250.163,52.589 231.037,33.463 207.48,33.463L122.114,33.463C98.556,33.463 79.431,52.589 79.431,76.146L79.431,161.512C79.431,185.07 98.556,204.195 122.114,204.195L207.48,204.195C231.037,204.195 250.163,185.07 250.163,161.512L250.163,76.146ZM235.163,83.646C235.163,64.228 219.398,48.463 199.98,48.463L129.614,48.463C110.196,48.463 94.431,64.228 94.431,83.646L94.431,154.012C94.431,173.43 110.196,189.195 129.614,189.195L199.98,189.195C219.398,189.195 235.163,173.43 235.163,154.012L235.163,83.646Z" style="fill:currentColor;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.906286,0,0,0.906286,-20.9871,-22.3274)">
|
||||
<path d="M250.163,76.146C250.163,52.589 231.037,33.463 207.48,33.463L122.114,33.463C98.556,33.463 79.431,52.589 79.431,76.146L79.431,161.512C79.431,185.07 98.556,204.195 122.114,204.195L207.48,204.195C231.037,204.195 250.163,185.07 250.163,161.512L250.163,76.146Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.333526,0,0,0.333526,43.0167,0)">
|
||||
<path d="M511.8,130.7C511.8,115 510.5,99.3 506.7,84C500,56 484,34.7 460.2,19C448,11 434.5,6.1 420.1,3.5C409.1,1.5 397.9,0.6 386.8,0.3L384.1,0L127.6,0C124.4,0.3 121.1,0.4 117.9,0.6C102,1.5 86.2,3.2 71.1,9.2C42.7,20.4 22.1,40.1 10.1,68.4C5.9,78 3.8,88.2 2.3,98.5C1.1,106.8 0.4,115.3 0.1,123.7L-0.1,125.7L-0.1,386.4C0.1,389.4 0.2,392.4 0.4,395.4C1.5,412.8 3.7,430.1 11.1,446.1C24.9,476.4 48.2,496.3 80.1,505.8C89,508.6 98.3,509.8 107.7,510.6C119.5,511.8 131.4,511.9 143.2,511.9L378.5,511.9C389.7,511.9 400.8,511.2 412,509.7C429.6,507.5 446.1,502.3 461,492.5C478.9,480.7 492.4,465 501.1,445.4C505.1,436.4 507.3,426.8 509,417.2C511.4,402.8 511.9,388.2 511.9,373.6C511.8,292.6 511.9,211.6 511.8,130.6L511.8,130.7ZM374.8,93.4L374.8,337.6C374.8,346.5 373.6,355.3 369.6,363.3C363.4,375.9 353.4,383.8 340,387.6C332.6,389.8 324.9,390.9 317.2,391.3C297,392.3 279.4,378.6 275.8,358.6C272.7,342.1 280.6,323.9 298,315.4C304.8,312.1 312.2,310.1 319.7,308.6C327.8,306.9 335.9,305.3 343.9,303.4C349.8,302.1 353.6,298.5 354.8,292.4L355.2,288.3L355.2,172.1L354.6,168.2C353.8,165 351.4,163 348.1,163.2C344.7,163.4 341.4,163.9 338,164.6C321.7,167.8 305.5,171 289.3,174.3L210.4,190.2L209.3,190.5C203.4,192.2 201.3,194.8 201,201L201,203.7C200.9,259.2 201,314.7 200.9,370.2C200.9,379.2 199.9,388 196.3,396.4C190.4,410.1 179.9,418.7 165.7,422.7C158.2,424.9 150.5,426.1 142.7,426.4C122.3,427.2 105.3,413.6 101.8,393.5C98.8,376.2 106.7,357.5 126.4,349.2C134.1,346 142,344.3 150.1,342.6C156.2,341.4 162.4,340.1 168.4,338.9C176.6,337.2 180.8,332 181.2,323.7L181.2,131C181.2,128.3 181.5,125.7 182.1,123.1C183.6,117 187.9,113.5 193.8,112.1C199.2,110.7 204.8,109.7 210.3,108.5C226,105.3 241.5,102.2 257.2,99.1L305.6,89.3C319.9,86.5 334.2,83.6 348.5,80.7C353.2,79.8 357.9,78.8 362.7,78.4C369.3,77.8 373.9,82 374.5,88.7C374.7,90.3 374.8,91.9 374.8,93.4Z" style="fill:currentColor;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
Loading…
Add table
Add a link
Reference in a new issue