xref: /MusicFree/src/utils/fileUtils.ts (revision ddece18e7942a667c4a0b92c4f164e9a18b0ceee)
1import pathConst from '@/constants/pathConst';
2import FastImage from 'react-native-fast-image';
3import {
4    copyFile,
5    downloadFile,
6    exists,
7    mkdir,
8    PicturesDirectoryPath,
9    readDir,
10    unlink,
11    writeFile,
12} from 'react-native-fs';
13import {errorLog} from './log';
14
15export const galleryBasePath = `${PicturesDirectoryPath}/MusicFree/`;
16
17export async function saveToGallery(src: string) {
18    const fileName = `${galleryBasePath}${Date.now()}.png`;
19    if (!(await exists(galleryBasePath))) {
20        await mkdir(galleryBasePath);
21    }
22    if (await exists(src)) {
23        try {
24            await copyFile(src, fileName);
25        } catch (e) {
26            console.log('... ', e);
27        }
28    }
29    if (src.startsWith('http')) {
30        await downloadFile({
31            fromUrl: src,
32            toFile: fileName,
33            background: true,
34        });
35    }
36    if (src.startsWith('data')) {
37        await writeFile(fileName, src);
38    }
39}
40
41export function sizeFormatter(bytes: number | string) {
42    if (typeof bytes === 'string') {
43        return bytes;
44    }
45    if (bytes === 0) return '0B';
46    let k = 1024,
47        sizes = ['B', 'KB', 'MB', 'GB'],
48        i = Math.floor(Math.log(bytes) / Math.log(k));
49    return (bytes / Math.pow(k, i)).toFixed(1) + sizes[i];
50}
51
52export async function checkAndCreateDir(path: string) {
53    const filePath = path;
54    try {
55        if (!(await exists(filePath))) {
56            await mkdir(filePath);
57        }
58    } catch (e) {
59        errorLog('无法初始化目录', {path, e});
60    }
61}
62
63async function getFolderSize(path: string): Promise<number> {
64    let size = 0;
65    try {
66        const fns = await readDir(path);
67        for (let fn of fns) {
68            if (fn.isFile()) {
69                size += fn.size;
70            }
71            // todo: 可以改成并行 promise.all
72            if (fn.isDirectory()) {
73                size += await getFolderSize(fn.path);
74            }
75        }
76    } catch {}
77    return size;
78}
79
80export async function getCacheSize(
81    type: 'music' | 'lyric' | 'image',
82): Promise<number> {
83    if (type === 'music') {
84        return getFolderSize(pathConst.musicCachePath);
85    } else if (type === 'lyric') {
86        return getFolderSize(pathConst.lrcCachePath);
87    } else if (type === 'image') {
88        return getFolderSize(pathConst.imageCachePath);
89    }
90    throw new Error();
91}
92
93export async function clearCache(type: 'music' | 'lyric' | 'image') {
94    if (type === 'music') {
95        try {
96            if (await exists(pathConst.musicCachePath)) {
97                return unlink(pathConst.musicCachePath);
98            }
99        } catch {}
100    } else if (type === 'lyric') {
101        try {
102            const lrcs = readDir(pathConst.lrcCachePath);
103            return Promise.all((await lrcs).map(_ => unlink(_.path)));
104        } catch {}
105    } else if (type === 'image') {
106        return FastImage.clearDiskCache();
107    }
108}
109
110export function addFileScheme(fileName: string) {
111    if (fileName.startsWith('/')) {
112        return `file://${fileName}`;
113    }
114    return fileName;
115}
116
117export function addRandomHash(url: string) {
118    if (url.indexOf('#') === -1) {
119        return `${url}#${Date.now()}`;
120    }
121    return url;
122}
123
124export function trimHash(url: string) {
125    const index = url.lastIndexOf('#');
126    if (index === -1) {
127        return url;
128    }
129    return url.substring(0, index);
130}
131
132export function escapeCharacter(str?: string) {
133    return str !== undefined ? `${str}`.replace(/\//g, '_') : '';
134}
135