mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-11 14:08:55 +08:00
refactor(editor): unify directories naming (#11516)
**Directory Structure Changes** - Renamed multiple block-related directories by removing the "block-" prefix: - `block-attachment` → `attachment` - `block-bookmark` → `bookmark` - `block-callout` → `callout` - `block-code` → `code` - `block-data-view` → `data-view` - `block-database` → `database` - `block-divider` → `divider` - `block-edgeless-text` → `edgeless-text` - `block-embed` → `embed`
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
export * from './page-clipboard.js';
|
||||
export * from './readonly-clipboard.js';
|
||||
@@ -0,0 +1,171 @@
|
||||
import { deleteTextCommand } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
pasteMiddleware,
|
||||
replaceIdMiddleware,
|
||||
surfaceRefToEmbed,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import {
|
||||
clearAndSelectFirstModelCommand,
|
||||
deleteSelectedModelsCommand,
|
||||
getBlockIndexCommand,
|
||||
getBlockSelectionsCommand,
|
||||
getImageSelectionsCommand,
|
||||
getSelectedModelsCommand,
|
||||
getTextSelectionCommand,
|
||||
retainFirstModelCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import { DisposableGroup } from '@blocksuite/global/disposable';
|
||||
import type { UIEventHandler } from '@blocksuite/std';
|
||||
import type { BlockSnapshot, Store } from '@blocksuite/store';
|
||||
|
||||
import { ReadOnlyClipboard } from './readonly-clipboard';
|
||||
|
||||
/**
|
||||
* PageClipboard is a class that provides a clipboard for the page root block.
|
||||
* It is supported to copy and paste models in the page root block.
|
||||
*/
|
||||
export class PageClipboard extends ReadOnlyClipboard {
|
||||
static override key = 'affine-page-clipboard';
|
||||
|
||||
protected _init = () => {
|
||||
this._initAdapters();
|
||||
const paste = pasteMiddleware(this.std);
|
||||
// Use surfaceRefToEmbed middleware to convert surface-ref to embed-linked-doc
|
||||
// When pastina a surface-ref block to another doc
|
||||
const surfaceRefToEmbedMiddleware = surfaceRefToEmbed(this.std);
|
||||
const replaceId = replaceIdMiddleware(this.std.store.workspace.idGenerator);
|
||||
this.std.clipboard.use(paste);
|
||||
this.std.clipboard.use(surfaceRefToEmbedMiddleware);
|
||||
this.std.clipboard.use(replaceId);
|
||||
this._disposables.add({
|
||||
dispose: () => {
|
||||
this.std.clipboard.unuse(paste);
|
||||
this.std.clipboard.unuse(surfaceRefToEmbedMiddleware);
|
||||
this.std.clipboard.unuse(replaceId);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onBlockSnapshotPaste = async (
|
||||
snapshot: BlockSnapshot,
|
||||
doc: Store,
|
||||
parent?: string,
|
||||
index?: number
|
||||
) => {
|
||||
const block = await this.std.clipboard.pasteBlockSnapshot(
|
||||
snapshot,
|
||||
doc,
|
||||
parent,
|
||||
index
|
||||
);
|
||||
return block?.id ?? null;
|
||||
};
|
||||
|
||||
onPageCut: UIEventHandler = ctx => {
|
||||
const e = ctx.get('clipboardState').raw;
|
||||
e.preventDefault();
|
||||
|
||||
this._copySelected(() => {
|
||||
this.std.command
|
||||
.chain()
|
||||
.try<{}>(cmd => [
|
||||
cmd.pipe(getTextSelectionCommand).pipe(deleteTextCommand),
|
||||
cmd.pipe(getSelectedModelsCommand).pipe(deleteSelectedModelsCommand),
|
||||
])
|
||||
.run();
|
||||
}).run();
|
||||
};
|
||||
|
||||
onPagePaste: UIEventHandler = ctx => {
|
||||
const e = ctx.get('clipboardState').raw;
|
||||
e.preventDefault();
|
||||
|
||||
this.std.store.captureSync();
|
||||
this.std.command
|
||||
.chain()
|
||||
.try<{}>(cmd => [
|
||||
cmd.pipe(getTextSelectionCommand).pipe((ctx, next) => {
|
||||
const { currentTextSelection } = ctx;
|
||||
if (!currentTextSelection) {
|
||||
return;
|
||||
}
|
||||
const { from, to } = currentTextSelection;
|
||||
if (to && from.blockId !== to.blockId) {
|
||||
this.std.command.exec(deleteTextCommand, {
|
||||
currentTextSelection,
|
||||
});
|
||||
}
|
||||
return next();
|
||||
}),
|
||||
cmd
|
||||
.pipe(getSelectedModelsCommand)
|
||||
.pipe(clearAndSelectFirstModelCommand)
|
||||
.pipe(retainFirstModelCommand)
|
||||
.pipe(deleteSelectedModelsCommand),
|
||||
])
|
||||
.try<{ currentSelectionPath: string }>(cmd => [
|
||||
cmd.pipe(getTextSelectionCommand).pipe((ctx, next) => {
|
||||
const textSelection = ctx.currentTextSelection;
|
||||
if (!textSelection) {
|
||||
return;
|
||||
}
|
||||
next({ currentSelectionPath: textSelection.from.blockId });
|
||||
}),
|
||||
cmd.pipe(getBlockSelectionsCommand).pipe((ctx, next) => {
|
||||
const currentBlockSelections = ctx.currentBlockSelections;
|
||||
if (!currentBlockSelections) {
|
||||
return;
|
||||
}
|
||||
const blockSelection = currentBlockSelections.at(-1);
|
||||
if (!blockSelection) {
|
||||
return;
|
||||
}
|
||||
next({ currentSelectionPath: blockSelection.blockId });
|
||||
}),
|
||||
cmd.pipe(getImageSelectionsCommand).pipe((ctx, next) => {
|
||||
const currentImageSelections = ctx.currentImageSelections;
|
||||
if (!currentImageSelections) {
|
||||
return;
|
||||
}
|
||||
const imageSelection = currentImageSelections.at(-1);
|
||||
if (!imageSelection) {
|
||||
return;
|
||||
}
|
||||
next({ currentSelectionPath: imageSelection.blockId });
|
||||
}),
|
||||
])
|
||||
.pipe(getBlockIndexCommand)
|
||||
.pipe((ctx, next) => {
|
||||
if (!ctx.parentBlock) {
|
||||
return;
|
||||
}
|
||||
this.std.clipboard
|
||||
.paste(
|
||||
e,
|
||||
this.std.store,
|
||||
ctx.parentBlock.model.id,
|
||||
ctx.blockIndex ? ctx.blockIndex + 1 : 1
|
||||
)
|
||||
.catch(console.error);
|
||||
|
||||
return next();
|
||||
})
|
||||
.run();
|
||||
};
|
||||
|
||||
override mounted() {
|
||||
if (!navigator.clipboard) {
|
||||
console.error(
|
||||
'navigator.clipboard is not supported in current environment.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (this._disposables.disposed) {
|
||||
this._disposables = new DisposableGroup();
|
||||
}
|
||||
this.std.event.add('copy', this.onPageCopy);
|
||||
this.std.event.add('paste', this.onPagePaste);
|
||||
this.std.event.add('cut', this.onPageCut);
|
||||
this._init();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image';
|
||||
import {
|
||||
AttachmentAdapter,
|
||||
ClipboardAdapter,
|
||||
copyMiddleware,
|
||||
HtmlAdapter,
|
||||
ImageAdapter,
|
||||
MixTextAdapter,
|
||||
NotionTextAdapter,
|
||||
titleMiddleware,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import {
|
||||
copySelectedModelsCommand,
|
||||
draftSelectedModelsCommand,
|
||||
getSelectedModelsCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import { DisposableGroup } from '@blocksuite/global/disposable';
|
||||
import {
|
||||
ClipboardAdapterConfigExtension,
|
||||
LifeCycleWatcher,
|
||||
type UIEventHandler,
|
||||
} from '@blocksuite/std';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
const SnapshotClipboardConfig = ClipboardAdapterConfigExtension({
|
||||
mimeType: ClipboardAdapter.MIME,
|
||||
adapter: ClipboardAdapter,
|
||||
priority: 100,
|
||||
});
|
||||
|
||||
const NotionClipboardConfig = ClipboardAdapterConfigExtension({
|
||||
mimeType: 'text/_notion-text-production',
|
||||
adapter: NotionTextAdapter,
|
||||
priority: 95,
|
||||
});
|
||||
|
||||
const HtmlClipboardConfig = ClipboardAdapterConfigExtension({
|
||||
mimeType: 'text/html',
|
||||
adapter: HtmlAdapter,
|
||||
priority: 90,
|
||||
});
|
||||
|
||||
const imageClipboardConfigs = [
|
||||
'image/apng',
|
||||
'image/avif',
|
||||
'image/gif',
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/svg+xml',
|
||||
'image/webp',
|
||||
].map(mimeType => {
|
||||
return ClipboardAdapterConfigExtension({
|
||||
mimeType,
|
||||
adapter: ImageAdapter,
|
||||
priority: 80,
|
||||
});
|
||||
});
|
||||
|
||||
const PlainTextClipboardConfig = ClipboardAdapterConfigExtension({
|
||||
mimeType: 'text/plain',
|
||||
adapter: MixTextAdapter,
|
||||
priority: 70,
|
||||
});
|
||||
|
||||
const AttachmentClipboardConfig = ClipboardAdapterConfigExtension({
|
||||
mimeType: '*/*',
|
||||
adapter: AttachmentAdapter,
|
||||
priority: 60,
|
||||
});
|
||||
|
||||
export const clipboardConfigs: ExtensionType[] = [
|
||||
SnapshotClipboardConfig,
|
||||
NotionClipboardConfig,
|
||||
HtmlClipboardConfig,
|
||||
...imageClipboardConfigs,
|
||||
PlainTextClipboardConfig,
|
||||
AttachmentClipboardConfig,
|
||||
];
|
||||
|
||||
/**
|
||||
* ReadOnlyClipboard is a class that provides a read-only clipboard for the root block.
|
||||
* It is supported to copy models in the root block.
|
||||
*/
|
||||
export class ReadOnlyClipboard extends LifeCycleWatcher {
|
||||
static override key = 'affine-readonly-clipboard';
|
||||
|
||||
protected readonly _copySelected = (onCopy?: () => void) => {
|
||||
return this.std.command
|
||||
.chain()
|
||||
.with({ onCopy })
|
||||
.pipe(getSelectedModelsCommand)
|
||||
.pipe(draftSelectedModelsCommand)
|
||||
.pipe(copySelectedModelsCommand);
|
||||
};
|
||||
|
||||
protected _disposables = new DisposableGroup();
|
||||
|
||||
protected _initAdapters = () => {
|
||||
const copy = copyMiddleware(this.std);
|
||||
this.std.clipboard.use(copy);
|
||||
this.std.clipboard.use(
|
||||
titleMiddleware(this.std.store.workspace.meta.docMetas)
|
||||
);
|
||||
this.std.clipboard.use(defaultImageProxyMiddleware);
|
||||
|
||||
this._disposables.add({
|
||||
dispose: () => {
|
||||
this.std.clipboard.unuse(copy);
|
||||
this.std.clipboard.unuse(
|
||||
titleMiddleware(this.std.store.workspace.meta.docMetas)
|
||||
);
|
||||
this.std.clipboard.unuse(defaultImageProxyMiddleware);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onPageCopy: UIEventHandler = ctx => {
|
||||
const e = ctx.get('clipboardState').raw;
|
||||
e.preventDefault();
|
||||
|
||||
this._copySelected().run();
|
||||
};
|
||||
|
||||
override mounted(): void {
|
||||
if (!navigator.clipboard) {
|
||||
console.error(
|
||||
'navigator.clipboard is not supported in current environment.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (this._disposables.disposed) {
|
||||
this._disposables = new DisposableGroup();
|
||||
}
|
||||
this.std.event.add('copy', this.onPageCopy);
|
||||
this._initAdapters();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user