feat: update image by paste in editor

This commit is contained in:
boojack 2021-12-16 22:39:45 +08:00
parent cc2af0e449
commit ee3c753c99
4 changed files with 82 additions and 3 deletions

View File

@ -1,6 +1,8 @@
import { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef } from "react"; import { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef } from "react";
import TinyUndo from "tiny-undo"; import TinyUndo from "tiny-undo";
import toastHelper from "../Toast";
import appContext from "../../stores/appContext"; import appContext from "../../stores/appContext";
import resourceService from "../../services/resourceService";
import { storage } from "../../helpers/storage"; import { storage } from "../../helpers/storage";
import useRefresh from "../../hooks/useRefresh"; import useRefresh from "../../hooks/useRefresh";
import Only from "../common/OnlyWhen"; import Only from "../common/OnlyWhen";
@ -46,10 +48,50 @@ const Editor = forwardRef((props: Props, ref: React.ForwardedRef<EditorRefAction
const refresh = useRefresh(); const refresh = useRefresh();
useEffect(() => { useEffect(() => {
if (initialContent && editorRef.current) { if (!editorRef.current) {
return;
}
if (initialContent) {
editorRef.current.value = initialContent; editorRef.current.value = initialContent;
refresh(); refresh();
} }
const handlePasteEvent = async (event: ClipboardEvent) => {
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 resource = await resourceService.upload(file);
const url = `https://memos.justsven.top/r/${resource.id}/${resource.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(() => { useEffect(() => {
@ -102,7 +144,8 @@ const Editor = forwardRef((props: Props, ref: React.ForwardedRef<EditorRefAction
} }
const prevValue = editorRef.current.value; const prevValue = editorRef.current.value;
editorRef.current.value = prevValue + rawText; editorRef.current.value =
prevValue.slice(0, editorRef.current.selectionStart) + rawText + prevValue.slice(editorRef.current.selectionStart);
handleContentChangeCallback(editorRef.current.value); handleContentChangeCallback(editorRef.current.value);
refresh(); refresh();
}, },

View File

@ -199,7 +199,7 @@ namespace api {
} }
export function uploadFile(formData: FormData) { export function uploadFile(formData: FormData) {
return request({ return request<Model.Resource>({
method: "PUT", method: "PUT",
url: "/api/resource/", url: "/api/resource/",
data: formData, data: formData,

View File

@ -0,0 +1,28 @@
import api from "../helpers/api";
class ResourceService {
/**
* Upload resource file to server,
* @param file file
* @returns resource: id, filename
*/
public async upload(file: File) {
const { name: filename, size } = file;
if (size > 5 << 20) {
return Promise.reject("超过最大文件大小 5Mb");
}
const formData = new FormData();
formData.append("file", file, filename);
const { data } = await api.uploadFile(formData);
return data;
}
}
const resourceService = new ResourceService();
export default resourceService;

View File

@ -20,4 +20,12 @@ declare namespace Model {
querystring: string; querystring: string;
pinnedAt: string; pinnedAt: string;
} }
interface Resource {
id: string;
filename: string;
type: string;
size: string;
createdAt: string;
}
} }