Skip to content

Commit

Permalink
feat: support copy cut and paste in doc
Browse files Browse the repository at this point in the history
  • Loading branch information
Jocs committed Nov 11, 2023
1 parent 76d8c9a commit deafe4c
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 9 deletions.
33 changes: 29 additions & 4 deletions packages/ui-plugin-docs/src/commands/commands/clipboard.command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CopyCommand, CutCommand, PasteCommand } from '@univerjs/base-ui';
import { CommandType, FOCUSING_DOC, IMultiCommand } from '@univerjs/core';
import { CopyCommand, CutCommand, IClipboardInterfaceService, PasteCommand } from '@univerjs/base-ui';
import { CommandType, FOCUSING_DOC, ILogService, IMultiCommand } from '@univerjs/core';

import { IDocClipboardService } from '../../services/clipboard/clipboard.service';

Expand Down Expand Up @@ -37,7 +37,32 @@ export const DocPasteCommand: IMultiCommand = {
priority: 1100,
preconditions: (contextService) => contextService.getContextValue(FOCUSING_DOC),
handler: async (accessor, params) => {
const docClipboardService = accessor.get(IDocClipboardService);
return docClipboardService.paste();
const logService = accessor.get(ILogService);

// use cell editor to get ClipboardData first
// if that doesn't work, use the browser's clipboard API
// this clipboard API would ask user for permission, so we may need to notify user (and retry perhaps)
logService.log('[DocPasteCommand]', 'the focusing element is', document.activeElement);

const result = document.execCommand('paste');

if (!result) {
logService.log(
'[DocPasteCommand]',
'failed to execute paste command on the activeElement, trying to use clipboard API.'
);

const clipboardInterfaceService = accessor.get(IClipboardInterfaceService);
const clipboardItems = await clipboardInterfaceService.read();
const sheetClipboardService = accessor.get(IDocClipboardService);

if (clipboardItems.length !== 0) {
return sheetClipboardService.paste(clipboardItems[0]);
}

return false;
}

return false;
},
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Disposable, ICommandService, IUniverInstanceService } from '@univerjs/core';

import { DocCopyCommand } from '../commands/commands/clipboard.command';
import { DocCopyCommand, DocCutCommand, DocPasteCommand } from '../commands/commands/clipboard.command';
import { IDocClipboardService } from '../services/clipboard/clipboard.service';

export class DocClipboardController extends Disposable {
Expand All @@ -13,7 +13,7 @@ export class DocClipboardController extends Disposable {
}

initialize() {
[DocCopyCommand, DocCopyCommand, DocCopyCommand].forEach((command) =>
[DocCopyCommand, DocCutCommand, DocPasteCommand].forEach((command) =>
this.disposeWithMe(this._commandService.registerAsMultipleCommand(command))
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { IClipboardInterfaceService } from '@univerjs/base-ui';
import {
HTML_CLIPBOARD_MIME_TYPE,
IClipboardInterfaceService,
PLAIN_TEXT_CLIPBOARD_MIME_TYPE,
} from '@univerjs/base-ui';
import { Disposable, IUniverInstanceService, toDisposable } from '@univerjs/core';
import { createIdentifier, IDisposable } from '@wendellhu/redi';

Expand All @@ -12,7 +16,7 @@ export interface IDocClipboardHook {
export interface IDocClipboardService {
copy(): Promise<boolean>;
cut(): Promise<boolean>;
paste(): Promise<boolean>;
paste(item: ClipboardItem): Promise<boolean>;

addClipboardHook(hook: IDocClipboardHook): IDisposable;
}
Expand All @@ -37,14 +41,23 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ
throw new Error('Method not implemented.');
}

paste(): Promise<boolean> {
async paste(item: ClipboardItem): Promise<boolean> {
const text = await item.getType(PLAIN_TEXT_CLIPBOARD_MIME_TYPE).then((blob) => blob && blob.text());
const html = await item.getType(HTML_CLIPBOARD_MIME_TYPE).then((blob) => blob && blob.text());

console.log(text);
console.log(html);

// this._logService.error('[SheetClipboardService]', 'No valid data on clipboard');
throw new Error('Method not implemented.');
}

addClipboardHook(hook: IDocClipboardHook): IDisposable {
this._clipboardHooks.push(hook);

return toDisposable(() => {
const index = this._clipboardHooks.indexOf(hook);

if (index > -1) {
this._clipboardHooks.splice(index, 1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const SheetPasteCommand: IMultiCommand = {
logService.log('[SheetPasteCommand]', 'the focusing element is', document.activeElement);

const result = document.execCommand('paste');

if (!result) {
logService.log(
'[SheetPasteCommand]',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
const colStyles = getColStyle(getArrayFromTo(startColumn, endColumn), hooks);
// row styles and table contents
const rowContents: string[] = [];

matrix.forRow((row, cols) => {
// TODO: cols here should filtered out those in span cells
rowContents.push(getRowContent(row, cols, hooks, matrix));
Expand Down Expand Up @@ -737,6 +738,7 @@ function getTDContent(
const mergedProperties = mergeProperties(properties);
const str = zipClipboardPropertyItemToString(mergedProperties);
const content = hooks.reduce((acc, hook) => acc || hook.onCopyCellContent?.(row, col) || '', '');

return `<td${str}>${content}</td>`;
}

Expand Down

0 comments on commit deafe4c

Please sign in to comment.