From ba189b26e289e274281a08319ec7f56693e3eca4 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Fri, 25 Nov 2022 14:27:10 +0800 Subject: [PATCH] use loading id to find correct position --- .../src/tiptap/core/extensions/loading.ts | 20 ++++- .../client/src/tiptap/prose-utils/upload.ts | 79 +++++++++++++------ 2 files changed, 76 insertions(+), 23 deletions(-) diff --git a/packages/client/src/tiptap/core/extensions/loading.ts b/packages/client/src/tiptap/core/extensions/loading.ts index 5965ffe1..b442c7d7 100644 --- a/packages/client/src/tiptap/core/extensions/loading.ts +++ b/packages/client/src/tiptap/core/extensions/loading.ts @@ -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, }, diff --git a/packages/client/src/tiptap/prose-utils/upload.ts b/packages/client/src/tiptap/prose-utils/upload.ts index 20a9ec80..2808a45e 100644 --- a/packages/client/src/tiptap/prose-utils/upload.ts +++ b/packages/client/src/tiptap/prose-utils/upload.ts @@ -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('上传文件失败!'); } };