290 lines
No EOL
15 KiB
Text
290 lines
No EOL
15 KiB
Text
<script type="text/x-template" id="cider-playlist">
|
|
<div class="content-inner playlist-page" v-if="data != [] && data.attributes != null"
|
|
:style="{'--bgColor': (data.attributes.artwork != null && data.attributes.artwork['bgColor'] != null) ? ('#' + data.attributes.artwork.bgColor) : ''}">
|
|
<template v-if="app.playlists.loadingState == 0">
|
|
<div class="content-inner centered">
|
|
<div class="spinner"></div>
|
|
</div>
|
|
</template>
|
|
<template v-if="app.playlists.loadingState == 1">
|
|
<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
|
|
:video-priority="true"
|
|
: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" @click="editPlaylistName()" v-show="!nameEditing">
|
|
{{data.attributes ? (data.attributes.name ??
|
|
(data.attributes.title ?? '') ?? '') : ''}}
|
|
</div>
|
|
<div class="playlist-name" v-show="nameEditing"><input type="text" spellcheck="false"
|
|
class="nameEdit"
|
|
v-model="data.attributes.name"
|
|
@blur="editPlaylist"
|
|
@change="editPlaylist"
|
|
@keydown.enter="editPlaylist"/></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>
|
|
<button class="wr-btn" style="min-width: 120px;" v-if="inLibrary!=null"
|
|
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString())">
|
|
{{ (!inLibrary) ? "Add to Library" : "Remove from Library" }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="playlist-body">
|
|
<div class="well">
|
|
<div style="width:100%">
|
|
<draggable :sort="data.attributes.canEdit && data.type == 'library-playlists'"
|
|
v-model="data.relationships.tracks.data" @start="drag=true" @end="drag=false;put()">
|
|
<mediaitem-list-item :item="item" :parent="getItemParent(data)" :index="index"
|
|
:context-ext="buildContextMenu()"
|
|
v-for="(item,index) in data.relationships.tracks.data"></mediaitem-list-item>
|
|
</draggable>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="friends-info" v-if="itemBadges.length != 0">
|
|
<div class="well">
|
|
<div class="badge-container">
|
|
<div class="socialBadge" :title="`${badge.attributes.name} - @${badge.attributes.handle}`" v-for="badge in itemBadges">
|
|
<mediaitem-artwork
|
|
:url="badge.attributes.artwork.url"
|
|
:size="60"></mediaitem-artwork>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="playlist-time">
|
|
{{getFormattedDate(data.attributes.releaseDate)}}
|
|
</div>
|
|
<div class="playlist-time total">{{app.getTotalTime()}}</div>
|
|
<div class="playlist-time item-navigate" @click="app.searchAndNavigate(data,'recordLabel') "
|
|
style="width: 50%;">
|
|
{{data.attributes.copyright}}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
</script>
|
|
<script>
|
|
Vue.component('cider-playlist', {
|
|
template: "#cider-playlist",
|
|
props: ["data"],
|
|
data: function () {
|
|
return {
|
|
editorialNotesExpanded: false,
|
|
drag: false,
|
|
nameEditing: false,
|
|
inLibrary: null,
|
|
app: this.$root,
|
|
itemBadges: [],
|
|
badgesRequested: false
|
|
}
|
|
},
|
|
mounted: function () {
|
|
this.$nextTick(function () {
|
|
this.isInLibrary()
|
|
})
|
|
},
|
|
watch: {
|
|
data: function () {
|
|
this.isInLibrary()
|
|
this.getBadges()
|
|
}
|
|
},
|
|
methods: {
|
|
getBadges() {
|
|
return
|
|
if(this.badgesRequested) {
|
|
return
|
|
}
|
|
this.badgesRequested = true
|
|
this.itemBadges = []
|
|
let self = this
|
|
var id = 0
|
|
try {
|
|
id = this.data.attributes.playParams.id
|
|
} catch (e) {
|
|
id = this.data.id
|
|
}
|
|
this.$root.getSocialBadges((badges) => {
|
|
let friends = badges[id]
|
|
if(friends) {
|
|
friends.forEach(function (friend) {
|
|
self.app.mk.api.socialProfile(friend).then(data => {
|
|
self.itemBadges.push(data)
|
|
})
|
|
})
|
|
}
|
|
})
|
|
},
|
|
async isInLibrary() {
|
|
if (this.data.type && !this.data.type.includes("library")) {
|
|
// please keep using vars here
|
|
var params = {"fields[playlists]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library"}
|
|
var res = await app.mkapi(this.data.attributes.playParams.kind ?? this.data.type, this.data.attributes.playParams.isLibrary ?? false, this.data.attributes.playParams.id ?? this.data.id, params);
|
|
this.inLibrary = (res && res.attributes && res.attributes.inLibrary) ? res.attributes.inLibrary : false
|
|
console.log(res)
|
|
} else {
|
|
this.inLibrary = true
|
|
}
|
|
},
|
|
editPlaylist() {
|
|
this.app.editPlaylist(this.data.id, this.data.attributes.name);
|
|
this.app.playlists.listing.forEach(playlist => {
|
|
if (playlist.id == this.data.id) {
|
|
playlist.attributes.name = this.data.attributes.name
|
|
}
|
|
})
|
|
this.nameEditing = false
|
|
},
|
|
addToLibrary(id) {
|
|
app.mk.addToLibrary(id)
|
|
this.inLibrary = true
|
|
},
|
|
async removeFromLibrary(id) {
|
|
var params = {"fields[somgs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library"}
|
|
var id = this.data.id ?? this.data.attributes.playParams.id
|
|
var res = await app.mkapi(this.data.attributes.playParams.kind ?? this.data.type, this.data.attributes.playParams.isLibrary ?? false, this.data.attributes.playParams.id ?? this.data.id, params);
|
|
if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) {
|
|
id = res.relationships.library.data[0].id
|
|
}
|
|
let kind = this.data.attributes.playParams.kind ?? this.data.type ?? '';
|
|
var truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
|
app.mk.api.library.remove({[truekind]: id})
|
|
this.inLibrary = false
|
|
},
|
|
editPlaylistName() {
|
|
if (this.data.attributes.canEdit && this.data.type == "library-playlists") {
|
|
this.nameEditing = true
|
|
setTimeout(() => {
|
|
document.querySelector(".nameEdit").focus()
|
|
}, 100)
|
|
}
|
|
},
|
|
buildContextMenu(index) {
|
|
let self = this
|
|
if (!this.data.attributes.canEdit) {
|
|
return
|
|
}
|
|
return {
|
|
normal: [
|
|
{
|
|
name: 'Remove from Playlist',
|
|
action: () => {
|
|
self.remove()
|
|
}
|
|
},
|
|
],
|
|
multiple: [
|
|
{
|
|
name: 'Remove selected tracks from Playlist',
|
|
action: () => {
|
|
self.remove()
|
|
}
|
|
},
|
|
]
|
|
}
|
|
},
|
|
async put() {
|
|
if (!this.data.attributes.canEdit) {
|
|
return
|
|
}
|
|
await app.mk.api.library.putPlaylistTracklisting(this.data.attributes.playParams.id, this.convert())
|
|
},
|
|
async remove() {
|
|
if (!this.data.attributes.canEdit) {
|
|
return
|
|
}
|
|
// for each app.selectedMediaItems splice the items from the playlist
|
|
for (let i = 0; i < app.selectedMediaItems.length; i++) {
|
|
let item = app.selectedMediaItems[i]
|
|
let index = this.data.relationships.tracks.data.findIndex(x => x.id == item.id)
|
|
if (index > -1) {
|
|
this.data.relationships.tracks.data.splice(index, 1)
|
|
}
|
|
}
|
|
await this.put()
|
|
},
|
|
convert() {
|
|
let pl_tracks = []
|
|
for (let i = 0; i < this.data.relationships.tracks.data.length; i++) {
|
|
pl_tracks.push({
|
|
id: this.data.relationships.tracks.data[i].id,
|
|
type: this.data.relationships.tracks.data[i].type
|
|
})
|
|
}
|
|
return pl_tracks
|
|
},
|
|
getRecursive(url) {
|
|
app.apiCall(app.musicBaseUrl + "/v1/me/library/playlists/p.V7VYlrDso6kkYY/tracks?offset=100", res => {
|
|
this.data.relationships.tracks.data = this.data.relationships.tracks.data.concat(res.data.data)
|
|
if (res.data.next) {
|
|
this.getRecursive(res.data.next)
|
|
}
|
|
})
|
|
},
|
|
getItemParent: function (data) {
|
|
kind = data.attributes.playParams.kind;
|
|
id = data.attributes.playParams.id;
|
|
return `${kind}:${id}`
|
|
},
|
|
getFormattedDate: function (date) {
|
|
if (date == null || date === "") return "";
|
|
try {
|
|
var releaseDate = new Date(date);
|
|
month = new Intl.DateTimeFormat('en-US', {month: 'long'}).format(releaseDate);
|
|
date = releaseDate.getDate();
|
|
year = releaseDate.getFullYear();
|
|
|
|
return date + " " + month + " " + year;
|
|
} catch (e) {
|
|
return ""
|
|
}
|
|
}
|
|
}
|
|
})
|
|
</script> |