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

@ -115,6 +115,7 @@ export function splitSoundtrackAlbumTitle(title) {
"Original MGM Motion Picture Soundtrack",
"Complete Original Motion Picture Score",
"Original Music From The Motion Picture",
"Music From The Disney+ Original Movie",
"Original Music From The Netflix Film",
"Original Score to the Motion Picture",
"Original Motion Picture Soundtrack",
@ -153,7 +154,13 @@ export function splitSoundtrackAlbumTitle(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) {
if (title.includes(keyword) === false) continue;
return {
@ -171,3 +178,18 @@ export function splitAlbumTitle(title) {
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>
</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="left">
<div class="title"> Show Github Icon </div>
@ -129,10 +139,19 @@
<script>
import { mapState } from "vuex";
import { doLogout } from "@/utils/auth";
import { changeAppearance } from "@/utils/common";
import { changeAppearance, bytesToSize } from "@/utils/common";
import { countDBSize, clearDB } from "@/utils/db";
export default {
name: "settings",
data() {
return {
tracksCache: {
size: "0KB",
length: 0,
},
};
},
computed: {
...mapState(["settings", "data"]),
lang: {
@ -159,11 +178,13 @@ export default {
},
musicQuality: {
get() {
if (this.settings.appearance === undefined) return 320000;
if (this.settings.musicQuality === undefined) return 320000;
return this.settings.musicQuality;
},
set(value) {
if (value === this.settings.musicQuality) return;
this.$store.commit("changeMusicQuality", value);
this.clearCache("tracks");
},
},
showGithubIcon: {
@ -208,6 +229,31 @@ export default {
doLogout();
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>
@ -329,6 +375,21 @@ h2 {
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 {

Loading…
Cancel
Save