refactor(editor): split openFileOrFiles into openSingleFileWith and openFilesWith (#12523)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
	- Improved file selection dialogs for attachments, imports, and uploads, allowing for more consistent and streamlined file picking across the app.

- **Bug Fixes**
	- Resolved inconsistencies when selecting single or multiple files, ensuring a smoother user experience during file import and upload.

- **Refactor**
	- Unified and simplified file selection logic throughout the app for better reliability and maintainability.
	- Standardized import functions to uniformly handle arrays of files, enhancing consistency in file processing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fundon
2025-05-28 03:06:32 +00:00
parent cf456c888f
commit c43e1bcc4e
12 changed files with 72 additions and 118 deletions

View File

@@ -112,21 +112,11 @@ type AcceptTypes =
| 'Html'
| 'Zip'
| 'MindMap';
export function openFileOrFiles(options?: {
acceptType?: AcceptTypes;
}): Promise<File | null>;
export function openFileOrFiles(options: {
acceptType?: AcceptTypes;
multiple: false;
}): Promise<File | null>;
export function openFileOrFiles(options: {
acceptType?: AcceptTypes;
multiple: true;
}): Promise<File[] | null>;
export async function openFileOrFiles({
acceptType = 'Any',
multiple = false,
} = {}) {
export async function openFilesWith(
acceptType: AcceptTypes = 'Any',
multiple: boolean = true
): Promise<File[] | null> {
// Feature detection. The API needs to be supported
// and the app not run in an iframe.
const supportsFileSystemAccess =
@@ -138,6 +128,7 @@ export async function openFileOrFiles({
return false;
}
})();
// If the File System Access API is supported…
if (supportsFileSystemAccess && window.showOpenFilePicker) {
try {
@@ -153,30 +144,14 @@ export async function openFileOrFiles({
} satisfies OpenFilePickerOptions;
// Show the file picker, optionally allowing multiple files.
const handles = await window.showOpenFilePicker(pickerOpts);
// Only one file is requested.
if (!multiple) {
// Add the `FileSystemFileHandle` as `.handle`.
const file = await handles[0].getFile();
// Add the `FileSystemFileHandle` as `.handle`.
// file.handle = handles[0];
return file;
} else {
const files = await Promise.all(
handles.map(async handle => {
const file = await handle.getFile();
// Add the `FileSystemFileHandle` as `.handle`.
// file.handle = handles[0];
return file;
})
);
return files;
}
return await Promise.all(handles.map(handle => handle.getFile()));
} catch (err) {
console.error('Error opening file');
console.error(err);
return null;
}
}
// Fallback if the File System Access API is not supported.
return new Promise(resolve => {
// Append a new `<input type="file" multiple? />` and hide it.
@@ -184,9 +159,8 @@ export async function openFileOrFiles({
input.classList.add('affine-upload-input');
input.style.display = 'none';
input.type = 'file';
if (multiple) {
input.multiple = true;
}
input.multiple = multiple;
if (acceptType !== 'Any') {
// For example, `accept="image/*"` or `accept="video/*,audio/*"`.
input.accept = Object.keys(
@@ -198,17 +172,8 @@ export async function openFileOrFiles({
input.addEventListener('change', () => {
// Remove the `<input type="file" multiple? />` again from the DOM.
input.remove();
// If no files were selected, return.
if (!input.files) {
resolve(null);
return;
}
// Return all files or just one file.
if (multiple) {
resolve(Array.from(input.files));
return;
}
resolve(input.files[0]);
resolve(input.files ? Array.from(input.files) : null);
});
// The `cancel` event fires when the user cancels the dialog.
input.addEventListener('cancel', () => {
@@ -223,11 +188,14 @@ export async function openFileOrFiles({
});
}
export function openSingleFileWith(
acceptType?: AcceptTypes
): Promise<File | null> {
return openFilesWith(acceptType, false).then(files => files?.at(0) ?? null);
}
export async function getImageFilesFromLocal() {
const imageFiles = await openFileOrFiles({
acceptType: 'Images',
multiple: true,
});
const imageFiles = await openFilesWith('Images');
if (!imageFiles) return [];
return imageFiles;
}