mirror of
https://github.com/usememos/memos.git
synced 2025-03-26 23:50:15 +01:00
feat: update image by paste in editor
This commit is contained in:
parent
cc2af0e449
commit
ee3c753c99
@ -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();
|
||||||
},
|
},
|
||||||
|
@ -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,
|
||||||
|
28
web/src/services/resourceService.ts
Normal file
28
web/src/services/resourceService.ts
Normal 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;
|
8
web/src/types/models.d.ts
vendored
8
web/src/types/models.d.ts
vendored
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user