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

@@ -5,7 +5,7 @@ import track from '@affine/track';
import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit';
import { scrollbarStyle } from '@blocksuite/affine/shared/styles';
import { unsafeCSSVar, unsafeCSSVarV2 } from '@blocksuite/affine/shared/theme';
import { openFileOrFiles } from '@blocksuite/affine/shared/utils';
import { openFilesWith } from '@blocksuite/affine/shared/utils';
import { ShadowlessElement } from '@blocksuite/affine/std';
import type { DocMeta } from '@blocksuite/affine/store';
import {
@@ -159,9 +159,7 @@ export class ChatPanelAddPopover extends SignalWatcher(
};
private readonly _addFileChip = async () => {
const files = await openFileOrFiles({
multiple: true,
});
const files = await openFilesWith();
if (!files || files.length === 0) return;
const images = files.filter(file => file.type.startsWith('image/'));

View File

@@ -3,7 +3,7 @@ import { stopPropagation } from '@affine/core/utils';
import type { CopilotSessionType } from '@affine/graphql';
import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit';
import { unsafeCSSVar, unsafeCSSVarV2 } from '@blocksuite/affine/shared/theme';
import { openFileOrFiles } from '@blocksuite/affine/shared/utils';
import { openFilesWith } from '@blocksuite/affine/shared/utils';
import type { EditorHost } from '@blocksuite/affine/std';
import {
CloseIcon,
@@ -533,10 +533,7 @@ export class AIChatInput extends SignalWatcher(WithDisposable(LitElement)) {
private readonly _uploadImageFiles = async (_e: MouseEvent) => {
if (this._isImageUploadDisabled) return;
const images = await openFileOrFiles({
acceptType: 'Images',
multiple: true,
});
const images = await openFilesWith('Images');
if (!images) return;
if (this.chatContextValue.images.length + images.length > MAX_IMAGE_COUNT) {
toast(`You can only upload up to ${MAX_IMAGE_COUNT} images`);

View File

@@ -9,7 +9,7 @@ import {
type DataViewCellLifeCycle,
EditorHostKey,
} from '@blocksuite/affine/blocks/database';
import { openFileOrFiles } from '@blocksuite/affine/shared/utils';
import { openFilesWith } from '@blocksuite/affine/shared/utils';
import type { BlobEngine } from '@blocksuite/affine/sync';
import {
DeleteIcon,
@@ -402,7 +402,7 @@ const FileCellComponent: ForwardRefRenderFunction<
>
<Button
onClick={() => {
openFileOrFiles({ multiple: true })
openFilesWith()
.then(files => {
files?.forEach(file => {
manager.uploadFile(file);
@@ -447,7 +447,7 @@ const FileCellComponent: ForwardRefRenderFunction<
<div className={styles.uploadContainer}>
<div
onClick={() => {
openFileOrFiles({ multiple: true })
openFilesWith()
.then(files => {
files?.forEach(file => {
manager.uploadFile(file);

View File

@@ -13,7 +13,7 @@ import {
import { DebugLogger } from '@affine/debug';
import { useI18n } from '@affine/i18n';
import track from '@affine/track';
import { openFileOrFiles } from '@blocksuite/affine/shared/utils';
import { openFilesWith } from '@blocksuite/affine/shared/utils';
import type { Workspace } from '@blocksuite/affine/store';
import {
HtmlTransformer,
@@ -56,7 +56,7 @@ type ImportConfig = {
fileOptions: { acceptType: AcceptType; multiple: boolean };
importFunction: (
docCollection: Workspace,
file: File | File[]
files: File[]
) => Promise<ImportResult>;
};
@@ -134,9 +134,6 @@ const importConfigs: Record<ImportType, ImportConfig> = {
markdown: {
fileOptions: { acceptType: 'Markdown', multiple: true },
importFunction: async (docCollection, files) => {
if (!Array.isArray(files)) {
throw new Error('Expected an array of files for markdown files import');
}
const docIds: string[] = [];
for (const file of files) {
const text = await file.text();
@@ -157,8 +154,9 @@ const importConfigs: Record<ImportType, ImportConfig> = {
},
markdownZip: {
fileOptions: { acceptType: 'Zip', multiple: false },
importFunction: async (docCollection, file) => {
if (Array.isArray(file)) {
importFunction: async (docCollection, files) => {
const file = files.length === 1 ? files[0] : null;
if (!file) {
throw new Error('Expected a single zip file for markdownZip import');
}
const docIds = await MarkdownTransformer.importMarkdownZip({
@@ -175,9 +173,6 @@ const importConfigs: Record<ImportType, ImportConfig> = {
html: {
fileOptions: { acceptType: 'Html', multiple: true },
importFunction: async (docCollection, files) => {
if (!Array.isArray(files)) {
throw new Error('Expected an array of files for html files import');
}
const docIds: string[] = [];
for (const file of files) {
const text = await file.text();
@@ -198,8 +193,9 @@ const importConfigs: Record<ImportType, ImportConfig> = {
},
notion: {
fileOptions: { acceptType: 'Zip', multiple: false },
importFunction: async (docCollection, file) => {
if (Array.isArray(file)) {
importFunction: async (docCollection, files) => {
const file = files.length === 1 ? files[0] : null;
if (!file) {
throw new Error('Expected a single zip file for notion import');
}
const { entryId, pageIds, isWorkspaceFile } =
@@ -218,8 +214,9 @@ const importConfigs: Record<ImportType, ImportConfig> = {
},
snapshot: {
fileOptions: { acceptType: 'Zip', multiple: false },
importFunction: async (docCollection, file) => {
if (Array.isArray(file)) {
importFunction: async (docCollection, files) => {
const file = files.length === 1 ? files[0] : null;
if (!file) {
throw new Error('Expected a single zip file for snapshot import');
}
const docIds = (
@@ -412,9 +409,10 @@ export const ImportDialog = ({
setImportError(null);
try {
const importConfig = importConfigs[type];
const file = await openFileOrFiles(importConfig.fileOptions);
const { acceptType, multiple } = importConfig.fileOptions;
const files = await openFilesWith(acceptType, multiple);
if (!file || (Array.isArray(file) && file.length === 0)) {
if (!files || files.length === 0) {
throw new Error(
t['com.affine.import.status.failed.message.no-file-selected']()
);
@@ -427,7 +425,7 @@ export const ImportDialog = ({
});
const { docIds, entryId, isWorkspaceFile } =
await importConfig.importFunction(docCollection, file);
await importConfig.importFunction(docCollection, files);
setImportResult({ docIds, entryId, isWorkspaceFile });
setStatus('success');