diff --git a/package.json b/package.json index ebf23f5..67a9a69 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "core-js": "^3.6.5", "crypto-js": "^4.0.0", "dayjs": "^1.8.36", + "dexie": "^3.0.3", "discord-rich-presence": "^0.0.8", "electron": "^12.0.0", "electron-builder": "^22.10.5", @@ -50,7 +51,6 @@ "extract-zip": "^2.0.1", "howler": "^2.2.0", "js-cookie": "^2.2.1", - "localforage": "^1.9.0", "lodash": "^4.17.20", "nprogress": "^0.2.0", "pac-proxy-agent": "^4.1.0", diff --git a/src/utils/Player.js b/src/utils/Player.js index e59375f..35f6fee 100644 --- a/src/utils/Player.js +++ b/src/utils/Player.js @@ -1,8 +1,7 @@ import { getTrackDetail, scrobble, getMP3 } from "@/api/track"; import { shuffle } from "lodash"; import { Howler, Howl } from "howler"; -import localforage from "localforage"; -import { cacheTrack } from "@/utils/db"; +import { cacheTrackSource, getTrackSource } from "@/utils/db"; import { getAlbum } from "@/api/album"; import { getPlaylistDetail } from "@/api/playlist"; import { getArtist } from "@/api/artist"; @@ -201,10 +200,9 @@ export default class { }); } _getAudioSourceFromCache(id) { - let tracks = localforage.createInstance({ name: "tracks" }); - return tracks.getItem(id).then((t) => { - if (t === null) return null; - const source = URL.createObjectURL(new Blob([t.mp3])); + return getTrackSource(id).then((t) => { + if (!t) return null; + const source = URL.createObjectURL(new Blob([t.source])); return source; }); } @@ -216,7 +214,7 @@ export default class { if (result.data[0].freeTrialInfo !== null) return null; // 跳过只能试听的歌曲 const source = result.data[0].url.replace(/^http:/, "https:"); if (store.state.settings.automaticallyCacheSongs) { - cacheTrack(track.id, source); + cacheTrackSource(track, source, result.data[0].br); } return source; }); @@ -230,7 +228,8 @@ export default class { if (process.env.IS_ELECTRON !== true) return null; const source = ipcRenderer.sendSync("unblock-music", track); if (store.state.settings.automaticallyCacheSongs && source?.url) { - cacheTrack(track.id, source.url); + // TODO: 将unblockMusic字样换成真正的来源(比如酷我咪咕等) + cacheTrackSource(track, source.url, 128000, "unblockMusic"); } return source?.url; } diff --git a/src/utils/db.js b/src/utils/db.js index e7bb5bf..2e3537a 100644 --- a/src/utils/db.js +++ b/src/utils/db.js @@ -1,54 +1,66 @@ import axios from "axios"; -import localforage from "localforage"; +import Dexie from "dexie"; +// import pkg from "../../package.json"; -export function cacheTrack(id, url) { - let tracks = localforage.createInstance({ - name: "tracks", - }); +const db = new Dexie("yesplaymusic"); +db.version(1).stores({ + trackSources: "&id", +}); - // 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 +export function cacheTrackSource(trackInfo, url, bitRate, from = "netease") { + const name = trackInfo.name; + const artist = trackInfo.ar[0]?.name || trackInfo.artists[0]?.name; return axios .get(url, { responseType: "arraybuffer", }) .then((response) => { - tracks.setItem(`${id}`, { mp3: response.data }); - return { mp3: response.data }; + db.trackSources.put({ + id: trackInfo.id, + source: response.data, + bitRate, + from, + name, + artist, + }); + console.debug(`[debug][db.js] cached track 👉 ${name} by ${artist}`); + return { trackID: trackInfo.id, source: response.data, bitRate }; }); } -export function countDBSize(dbName) { - let db = localforage.createInstance({ - name: dbName, +export function getTrackSource(id) { + return db.trackSources.get(Number(id)).then((track) => { + if (!track) return null; + console.debug( + `[debug][db.js] get track from cache 👉 ${track.name} by ${track.artist}` + ); + return track; }); +} + +export function countDBSize() { let trackSizes = []; - return db - .iterate((value) => { - trackSizes.push(value.mp3.byteLength); + return db.trackSources + .each((track) => { + trackSizes.push(track.source.byteLength); }) .then(() => { return { bytes: trackSizes.reduce((s1, s2) => s1 + s2, 0), length: trackSizes.length, }; - }) - .catch((err) => { - console.log(err); }); } -export function clearDB(dbName) { - let db = localforage.createInstance({ - name: dbName, +export function clearDB() { + return new Promise((resolve) => { + db.tables.forEach(function (table) { + table.clear(); + }); + resolve(); }); - return db.clear(); } + +window.cacheTrackSource = cacheTrackSource; +window.db = db; +window.countDBSize = countDBSize; diff --git a/src/utils/updateApp.js b/src/utils/updateApp.js index ec1b777..bd1b565 100644 --- a/src/utils/updateApp.js +++ b/src/utils/updateApp.js @@ -54,9 +54,15 @@ const updatePlayer = () => { localStorage.setItem("player", JSON.stringify(data)); }; +const removeOldStuff = () => { + // remove old indexedDB databases created by localforage + indexedDB.deleteDatabase("tracks"); +}; + export default function () { updateSetting(); updateData(); updatePlayer(); + removeOldStuff(); localStorage.setItem("appVersion", JSON.stringify(pkg.version)); } diff --git a/src/views/settings.vue b/src/views/settings.vue index e647b50..d7307c0 100644 --- a/src/views/settings.vue +++ b/src/views/settings.vue @@ -122,7 +122,7 @@ >
-
@@ -365,7 +365,7 @@ export default { set(value) { if (value === this.settings.musicQuality) return; this.$store.commit("changeMusicQuality", value); - this.clearCache("tracks"); + this.clearCache(); }, }, lyricFontSize: { @@ -443,7 +443,7 @@ export default { value, }); if (value === false) { - this.clearCache("tracks"); + this.clearCache(); } }, }, @@ -520,8 +520,8 @@ export default { doLogout(); this.$router.push({ name: "home" }); }, - countDBSize(dbName) { - countDBSize(dbName).then((data) => { + countDBSize() { + countDBSize().then((data) => { if (data === undefined) { this.tracksCache = { size: "0KB", @@ -533,10 +533,9 @@ export default { this.tracksCache.length = data.length; }); }, - clearCache(dbName) { - // TODO: toast - clearDB(dbName).then(() => { - this.countDBSize("tracks"); + clearCache() { + clearDB().then(() => { + this.countDBSize(); }); }, lastfmConnect() { diff --git a/yarn.lock b/yarn.lock index 273b851..d88d4bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4258,6 +4258,11 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== +dexie@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dexie/-/dexie-3.0.3.tgz#ede63849dfe5f07e13e99bb72a040e8ac1d29dab" + integrity sha512-BSFhGpngnCl1DOr+8YNwBDobRMH0ziJs2vts69VilwetHYOtEDcLqo7d/XiIphM0tJZ2rPPyAGd31lgH2Ln3nw== + dicer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872" @@ -7319,13 +7324,6 @@ localforage@1.8.1: dependencies: lie "3.1.1" -localforage@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.9.0.tgz#f3e4d32a8300b362b4634cc4e066d9d00d2f09d1" - integrity sha512-rR1oyNrKulpe+VM9cYmcFn6tsHuokyVHFaCM3+osEmxaHTbEk8oQu6eGDfS6DQLWi/N67XRmB8ECG37OES368g== - dependencies: - lie "3.1.1" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"