mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-28 11:16:23 +08:00
feat: support Last.fm scrobble
This commit is contained in:
parent
cc50faeb09
commit
55585a921f
|
@ -2,4 +2,7 @@ VUE_APP_NETEASE_API_URL=/api
|
||||||
VUE_APP_ELECTRON_API_URL=/api
|
VUE_APP_ELECTRON_API_URL=/api
|
||||||
VUE_APP_ELECTRON_API_URL_DEV=http://127.0.0.1:3000
|
VUE_APP_ELECTRON_API_URL_DEV=http://127.0.0.1:3000
|
||||||
VUE_APP_ENABLE_SENTRY=false
|
VUE_APP_ENABLE_SENTRY=false
|
||||||
|
VUE_APP_LASTFM_API_KEY=09c55292403d961aa517ff7f5e8a3d9c
|
||||||
|
VUE_APP_LASTFM_API_SHARED_SECRET=307c9fda32b3904e53654baff215cb67
|
||||||
DEV_SERVER_PORT=20201
|
DEV_SERVER_PORT=20201
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
- 👆 支持 Touch Bar
|
- 👆 支持 Touch Bar
|
||||||
- 🖥️ 支持 PWA,可在 Chrome/Edge 里点击地址栏右边的 ➕ 安装到电脑
|
- 🖥️ 支持 PWA,可在 Chrome/Edge 里点击地址栏右边的 ➕ 安装到电脑
|
||||||
- 🙉 支持显示歌曲和专辑的 Explicit 标志
|
- 🙉 支持显示歌曲和专辑的 Explicit 标志
|
||||||
|
- 🟥 支持 Last.fm Scrobble
|
||||||
- 🛠 更多特性开发中
|
- 🛠 更多特性开发中
|
||||||
|
|
||||||
## 📦️ 安装
|
## 📦️ 安装
|
||||||
|
@ -148,15 +149,9 @@ API 源代码来自 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryif
|
||||||
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
|
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
|
||||||
|
|
||||||
[album-screenshot]: images/album.png
|
[album-screenshot]: images/album.png
|
||||||
|
|
||||||
[artist-screenshot]: images/artist.png
|
[artist-screenshot]: images/artist.png
|
||||||
|
|
||||||
[explore-screenshot]: images/explore.png
|
[explore-screenshot]: images/explore.png
|
||||||
|
|
||||||
[home-screenshot]: images/home.png
|
[home-screenshot]: images/home.png
|
||||||
|
|
||||||
[library-screenshot]: images/library.png
|
[library-screenshot]: images/library.png
|
||||||
|
|
||||||
[playlist-screenshot]: images/playlist.png
|
[playlist-screenshot]: images/playlist.png
|
||||||
|
|
||||||
[search-screenshot]: images/search.png
|
[search-screenshot]: images/search.png
|
||||||
|
|
BIN
public/img/logos/lastfm.png
Normal file
BIN
public/img/logos/lastfm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
28
src/App.vue
28
src/App.vue
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<Navbar ref="navbar" />
|
<Navbar ref="navbar" v-show="showNavbar" />
|
||||||
<main v-show="!this.$store.state.showLyrics">
|
<main v-show="!this.$store.state.showLyrics">
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<router-view v-if="$route.meta.keepAlive"></router-view>
|
<router-view v-if="$route.meta.keepAlive"></router-view>
|
||||||
|
@ -8,15 +8,12 @@
|
||||||
<router-view v-if="!$route.meta.keepAlive"></router-view>
|
<router-view v-if="!$route.meta.keepAlive"></router-view>
|
||||||
</main>
|
</main>
|
||||||
<transition name="slide-up">
|
<transition name="slide-up">
|
||||||
<Player
|
<Player v-if="enablePlayer" ref="player" v-show="showPlayer"
|
||||||
v-if="this.$store.state.player.enabled"
|
|
||||||
ref="player"
|
|
||||||
v-show="showPlayer"
|
|
||||||
/></transition>
|
/></transition>
|
||||||
<Toast />
|
<Toast />
|
||||||
<ModalAddTrackToPlaylist v-if="isAccountLoggedIn" />
|
<ModalAddTrackToPlaylist v-if="isAccountLoggedIn" />
|
||||||
<ModalNewPlaylist v-if="isAccountLoggedIn" />
|
<ModalNewPlaylist v-if="isAccountLoggedIn" />
|
||||||
<transition name="slide-up" v-if="this.$store.state.player.enabled">
|
<transition name="slide-up" v-if="enablePlayer">
|
||||||
<Lyrics v-show="this.$store.state.showLyrics" />
|
<Lyrics v-show="this.$store.state.showLyrics" />
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,11 +50,24 @@ export default {
|
||||||
},
|
},
|
||||||
showPlayer() {
|
showPlayer() {
|
||||||
return (
|
return (
|
||||||
["mv", "loginUsername", "login", "loginAccount"].includes(
|
[
|
||||||
this.$route.name
|
"mv",
|
||||||
) === false
|
"loginUsername",
|
||||||
|
"login",
|
||||||
|
"loginAccount",
|
||||||
|
"lastfmCallback",
|
||||||
|
].includes(this.$route.name) === false
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
enablePlayer() {
|
||||||
|
return (
|
||||||
|
this.$store.state.player.enabled &&
|
||||||
|
this.$route.name !== "lastfmCallback"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
showNavbar() {
|
||||||
|
return this.$route.name !== "lastfmCallback";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.isElectron) {
|
if (this.isElectron) {
|
||||||
|
|
79
src/api/lastfm.js
Normal file
79
src/api/lastfm.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Last.fm API documents 👉 https://www.last.fm/api
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
import md5 from "crypto-js/md5";
|
||||||
|
|
||||||
|
const apiKey = process.env.VUE_APP_LASTFM_API_KEY;
|
||||||
|
const apiSharedSecret = process.env.VUE_APP_LASTFM_API_SHARED_SECRET;
|
||||||
|
const baseUrl = window.location.origin;
|
||||||
|
const url = "https://ws.audioscrobbler.com/2.0/";
|
||||||
|
|
||||||
|
const sign = (params) => {
|
||||||
|
const sortParamsKeys = Object.keys(params).sort();
|
||||||
|
const sortedParams = sortParamsKeys.reduce((acc, key) => {
|
||||||
|
acc[key] = params[key];
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
let signature = "";
|
||||||
|
for (const [key, value] of Object.entries(sortedParams)) {
|
||||||
|
signature += `${key}${value}`;
|
||||||
|
}
|
||||||
|
return md5(signature + apiSharedSecret).toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
export function auth() {
|
||||||
|
window.open(
|
||||||
|
`https://www.last.fm/api/auth/?api_key=${apiKey}&cb=${baseUrl}/#/lastfm/callback`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function authGetSession(token) {
|
||||||
|
const signature = md5(
|
||||||
|
`api_key${apiKey}methodauth.getSessiontoken${token}${apiSharedSecret}`
|
||||||
|
).toString();
|
||||||
|
return axios({
|
||||||
|
url,
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
method: "auth.getSession",
|
||||||
|
format: "json",
|
||||||
|
api_key: apiKey,
|
||||||
|
api_sig: signature,
|
||||||
|
token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function trackUpdateNowPlaying(params) {
|
||||||
|
params.api_key = apiKey;
|
||||||
|
params.method = "track.updateNowPlaying";
|
||||||
|
params.sk = JSON.parse(localStorage.getItem("lastfm"))["key"];
|
||||||
|
const signature = sign(params);
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
url,
|
||||||
|
method: "POST",
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
api_sig: signature,
|
||||||
|
format: "json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function trackScrobble(params) {
|
||||||
|
params.api_key = apiKey;
|
||||||
|
params.method = "track.scrobble";
|
||||||
|
params.sk = JSON.parse(localStorage.getItem("lastfm"))["key"];
|
||||||
|
const signature = sign(params);
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
url,
|
||||||
|
method: "POST",
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
api_sig: signature,
|
||||||
|
format: "json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
|
@ -103,6 +103,7 @@ class Background {
|
||||||
minHeight: 720,
|
minHeight: 720,
|
||||||
titleBarStyle: "hiddenInset",
|
titleBarStyle: "hiddenInset",
|
||||||
frame: process.platform !== "win32",
|
frame: process.platform !== "win32",
|
||||||
|
title: "YesPlayMusic",
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
webSecurity: false,
|
webSecurity: false,
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
|
@ -186,6 +187,25 @@ class Background {
|
||||||
|
|
||||||
this.window.webContents.on("new-window", function (e, url) {
|
this.window.webContents.on("new-window", function (e, url) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
console.log("open url");
|
||||||
|
const excludeHosts = ["www.last.fm"];
|
||||||
|
const exclude = excludeHosts.find((host) => url.includes(host));
|
||||||
|
if (exclude) {
|
||||||
|
const newWindow = new BrowserWindow({
|
||||||
|
width: 800,
|
||||||
|
height: 600,
|
||||||
|
titleBarStyle: "default",
|
||||||
|
title: "YesPlayMusic",
|
||||||
|
webPreferences: {
|
||||||
|
webSecurity: false,
|
||||||
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true,
|
||||||
|
contextIsolation: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
newWindow.loadURL(url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
shell.openExternal(url);
|
shell.openExternal(url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,11 @@ const routes = [
|
||||||
name: "dailySongs",
|
name: "dailySongs",
|
||||||
component: () => import("@/views/dailyTracks.vue"),
|
component: () => import("@/views/dailyTracks.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/lastfm/callback",
|
||||||
|
name: "lastfmCallback",
|
||||||
|
component: () => import("@/views/lastfmCallback.vue"),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
routes,
|
routes,
|
||||||
|
@ -160,7 +165,7 @@ router.beforeEach((to, from, next) => {
|
||||||
router.afterEach((to) => {
|
router.afterEach((to) => {
|
||||||
if (
|
if (
|
||||||
to.matched.some((record) => !record.meta.keepAlive) &&
|
to.matched.some((record) => !record.meta.keepAlive) &&
|
||||||
!["settings", "dailySongs"].includes(to.name)
|
!["settings", "dailySongs", "lastfmCallback"].includes(to.name)
|
||||||
) {
|
) {
|
||||||
NProgress.start();
|
NProgress.start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,7 @@ export default {
|
||||||
updateDailyTracks(state, dailyTracks) {
|
updateDailyTracks(state, dailyTracks) {
|
||||||
state.dailyTracks = dailyTracks;
|
state.dailyTracks = dailyTracks;
|
||||||
},
|
},
|
||||||
|
updateLastfm(state, session) {
|
||||||
|
state.lastfm = session;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,6 +35,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dailyTracks: [],
|
dailyTracks: [],
|
||||||
|
lastfm: JSON.parse(localStorage.getItem("lastfm")) || {},
|
||||||
player: JSON.parse(localStorage.getItem("player")),
|
player: JSON.parse(localStorage.getItem("player")),
|
||||||
settings: JSON.parse(localStorage.getItem("settings")),
|
settings: JSON.parse(localStorage.getItem("settings")),
|
||||||
data: JSON.parse(localStorage.getItem("data")),
|
data: JSON.parse(localStorage.getItem("data")),
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { getArtist } from "@/api/artist";
|
||||||
import { personalFM, fmTrash } from "@/api/others";
|
import { personalFM, fmTrash } from "@/api/others";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { isAccountLoggedIn } from "@/utils/auth";
|
import { isAccountLoggedIn } from "@/utils/auth";
|
||||||
|
import { trackUpdateNowPlaying, trackScrobble } from "@/api/lastfm";
|
||||||
|
|
||||||
const electron =
|
const electron =
|
||||||
process.env.IS_ELECTRON === true ? window.require("electron") : null;
|
process.env.IS_ELECTRON === true ? window.require("electron") : null;
|
||||||
|
@ -160,16 +161,29 @@ export default class {
|
||||||
this._shuffledList = shuffle(list);
|
this._shuffledList = shuffle(list);
|
||||||
if (firstTrackID !== "first") this._shuffledList.unshift(firstTrackID);
|
if (firstTrackID !== "first") this._shuffledList.unshift(firstTrackID);
|
||||||
}
|
}
|
||||||
async _scrobble(complete = false) {
|
async _scrobble(track, time, complete = false) {
|
||||||
let time = this._howler.seek();
|
console.log("scrobble");
|
||||||
if (complete) {
|
const trackDuration = ~~(track.dt / 1000);
|
||||||
time = ~~(this._currentTrack.dt / 100);
|
|
||||||
}
|
|
||||||
scrobble({
|
scrobble({
|
||||||
id: this._currentTrack.id,
|
id: track.id,
|
||||||
sourceid: this.playlistSource.id,
|
sourceid: this.playlistSource.id,
|
||||||
time,
|
time: complete ? trackDuration : time,
|
||||||
});
|
});
|
||||||
|
if (
|
||||||
|
store.state.lastfm.key !== undefined &&
|
||||||
|
(time >= trackDuration / 2 || time >= 240)
|
||||||
|
) {
|
||||||
|
console.log({ currentTrack: track });
|
||||||
|
const timestamp = ~~(new Date().getTime() / 1000) - time;
|
||||||
|
trackScrobble({
|
||||||
|
artist: track.ar[0].name,
|
||||||
|
track: track.name,
|
||||||
|
timestamp,
|
||||||
|
album: track.al.name,
|
||||||
|
trackNumber: track.no,
|
||||||
|
duration: trackDuration,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_playAudioSource(source, autoplay = true) {
|
_playAudioSource(source, autoplay = true) {
|
||||||
Howler.unload();
|
Howler.unload();
|
||||||
|
@ -235,6 +249,7 @@ export default class {
|
||||||
autoplay = true,
|
autoplay = true,
|
||||||
ifUnplayableThen = "playNextTrack"
|
ifUnplayableThen = "playNextTrack"
|
||||||
) {
|
) {
|
||||||
|
if (autoplay) this._scrobble(this.currentTrack, this._howler.seek(), true);
|
||||||
return getTrackDetail(id).then((data) => {
|
return getTrackDetail(id).then((data) => {
|
||||||
let track = data.songs[0];
|
let track = data.songs[0];
|
||||||
this._currentTrack = track;
|
this._currentTrack = track;
|
||||||
|
@ -321,7 +336,6 @@ export default class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_nextTrackCallback() {
|
_nextTrackCallback() {
|
||||||
this._scrobble(true);
|
|
||||||
if (this.repeatMode === "one") {
|
if (this.repeatMode === "one") {
|
||||||
this._replaceCurrentTrack(this._currentTrack.id);
|
this._replaceCurrentTrack(this._currentTrack.id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -410,6 +424,16 @@ export default class {
|
||||||
this._playing = true;
|
this._playing = true;
|
||||||
document.title = `${this._currentTrack.name} · ${this._currentTrack.ar[0].name} - YesPlayMusic`;
|
document.title = `${this._currentTrack.name} · ${this._currentTrack.ar[0].name} - YesPlayMusic`;
|
||||||
this._playDiscordPresence(this._currentTrack, this.seek());
|
this._playDiscordPresence(this._currentTrack, this.seek());
|
||||||
|
if (store.state.lastfm.key !== undefined) {
|
||||||
|
console.log({ currentTrack: this.currentTrack });
|
||||||
|
trackUpdateNowPlaying({
|
||||||
|
artist: this.currentTrack.ar[0].name,
|
||||||
|
track: this.currentTrack.name,
|
||||||
|
album: this.currentTrack.al.name,
|
||||||
|
trackNumber: this.currentTrack.no,
|
||||||
|
duration: ~~(this.currentTrack.dt / 1000),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
playOrPause() {
|
playOrPause() {
|
||||||
if (this._howler.playing()) {
|
if (this._howler.playing()) {
|
||||||
|
|
98
src/views/lastfmCallback.vue
Normal file
98
src/views/lastfmCallback.vue
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
<template>
|
||||||
|
<div class="lastfm-callback">
|
||||||
|
<div class="section-1">
|
||||||
|
<img src="/img/logos/yesplaymusic.png" />
|
||||||
|
<svg-icon icon-class="x"></svg-icon>
|
||||||
|
<img src="/img/logos/lastfm.png" />
|
||||||
|
</div>
|
||||||
|
<div class="message">{{ message }}</div>
|
||||||
|
<button @click="close" v-show="done"> 完成 </button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { authGetSession } from "@/api/lastfm";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "lastfmCallback",
|
||||||
|
data() {
|
||||||
|
return { message: "请稍等...", done: false };
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
const token = new URLSearchParams(window.location.search).get("token");
|
||||||
|
if (!token) {
|
||||||
|
this.message = "连接失败,请重试或联系开发者(无Token)";
|
||||||
|
this.done = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(token);
|
||||||
|
authGetSession(token).then((result) => {
|
||||||
|
console.log(result);
|
||||||
|
if (!result.data.session) {
|
||||||
|
this.message = "连接失败,请重试或联系开发者(无Session)";
|
||||||
|
this.done = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
localStorage.setItem("lastfm", JSON.stringify(result.data.session));
|
||||||
|
this.$store.commit("updateLastfm", result.data.session);
|
||||||
|
this.message = "已成功连接到 Last.fm";
|
||||||
|
this.done = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close() {
|
||||||
|
window.close();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.lastfm-callback {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: calc(100vh - 192px);
|
||||||
|
}
|
||||||
|
.section-1 {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
img {
|
||||||
|
height: 64px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
.svg-icon {
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
color: rgba(82, 82, 82, 0.28);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: var(--color-primary-bg);
|
||||||
|
color: var(--color-primary);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-top: 24px;
|
||||||
|
transition: 0.2s;
|
||||||
|
padding: 8px 16px;
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.06);
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.94);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -197,6 +197,25 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="item">
|
||||||
|
<div class="left">
|
||||||
|
<div class="title">
|
||||||
|
{{
|
||||||
|
isLastfmConnected
|
||||||
|
? `已连接到 Last.fm (${lastfm.name})`
|
||||||
|
: "连接 Last.fm "
|
||||||
|
}}</div
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<button @click="lastfmDisconnect()" v-if="isLastfmConnected"
|
||||||
|
>断开连接
|
||||||
|
</button>
|
||||||
|
<button @click="lastfmConnect()" v-else> 授权连接 </button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
|
@ -282,6 +301,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from "vuex";
|
import { mapState } from "vuex";
|
||||||
import { doLogout } from "@/utils/auth";
|
import { doLogout } from "@/utils/auth";
|
||||||
|
import { auth as lastfmAuth } from "@/api/lastfm";
|
||||||
import { changeAppearance, bytesToSize } from "@/utils/common";
|
import { changeAppearance, bytesToSize } from "@/utils/common";
|
||||||
import { countDBSize, clearDB } from "@/utils/db";
|
import { countDBSize, clearDB } from "@/utils/db";
|
||||||
import pkg from "../../package.json";
|
import pkg from "../../package.json";
|
||||||
|
@ -304,7 +324,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["player", "settings", "data"]),
|
...mapState(["player", "settings", "data", "lastfm"]),
|
||||||
isElectron() {
|
isElectron() {
|
||||||
return process.env.IS_ELECTRON;
|
return process.env.IS_ELECTRON;
|
||||||
},
|
},
|
||||||
|
@ -470,6 +490,9 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
isLastfmConnected() {
|
||||||
|
return this.lastfm.key !== undefined;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getAllOutputDevices() {
|
getAllOutputDevices() {
|
||||||
|
@ -515,6 +538,20 @@ export default {
|
||||||
this.countDBSize("tracks");
|
this.countDBSize("tracks");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
lastfmConnect() {
|
||||||
|
lastfmAuth();
|
||||||
|
let lastfmChecker = setInterval(() => {
|
||||||
|
const session = localStorage.getItem("lastfm");
|
||||||
|
if (session) {
|
||||||
|
this.$store.commit("updateLastfm", JSON.parse(session));
|
||||||
|
clearInterval(lastfmChecker);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
lastfmDisconnect() {
|
||||||
|
localStorage.removeItem("lastfm");
|
||||||
|
this.$store.commit("updateLastfm", {});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.countDBSize("tracks");
|
this.countDBSize("tracks");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user