Skip to content

Commit ea85184

Browse files
committed
feat: paste to insert image or files
1 parent 606924b commit ea85184

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

web/src/components/MemoEditor/handlers.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Resource } from "@/types/proto/api/v1/resource_service";
2+
import { getResourceUrl } from "@/utils/resource";
13
import { EditorRefActions } from "./Editor";
24

35
export const handleEditorKeydownWithMarkdownShortcuts = (event: React.KeyboardEvent, editorRef: EditorRefActions) => {
@@ -50,3 +52,32 @@ const styleHighlightedText = (editor: EditorRefActions, delimiter: string) => {
5052
editor.setCursorPosition(cursorPosition + delimiter.length, cursorPosition + delimiter.length + selectedContent.length);
5153
}
5254
};
55+
56+
export function insertResourceText(editor: EditorRefActions, resources: Resource[], placeholder: string) {
57+
let text = editor.getContent();
58+
const pos = text.indexOf(placeholder);
59+
if (pos === -1) return;
60+
61+
const insertingParts: string[] = [];
62+
for (const res of resources) {
63+
const isImage = String(res.type).startsWith("image/");
64+
const title = res.filename;
65+
const url = getResourceUrl(res);
66+
67+
let part = `[${title}](${url})`;
68+
if (isImage) part = `!${part}`;
69+
70+
insertingParts.push(part);
71+
}
72+
const inserting = insertingParts.join(" ");
73+
74+
// compute new cursorPos
75+
let cursorPos = editor.getCursorPosition();
76+
if (cursorPos >= pos + placeholder.length) cursorPos += inserting.length - placeholder.length;
77+
else if (cursorPos > pos) cursorPos = pos + inserting.length;
78+
79+
text = text.slice(0, pos) + inserting + text.slice(pos + placeholder.length);
80+
81+
editor.setContent(text);
82+
editor.setCursorPosition(cursorPos);
83+
}

web/src/components/MemoEditor/index.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import UploadResourceButton from "./ActionButton/UploadResourceButton";
2929
import Editor, { EditorRefActions } from "./Editor";
3030
import RelationListView from "./RelationListView";
3131
import ResourceListView from "./ResourceListView";
32-
import { handleEditorKeydownWithMarkdownShortcuts, hyperlinkHighlightedText } from "./handlers";
32+
import { handleEditorKeydownWithMarkdownShortcuts, hyperlinkHighlightedText, insertResourceText } from "./handlers";
3333
import { MemoEditorContext } from "./types";
3434
import "react-datepicker/dist/react-datepicker.css";
3535

@@ -233,7 +233,7 @@ const MemoEditor = observer((props: Props) => {
233233
}
234234
};
235235

236-
const uploadMultiFiles = async (files: FileList) => {
236+
const uploadMultiFiles = async (files: FileList): Promise<Resource[]> => {
237237
const uploadedResourceList: Resource[] = [];
238238
for (const file of files) {
239239
const resource = await handleUploadResource(file);
@@ -256,6 +256,7 @@ const MemoEditor = observer((props: Props) => {
256256
resourceList: [...prevState.resourceList, ...uploadedResourceList],
257257
}));
258258
}
259+
return uploadedResourceList;
259260
};
260261

261262
const handleDropEvent = async (event: React.DragEvent) => {
@@ -294,7 +295,20 @@ const MemoEditor = observer((props: Props) => {
294295
const handlePasteEvent = async (event: React.ClipboardEvent) => {
295296
if (event.clipboardData && event.clipboardData.files.length > 0) {
296297
event.preventDefault();
297-
await uploadMultiFiles(event.clipboardData.files);
298+
299+
const editor = editorRef.current;
300+
let placeholder = "";
301+
302+
if (editor) {
303+
placeholder = `<resource_${Date.now()}>`;
304+
editor.insertText(placeholder);
305+
}
306+
307+
const resources = await uploadMultiFiles(event.clipboardData.files);
308+
309+
if (editor) {
310+
insertResourceText(editor, resources, placeholder);
311+
}
298312
} else if (
299313
editorRef.current != null &&
300314
editorRef.current.getSelectedContent().length != 0 &&

0 commit comments

Comments
 (0)