Merge branch 'upcoming' into upcoming

This commit is contained in:
cryptofyre 2022-01-19 21:27:31 -06:00 committed by GitHub
commit e0814e3c95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 432 additions and 138 deletions

3
.gitignore vendored
View file

@ -308,4 +308,5 @@ GitHub.sublime-settings
#Service Worker mappings
src/renderer/sw.js.map
src/renderer/workbox-962786f2.js.map
src/renderer/workbox-962786f2.js.map
/src/renderer/musickit-dev.js

View file

@ -57,7 +57,8 @@ export class ConfigStore {
"animated_artwork": "limited", // 0 = always, 1 = limited, 2 = never
"animated_artwork_qualityLevel": 1,
"bg_artwork_rotation": false,
"hw_acceleration": "default" // default, webgpu, disabled
"hw_acceleration": "default", // default, webgpu, disabled
"showuserinfo": true
},
"lyrics": {
"enable_mxm": false,

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-mic"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path><path d="M19 10v2a7 7 0 0 1-14 0v-2"></path><line x1="12" y1="19" x2="12" y2="23"></line><line x1="8" y1="23" x2="16" y2="23"></line></svg>

After

Width:  |  Height:  |  Size: 418 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -257,7 +257,7 @@ const app = new Vue({
tmpVar: [],
notification: false,
chrome: {
hideUserInfo: ipcRenderer.sendSync("is-dev"),
hideUserInfo: ipcRenderer.sendSync("is-dev") || false,
artworkReady: false,
userinfo: {
"id": "",
@ -486,13 +486,21 @@ const app = new Vue({
let self = this
clearTimeout(this.hangtimer)
this.mk = MusicKit.getInstance()
let needsReload = (typeof localStorage["music.ampwebplay.media-user-token"] == "undefined")
this.mk.authorize().then(() => {
self.mkIsReady = true
//document.location.reload()
if(needsReload) {
document.location.reload()
}
})
this.$forceUpdate()
if (this.isDev) {
this.mk.privateEnabled = true
// Hide UserInfo if Dev mode
this.chrome.hideUserInfo = true
} else {
// Get Hide User from Settings
this.chrome.hideUserInfo = !this.cfg.visual.showuserinfo
}
if (this.cfg.visual.hw_acceleration == "disabled") {
document.body.classList.add("no-gpu")
@ -560,7 +568,8 @@ const app = new Vue({
app.mk.bitrate = app.cfg.audio.quality = 64
break;
default:
app.mk.bitrate = app.cfg.audio.quality
// app.mk.bitrate = app.cfg.audio.quality
break;
}
@ -717,6 +726,10 @@ const app = new Vue({
this.$forceUpdate()
}, 500)
},
unauthorize() {
this.mk.unauthorize()
document.location.reload()
},
getAppClasses() {
if (this.cfg.advanced.experiments.includes('compactui')) {
return { compact: true }
@ -3254,6 +3267,15 @@ const app = new Vue({
return 0 !== s && (h = s > 0 ? "-" : "+"),
`${h}${leadingZeros(n, 2)}:${leadingZeros(d, 2)}`
},
toggleHideUserInfo() {
if(this.chrome.hideUserInfo) {
this.cfg.visual.showuserinfo = true
this.chrome.hideUserInfo = false
} else {
this.cfg.visual.showuserinfo = false
this.chrome.hideUserInfo = true
}
}
}
})
@ -3518,4 +3540,4 @@ async function webGPU() {
webGPU().then()
let screenWidth = screen.width;
let screenHeight = screen.height;
let screenHeight = screen.height;

View file

@ -1056,7 +1056,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
height: 1.2em;
line-height: 1.3em;
overflow: hidden;
margin: 0 0 0.5em;
margin: 0 0 0 0.25em;
}
.app-chrome .app-chrome-item > .app-playback-controls .song-artist {
@ -2058,9 +2058,9 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
.md-btn {
background: rgba(100, 100, 100, 0.5);
padding: 4px 12px;
padding: 6px 12px;
border-radius: 4px;
font-size: 13px;
font-size: 16px;
border: 1px solid rgb(100 100 100 / 35%);
color: #eee;
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3), 0px 1px 1px rgba(0, 0, 0, 0.4);
@ -2094,6 +2094,40 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
}
}
.md-ico-play {
content:url("./assets/playPng.png");
width: 10px;
height: 12px;
margin-right: 1px;
align-self: center;
}
.md-ico-shuffle {
content:url("./assets/shufflePng.png");
width: 15px;
height: 13px;
margin-right: 1px;
align-self: center;
}
.md-ico-remove {
content:url("./assets/feather/x-circlePng.png");
width: 16px;
height: 16px;
margin-right: 1px;
margin-bottom: -1.5px;
align-self: center;
}
.md-ico-add {
content:url("./assets/feather/plus-circle-white.svg");
width: 16px;
height: 16px;
margin-right: 1px;
margin-bottom: -1.5px;
align-self: center;
}
.md-select {
width: 100%;
padding: 6px;
@ -2519,6 +2553,107 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
}
}
// Podcast Page
.content-inner.podcasts-page {
display: flex;
height: calc(100% - var(--navigationBarHeight));
padding: 0px;
.podcast-artwork {
width: 200px;
margin: 16px auto;
height: 200px;
}
.podcasts-list {
height: 100%;
width: 280px;
background: rgb(200 200 200 / 10%);
overflow-y: overlay;
border-right: 1px solid var(--color2);
flex: none;
overflow-x: hidden;
}
.episodes-list {
height: 100%;
width: 100%;
background: rgb(200 200 200 / 6%);
overflow-y: overlay;
overflow-x: hidden;
.episodes-inline-info {
padding: 14px 14px 0px 14px;
.podcast-show-info {
display: flex;
justify-content: center;
flex-direction: column;
}
.podcast-show-description {
margin: 32px 6px;
font-size: 0.8rem;
white-space: pre-wrap;
display:block;
}
.podcast-artwork {
width: 120px;
margin: 0px auto;
height: 120px;
}
}
}
.podcasts-details {
height: 100%;
width: 400px;
flex: none;
background: rgba(200, 200, 200, 0.1);
overflow-y: overlay;
border-left: 1px solid var(--color2);
overflow-x: hidden;
.podcast-genre {
text-align: center;
margin: 6px;
font-size: 0.8em;
font-weight: 500;
opacity: 0.8;
}
.podcast-metainfo {
text-align: center;
font-size: 0.7em;
opacity: 0.8;
}
.podcast-header {
text-align:center;
}
.podcast-play-btn {
width: 50%;
display: block;
margin: 0 auto;
}
.podcast-description {
margin: 12px;
font-size: 0.75em;
white-space: pre-wrap;
display:block;
}
}
}
/* Album / Playlist Page */
.playlist-page {
--bgColor: transparent;
@ -4372,7 +4507,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
height: 1.2em;
line-height: 1.3em;
overflow: hidden;
margin: 0 0 0.5em;
margin: 0 0 0 0.25em;
}
&:hover {

View file

@ -2,28 +2,20 @@
<div v-observe-visibility="{callback: visibilityChanged}"
@click="select"
class="cd-mediaitem-list-item"
:class="{'mediaitem-selected': app.select_hasMediaItem(guid)}">
:class="{'mediaitem-selected': app.select_hasMediaItem(guid)}"
@contextmenu="contextMenu">
<template v-if="isVisible">
<div class="artwork" v-if="showArtwork == true">
<mediaitem-artwork
:url="getArtwork()"
size="50"
:type="item.type"></mediaitem-artwork>
<button class="overlay-play" @click="select"></button>
</div>
<div class="info-rect" :style="{'padding-left': (showArtwork ? '' : '16px')}"
@dblclick="app.routeView(item)">
<div class="title text-overflow-elipsis">
{{ item.attributes.name }}
</div>
<div class="subtitle text-overflow-elipsis" style="-webkit-box-orient: horizontal;">
<template v-if="item.attributes.name">
<div class="artist item-navigate text-overflow-elipsis"
@click="select">
{{ item.attributes.artistName }}
</div>
</template>
</div>
</div>
</template>
</div>
@ -62,22 +54,19 @@
return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
},
getDataType() {
if (this.item.attributes.playParams.isLibrary) {
return this.item.type
} else {
return this.item.attributes.playParams.kind
}
return this.item.type
},
async select(e) {
let u = this.item
let u1 = await app.mk.api.v3.music(`/v1/me/library/artists/${u.id}/albums`,
{platform: "web",
"include[library-albums]": "artists,tracks",
"include[library-artists]": "catalog",
"fields[artists]": "url",
"includeOnly": "catalog,artists"}
)
let u1 = await app.mk.api.v3.music(`/v1/me/library/artists/${u.id}/albums`, {
"platform": "web",
"include[library-albums]": "artists,tracks",
"include[library-artists]": "catalog",
"fields[artists]": "url",
"includeOnly": "catalog,artists"
})
app.showCollection({data : Object.assign({},u1.data.data)}, u.attributes.name?? '', '');
app.select_selectMediaItem(u.id, this.getDataType(), this.index, this.guid, true)
},
getArtwork(){
let u = ""
@ -87,79 +76,37 @@
return u;
},
contextMenu(event) {
let self = this
let data_type = this.getDataType()
let item_id = this.item.attributes.playParams.id ?? this.item.id
let isLibrary = this.item.attributes.playParams.isLibrary ?? false
let item = self.item
item.attributes.artistName = item.attributes.name;
let useMenu = "normal"
if (app.selectedMediaItems.length <= 1) {
app.selectedMediaItems = []
app.select_selectMediaItem(item_id, data_type, this.index, this.guid, isLibrary)
app.select_selectMediaItem(this.item.id, data_type, this.index, this.guid, true)
} else {
useMenu = "multiple"
}
let menus = {
multiple: {
items: [
{
"name": "Add to Playlist...",
"action": function () {
app.promptAddToPlaylist()
}
},
{
name: `Play ${app.selectedMediaItems.length} tracks next`,
action: () => {
let itemsToPlay = {}
app.selectedMediaItems.forEach(item => {
if (!itemsToPlay[item.kind]) {
itemsToPlay[item.kind] = []
}
itemsToPlay[item.kind].push(item.id)
})
// loop through itemsToPlay
for (let kind in itemsToPlay) {
let ids = itemsToPlay[kind]
if (ids.length > 0) {
app.mk.playNext({[kind + "s"]: itemsToPlay[kind]})
}
}
console.log(itemsToPlay)
app.selectedMediaItems = []
}
},
{
name: `Play ${app.selectedMediaItems.length} tracks later`,
action: () => {
let itemsToPlay = {}
app.selectedMediaItems.forEach(item => {
if (!itemsToPlay[item.kind]) {
itemsToPlay[item.kind] = []
}
itemsToPlay[item.kind].push(item.id)
})
// loop through itemsToPlay
for (let kind in itemsToPlay) {
let ids = itemsToPlay[kind]
if (ids.length > 0) {
app.mk.playLater({[kind + "s"]: itemsToPlay[kind]})
}
}
app.selectedMediaItems = []
}
},
]
items: [] //
},
normal: {
items: [
{
"name": "Add to Playlist...",
"name": "Go to Artist",
"icon": "./assets/feather/user.svg",
"action": function () {
app.promptAddToPlaylist()
app.searchAndNavigate(self.item, 'artist')
console.log(self.item)
}
},
{
"icon": "./assets/feather/radio.svg",
"name": "Start Radio",
"action": function () {
app.mk.setStationQueue({song: self.item.attributes.playParams.id ?? self.item.id}).then(() => {
@ -169,31 +116,15 @@
}
},
{
"name": "Play Next",
"icon": "./assets/feather/share.svg",
"name": "Share",
"action": function () {
app.mk.playNext({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
app.mk.queue._reindex()
app.selectedMediaItems = []
}
},
{
"name": "Play Later",
"action": function () {
app.mk.playLater({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
app.mk.queue._reindex()
app.selectedMediaItems = []
}
},
{
"name": "Go to Artist",
"action": function () {
app.searchAndNavigate(self.item, 'artist')
}
},
{
"name": "Go to Album",
"action": function () {
app.searchAndNavigate(self.item, 'album')
if (!self.item.attributes.url && self.item.relationships){
if (self.item.relationships.catalog){
app.mkapi(self.item.attributes.playParams.kind, false, self.item.relationships.catalog.data[0].id).then(u => {self.app.copyToClipboard((u.length && u.length > 0)? u[0].attributes.url : u.attributes.url)})
}
} else {
self.app.copyToClipboard(self.item.attributes.url)}
}
},
]
@ -208,7 +139,9 @@
menus.multiple.items = menus.multiple.items.concat(this.contextExt.multiple)
}
}
CiderContextMenu.Create(event, menus[useMenu])
//CiderContextMenu.Create(event, menus[useMenu]); // Depreciated Context Menu
app.showMenuPanel(menus[useMenu], event);
},
visibilityChanged: function (isVisible, entry) {
this.isVisible = isVisible

View file

@ -83,9 +83,11 @@
</div>
<div class="playback-info">
<div class="song-name" style="-webkit-box-orient: horizontal;"
:style="[mk.nowPlayingItem['attributes']['contentRating'] == 'explicit' ? {'margin-left' : '23px'} : {'margin-left' : '0px'} ]">
:style="[mk.nowPlayingItem['attributes']['contentRating'] == 'explicit' ? {'margin-left' : '23px'} : {'margin-left' : '0px'} ]">
{{ mk.nowPlayingItem["attributes"]["name"] }}
<div class="explicit-icon" v-if="mk.nowPlayingItem['attributes']['contentRating'] == 'explicit'" style="display: inline-block"></div>
<div class="explicit-icon"
v-if="mk.nowPlayingItem['attributes']['contentRating'] == 'explicit'"
style="display: inline-block"></div>
</div>
<div class="song-artist"
style="display: inline-block; -webkit-box-orient: horizontal; white-space: nowrap;">
@ -148,9 +150,9 @@
<div class="app-chrome-item generic">
<template v-if="lyrics && lyrics != [] && lyrics.length > 0">
<button class="playback-button--small lyrics" :class="{'active': drawer.panel == 'lyrics'}"
@click="invokeDrawer('lyrics')"></button>
</template>
@click="invokeDrawer('lyrics')"></button>
</template>
</div>
<div class="app-chrome-item full-height" v-if="chrome.windowControlPosition == 'right'">
<div class="window-controls">
@ -198,6 +200,8 @@
page="browse"></sidebar-library-item>
<sidebar-library-item name="Radio" svg-icon="./assets/feather/radio.svg"
page="radio"></sidebar-library-item>
<sidebar-library-item name="Podcasts" svg-icon="./assets/feather/mic.svg"
page="podcasts"></sidebar-library-item>
<div class="app-sidebar-header-text">
Library
</div>
@ -218,7 +222,7 @@
<transition name="wpfade">
<div class="usermenu-container" v-if="chrome.menuOpened">
<div class="usermenu-body">
<button class="usermenu-item" @click="chrome.hideUserInfo = !chrome.hideUserInfo">
<button class="usermenu-item" @click="toggleHideUserInfo()">
<div class="row nopadding">
<div class="col nopadding">
Show Personal Info
@ -254,7 +258,7 @@
<button class="usermenu-item" @click="appRoute('settings')">
Settings
</button>
<button class="usermenu-item" @click="mk.unauthorize()">
<button class="usermenu-item" @click="unauthorize()">
Sign Out
</button>
</div>
@ -312,7 +316,7 @@
<template v-if="chrome.userinfo.id">
<div class="fullname text-overflow-elipsis">{{ chrome.userinfo.attributes.name }}
</div>
<div class="handle-text text-overflow-elipsis">@{{ chrome.userinfo.attributes.handle
<div class="handle-text text-overflow-elipsis">{{ chrome.userinfo.attributes.handle
}}
</div>
</template>
@ -339,6 +343,14 @@
<button class="nav-item"
@click="navigateForward()"><%- include('svg/chevron-right.svg') %></button>
</div>
<!-- Podcasts -->
<transition name="wpfade">
<template v-if="page == 'podcasts'">
<apple-podcasts></apple-podcasts>
</template>
</transition>
<!-- Apple Setings Page -->
<transition name="wpfade">
<template v-if="page == 'apple-account-settings'">
@ -524,7 +536,8 @@
</div>
<transition name="drawertransition">
<div class="app-drawer" v-if="drawer.open && drawer.panel == 'lyrics' && lyrics && lyrics != [] && lyrics.length > 0">
<div class="app-drawer"
v-if="drawer.open && drawer.panel == 'lyrics' && lyrics && lyrics != [] && lyrics.length > 0">
<div class="bgArtworkMaterial">
<div class="bg-artwork-container">
<img class="bg-artwork a" :src="$store.state.artwork.playerLCD">
@ -607,6 +620,9 @@
</div>
</div>
<!-- Apple Settings Page -->
<%- include('pages/podcasts') %>
<!-- Apple Settings Page -->
<%- include('pages/apple-account-settings') %>
<!-- Library - Songs -->

View file

@ -62,20 +62,20 @@
</div>
</template>
<div class="playlist-controls" v-observe-visibility="{callback: isHeaderVisible}">
<button class="md-btn" style="min-width: 120px;"
@click="app.mk.shuffleMode = 0; play()">
<button class="md-btn" style="min-width: 100px;"
@click="app.mk.shuffleMode = 0; play()"> <img class="md-ico-play">
Play
</button>
<button class="md-btn" style="min-width: 120px;"
@click="app.mk.shuffleMode = 1;play()">
<button class="md-btn" style="min-width: 100px;"
@click="app.mk.shuffleMode = 1;play()"> <img class="md-ico-shuffle">
Shuffle
</button>
<button class="md-btn" style="min-width: 120px;" v-if="inLibrary!=null && confirm!=true"
@click="confirmButton()">
<button class="md-btn" style="min-width: 180px;" v-if="inLibrary!=null && confirm!=true"
@click="confirmButton()"> <img :class="(!inLibrary) ? 'md-ico-add' : 'md-ico-remove'">
{{ (!inLibrary) ? "Add to Library" : "Remove from Library" }}
</button>
<button class="md-btn" style="min-width: 120px;" v-if="confirm==true"
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString()) ">
<button class="md-btn" style="min-width: 180px;" v-if="confirm==true"
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString()) "> <img class="md-ico-remove">
Confirm?
</button>
<button class="more-btn-round" style="float:right;" @click="menu">
@ -98,20 +98,20 @@
</div>
<div class="col-auto flex-center">
<div>
<button class="md-btn" style="min-width: 120px;"
@click="app.mk.shuffleMode = 0; play()">
<button class="md-btn" style="min-width: 100px;"
@click="app.mk.shuffleMode = 0; play()"> <img class="md-ico-play">
Play
</button>
<button class="md-btn" style="min-width: 120px;"
@click="app.mk.shuffleMode = 1;play()">
<button class="md-btn" style="min-width: 100px;"
@click="app.mk.shuffleMode = 1;play()"> <img class="md-ico-shuffle">
Shuffle
</button>
<button class="md-btn" style="min-width: 120px;" v-if="inLibrary!=null && confirm!=true"
@click="confirmButton()">
<button class="md-btn" style="min-width: 180px;" v-if="inLibrary!=null && confirm!=true"
@click="confirmButton()"> <img :class="(!inLibrary) ? 'md-ico-add' : 'md-ico-remove'">
{{ (!inLibrary) ? "Add to Library" : "Remove from Library" }}
</button>
<button class="md-btn" style="min-width: 120px;" v-if="confirm==true"
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString()) ">
<button class="md-btn" style="min-width: 180px;" v-if="confirm==true"
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString()) "> <img class="md-ico-remove">
Confirm?
</button>
</div>
@ -482,4 +482,4 @@
}
})
</script>
</script>

View file

@ -0,0 +1,173 @@
<script type="text/x-template" id="apple-podcasts">
<div class="content-inner podcasts-page">
<div class="podcasts-list">
<podcast-tab :isselected="podcastSelected.id == podcast.id" @click.native="selectPodcast(podcast)" v-for="podcast in podcasts" :item="podcast"></podcast-tab>
</div>
<div class="episodes-list">
<div v-if="podcastSelected.id != -1" class="episodes-inline-info">
<div class="row">
<div class="col-auto flex-center">
<div class="podcast-artwork">
<mediaitem-artwork shadow="large" :url="podcastSelected.attributes.artwork.url" size="300"></mediaitem-artwork>
</div>
</div>
<div class="col podcast-show-info">
<h1>{{ podcastSelected.attributes.name }}</h1>
<small>{{ podcastSelected.attributes.releaseFrequency }}</small>
<small>Created: {{ new Date(podcastSelected.attributes.createdDate).toLocaleDateString() }}</small>
</div>
</div>
<div class="well podcast-show-description">{{ podcastSelected.attributes.description.standard }}</div>
<h3>Episodes</h3>
</div>
<podcast-episode :isselected="selected.id == episode.id" @dblclick.native="playEpisode(episode)" @click.native="selectEpisode(episode)" :item="episode"
v-for="episode in episodes"></podcast-episode>
</div>
<div class="podcasts-details" v-if="selected.id != -1">
<div class="podcast-artwork">
<mediaitem-artwork shadow="large" :url="selected.attributes.artwork.url" size="300"></mediaitem-artwork>
</div>
<h3 class="podcast-header">{{ selected.attributes.name }}</h3>
<button @click="playEpisode(selected)" class="md-btn podcast-play-btn">Play Episode</button>
<div class="podcast-genre">
{{ selected.attributes.genreNames[0] }}
</div>
<div class="podcast-metainfo">
{{ msToMinSec(selected.attributes.durationInMilliseconds) }} • {{ new Date(selected.attributes.releaseDateTime).toLocaleString() }}
</div>
<div class="well podcast-description" v-if="selected.attributes.description.standard">{{ selected.attributes.description.standard }}</div>
<div class="row">
<div class="col">
<button class="md-btn md-btn-block" @click="openUrl(selected.attributes.websiteUrl)">Podcast Website</button>
</div>
<div class="col">
<button class="md-btn md-btn-block">Share</button>
</div>
</div>
</div>
</div>
</script>
<script type="text/x-template" id="podcast-tab">
<div class="cd-mediaitem-list-item" :class="{'mediaitem-selected': isselected}">
<div class="artwork">
<mediaitem-artwork
:url="item.attributes.artwork.url"
size="50"
type="podcast"></mediaitem-artwork>
</div>
<div class="info-rect">
<div class="title text-overflow-elipsis">
{{ item.attributes.name }}
</div>
</div>
</div>
</script>
<script type="text/x-template" id="podcast-episode">
<div class="cd-mediaitem-list-item" :class="{'mediaitem-selected': isselected}">
<div class="info-rect" :style="{'padding-left':'16px'}">
<div class="title text-overflow-elipsis">
{{ item.attributes.name }}
</div>
<div class="subtitle text-overflow-elipsis">
{{ item.attributes.description.standard }}
</div>
<div class="subtitle text-overflow-elipsis">
{{ msToMinSec(item.attributes.durationInMilliseconds) }} • {{ new Date(item.attributes.releaseDateTime).toLocaleString() }}
</div>
</div>
</div>
</script>
<script>
Vue.component('podcast-episode', {
template: '#podcast-episode',
props: ['item', 'isselected'],
methods: {
msToMinSec(ms) {
var minutes = Math.floor(ms / 60000);
var seconds = ((ms % 60000) / 1000).toFixed(0);
return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
}
}
});
Vue.component('podcast-tab', {
template: '#podcast-tab',
props: ['item', 'isselected'],
methods: {}
});
Vue.component('apple-podcasts', {
template: '#apple-podcasts',
data: function () {
return {
podcasts: [],
episodes: [],
podcastSelected: {
id: -1
},
selected: {
id: -1
}
}
},
async mounted() {
let podcastShow = await app.mk.api.v3.podcasts(`/v1/me/library/podcasts?include=episodes`)
this.podcasts = podcastShow.data.data
if (podcastShow.data.next) {
await this.getNext(podcastShow.data.next)
}
// this.episodes = podcastShow.data.data[0].relationships.episodes.data
},
methods: {
openUrl(url) {
window.open(url)
},
msToMinSec(ms) {
var minutes = Math.floor(ms / 60000);
var seconds = ((ms % 60000) / 1000).toFixed(0);
return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
},
playEpisode(episode) {
app.mk.setQueue({'episode': episode.id}).then(() => {app.mk.play()})
},
selectPodcast(podcast) {
this.podcastSelected = podcast
this.getEpisodes(podcast)
},
selectEpisode(episode) {
this.selected = episode
},
async getEpisodes(podcast) {
this.episodes = []
let eps = await app.mk.api.v3.podcasts(`/v1/catalog/${app.mk.storefrontId}/podcasts/${podcast.id}?include=episodes`)
eps.data.data[0].relationships.episodes.data.forEach(ep => {
this.episodes.push(ep)
})
if (eps.data.data[0].relationships.episodes.next) {
await this.getNextEpisodes(eps.data.data[0].relationships.episodes.next, podcast.id)
}
},
async getNextEpisodes(next, podcastId) {
let podcastShow = await app.mk.api.v3.podcasts(next)
if(podcastId != this.podcastSelected.id) {
return
}
podcastShow.data.data.forEach(ep => {
this.episodes.push(ep)
})
if (podcastShow.data.next) {
await this.getNextEpisodes(podcastShow.data.next, podcastId)
}
},
async getNext(next) {
let podcastShow = await app.mk.api.v3.podcasts(next)
this.podcasts = this.podcasts.concat(podcastShow.data.data)
if (podcastShow.data.next) {
await this.getNext(podcastShow.data.next)
}
}
}
});
</script>

View file

@ -10,7 +10,7 @@
</div>
<div class="md-option-segment md-option-segment_auto">
<select class="md-select" style="width:180px;" v-model="app.cfg.audio.quality" v-on:change="changeAudioQuality">
<option value="990">Extreme</option>
<!-- // <option value="990">Extreme</option> -->
<option value="256">High</option>
<option value="64">Low</option>
<option value="auto">Auto</option>
@ -103,6 +103,14 @@
</select>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
Show Personal Info
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="checkbox" v-model="app.cfg.visual.showuserinfo" v-on:change="toggleUserInfo" switch/>
</div>
</div>
<div class="md-option-header">
<span>Lyrics</span>
</div>
@ -605,6 +613,9 @@
},
changeAudioQuality : function(){
app.mk.bitrate = app.cfg.audio.quality
},
toggleUserInfo : function(){
app.chrome.hideUserInfo = !app.cfg.visual.showuserinfo
}
}
})