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