mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 13:17:46 +00:00
feat: cache songs
This commit is contained in:
parent
a41719fb48
commit
da6b7cdd95
4 changed files with 159 additions and 10 deletions
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
57
src/utils/db.js
Normal file
57
src/utils/db.js
Normal file
|
|
@ -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…
Add table
Add a link
Reference in a new issue