Refactor and extract
This commit is contained in:
parent
82bbb1c6dd
commit
297ca09535
4 changed files with 44 additions and 28 deletions
|
@ -34,7 +34,7 @@ import {
|
|||
mergeMetadata,
|
||||
splitFilenameAndExtension,
|
||||
} from "utils/file";
|
||||
import { safeDirectoryName, sanitizedUniqueFileName } from "utils/native-fs";
|
||||
import { safeDirectoryName, safeFileName } from "utils/native-fs";
|
||||
import { getAllLocalCollections } from "../collectionService";
|
||||
import downloadManager from "../download";
|
||||
import { getAllLocalFiles } from "../fileService";
|
||||
|
@ -1057,7 +1057,7 @@ class ExportService {
|
|||
file,
|
||||
);
|
||||
} else {
|
||||
const fileExportName = await sanitizedUniqueFileName(
|
||||
const fileExportName = await safeFileName(
|
||||
collectionExportPath,
|
||||
file.metadata.title,
|
||||
);
|
||||
|
@ -1096,11 +1096,11 @@ class ExportService {
|
|||
) {
|
||||
const fileBlob = await new Response(fileStream).blob();
|
||||
const livePhoto = await decodeLivePhoto(file, fileBlob);
|
||||
const imageExportName = await sanitizedUniqueFileName(
|
||||
const imageExportName = await safeFileName(
|
||||
collectionExportPath,
|
||||
livePhoto.imageNameTitle,
|
||||
);
|
||||
const videoExportName = await sanitizedUniqueFileName(
|
||||
const videoExportName = await safeFileName(
|
||||
collectionExportPath,
|
||||
livePhoto.videoNameTitle,
|
||||
);
|
||||
|
|
|
@ -52,7 +52,7 @@ import {
|
|||
import { VISIBILITY_STATE } from "types/magicMetadata";
|
||||
import { FileTypeInfo } from "types/upload";
|
||||
import { isArchivedFile, updateMagicMetadata } from "utils/magicMetadata";
|
||||
import { sanitizedUniqueFileName } from "utils/native-fs";
|
||||
import { safeFileName } from "utils/native-fs";
|
||||
|
||||
const WAIT_TIME_IMAGE_CONVERSION = 30 * 1000;
|
||||
|
||||
|
@ -812,7 +812,7 @@ async function downloadFileDesktop(
|
|||
if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) {
|
||||
const fileBlob = await new Response(updatedFileStream).blob();
|
||||
const livePhoto = await decodeLivePhoto(file, fileBlob);
|
||||
const imageExportName = await sanitizedUniqueFileName(
|
||||
const imageExportName = await safeFileName(
|
||||
downloadPath,
|
||||
livePhoto.imageNameTitle,
|
||||
);
|
||||
|
@ -822,7 +822,7 @@ async function downloadFileDesktop(
|
|||
imageStream,
|
||||
);
|
||||
try {
|
||||
const videoExportName = await sanitizedUniqueFileName(
|
||||
const videoExportName = await safeFileName(
|
||||
downloadPath,
|
||||
livePhoto.videoNameTitle,
|
||||
);
|
||||
|
@ -836,7 +836,7 @@ async function downloadFileDesktop(
|
|||
throw e;
|
||||
}
|
||||
} else {
|
||||
const fileExportName = await sanitizedUniqueFileName(
|
||||
const fileExportName = await safeFileName(
|
||||
downloadPath,
|
||||
file.metadata.title,
|
||||
);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { ensureElectron } from "@/next/electron";
|
||||
import { nameAndExtension } from "@/next/file";
|
||||
import sanitize from "sanitize-filename";
|
||||
import { exportTrashDirectoryName } from "services/export";
|
||||
import { splitFilenameAndExtension } from "utils/file";
|
||||
import {
|
||||
exportMetadataDirectoryName,
|
||||
exportTrashDirectoryName,
|
||||
} from "services/export";
|
||||
|
||||
/**
|
||||
* Sanitize string for use as file or directory name.
|
||||
|
@ -14,8 +17,8 @@ export const sanitizeFilename = (s: string) =>
|
|||
sanitize(s, { replacement: "_" });
|
||||
|
||||
/**
|
||||
* Return a new unique directory name based on {@link name} that is not the same
|
||||
* as any existing directory in the given {@link directoryPath}.
|
||||
* Return a new sanitized and unique directory name based on {@link name} that
|
||||
* is not the same as any existing item in the given {@link directoryPath}.
|
||||
*
|
||||
* We also ensure we don't return names which might collide with our own special
|
||||
* directories.
|
||||
|
@ -30,11 +33,16 @@ export const safeDirectoryName = async (
|
|||
directoryPath: string,
|
||||
name: string,
|
||||
): Promise<string> => {
|
||||
const specialDirectoryNames = [
|
||||
exportTrashDirectoryName,
|
||||
exportMetadataDirectoryName,
|
||||
];
|
||||
|
||||
let result = sanitizeFilename(name);
|
||||
let count = 1;
|
||||
while (
|
||||
(await exists(`${directoryPath}/${result}`)) ||
|
||||
result == exportTrashDirectoryName
|
||||
specialDirectoryNames.includes(result)
|
||||
) {
|
||||
result = `${sanitizeFilename(name)}(${count})`;
|
||||
count++;
|
||||
|
@ -43,28 +51,22 @@ export const safeDirectoryName = async (
|
|||
};
|
||||
|
||||
/**
|
||||
* Return a new unique file name based on {@link name} that is not the same as
|
||||
* any existing directory in the given {@link directoryPath}.
|
||||
* Return a new sanitized and unique file name based on {@link name} that is not
|
||||
* the same as any existing item in the given {@link directoryPath}.
|
||||
*
|
||||
* This function only works when we are running inside an electron app.
|
||||
* @see {@link safeDirectoryName}.
|
||||
*/
|
||||
export const sanitizedUniqueFileName = async (
|
||||
directoryPath: string,
|
||||
name: string,
|
||||
) => {
|
||||
let fileExportName = sanitizeFilename(name);
|
||||
export const safeFileName = async (directoryPath: string, name: string) => {
|
||||
let result = sanitizeFilename(name);
|
||||
let count = 1;
|
||||
while (await exists(`${directoryPath}/${fileExportName}`)) {
|
||||
const filenameParts = splitFilenameAndExtension(sanitizeFilename(name));
|
||||
if (filenameParts[1]) {
|
||||
fileExportName = `${filenameParts[0]}(${count}).${filenameParts[1]}`;
|
||||
} else {
|
||||
fileExportName = `${filenameParts[0]}(${count})`;
|
||||
}
|
||||
while (await exists(`${directoryPath}/${result}`)) {
|
||||
const [fn, ext] = nameAndExtension(sanitizeFilename(name));
|
||||
if (ext) result = `${fn}(${count}).${ext}`;
|
||||
else result = `${fn}(${count})`;
|
||||
count++;
|
||||
}
|
||||
return fileExportName;
|
||||
return result;
|
||||
};
|
||||
|
||||
const exists = (path: string) => ensureElectron().fs.exists(path);
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
import type { ElectronFile } from "./types/file";
|
||||
|
||||
/**
|
||||
* Split a filename into its components - the name itself, and the extension (if
|
||||
* any) - returning both. The dot is not included in either.
|
||||
*
|
||||
* For example, `foo-bar.png` will be split into ["foo-bar", "png"].
|
||||
*/
|
||||
export const nameAndExtension = (
|
||||
fileName: string,
|
||||
): [string, string | undefined] => {
|
||||
const i = fileName.lastIndexOf(".");
|
||||
if (i == -1) return [fileName, undefined];
|
||||
else return [fileName.slice(0, i), fileName.slice(i + 1)];
|
||||
};
|
||||
|
||||
export function getFileNameSize(file: File | ElectronFile) {
|
||||
return `${file.name}_${convertBytesToHumanReadable(file.size)}`;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue