feat: cache songs

master
qier222 4 years ago
parent a41719fb48
commit da6b7cdd95
No known key found for this signature in database
GPG Key ID: 9C85007ED905F14D

@ -1,13 +1,16 @@
import { updateMediaSessionMetaData } from "@/utils/mediaSession"; import { updateMediaSessionMetaData } from "@/utils/mediaSession";
import { getTrackDetail, scrobble, getMP3 } from "@/api/track"; import { getTrackDetail, scrobble } from "@/api/track";
import { isAccountLoggedIn } from "@/utils/auth"; import { isAccountLoggedIn } from "@/utils/auth";
import { updateHttps } from "@/utils/common"; // import { updateHttps } from "@/utils/common";
import localforage from "localforage";
import { cacheTrack } from "@/utils/db";
export default { export default {
switchTrack({ state, dispatch, commit }, basicTrack) { switchTrack({ state, dispatch, commit }, basicTrack) {
getTrackDetail(basicTrack.id).then((data) => { getTrackDetail(basicTrack.id).then((data) => {
let track = data.songs[0]; let track = data.songs[0];
track.sort = basicTrack.sort; track.sort = basicTrack.sort;
// 获取当前的播放时间。初始化为 loading 状态时返回 howler 的实例而不是浮点数时间,比如 1.332 // 获取当前的播放时间。初始化为 loading 状态时返回 howler 的实例而不是浮点数时间,比如 1.332
let time = state.howler.seek(); let time = state.howler.seek();
let currentTime = 0; let currentTime = 0;
@ -26,6 +29,7 @@ export default {
sourceid: state.player.listInfo.id, sourceid: state.player.listInfo.id,
time: currentTime, time: currentTime,
}); });
commit("updateCurrentTrack", track); commit("updateCurrentTrack", track);
updateMediaSessionMetaData(track); updateMediaSessionMetaData(track);
document.title = `${track.name} · ${track.ar[0].name} - YesPlayMusic`; document.title = `${track.name} · ${track.ar[0].name} - YesPlayMusic`;
@ -42,11 +46,16 @@ export default {
}); });
} }
if (isAccountLoggedIn()) { if (isAccountLoggedIn()) {
getMP3(track.id).then((data) => { let tracks = localforage.createInstance({
// 未知情况下会没有返回数据导致报错,增加防范逻辑 name: "tracks",
if (data.data[0]) { });
const url = updateHttps(data.data[0].url); tracks.getItem(`${track.id}`).then((t) => {
commitMP3(url); if (t !== null) {
commitMP3(URL.createObjectURL(t.mp3));
} else {
cacheTrack(`${track.id}`).then((t) => {
commitMP3(URL.createObjectURL(t.mp3));
});
} }
}); });
} else { } else {

@ -115,6 +115,7 @@ export function splitSoundtrackAlbumTitle(title) {
"Original MGM Motion Picture Soundtrack", "Original MGM Motion Picture Soundtrack",
"Complete Original Motion Picture Score", "Complete Original Motion Picture Score",
"Original Music From The Motion Picture", "Original Music From The Motion Picture",
"Music From The Disney+ Original Movie",
"Original Music From The Netflix Film", "Original Music From The Netflix Film",
"Original Score to the Motion Picture", "Original Score to the Motion Picture",
"Original Motion Picture Soundtrack", "Original Motion Picture Soundtrack",
@ -153,7 +154,13 @@ export function splitSoundtrackAlbumTitle(title) {
} }
export function splitAlbumTitle(title) { export function splitAlbumTitle(title) {
let keywords = ["Bonus Tracks Edition", "Complete Edition", "Deluxe Edition"]; let keywords = [
"Bonus Tracks Edition",
"Complete Edition",
"Deluxe Edition",
"Deluxe Version",
"Tour Edition",
];
for (let keyword of keywords) { for (let keyword of keywords) {
if (title.includes(keyword) === false) continue; if (title.includes(keyword) === false) continue;
return { return {
@ -171,3 +178,18 @@ export function splitAlbumTitle(title) {
subtitle: "", subtitle: "",
}; };
} }
export function bytesToSize(bytes) {
var marker = 1024; // Change to 1000 if required
var decimal = 2; // Change as required
var kiloBytes = marker;
var megaBytes = marker * marker;
var gigaBytes = marker * marker * marker;
if (bytes < kiloBytes) return bytes + " Bytes";
else if (bytes < megaBytes)
return (bytes / kiloBytes).toFixed(decimal) + " KB";
else if (bytes < gigaBytes)
return (bytes / megaBytes).toFixed(decimal) + " MB";
else return (bytes / gigaBytes).toFixed(decimal) + " GB";
}

@ -0,0 +1,57 @@
import axios from "axios";
import localforage from "localforage";
import { getMP3 } from "@/api/track";
export function cacheTrack(id) {
let tracks = localforage.createInstance({
name: "tracks",
});
// TODO: limit cache songs number
// tracks.length().then(function (length) {
// if (length > 2) {
// tracks.keys().then(function (keys) {
// tracks.removeItem(keys[keys.length - 2]);
// });
// }
// });
// TODO: cache track details
return getMP3(id).then((data) => {
return axios
.get(data.data[0].url.replace(/^http:/, "https:"), {
responseType: "blob",
})
.then((data) => {
tracks.setItem(`${id}`, { mp3: data.data });
return { mp3: data.data };
});
});
}
export function countDBSize(dbName) {
let db = localforage.createInstance({
name: dbName,
});
let trackSizes = [];
return db
.iterate((value) => {
trackSizes.push(value.mp3.size);
})
.then(() => {
return {
bytes: trackSizes.reduce((s1, s2) => s1 + s2),
length: trackSizes.length,
};
})
.catch((err) => {
console.log(err);
});
}
export function clearDB(dbName) {
let db = localforage.createInstance({
name: dbName,
});
return db.clear();
}

@ -74,6 +74,16 @@
</select> </select>
</div> </div>
</div> </div>
<div class="item">
<div class="left">
<div class="title"
>Cached {{ tracksCache.length }} songs ({{ tracksCache.size }})</div
>
</div>
<div class="right">
<button @click="clearCache('tracks')"> Clear Songs Cache </button>
</div>
</div>
<div class="item"> <div class="item">
<div class="left"> <div class="left">
<div class="title"> Show Github Icon </div> <div class="title"> Show Github Icon </div>
@ -129,10 +139,19 @@
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import { doLogout } from "@/utils/auth"; import { doLogout } from "@/utils/auth";
import { changeAppearance } from "@/utils/common"; import { changeAppearance, bytesToSize } from "@/utils/common";
import { countDBSize, clearDB } from "@/utils/db";
export default { export default {
name: "settings", name: "settings",
data() {
return {
tracksCache: {
size: "0KB",
length: 0,
},
};
},
computed: { computed: {
...mapState(["settings", "data"]), ...mapState(["settings", "data"]),
lang: { lang: {
@ -159,11 +178,13 @@ export default {
}, },
musicQuality: { musicQuality: {
get() { get() {
if (this.settings.appearance === undefined) return 320000; if (this.settings.musicQuality === undefined) return 320000;
return this.settings.musicQuality; return this.settings.musicQuality;
}, },
set(value) { set(value) {
if (value === this.settings.musicQuality) return;
this.$store.commit("changeMusicQuality", value); this.$store.commit("changeMusicQuality", value);
this.clearCache("tracks");
}, },
}, },
showGithubIcon: { showGithubIcon: {
@ -208,6 +229,31 @@ export default {
doLogout(); doLogout();
this.$router.push({ name: "home" }); this.$router.push({ name: "home" });
}, },
countDBSize(dbName) {
countDBSize(dbName).then((data) => {
if (data === undefined) {
this.tracksCache = {
size: "0KB",
length: 0,
};
return;
}
this.tracksCache.size = bytesToSize(data.bytes);
this.tracksCache.length = data.length;
});
},
clearCache(dbName) {
// TODO: toast
clearDB(dbName).then(() => {
this.countDBSize("tracks");
});
},
},
created() {
this.countDBSize("tracks");
},
activated() {
this.countDBSize("tracks");
}, },
}; };
</script> </script>
@ -329,6 +375,21 @@ h2 {
background: var(--color-primary-bg); background: var(--color-primary-bg);
} }
} }
button {
color: var(--color-text);
background: var(--color-secondary-bg);
padding: 8px 12px 8px 12px;
font-weight: 600;
border-radius: 8px;
transition: 0.2s;
&:hover {
transform: scale(1.06);
}
&:active {
transform: scale(0.94);
}
}
} }
.beforeAnimation { .beforeAnimation {

Loading…
Cancel
Save