From 9ae15c198de38296e74a1c572de29e7035e856fa Mon Sep 17 00:00:00 2001 From: Map1en_ Date: Mon, 19 Apr 2021 10:43:52 +0800 Subject: [PATCH] feat(cache): add songs cache limit feature (#548) resolve #232 --- src/locale/lang/en.js | 4 +++ src/locale/lang/tr.js | 4 +++ src/locale/lang/zh-CN.js | 4 +++ src/store/initLocalStorage.js | 1 + src/utils/db.js | 49 +++++++++++++++++++++++++++++++++-- src/views/home.vue | 2 ++ src/views/settings.vue | 27 +++++++++++++++++++ 7 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/locale/lang/en.js b/src/locale/lang/en.js index 2d8c29d..cec45cf 100644 --- a/src/locale/lang/en.js +++ b/src/locale/lang/en.js @@ -124,6 +124,10 @@ export default { high: "High", lossless: "Lossless", }, + cacheLimit: { + text: "Songs Cache limit", + none: "None", + }, lyricFontSize: { text: "Lyric Font Size", small: "Small", diff --git a/src/locale/lang/tr.js b/src/locale/lang/tr.js index 1474225..08b2f7c 100644 --- a/src/locale/lang/tr.js +++ b/src/locale/lang/tr.js @@ -124,6 +124,10 @@ export default { high: "Yüksek", lossless: "Kaliteli", }, + cacheLimit: { + text: "Şarkılar Önbellek sınırı", + none: "Yok", + }, lyricFontSize: { text: "Şarkı Sözleri Yazı Boyutu", small: "Küçük", diff --git a/src/locale/lang/zh-CN.js b/src/locale/lang/zh-CN.js index 41c1226..dcea828 100644 --- a/src/locale/lang/zh-CN.js +++ b/src/locale/lang/zh-CN.js @@ -125,6 +125,10 @@ export default { high: "极高", lossless: "无损", }, + cacheLimit: { + text: "歌曲缓存上限", + none: "无限制", + }, lyricFontSize: { text: "歌词字体大小", small: "小", diff --git a/src/store/initLocalStorage.js b/src/store/initLocalStorage.js index 3fb106f..040f324 100644 --- a/src/store/initLocalStorage.js +++ b/src/store/initLocalStorage.js @@ -12,6 +12,7 @@ let localStorage = { showPlaylistsByAppleMusic: true, showUnavailableSongInGreyStyle: true, automaticallyCacheSongs: false, + cacheLimit: false, nyancatStyle: false, showLyricsTranslation: true, showLyricsDynamicBackground: false, diff --git a/src/utils/db.js b/src/utils/db.js index a5314fd..abbb962 100644 --- a/src/utils/db.js +++ b/src/utils/db.js @@ -1,12 +1,49 @@ import axios from "axios"; import Dexie from "dexie"; +import store from "@/store"; // import pkg from "../../package.json"; const db = new Dexie("yesplaymusic"); + +db.version(2) + .stores({ + trackSources: "&id, createTime", + }) + .upgrade((tx) => + tx + .table("trackSources") + .toCollection() + .modify( + (track) => + !track.createTime && (track.createTime = new Date().getTime()) + ) + ); + db.version(1).stores({ trackSources: "&id", }); +let tracksCacheBytes = 0; + +async function deleteExcessCache() { + if ( + store.state.settings.cacheLimit === false || + tracksCacheBytes < store.state.settings.cacheLimit * Math.pow(1024, 2) + ) + return; + try { + const delCache = await db.trackSources.orderBy("createTime").first(); + await db.trackSources.delete(delCache.id); + tracksCacheBytes -= delCache.source.byteLength; + console.debug( + `[debug][db.js] deleteExcessCacheSucces, track: ${delCache.name}, size: ${delCache.source.byteLength}, cacheSize:${tracksCacheBytes}` + ); + deleteExcessCache(); + } catch (error) { + console.debug("[debug][db.js] deleteExcessCacheFailed", error); + } +} + export function cacheTrackSource(trackInfo, url, bitRate, from = "netease") { const name = trackInfo.name; const artist = trackInfo.ar[0]?.name || trackInfo.artists[0]?.name; @@ -22,8 +59,11 @@ export function cacheTrackSource(trackInfo, url, bitRate, from = "netease") { from, name, artist, + createTime: new Date().getTime(), }); console.debug(`[debug][db.js] cached track 👉 ${name} by ${artist}`); + tracksCacheBytes += response.data.byteLength; + deleteExcessCache(); return { trackID: trackInfo.id, source: response.data, bitRate }; }); } @@ -39,16 +79,21 @@ export function getTrackSource(id) { } export function countDBSize() { - let trackSizes = []; + const trackSizes = []; return db.trackSources .each((track) => { trackSizes.push(track.source.byteLength); }) .then(() => { - return { + const res = { bytes: trackSizes.reduce((s1, s2) => s1 + s2, 0), length: trackSizes.length, }; + tracksCacheBytes = res.bytes; + console.debug( + `[debug][db.js] load tracksCacheBytes: ${tracksCacheBytes}` + ); + return res; }); } diff --git a/src/views/home.vue b/src/views/home.vue index 78912d9..b1c28f3 100644 --- a/src/views/home.vue +++ b/src/views/home.vue @@ -65,6 +65,7 @@ import { toplists, recommendPlaylist } from "@/api/playlist"; import { toplistOfArtists } from "@/api/artist"; import { byAppleMusic } from "@/utils/staticData"; +import { countDBSize } from "@/utils/db"; import { newAlbums } from "@/api/album"; import NProgress from "nprogress"; import { mapState } from "vuex"; @@ -128,6 +129,7 @@ export default { this.topList.ids.includes(l.id) ); }); + countDBSize(); }, }, activated() { diff --git a/src/views/settings.vue b/src/views/settings.vue index aca6718..13d28b8 100644 --- a/src/views/settings.vue +++ b/src/views/settings.vue @@ -110,6 +110,22 @@ +
+
+
{{ $t("settings.cacheLimit.text") }}
+
+
+ +
+
@@ -522,6 +538,17 @@ export default { }); }, }, + cacheLimit: { + get() { + return this.settings.cacheLimit || false; + }, + set(value) { + this.$store.commit("updateSettings", { + key: "cacheLimit", + value, + }); + }, + }, isLastfmConnected() { return this.lastfm.key !== undefined; },