From 494c4f45786f6133a0765faff476ba043b4c1bc0 Mon Sep 17 00:00:00 2001 From: boojack Date: Fri, 17 Dec 2021 08:11:02 +0800 Subject: [PATCH] feat: handle upload image by drop event --- web/src/components/Editor/Editor.tsx | 40 ++------------------- web/src/components/MemoEditor.tsx | 53 +++++++++++++++++++++++++++- web/src/services/index.ts | 3 +- web/vite.config.ts | 4 +++ 4 files changed, 60 insertions(+), 40 deletions(-) diff --git a/web/src/components/Editor/Editor.tsx b/web/src/components/Editor/Editor.tsx index c60d6f71..4a30d259 100644 --- a/web/src/components/Editor/Editor.tsx +++ b/web/src/components/Editor/Editor.tsx @@ -1,14 +1,13 @@ import { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef } from "react"; import TinyUndo from "tiny-undo"; -import toastHelper from "../Toast"; import appContext from "../../stores/appContext"; -import resourceService from "../../services/resourceService"; import { storage } from "../../helpers/storage"; import useRefresh from "../../hooks/useRefresh"; import Only from "../common/OnlyWhen"; import "../../less/editor.less"; export interface EditorRefActions { + element: HTMLTextAreaElement; focus: FunctionType; insertText: (text: string) => void; setContent: (text: string) => void; @@ -56,42 +55,6 @@ const Editor = forwardRef((props: Props, ref: React.ForwardedRef { - if (event.clipboardData && event.clipboardData.files.length > 0) { - const file = event.clipboardData.files[0]; - const { type } = file; - - if (!type.startsWith("image")) { - return; - } - - event.preventDefault(); - - try { - if (!editorRef.current) { - return; - } - - const image = await resourceService.upload(file); - const url = `/r/${image.id}/${image.filename}`; - - const prevValue = editorRef.current.value; - editorRef.current.value = - prevValue.slice(0, editorRef.current.selectionStart) + url + prevValue.slice(editorRef.current.selectionStart); - handleContentChangeCallback(editorRef.current.value); - refresh(); - } catch (error: any) { - toastHelper.error(error); - } - } - }; - - editorRef.current.addEventListener("paste", handlePasteEvent); - - return () => { - editorRef.current?.removeEventListener("paste", handlePasteEvent); - }; }, []); useEffect(() => { @@ -135,6 +98,7 @@ const Editor = forwardRef((props: Props, ref: React.ForwardedRef ({ + element: editorRef.current as HTMLTextAreaElement, focus: () => { editorRef.current?.focus(); }, diff --git a/web/src/components/MemoEditor.tsx b/web/src/components/MemoEditor.tsx index edcbeb19..00aa329c 100644 --- a/web/src/components/MemoEditor.tsx +++ b/web/src/components/MemoEditor.tsx @@ -1,6 +1,6 @@ import { useCallback, useContext, useEffect, useMemo, useRef } from "react"; import appContext from "../stores/appContext"; -import { globalStateService, locationService, memoService } from "../services"; +import { globalStateService, locationService, memoService, resourceService } from "../services"; import utils from "../helpers/utils"; import { storage } from "../helpers/storage"; import toastHelper from "./Toast"; @@ -33,6 +33,57 @@ const MemoEditor: React.FC = () => { prevGlobalStateRef.current = globalState; }, [globalState.markMemoId, globalState.editMemoId]); + useEffect(() => { + if (!editorRef.current) { + return; + } + + const handleUploadFile = async (file: File) => { + const { type } = file; + + if (!type.startsWith("image")) { + return; + } + + try { + if (!editorRef.current) { + return; + } + + const image = await resourceService.upload(file); + const url = `/r/${image.id}/${image.filename}`; + + editorRef.current.insertText(url); + } catch (error: any) { + toastHelper.error(error); + } + }; + + const handlePasteEvent = async (event: ClipboardEvent) => { + if (event.clipboardData && event.clipboardData.files.length > 0) { + event.preventDefault(); + const file = event.clipboardData.files[0]; + handleUploadFile(file); + } + }; + + const handleDropEvent = async (event: DragEvent) => { + if (event.dataTransfer && event.dataTransfer.files.length > 0) { + event.preventDefault(); + const file = event.dataTransfer.files[0]; + handleUploadFile(file); + } + }; + + editorRef.current.element.addEventListener("paste", handlePasteEvent); + editorRef.current.element.addEventListener("drop", handleDropEvent); + + return () => { + editorRef.current?.element.removeEventListener("paste", handlePasteEvent); + editorRef.current?.element.removeEventListener("drop", handleDropEvent); + }; + }, []); + const handleSaveBtnClick = useCallback(async (content: string) => { if (content === "") { toastHelper.error("内容不能为空呀"); diff --git a/web/src/services/index.ts b/web/src/services/index.ts index 3e4d91fc..5296a7cd 100644 --- a/web/src/services/index.ts +++ b/web/src/services/index.ts @@ -3,5 +3,6 @@ import locationService from "./locationService"; import memoService from "./memoService"; import queryService from "./queryService"; import userService from "./userService"; +import resourceService from "./resourceService"; -export { globalStateService, locationService, memoService, userService, queryService }; +export { globalStateService, locationService, memoService, queryService, userService, resourceService }; diff --git a/web/vite.config.ts b/web/vite.config.ts index dfc20051..569c38ee 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -12,6 +12,10 @@ export default defineConfig({ target: "https://memos.justsven.top/", changeOrigin: true, }, + "/r": { + target: "https://memos.justsven.top/", + changeOrigin: true, + }, }, }, });