Files
AFFiNE-Mirror/blocksuite/affine/block-code/src/clipboard/index.ts

107 lines
2.9 KiB
TypeScript

import { deleteTextCommand } from '@blocksuite/affine-components/rich-text';
import {
HtmlAdapter,
pasteMiddleware,
PlainTextAdapter,
} from '@blocksuite/affine-shared/adapters';
import {
getBlockIndexCommand,
getBlockSelectionsCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import {
type BlockComponent,
Clipboard,
type UIEventHandler,
} from '@blocksuite/block-std';
import { DisposableGroup } from '@blocksuite/global/utils';
export class CodeClipboardController {
private _clipboard!: Clipboard;
protected _disposables = new DisposableGroup();
protected _init = () => {
this._clipboard.registerAdapter('text/plain', PlainTextAdapter, 90);
this._clipboard.registerAdapter('text/html', HtmlAdapter, 80);
const paste = pasteMiddleware(this._std);
this._clipboard.use(paste);
this._disposables.add({
dispose: () => {
this._clipboard.unregisterAdapter('text/plain');
this._clipboard.unregisterAdapter('text/html');
this._clipboard.unuse(paste);
},
});
};
host: BlockComponent;
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 textSelection = ctx.currentTextSelection;
if (!textSelection) return;
const end = textSelection.to ?? textSelection.from;
next({ currentSelectionPath: end.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 });
}),
])
.pipe(getBlockIndexCommand)
.try(cmd => [cmd.pipe(getTextSelectionCommand).pipe(deleteTextCommand)])
.pipe((ctx, next) => {
if (!ctx.parentBlock) {
return;
}
this._clipboard
.paste(
e,
this._std.store,
ctx.parentBlock.model.id,
ctx.blockIndex ? ctx.blockIndex + 1 : 1
)
.catch(console.error);
return next();
})
.run();
return true;
};
private get _std() {
return this.host.std;
}
constructor(host: BlockComponent) {
this.host = host;
}
hostConnected() {
if (this._disposables.disposed) {
this._disposables = new DisposableGroup();
}
if (navigator.clipboard) {
this._clipboard = new Clipboard(this._std);
this.host.handleEvent('paste', this.onPagePaste);
this._init();
}
}
hostDisconnected() {
this._disposables.dispose();
}
}