add ratings, library change to web remote (#1285)
This commit is contained in:
parent
3ab6d3e56c
commit
8cf2ddf8dd
5 changed files with 246 additions and 13 deletions
|
@ -64,6 +64,15 @@ export class wsapi {
|
||||||
electron.ipcMain.on('wsapi-returnvolumeMax', (_event: any, arg: any) => {
|
electron.ipcMain.on('wsapi-returnvolumeMax', (_event: any, arg: any) => {
|
||||||
this.returnmaxVolume(JSON.parse(arg));
|
this.returnmaxVolume(JSON.parse(arg));
|
||||||
});
|
});
|
||||||
|
electron.ipcMain.on('wsapi-libraryStatus', (_event: any, inLibrary: boolean, rating: number) => {
|
||||||
|
this.returnLibraryStatus(inLibrary, rating);
|
||||||
|
});
|
||||||
|
electron.ipcMain.on('wsapi-rate', (_event: any, kind: string, id: string, rating: number) => {
|
||||||
|
this.returnRatingStatus(kind, id, rating);
|
||||||
|
});
|
||||||
|
electron.ipcMain.on('wsapi-change-library', (_event: any, kind: string, id: string, shouldAdd: boolean) => {
|
||||||
|
this.returnLibraryChange(kind, id, shouldAdd);
|
||||||
|
});
|
||||||
this.wss = new WebSocketServer({
|
this.wss = new WebSocketServer({
|
||||||
port: this.port,
|
port: this.port,
|
||||||
perMessageDeflate: {
|
perMessageDeflate: {
|
||||||
|
@ -242,6 +251,15 @@ export class wsapi {
|
||||||
case "get-currentmediaitem":
|
case "get-currentmediaitem":
|
||||||
this._win.webContents.executeJavaScript(`wsapi.getPlaybackState()`);
|
this._win.webContents.executeJavaScript(`wsapi.getPlaybackState()`);
|
||||||
break;
|
break;
|
||||||
|
case "library-status":
|
||||||
|
this._win.webContents.executeJavaScript(`wsapi.getLibraryStatus("${data.type}", "${data.id}")`);
|
||||||
|
break;
|
||||||
|
case "rating":
|
||||||
|
this._win.webContents.executeJavaScript(`wsapi.rate("${data.type}", "${data.id}", ${data.rating})`);
|
||||||
|
break;
|
||||||
|
case "change-library":
|
||||||
|
this._win.webContents.executeJavaScript(`wsapi.changeLibrary("${data.type}", "${data.id}", ${data.add})`);
|
||||||
|
break;
|
||||||
case "quit":
|
case "quit":
|
||||||
electron.app.quit();
|
electron.app.quit();
|
||||||
break;
|
break;
|
||||||
|
@ -317,4 +335,35 @@ export class wsapi {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
returnLibraryStatus(inLibrary: boolean, rating: number) {
|
||||||
|
const response: standardResponse = {
|
||||||
|
status: 0, data: {
|
||||||
|
inLibrary, rating
|
||||||
|
}, message: "OK", type: "libraryStatus"
|
||||||
|
}
|
||||||
|
this.clients.forEach(function each(client: any) {
|
||||||
|
client.send(JSON.stringify(response));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
returnRatingStatus(kind: string, id: string, rating: number) {
|
||||||
|
const response: standardResponse = {
|
||||||
|
status: 0, data: { kind, id, rating },
|
||||||
|
message: "OK", type: "rate"
|
||||||
|
};
|
||||||
|
this.clients.forEach(function each(client: any) {
|
||||||
|
client.send(JSON.stringify(response));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
returnLibraryChange(kind: string, id: string, shouldAdd: boolean) {
|
||||||
|
const response: standardResponse = {
|
||||||
|
status: 0, data: { kind, id, add: shouldAdd },
|
||||||
|
message: "OK", type: "change-library"
|
||||||
|
};
|
||||||
|
this.clients.forEach(function each(client: any) {
|
||||||
|
client.send(JSON.stringify(response));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -118,6 +118,76 @@ const wsapi = {
|
||||||
},
|
},
|
||||||
getmaxVolume() {
|
getmaxVolume() {
|
||||||
ipcRenderer.send('wsapi-returnvolumeMax',JSON.stringify(app.cfg.audio.maxVolume));
|
ipcRenderer.send('wsapi-returnvolumeMax',JSON.stringify(app.cfg.audio.maxVolume));
|
||||||
|
},
|
||||||
|
getLibraryStatus(kind, id) {
|
||||||
|
if (kind === undefined || id === "no-id-found") return;
|
||||||
|
|
||||||
|
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||||
|
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${id}`, {
|
||||||
|
relate: "library",
|
||||||
|
fields: "inLibrary"
|
||||||
|
}).then(data => {
|
||||||
|
const res = data.data.data[0];
|
||||||
|
const inLibrary = res && res.attributes && res.attributes.inLibrary;
|
||||||
|
|
||||||
|
app.getRating({ type: truekind, id: id }).then(rating => {
|
||||||
|
ipcRenderer.send('wsapi-libraryStatus', inLibrary, rating);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
rate(kind, id, rating) {
|
||||||
|
if (kind === undefined || id === "no-id-found") return;
|
||||||
|
|
||||||
|
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||||
|
|
||||||
|
if (rating === 0) {
|
||||||
|
app.mk.api.v3.music(`/v1/me/ratings/${truekind}/${id}`, {}, {
|
||||||
|
fetchOptions: {
|
||||||
|
method: "DELETE",
|
||||||
|
}
|
||||||
|
}).then(function () {
|
||||||
|
ipcRenderer.send('wsapi-rate', kind, id, rating);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
app.mk.api.v3.music(`/v1/me/ratings/${truekind}/${id}`, {}, {
|
||||||
|
fetchOptions: {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify({
|
||||||
|
"type": "rating",
|
||||||
|
"attributes": {
|
||||||
|
"value": rating
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).then(function () {
|
||||||
|
ipcRenderer.send('wsapi-rate', kind, id, rating);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeLibrary(kind, id, shouldAdd) {
|
||||||
|
if (shouldAdd) {
|
||||||
|
app.addToLibrary(id);
|
||||||
|
ipcRenderer.send('wsapi-change-library', kind, id, shouldAdd);
|
||||||
|
} else {
|
||||||
|
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||||
|
|
||||||
|
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${id}`, {
|
||||||
|
relate: "library",
|
||||||
|
fields: "inLibrary"
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
res = res.data.data[0]
|
||||||
|
if (res && res.relationships && res.relationships.library && res.relationships.library.data) {
|
||||||
|
const item = res.relationships.library.data[0];
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
app.removeFromLibrary(kind, item.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcRenderer.send('wsapi-change-library', kind, id, shouldAdd);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,11 @@ var app = new Vue({
|
||||||
lyricsScrollingBlocked: false,
|
lyricsScrollingBlocked: false,
|
||||||
queue: {},
|
queue: {},
|
||||||
lowerPanelState: "controls",
|
lowerPanelState: "controls",
|
||||||
userInteraction: false
|
userInteraction: false,
|
||||||
|
status: {
|
||||||
|
inLibrary: false,
|
||||||
|
rating: 0
|
||||||
|
}
|
||||||
},
|
},
|
||||||
queue: {
|
queue: {
|
||||||
temp: []
|
temp: []
|
||||||
|
@ -246,6 +250,17 @@ var app = new Vue({
|
||||||
id: id
|
id: id
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
getLibraryStatus(type, id) {
|
||||||
|
if (type !== undefined && id !== "no-id-found") {
|
||||||
|
socket.send(JSON.stringify({
|
||||||
|
action: "library-status",
|
||||||
|
type: type,
|
||||||
|
id: id
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
this.player.status = {};
|
||||||
|
}
|
||||||
|
},
|
||||||
searchQuery() {
|
searchQuery() {
|
||||||
if (this.search.query.length == 0) {
|
if (this.search.query.length == 0) {
|
||||||
this.search.state = 0;
|
this.search.state = 0;
|
||||||
|
@ -412,8 +427,8 @@ var app = new Vue({
|
||||||
this.getQueue()
|
this.getQueue()
|
||||||
},
|
},
|
||||||
queueMove(evt) {
|
queueMove(evt) {
|
||||||
console.log(evt)
|
// console.log(evt)
|
||||||
console.log(`new: ${evt.moved.newIndex} old: ${evt.moved.oldIndex}`)
|
// console.log(`new: ${evt.moved.newIndex} old: ${evt.moved.oldIndex}`)
|
||||||
this.queue.temp.splice(evt.moved.newIndex, 0, this.queue.temp.splice(evt.moved.oldIndex, 1)[0])
|
this.queue.temp.splice(evt.moved.newIndex, 0, this.queue.temp.splice(evt.moved.oldIndex, 1)[0])
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
action: "queue-move",
|
action: "queue-move",
|
||||||
|
@ -557,11 +572,9 @@ var app = new Vue({
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.onmessage = (e) => {
|
socket.onmessage = (e) => {
|
||||||
console.log(e.data)
|
|
||||||
const response = JSON.parse(e.data);
|
const response = JSON.parse(e.data);
|
||||||
switch (response.type) {
|
switch (response.type) {
|
||||||
default: console.log(response);
|
default: break;
|
||||||
break;
|
|
||||||
case "musickitapi.search":
|
case "musickitapi.search":
|
||||||
self.showArtist(response.data["artists"][0]["id"]);
|
self.showArtist(response.data["artists"][0]["id"]);
|
||||||
break;
|
break;
|
||||||
|
@ -577,7 +590,8 @@ var app = new Vue({
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "queue":
|
case "queue":
|
||||||
self.player.queue = response.data;
|
// console.log(response.data);
|
||||||
|
self.player.queue = response.data;
|
||||||
self.queue.temp = response.data["_queueItems"];
|
self.queue.temp = response.data["_queueItems"];
|
||||||
self.$forceUpdate()
|
self.$forceUpdate()
|
||||||
break;
|
break;
|
||||||
|
@ -601,6 +615,27 @@ var app = new Vue({
|
||||||
case "maxVolume":
|
case "maxVolume":
|
||||||
this.player.maxVolume = response.data;
|
this.player.maxVolume = response.data;
|
||||||
break;
|
break;
|
||||||
|
case "libraryStatus":
|
||||||
|
this.player.status = response.data;
|
||||||
|
break;
|
||||||
|
case "rate":
|
||||||
|
var params = this.player.currentMediaItem.playParams;
|
||||||
|
if (params && params.id === response.data.id && params.kind === response.data.kind) {
|
||||||
|
this.player.status = {
|
||||||
|
rating: response.data.rating,
|
||||||
|
inLibrary: this.player.status.inLibrary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "change-library":
|
||||||
|
var params = this.player.currentMediaItem.playParams;
|
||||||
|
if (params && params.id === response.data.id && params.kind === response.data.kind) {
|
||||||
|
this.player.status = {
|
||||||
|
rating: this.player.status.rating,
|
||||||
|
inLibrary: response.data.add
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// console.log(e.data);
|
// console.log(e.data);
|
||||||
}
|
}
|
||||||
|
@ -608,6 +643,8 @@ var app = new Vue({
|
||||||
updatePlaybackState(mediaitem) {
|
updatePlaybackState(mediaitem) {
|
||||||
var lyricsDisplayed = this.screen == "lyrics" || this.player.lowerPanelState == "lyrics"
|
var lyricsDisplayed = this.screen == "lyrics" || this.player.lowerPanelState == "lyrics"
|
||||||
if (this.player.currentMediaItem["isrc"] != mediaitem["isrc"]) {
|
if (this.player.currentMediaItem["isrc"] != mediaitem["isrc"]) {
|
||||||
|
this.getLibraryStatus(mediaitem.playParams.kind, mediaitem.playParams.id)
|
||||||
|
|
||||||
if (lyricsDisplayed) {
|
if (lyricsDisplayed) {
|
||||||
this.getLyrics()
|
this.getLyrics()
|
||||||
}
|
}
|
||||||
|
@ -617,6 +654,39 @@ var app = new Vue({
|
||||||
}
|
}
|
||||||
this.player.currentMediaItem = mediaitem
|
this.player.currentMediaItem = mediaitem
|
||||||
},
|
},
|
||||||
|
openSongMenu() {
|
||||||
|
const params = this.player.currentMediaItem.playParams;
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
this.getLibraryStatus(params.kind, params.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.player.songActions = true;
|
||||||
|
},
|
||||||
|
rate(rating) {
|
||||||
|
const params = this.player.currentMediaItem.playParams;
|
||||||
|
|
||||||
|
if (params && params.kind !== undefined && params.id !== "no-id-found") {
|
||||||
|
socket.send(JSON.stringify({
|
||||||
|
action: "rating",
|
||||||
|
type: params.kind,
|
||||||
|
id: params.id,
|
||||||
|
rating: rating
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toLibrary(shouldAdd) {
|
||||||
|
const params = this.player.currentMediaItem.playParams;
|
||||||
|
|
||||||
|
if (params && params.kind !== undefined && params.id !== "no-id-found") {
|
||||||
|
socket.send(JSON.stringify({
|
||||||
|
action: "change-library",
|
||||||
|
type: params.kind,
|
||||||
|
id: params.id,
|
||||||
|
add: shouldAdd
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
quit() {
|
quit() {
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
action: "quit"
|
action: "quit"
|
||||||
|
|
|
@ -838,6 +838,15 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.context-menu .context-menu-item:disabled {
|
||||||
|
cursor: default;
|
||||||
|
filter: brightness(125%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu .context-menu-item:active:disabled {
|
||||||
|
filter: brightness(125%);
|
||||||
|
}
|
||||||
|
|
||||||
.context-menu .context-menu-item:active {
|
.context-menu .context-menu-item:active {
|
||||||
filter: brightness(75%);
|
filter: brightness(75%);
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,8 +130,8 @@
|
||||||
{{ player.currentMediaItem.artistName }}
|
{{ player.currentMediaItem.artistName }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto nopadding player-more-container" v-if="false" style="">
|
<div class="col-auto nopadding player-more-container" style="">
|
||||||
<button @click="player.songActions = true;" class="player-more-button">...</button>
|
<button @click="openSongMenu()" class="player-more-button">...</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -525,7 +525,8 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="md-body context-menu-body">
|
<div class="md-body context-menu-body">
|
||||||
<button class="context-menu-item context-menu-item--left" v-if="false">
|
<button class="context-menu-item context-menu-item--left" v-if="!player.status.inLibrary"
|
||||||
|
@click="toLibrary(true)">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
Add To Library
|
Add To Library
|
||||||
|
@ -535,7 +536,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button class="context-menu-item context-menu-item--left" v-if="false">
|
<button class="context-menu-item context-menu-item--left" v-if="player.status.inLibrary"
|
||||||
|
@click="toLibrary(false)">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
Remove From Library
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
➖
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button class="context-menu-item context-menu-item--left" :disabled="player.status.rating === 1"
|
||||||
|
@click="rate(1)">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
Love
|
Love
|
||||||
|
@ -545,7 +558,29 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button class="context-menu-item context-menu-item--left">
|
<button class="context-menu-item context-menu-item--left" :disabled="player.status.rating === 0"
|
||||||
|
@click="rate(0)">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
Remove Rating
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
❌
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button class="context-menu-item context-menu-item--left"
|
||||||
|
:disabled="player.status.rating === -1" @click="rate(-1)">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
Dislike
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
👎
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button class="context-menu-item context-menu-item--left" v-if="false">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
Share
|
Share
|
||||||
|
@ -555,7 +590,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button class="context-menu-item context-menu-item--left">
|
<button class="context-menu-item context-menu-item--left" v-if="false">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
Open in {{ musicAppVariant() }}
|
Open in {{ musicAppVariant() }}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue