use loading id to find correct position

This commit is contained in:
fantasticit 2022-11-25 14:27:10 +08:00
parent 55241f14cb
commit ba189b26e2
2 changed files with 76 additions and 23 deletions

View File

@ -1,7 +1,22 @@
import { Node } from '@tiptap/core'; import { Editor, Node } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react'; import { ReactNodeViewRenderer } from '@tiptap/react';
import { Node as PMNode } from 'prosemirror-state';
import { LoadingWrapper } from 'tiptap/core/wrappers/loading'; import { LoadingWrapper } from 'tiptap/core/wrappers/loading';
export function findLoadingById(editor: Editor, id: string): null | { node: PMNode; pos: number } {
let target: PMNode | null = null;
let pos = -1;
editor.state.doc.descendants((node, nodePos) => {
if (node.type.name === 'loading' && node.attrs.id === id) {
target = node;
pos = nodePos;
}
});
return target ? { node: target, pos } : null;
}
export const Loading = Node.create({ export const Loading = Node.create({
name: 'loading', name: 'loading',
inline: true, inline: true,
@ -10,6 +25,9 @@ export const Loading = Node.create({
addAttributes() { addAttributes() {
return { return {
id: {
default: null,
},
text: { text: {
default: null, default: null,
}, },

View File

@ -2,7 +2,7 @@ import { Editor } from '@tiptap/core';
import { uploadFile } from 'services/file'; import { uploadFile } from 'services/file';
import { Attachment } from 'tiptap/core/extensions/attachment'; import { Attachment } from 'tiptap/core/extensions/attachment';
import { Image } from 'tiptap/core/extensions/image'; import { Image } from 'tiptap/core/extensions/image';
import { Loading } from 'tiptap/core/extensions/loading'; import { findLoadingById, Loading } from 'tiptap/core/extensions/loading';
import { extractFileExtension, extractFilename } from './file'; import { extractFileExtension, extractFilename } from './file';
@ -28,50 +28,85 @@ interface FnProps {
*/ */
const uploadImage = async ({ file, fileInfo, editor }: FnProps & { fileInfo: FileInfo }) => { const uploadImage = async ({ file, fileInfo, editor }: FnProps & { fileInfo: FileInfo }) => {
const { view } = editor; const { view } = editor;
const { state } = view;
const { from } = state.selection; const id = `loading-${loadingId++}`;
const loadingNode = view.props.state.schema.nodes[Loading.name].create({ const loadingNode = editor.state.schema?.nodes?.[Loading.name]?.create({
id,
text: fileInfo.fileName, text: fileInfo.fileName,
}); });
view.dispatch(view.state.tr.replaceSelectionWith(loadingNode));
editor.view.dispatch(editor.view.state.tr.replaceSelectionWith(loadingNode));
try { try {
const url = await uploadFile(file); const url = await uploadFile(file);
const node = view.props.state.schema.nodes[Image.name].create({
src: url, const maybeLoading = findLoadingById(editor, id);
});
const transaction = view.state.tr.replaceRangeWith(from, from + loadingNode.nodeSize, node); if (maybeLoading) {
view.dispatch(transaction); const node = view.props.state.schema.nodes[Image.name].create({
src: url,
});
const transaction = view.state.tr.replaceRangeWith(
maybeLoading?.pos,
maybeLoading?.pos + maybeLoading?.node.nodeSize,
node
);
view.dispatch(transaction);
}
} catch (e) { } catch (e) {
editor.commands.deleteRange({ from: from, to: from + loadingNode.nodeSize }); const maybeLoading = findLoadingById(editor, id);
if (maybeLoading) {
editor.commands.deleteRange({
from: maybeLoading?.pos,
to: maybeLoading?.pos + maybeLoading?.node.nodeSize,
});
}
console.log('上传文件失败!'); console.log('上传文件失败!');
throw e; throw e;
} }
}; };
let loadingId = 0;
/** /**
* *
* @param param0 * @param param0
*/ */
const uploadAttachment = async ({ file, fileInfo, editor }: FnProps & { fileInfo: FileInfo }) => { const uploadAttachment = async ({ file, fileInfo, editor }: FnProps & { fileInfo: FileInfo }) => {
const { view } = editor; const { view } = editor;
const { state } = view;
const { from } = state.selection; const id = `loading-${loadingId++}`;
const loadingNode = view.props.state.schema.nodes[Loading.name].create({ const loadingNode = editor.state.schema?.nodes?.[Loading.name]?.create({
id,
text: fileInfo.fileName, text: fileInfo.fileName,
}); });
view.dispatch(view.state.tr.replaceSelectionWith(loadingNode));
editor.view.dispatch(editor.view.state.tr.replaceSelectionWith(loadingNode));
try { try {
const url = await uploadFile(file); const url = await uploadFile(file);
const node = view.props.state.schema.nodes[Attachment.name].create({ const maybeLoading = findLoadingById(editor, id);
url,
...fileInfo, if (maybeLoading) {
}); const node = view.props.state.schema.nodes[Attachment.name].create({
const transaction = view.state.tr.replaceRangeWith(from, from + loadingNode.nodeSize, node); url,
view.dispatch(transaction); ...fileInfo,
});
const transaction = view.state.tr.replaceRangeWith(
maybeLoading?.pos,
maybeLoading?.pos + maybeLoading?.node.nodeSize,
node
);
view.dispatch(transaction);
}
} catch (e) { } catch (e) {
editor.commands.deleteRange({ from: from, to: from + loadingNode.nodeSize }); const maybeLoading = findLoadingById(editor, id);
if (maybeLoading) {
editor.commands.deleteRange({
from: maybeLoading?.pos,
to: maybeLoading?.pos + maybeLoading?.node.nodeSize,
});
}
console.log('上传文件失败!'); console.log('上传文件失败!');
} }
}; };