File structure update - all source files now in src directory, cider-ui renamed to renderer, main/backend-related files in main directory, base implementation of mpris and start of backend rework
This commit is contained in:
parent
29be5dd481
commit
7d3e513187
85 changed files with 114 additions and 10 deletions
19
src/renderer/views/pages/about.ejs
Normal file
19
src/renderer/views/pages/about.ejs
Normal file
|
@ -0,0 +1,19 @@
|
|||
Major thanks to the Cider Development Team and all of our contributors.
|
||||
|
||||
<p>"Apple Music" - Copyright © 2021 <a href="https://www.apple.com/" class="dt-footer__link"
|
||||
target="_blank"
|
||||
rel="noopener" data-dt-link-to-exclude="">Apple Inc.</a>
|
||||
All Rights
|
||||
Reserved.</p>
|
||||
|
||||
cryptofyre - Developer - https://github.com/cryptofyre
|
||||
Core - Developer - https://github.com/coredev-uk
|
||||
Quacksire - Developer - https://github.com/child-duckling
|
||||
booploops - Developer - https://github.com/booploops
|
||||
vapormusic - Developer - https://github.com/vapormusic
|
||||
Void - Social Communications Team - https://twitter.com/MoonyVoid
|
||||
NoseySG - Social Communications Team - https://twitter.com/noah_grose
|
||||
|
||||
<img class="md-contributors"
|
||||
onclick="window.open('https://github.com/ciderapp/Cider/graphs/contributors')"
|
||||
src="https://contrib.rocks/image?repo=ciderapp/Cider"/>
|
173
src/renderer/views/pages/artist.ejs
Normal file
173
src/renderer/views/pages/artist.ejs
Normal file
|
@ -0,0 +1,173 @@
|
|||
<script type="text/x-template" id="cider-artist">
|
||||
<div class="content-inner artist-page">
|
||||
<div class="artist-header" :style="getArtistPalette(data)">
|
||||
<animatedartwork-view
|
||||
v-if="data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)"
|
||||
:video="data.attributes.editorialVideo.motionArtistWide16x9.video ?? (data.attributes.editorialVideo.motionArtistFullscreen16x9.video ?? '')">
|
||||
</animatedartwork-view>
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;">
|
||||
<div class="artist-image" v-if="!(data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9))">
|
||||
<mediaitem-artwork
|
||||
:shadow="true"
|
||||
|
||||
:url="data.attributes.artwork ? data.attributes.artwork.url : ''"
|
||||
size="220" type="artists"></mediaitem-artwork>
|
||||
<button class="overlay-play" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
})">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col flex-center artist-title"
|
||||
:class="{'artist-animation-on': (data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)) }"
|
||||
>
|
||||
<button class="artist-play" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
})"><%- include("../svg/play.svg") %></button>
|
||||
<h1>{{ data.attributes.name }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<button class="artist-more" @click="artistMenu"></button>
|
||||
</div>
|
||||
<div class="artist-body">
|
||||
<div class="row well">
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<div class="col-auto" v-if="data.views['latest-release'].data.length != 0">
|
||||
<h3>Latest Release</h3>
|
||||
<div style="width: auto;margin: 0 auto;">
|
||||
<mediaitem-square-sp v-for="song in data.views['latest-release'].data"
|
||||
:item="song">
|
||||
</mediaitem-square-sp>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col" v-if="data.views['top-songs']">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<h3>Top Songs</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['top-songs'].data.length >= 10" style="padding:0px;">
|
||||
<button class="cd-btn-seeall" @click="app.showArtistView(data.id, data.attributes.name + ' - Top Songs', 'top-songs')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-list-item
|
||||
v-for="(song, index) in data.views['top-songs'].data.limit(topSongsExpanded ? 10 : 5)"
|
||||
:index="index"
|
||||
:item="song"></mediaitem-list-item>
|
||||
<button class="showmoreless"
|
||||
@click="topSongsExpanded = !topSongsExpanded">
|
||||
<template v-if="!topSongsExpanded">
|
||||
Show more
|
||||
</template>
|
||||
<template v-else>
|
||||
Show less
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row well">
|
||||
<div class="col">
|
||||
<template v-for="(view) in data.meta.views.order"
|
||||
v-if="(data.views[view].data.length != 0) && (view != 'latest-release') && (view != 'top-songs')">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : "???"}}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views[view].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showArtistView(data.id, data.attributes.name + ' - ' + data.views[view].attributes.title, view)">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!((data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : '???').includes('Video') || (data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : '???').includes('More To See'))">
|
||||
<mediaitem-scroller-horizontal-large :items="data.views[view].data.limit(10)">
|
||||
</mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-mvview
|
||||
:items="data.views[view].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
</template>
|
||||
<div class="row">
|
||||
<div class="col" v-if="data.attributes.artistBio">
|
||||
<h3>About {{ data.attributes.name }}</h3>
|
||||
<p v-html="data.attributes.artistBio"></p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div v-if="data.attributes.origin">
|
||||
<h3>{{ data.attributes.isGroup ? "Origin" : "Hometown" }}</h3>
|
||||
{{ data.attributes.origin }}
|
||||
</div>
|
||||
<div v-if="data.attributes.bornOrFormed">
|
||||
<h3>{{ data.attributes.isGroup ? "Formed" : "Born" }}</h3>
|
||||
{{ data.attributes.bornOrFormed }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-artist', {
|
||||
template: "#cider-artist",
|
||||
props: ['data'],
|
||||
data: function () {
|
||||
return {
|
||||
topSongsExpanded: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
artistMenu (event) {
|
||||
let self = this
|
||||
CiderContextMenu.Create(event, {
|
||||
items: [
|
||||
{
|
||||
name: "Play Artist Radio",
|
||||
action: ()=>{
|
||||
app.mk.setStationQueue({artist:self.data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Follow Artist",
|
||||
action: ()=>{}
|
||||
},
|
||||
{
|
||||
name: "Share",
|
||||
action: ()=>{}
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
getArtistPalette(artist) {
|
||||
if (artist["attributes"]["artwork"]) {
|
||||
return {
|
||||
"background": "#" + artist["attributes"]["artwork"]["bgColor"],
|
||||
"color": "#" + artist["attributes"]["artwork"]["textColor1"],
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
"background": "#000000",
|
||||
"color": "#ffffff",
|
||||
}
|
||||
}
|
||||
},
|
||||
getTopResult() {
|
||||
if (this.search.results["meta"]) {
|
||||
return this.search.results[this.search.results.meta.results.order[0]]["data"][0]
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
37
src/renderer/views/pages/browse.ejs
Normal file
37
src/renderer/views/pages/browse.ejs
Normal file
|
@ -0,0 +1,37 @@
|
|||
<script type="text/x-template" id="cider-browse">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Browse</h1>
|
||||
<template v-if="data.relationships && data.relationships.tabs">
|
||||
<template v-for="(recom,index) in data.relationships.tabs.data[0].relationships.children.data">
|
||||
<div class="row">
|
||||
<div class="col" v-if="recom.attributes.name != 'Chart Set'">
|
||||
<h3>{{ recom.attributes.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="index != 0 && recom.relationships && ((recom.relationships.children && recom.relationships.children.data.length > 10) || (recom.relationships.contents && recom.relationships.contents.data.length > 10))">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection(recom.relationships.children ? recom.relationships.children : recom.relationships.contents, recom.attributes.name ?? '', 'listen_now')" >See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="recom.relationships && ((recom.relationships.children && recom.relationships.children.data) || (recom.relationships.contents && recom.relationships.contents.data))">
|
||||
<template v-if="(['385']).includes(recom.attributes.editorialElementKind) || index === 0">
|
||||
<mediaitem-scroller-horizontal-mvview :imagesize="800" :browsesp="index == 0"
|
||||
:items="recom.relationships.children ? recom.relationships.children.data.limit(10) : recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
<template v-else-if="recom.attributes.name == 'Chart Set'">
|
||||
<!-- ignored -->
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="recom.relationships.children ? recom.relationships.children.data.limit(10) : recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-browse', {
|
||||
template: "#cider-browse",
|
||||
props: ["data"]
|
||||
})
|
||||
</script>
|
90
src/renderer/views/pages/cider-playlist.ejs
Normal file
90
src/renderer/views/pages/cider-playlist.ejs
Normal file
|
@ -0,0 +1,90 @@
|
|||
<script type="text/x-template" id="cider-playlist">
|
||||
<template v-if="data != [] && data.attributes != null">
|
||||
<div class="content-inner playlist-page" :style="{'--bgColor': (data.attributes.artwork != null && data.attributes.artwork['bgColor'] != null) ? ('#' + data.attributes.artwork.bgColor) : ''}">
|
||||
<div class="playlist-display row"
|
||||
:style="{
|
||||
background: (data.attributes.artwork != null && data.attributes.artwork['bgColor'] != null) ? ('#' + data.attributes.artwork.bgColor) : '',
|
||||
color: (data.attributes.artwork != null && data.attributes.artwork['textColor1'] != null) ? ('#' + data.attributes.artwork.textColor1) : ''
|
||||
}">
|
||||
<div class="col-auto flex-center">
|
||||
<div style="width: 260px;height:260px;">
|
||||
<mediaitem-artwork
|
||||
:url="(data.attributes != null && data.attributes.artwork && data.attributes.artwork != null) ? data.attributes.artwork.url : ((data.relationships != null && data.relationships.tracks.data.length > 0) ? data.relationships.tracks.data[0].attributes.artwork.url ?? '':'')"
|
||||
:video="(data.attributes != null && data.attributes.editorialVideo != null) ? (data.attributes.editorialVideo.motionDetailSquare ? data.attributes.editorialVideo.motionDetailSquare.video : (data.attributes.editorialVideo.motionSquareVideo1x1 ? data.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
size="260"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col playlist-info">
|
||||
<template v-if="!editorialNotesExpanded">
|
||||
<div>
|
||||
<div class="playlist-name">{{data.attributes ? (data.attributes.name ??
|
||||
(data.attributes.title ?? '') ?? '') : ''}}
|
||||
</div>
|
||||
<div class="playlist-artist item-navigate" v-if="data.attributes && data.attributes.artistName" @click="if(data.attributes && data.attributes.artistName){ app.searchAndNavigate(data,'artist')}">
|
||||
{{data.attributes ? (data.attributes.artistName ?? '') :''}}
|
||||
</div>
|
||||
<div class="playlist-desc" v-if="data.attributes.editorialNotes">
|
||||
<div class="content"
|
||||
v-html="((data.attributes.editorialNotes) ? (data.attributes.editorialNotes.standard ?? (data.attributes.editorialNotes.short ?? '') ) : (data.attributes.description ? (data.attributes.description.standard ?? (data.attributes.description.short ?? '')) : ''))"></div>
|
||||
<button class="more-btn" @click="editorialNotesExpanded = !editorialNotesExpanded">
|
||||
More
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="editorialNotesExpanded">
|
||||
<div class="playlist-desc-expanded">
|
||||
<div class="content"
|
||||
v-html="((data.attributes.editorialNotes) ? (data.attributes.editorialNotes.standard ?? (data.attributes.editorialNotes.short ?? '') ) : (data.attributes.description ? (data.attributes.description.standard ?? (data.attributes.description.short ?? '')) : ''))"></div>
|
||||
<button class="more-btn" @click="editorialNotesExpanded = !editorialNotesExpanded">Less
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="playlist-controls">
|
||||
<button class="wr-btn" style="min-width: 120px;"
|
||||
@click="app.mk.shuffleMode = 0;app.playMediaItemById(data.attributes.playParams.id ?? data.id, data.attributes.playParams.kind ?? data.type, data.attributes.playParams.isLibrary ?? false, data.attributes.url)">
|
||||
Play
|
||||
</button>
|
||||
<button class="wr-btn" style="min-width: 120px;"
|
||||
@click="app.mk.shuffleMode = 1;app.playMediaItemById(data.attributes.playParams.id ?? data.id, data.attributes.playParams.kind ?? data.type, data.attributes.playParams.isLibrary ?? false, data.attributes.url)">
|
||||
Shuffle
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="playlist-body">
|
||||
<div class="well">
|
||||
<mediaitem-list-item :item="item" :parent="getItemParent(data)" :index="index"
|
||||
v-for="(item,index) in data.relationships.tracks.data"></mediaitem-list-item>
|
||||
</div>
|
||||
<div class="playlist-time">
|
||||
{{data.attributes.releaseDate}}
|
||||
</div>
|
||||
<div class="playlist-time item-navigate" @click="app.searchAndNavigate(data,'recordLabel') " style="width: 50%;">
|
||||
{{data.attributes.copyright}}
|
||||
</div>
|
||||
<div class="playlist-time">{{app.getTotalTime()}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-playlist', {
|
||||
template: "#cider-playlist",
|
||||
props: ["data"],
|
||||
data: function () {
|
||||
return {
|
||||
editorialNotesExpanded: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getItemParent: function (data) {
|
||||
kind = data.attributes.playParams.kind;
|
||||
id = data.attributes.playParams.id;
|
||||
return `${kind}:${id}`
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
124
src/renderer/views/pages/collection-list.ejs
Normal file
124
src/renderer/views/pages/collection-list.ejs
Normal file
|
@ -0,0 +1,124 @@
|
|||
<script type="text/x-template" id="cider-collection-list">
|
||||
<div class="content-inner collection-page">
|
||||
<h3 class="header-text" v-observe-visibility="{callback: headerVisibility}">{{ title }}</h3>
|
||||
<div v-if="data['data'] != 'null'" class="well">
|
||||
<template v-for="(item, key) in data.data">
|
||||
<template v-if="item.type == 'artists'">
|
||||
<mediaitem-square-large :item="item"></mediaitem-square-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-list-item
|
||||
v-if="item.attributes.playParams.kind == 'song'"
|
||||
:index="key"
|
||||
:item="item"></mediaitem-list-item>
|
||||
<mediaitem-mvview v-else-if="item.attributes.playParams.kind == 'musicVideo'" :item="item"></mediaitem-mvview>
|
||||
<mediaitem-square-large v-else :item="item"></mediaitem-square-large>
|
||||
</template>
|
||||
</template>
|
||||
<button v-if="triggerEnabled" style="opacity:0;height: 32px;" v-observe-visibility="{callback: visibilityChanged}">Show More</button>
|
||||
</div>
|
||||
<transition name="fabfade">
|
||||
<button class="top-fab" v-show="showFab" @click="scrollToTop()">
|
||||
<%- include("../svg/arrow-up.svg") %>
|
||||
</button>
|
||||
</transition>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-collection-list', {
|
||||
template: "#cider-collection-list",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "artists"
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
triggerEnabled: true,
|
||||
canSeeTrigger: false,
|
||||
showFab: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scrollToTop() {
|
||||
let target = document.querySelector(".header-text")
|
||||
target.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"})
|
||||
},
|
||||
getNext() {
|
||||
// if this.data.next is not null, then we can run this.data.next() and concat to this.data.data to get the next page
|
||||
switch(this.type) {
|
||||
default:
|
||||
case "artists":
|
||||
if (this.data.next && this.triggerEnabled) {
|
||||
this.triggerEnabled = false;
|
||||
this.data.next().then(data => {
|
||||
console.log(data);
|
||||
this.data.next = data.next;
|
||||
this.data.data = this.data.data.concat(data.data);
|
||||
this.triggerEnabled = true;
|
||||
});
|
||||
}else{
|
||||
console.log("No next page");
|
||||
this.triggerEnabled = false;
|
||||
}
|
||||
break;
|
||||
case "search":
|
||||
if (this.data.next && this.triggerEnabled) {
|
||||
this.triggerEnabled = false;
|
||||
this.data.next().then(data => {
|
||||
console.log(data);
|
||||
this.data.next = data[this.data.groups].next;
|
||||
this.data.data = this.data.data.concat(data[this.data.groups].data.data);
|
||||
this.triggerEnabled = true;
|
||||
});
|
||||
}else{
|
||||
console.log("No next page");
|
||||
this.triggerEnabled = false;
|
||||
}
|
||||
break;
|
||||
case "listen_now":
|
||||
case "curator":
|
||||
if (this.data.next && this.triggerEnabled) {
|
||||
this.triggerEnabled = false;
|
||||
app.mk.api.v3.music(this.data.next).then(data => {
|
||||
console.log(data);
|
||||
this.data.next = data.data.next;
|
||||
this.data.data = this.data.data.concat(data.data.data);
|
||||
this.triggerEnabled = true;
|
||||
});
|
||||
}else{
|
||||
console.log("No next page");
|
||||
this.triggerEnabled = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
},
|
||||
headerVisibility: function (isVisible, entry) {
|
||||
if(isVisible) {
|
||||
this.showFab = false;
|
||||
}else{
|
||||
this.showFab = true;
|
||||
}
|
||||
},
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
if(isVisible) {
|
||||
this.canSeeTrigger = true;
|
||||
this.getNext();
|
||||
}else{
|
||||
this.canSeeTrigger = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
56
src/renderer/views/pages/library-albums.ejs
Normal file
56
src/renderer/views/pages/library-albums.ejs
Normal file
|
@ -0,0 +1,56 @@
|
|||
<template v-if="page == 'library-albums'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<h1 class="header-text">Albums</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button v-if="library.albums.downloadState == 2" @click="getLibraryAlbumsFull(true)" class="reload-btn"><%- include('../svg/redo.svg') %></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="searchLibraryAlbums"
|
||||
v-model="library.albums.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.albums.sorting" @change="searchLibraryAlbums()">
|
||||
<optgroup label="Sort By">
|
||||
<option v-for="(sort, index) in library.albums.sortingOptions" :value="index">{{ sort }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.sortOrder" @change="searchLibraryAlbums()">
|
||||
<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="library.albums.viewAs">
|
||||
<optgroup label="View As">
|
||||
<option value="covers">Cover Art</option>
|
||||
<option value="list">List</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large v-if="library.albums.viewAs == 'covers'" :item="item" v-for="item in library.albums.displayListing">
|
||||
</mediaitem-square-large>
|
||||
<mediaitem-list-item v-if="library.albums.viewAs == 'list'" :show-duration="false" :show-meta-data="true" :show-library-status="false" :item="item" v-for="item in library.albums.displayListing">
|
||||
</mediaitem-list-item>
|
||||
</div>
|
||||
</template>
|
0
src/renderer/views/pages/library-recentlyadded.ejs
Normal file
0
src/renderer/views/pages/library-recentlyadded.ejs
Normal file
46
src/renderer/views/pages/library-songs.ejs
Normal file
46
src/renderer/views/pages/library-songs.ejs
Normal file
|
@ -0,0 +1,46 @@
|
|||
<template v-if="page == 'library-songs'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<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>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="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()">
|
||||
<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()">
|
||||
<optgroup label="Sort Order">
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="library.songs.downloadState == 3">Library contains no songs.</div>
|
||||
<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>
|
32
src/renderer/views/pages/listen_now.ejs
Normal file
32
src/renderer/views/pages/listen_now.ejs
Normal file
|
@ -0,0 +1,32 @@
|
|||
<script type="text/x-template" id="cider-listen-now">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Listen Now</h1>
|
||||
<template v-for="recom in data.data">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ recom.attributes.title ? recom.attributes.title.stringForDisplay : ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="recom.relationships.contents.data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection(recom.relationships.contents, recom.attributes.title ? recom.attributes.title.stringForDisplay : '', 'listen_now')" >See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="recom.attributes.display.kind == 'MusicCoverShelf'">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else-if="recom.attributes.display.kind == 'MusicSuperHeroShelf'">
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-sp
|
||||
:items="recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-sp>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-listen-now', {
|
||||
template: "#cider-listen-now",
|
||||
props: ["data"]
|
||||
})
|
||||
</script>
|
0
src/renderer/views/pages/radio.ejs
Normal file
0
src/renderer/views/pages/radio.ejs
Normal file
101
src/renderer/views/pages/recordLabel.ejs
Normal file
101
src/renderer/views/pages/recordLabel.ejs
Normal file
|
@ -0,0 +1,101 @@
|
|||
<script type="text/x-template" id="cider-recordlabel">
|
||||
<div class="content-inner artist-page">
|
||||
<div class="artist-header" :style="getArtistPalette(data)">
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;">
|
||||
<div class="artist-image">
|
||||
<mediaitem-artwork
|
||||
:shadow="true"
|
||||
:url="data.attributes.artwork ? data.attributes.artwork.url : ''"
|
||||
size="220" type="artists"></mediaitem-artwork>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col flex-center"
|
||||
>
|
||||
<h1>{{ data.attributes.name }}</h1>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="artist-body">
|
||||
<div v-if = "app.showingPlaylist.attributes.description">
|
||||
<div class="row">
|
||||
<h3>About </h3>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div>{{ app.showingPlaylist.attributes.description.standard }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<template v-if="data.views && data.views['latest-releases']">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ data.views["latest-releases"].attributes.title ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['latest-releases'].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showRecordLabelView(data.id, data.attributes.name + ' - Latest Releases', 'latest-releases')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item" v-for="item in data.views['latest-releases'].data">
|
||||
</mediaitem-square-large>
|
||||
</template>
|
||||
<template v-if="data.views && data.views['top-releases']">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ data.views["top-releases"].attributes.title ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['top-releases'].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showRecordLabelView(data.id, data.attributes.name + ' - Top Releases', 'top-releases')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item" v-for="item in data.views['top-releases'].data">
|
||||
</mediaitem-square-large>
|
||||
</template>
|
||||
<template v-if="data.relationships && data.relationships.playlists && data.relationships.playlists.data.length > 0">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Playlists</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.relationships.playlists.data.length >= 5">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection(data.relationships.playlists, data.attributes.name + ' - Playlists', 'curator')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item" v-for="item in data.relationships.playlists.data.limit(5)">
|
||||
</mediaitem-square-large>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-recordlabel', {
|
||||
template: "#cider-recordlabel",
|
||||
props: ['data'],
|
||||
data: function () {
|
||||
return {
|
||||
topSongsExpanded: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getArtistPalette(artist) {
|
||||
if (artist["attributes"]["artwork"]) {
|
||||
return {
|
||||
"background": "#" + artist["attributes"]["artwork"]["bgColor"],
|
||||
"color": "#" + artist["attributes"]["artwork"]["textColor1"],
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
"background": "#000000",
|
||||
"color": "#ffffff",
|
||||
}
|
||||
}
|
||||
},
|
||||
getTopResult() {
|
||||
if (this.search.results["meta"]) {
|
||||
return this.search.results[this.search.results.meta.results.order[0]]["data"][0]
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
64
src/renderer/views/pages/search.ejs
Normal file
64
src/renderer/views/pages/search.ejs
Normal file
|
@ -0,0 +1,64 @@
|
|||
<script type="text/x-template" id="cider-search">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;" v-if="getTopResult()">
|
||||
<template>
|
||||
<h3>Top Result</h3>
|
||||
<mediaitem-square-large :item="getTopResult()"></mediaitem-square-large>
|
||||
</template>
|
||||
</div>
|
||||
<div class="col" v-if="search.results.song">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Songs</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" @click="app.showSearchView(app.search.term, 'song', app.friendlyTypes('song'))" v-if="search.results.song.data.length >= 6">
|
||||
<button class="cd-btn-seeall">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<mediaitem-list-item :item="item" :index="index"
|
||||
v-for="(item, index) in search.results.song.data.limit(6)"></mediaitem-list-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="search.results['meta']">
|
||||
<template
|
||||
v-for="section in search.results.meta.results.order" v-if="section != 'song' && section != 'top'">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ app.friendlyTypes(section) }}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results[section].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showSearchView(app.search.term, section, app.friendlyTypes(section))">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!app.friendlyTypes(section).includes('Video')">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-mvview
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-search', {
|
||||
template: "#cider-search",
|
||||
props: ['search'],
|
||||
methods: {
|
||||
getTopResult() {
|
||||
if (this.search.results["meta"]) {
|
||||
return this.search.results[this.search.results.meta.results.order[0]]["data"][0]
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
178
src/renderer/views/pages/settings.ejs
Normal file
178
src/renderer/views/pages/settings.ejs
Normal file
|
@ -0,0 +1,178 @@
|
|||
<script type="text/x-template" id="cider-settings">
|
||||
<div class="content-inner settings-page">
|
||||
<h1 class="header-text">Settings <small>(non functional, stay tuned)</small></h1>
|
||||
<div class="md-option-container">
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Audio Quality
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select" style="width:180px;">
|
||||
<option value="990">Extreme</option>
|
||||
<option value="256">High</option>
|
||||
<option value="64">Low</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Seamless Audio Transitions
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Animated Artwork
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Always</option>
|
||||
<option value="1">Limit to pages and special entries</option>
|
||||
<option value="2">Disable Everywhere</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Discord Rich Presence
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Disabled</option>
|
||||
<option value="1">Display as 'Cider'</option>
|
||||
<option value="2">Display as 'Apple Music'</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Enable AudioContext Functionality
|
||||
<br>
|
||||
<small>Enabling AudioContext functionality will allow for extended audio features like Equalizers and Visualizers, however on some systems this may cause stuttering in audio tracks.</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
LastFM Scrobbling
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
LastFM Scrobble Delay
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Cider</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme Options
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<button class="btn">Theme Options</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Scrollbars
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Show on hover</option>
|
||||
<option value="1">Always show</option>
|
||||
<option value="2">Hidden</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Refresh Rate
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Automatic</option>
|
||||
<option value='30'>30</option>
|
||||
<option value='60'>60</option>
|
||||
<option value='144'>144</option>
|
||||
<option value='175'>175</option>
|
||||
<option value='240'>240</option>
|
||||
<option value='360'>30</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Enable Musixmatch Lyrics
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Musixmatch Preferred Language
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Close Button Behavior
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Minimize to system tray</option>
|
||||
<option value='1'>Minimize to taskbar ? dock</option>
|
||||
<option value='2'>Quit Cider</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Open Cider on Startup
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Never</option>
|
||||
<option value='1'>Always</option>
|
||||
<option value='2'>Always, minimized</option>
|
||||
<option value='2'>Always, hidden in tray</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-settings', {
|
||||
template: "#cider-settings",
|
||||
props: [],
|
||||
data: function () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
5
src/renderer/views/pages/webview.ejs
Normal file
5
src/renderer/views/pages/webview.ejs
Normal file
|
@ -0,0 +1,5 @@
|
|||
<template v-if="page == 'webview'">
|
||||
<div style="display:flex;width:100%;height:100%">
|
||||
<webview id="foo" :src="webview.url" style="display:inline-flex; width:100%;"></webview>
|
||||
</div>
|
||||
</template>
|
7
src/renderer/views/pages/zoo.ejs
Normal file
7
src/renderer/views/pages/zoo.ejs
Normal file
|
@ -0,0 +1,7 @@
|
|||
<template v-if="page == 'zoo'">
|
||||
<div class="content-inner">
|
||||
<h3>Welcome to element park. *BERR NERR NERR NERR NERRRRR BERR NER NER NER NERRR BERRR NR NR NRRRR*</h3>
|
||||
<button @click="app.playMediaItemById('1592151778', 'album')">Play Test Album</button>
|
||||
<cider-queue ref="queue"></cider-queue>
|
||||
</div>
|
||||
</template>
|
Loading…
Add table
Add a link
Reference in a new issue