xref: /MusicFree/src/core/mediaCache.ts (revision 4ade83edc3d07d31371dc1e6b3750001ca6d44da)
1import {addFileScheme} from '@/utils/fileUtils';
2import getOrCreateMMKV from '@/utils/getOrCreateMMKV';
3import {getMediaKey} from '@/utils/mediaItem';
4import safeParse from '@/utils/safeParse';
5import {exists, unlink} from 'react-native-fs';
6
7// Internal Method
8const mediaCacheStore = getOrCreateMMKV('cache.MediaCache', true);
9
10// 最多缓存1000条数据
11const maxCacheCount = 800;
12
13/** 获取meta信息 */
14const getMediaCache = (mediaItem: ICommon.IMediaBase) => {
15    if (mediaItem.platform && mediaItem.id) {
16        const cacheMediaItem = mediaCacheStore.getString(
17            getMediaKey(mediaItem),
18        );
19        return cacheMediaItem
20            ? safeParse<ICommon.IMediaBase>(cacheMediaItem)
21            : null;
22    }
23
24    return null;
25};
26
27/** 设置meta信息 */
28const setMediaCache = (mediaItem: ICommon.IMediaBase) => {
29    if (mediaItem.platform && mediaItem.id) {
30        const allKeys = mediaCacheStore.getAllKeys();
31        if (allKeys.length >= maxCacheCount) {
32            // TODO: 随机删一半
33            for (let i = 0; i < maxCacheCount / 2; ++i) {
34                const rawCacheMedia = mediaCacheStore.getString(allKeys[i]);
35                const cacheData = rawCacheMedia
36                    ? safeParse(rawCacheMedia)
37                    : null;
38                clearLocalCaches(cacheData);
39
40                mediaCacheStore.delete(allKeys[i]);
41            }
42        }
43
44        mediaCacheStore.set(getMediaKey(mediaItem), JSON.stringify(mediaItem));
45        return true;
46    }
47
48    return false;
49};
50
51async function clearLocalCaches(cacheData: IMusic.IMusicItemCache) {
52    if (cacheData.$localLyric) {
53        await checkPathAndRemove(cacheData.$localLyric.lrc);
54        const versions = cacheData.$localLyric.versions;
55        if (versions) {
56            for (let v in versions) {
57                await checkPathAndRemove(versions[v].lrc);
58            }
59        }
60    }
61}
62
63async function checkPathAndRemove(filePath?: string) {
64    if (!filePath) {
65        return;
66    }
67    filePath = addFileScheme(filePath);
68    if (await exists(filePath)) {
69        unlink(filePath);
70    }
71}
72
73/** 移除缓存信息 */
74const removeMediaCache = (mediaItem: ICommon.IMediaBase) => {
75    if (mediaItem.platform && mediaItem.id) {
76        mediaCacheStore.delete(getMediaKey(mediaItem));
77    }
78
79    return false;
80};
81
82const MediaCache = {
83    getMediaCache,
84    setMediaCache,
85    removeMediaCache,
86};
87
88export default MediaCache;
89