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 { Node as PMNode } from 'prosemirror-state';
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({
name: 'loading',
inline: true,
@ -10,6 +25,9 @@ export const Loading = Node.create({
addAttributes() {
return {
id: {
default: null,
},
text: {
default: null,
},

View File

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