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 @@ >