xref: /MusicFree/src/utils/fileUtils.ts (revision 095287552b9baf2f2ceeb9397c563c292a4f7934)
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';
14import path from 'path-browserify';
15
16export const galleryBasePath = `${PicturesDirectoryPath}/MusicFree/`;
17
18export async function saveToGallery(src: string) {
19    const fileName = `${galleryBasePath}${Date.now()}.png`;
20    if (!(await exists(galleryBasePath))) {
21        await mkdir(galleryBasePath);
22    }
23    if (await exists(src)) {
24        try {
25            await copyFile(src, fileName);
26        } catch (e) {
27            console.log('... ', e);
28        }
29    }
30    if (src.startsWith('http')) {
31        await downloadFile({
32            fromUrl: src,
33            toFile: fileName,
34            background: true,
35        });
36    }
37    if (src.startsWith('data')) {
38        await writeFile(fileName, src);
39    }
40}
41
42export function sizeFormatter(bytes: number | string) {
43    if (typeof bytes === 'string') {
44        return bytes;
45    }
46    if (bytes === 0) return '0B';
47    let k = 1024,
48        sizes = ['B', 'KB', 'MB', 'GB'],
49        i = Math.floor(Math.log(bytes) / Math.log(k));
50    return (bytes / Math.pow(k, i)).toFixed(1) + sizes[i];
51}
52
53export async function checkAndCreateDir(dirPath: string) {
54    const filePath = dirPath;
55    try {
56        if (!(await exists(filePath))) {
57            await mkdir(filePath);
58        }
59    } catch (e) {
60        errorLog('无法初始化目录', {path: dirPath, e});
61    }
62}
63
64async function getFolderSize(dirPath: string): Promise<number> {
65    let size = 0;
66    try {
67        const fns = await readDir(dirPath);
68        for (let fn of fns) {
69            if (fn.isFile()) {
70                size += fn.size;
71            }
72            // todo: 可以改成并行 promise.all
73            if (fn.isDirectory()) {
74                size += await getFolderSize(fn.path);
75            }
76        }
77    } catch {}
78    return size;
79}
80
81export async function getCacheSize(
82    type: 'music' | 'lyric' | 'image',
83): Promise<number> {
84    if (type === 'music') {
85        return getFolderSize(pathConst.musicCachePath);
86    } else if (type === 'lyric') {
87        return getFolderSize(pathConst.lrcCachePath);
88    } else if (type === 'image') {
89        return getFolderSize(pathConst.imageCachePath);
90    }
91    throw new Error();
92}
93
94export async function clearCache(type: 'music' | 'lyric' | 'image') {
95    if (type === 'music') {
96        try {
97            if (await exists(pathConst.musicCachePath)) {
98                return unlink(pathConst.musicCachePath);
99            }
100        } catch {}
101    } else if (type === 'lyric') {
102        try {
103            const lrcs = readDir(pathConst.lrcCachePath);
104            return Promise.all((await lrcs).map(_ => unlink(_.path)));
105        } catch {}
106    } else if (type === 'image') {
107        return FastImage.clearDiskCache();
108    }
109}
110
111export function addFileScheme(fileName: string) {
112    if (fileName.startsWith('/')) {
113        return `file://${fileName}`;
114    }
115    return fileName;
116}
117
118export function addRandomHash(url: string) {
119    if (url.indexOf('#') === -1) {
120        return `${url}#${Date.now()}`;
121    }
122    return url;
123}
124
125export function trimHash(url: string) {
126    const index = url.lastIndexOf('#');
127    if (index === -1) {
128        return url;
129    }
130    return url.substring(0, index);
131}
132
133export function escapeCharacter(str?: string) {
134    return str !== undefined ? `${str}`.replace(/\//g, '_') : '';
135}
136
137export function getDirectory(dirPath: string) {
138    const lastSlash = dirPath.lastIndexOf('/');
139    if (lastSlash === -1) {
140        return dirPath;
141    }
142    return dirPath.slice(0, lastSlash);
143}
144
145export function getFileName(filePath: string, withoutExt?: boolean) {
146    const lastSlash = filePath.lastIndexOf('/');
147    if (lastSlash === -1) {
148        return filePath;
149    }
150    const fileName = filePath.slice(lastSlash);
151    if (withoutExt) {
152        const lastDot = fileName.lastIndexOf('.');
153        return lastDot === -1 ? fileName : fileName.slice(0, lastDot);
154    } else {
155        return fileName;
156    }
157}
158
159export async function mkdirR(directory: string) {
160    let folder = directory;
161    const checkStack = [];
162    while (folder.length > 15) {
163        checkStack.push(folder);
164        folder = path.dirname(folder);
165    }
166    let existPos = 0;
167    for (let i = 0; i < checkStack.length; ++i) {
168        const isExist = await exists(checkStack[i]);
169        if (isExist) {
170            existPos = i;
171            break;
172        }
173    }
174
175    for (let j = existPos - 1; j >= 0; --j) {
176        try {
177            await mkdir(checkStack[j]);
178        } catch (e) {
179            console.log('error', e);
180        }
181    }
182}
183