From b48b0c68d604f4f4faf92e3cfb2b47c4e2f25845 Mon Sep 17 00:00:00 2001 From: yoma Date: Wed, 8 Jul 2026 10:01:33 +0800 Subject: [PATCH] Use Tiptap mobile editor inside workspace --- apps/web/src/components/EditorPane.tsx | 32 +++++++++++-------- .../MobileStandaloneTiptapEditor.tsx | 7 +++- apps/web/src/components/WorkspaceApp.tsx | 5 --- apps/web/src/mobile-edit.tsx | 1 - 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/apps/web/src/components/EditorPane.tsx b/apps/web/src/components/EditorPane.tsx index 06857095..0265a6c3 100644 --- a/apps/web/src/components/EditorPane.tsx +++ b/apps/web/src/components/EditorPane.tsx @@ -1,4 +1,4 @@ -import { useRef, useState, useEffect, useCallback, useMemo, type PointerEvent as ReactPointerEvent, type ReactNode } from "react"; +import { lazy, Suspense, useRef, useState, useEffect, useCallback, useMemo, type PointerEvent as ReactPointerEvent, type ReactNode } from "react"; import { useQueryClient, useMutation } from "@tanstack/react-query"; import { NodeViewWrapper, ReactNodeViewRenderer, useEditor, EditorContent, type Editor, type NodeViewProps } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; @@ -50,7 +50,6 @@ import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@ import { EditorToolbar } from "./EditorToolbar"; import { RevisionHistoryDialog } from "./dialogs/RevisionHistoryDialog"; import { api } from "@/lib/api"; -import { openStandaloneMobileEditor } from "@/lib/mobile-editor"; import { cn, formatDateTime, parseTagsText } from "@/lib/utils"; import { docToMarkdown, markdownToDoc, type Notebook, type MemoDetail, type TiptapDoc } from "@edgeever/shared"; import { compressImageForUpload } from "@/lib/image-compression"; @@ -70,6 +69,10 @@ const MIN_IMAGE_WIDTH_PERCENT = 25; const MAX_IMAGE_WIDTH_PERCENT = 100; const IMAGE_WIDTH_PRESETS = [35, 50, 72, 100]; +const MobileStandaloneTiptapEditor = lazy(() => + import("./MobileStandaloneTiptapEditor").then((module) => ({ default: module.MobileStandaloneTiptapEditor })) +); + type NoteSearchMatch = { from: number; to: number; @@ -946,12 +949,6 @@ export const EditorPane = (props: EditorPaneProps) => { (mobileDefaultEditRequested || mobileNativeEditMemoId === props.memo.id) ); - useEffect(() => { - if (isMobileViewport && mobileDefaultEditRequested && props.memo?.id) { - openStandaloneMobileEditor(props.memo.id); - } - }, [isMobileViewport, mobileDefaultEditRequested, props.memo?.id]); - useEffect(() => { const mediaQuery = window.matchMedia(MOBILE_EDITOR_QUERY); const updateMobileViewport = () => setIsMobileViewport(mediaQuery.matches); @@ -966,11 +963,21 @@ export const EditorPane = (props: EditorPaneProps) => { setMobileNativeEditMemoId(null); }, [props.memo?.id]); - if (mobileNativeEditingActive) { + if (mobileNativeEditingActive && props.memo) { + const activeMemoId = props.memo.id; + return ( -
- 打开编辑器 -
+ 加载编辑器}> + { + props.onMobileDefaultEditConsumed(); + setMobileNativeEditMemoId(null); + props.onBackToList(); + }} + /> + ); } @@ -981,7 +988,6 @@ export const EditorPane = (props: EditorPaneProps) => { onRequestMobileNativeEdit={() => { if (props.memo?.id && !readOnly) { setMobileNativeEditMemoId(props.memo.id); - openStandaloneMobileEditor(props.memo.id); } }} /> diff --git a/apps/web/src/components/MobileStandaloneTiptapEditor.tsx b/apps/web/src/components/MobileStandaloneTiptapEditor.tsx index 19751a17..a6da280d 100644 --- a/apps/web/src/components/MobileStandaloneTiptapEditor.tsx +++ b/apps/web/src/components/MobileStandaloneTiptapEditor.tsx @@ -4,6 +4,7 @@ import StarterKit from "@tiptap/starter-kit"; import Image from "@tiptap/extension-image"; import Placeholder from "@tiptap/extension-placeholder"; import { docToMarkdown, emptyDoc, type MemoDetail, type Notebook, type TiptapDoc } from "@edgeever/shared"; +import "@/styles/mobile-markdown-editor.css"; import { MobileEditorFallback, MobileEditorHeader, @@ -40,12 +41,14 @@ type MobileStandaloneTiptapEditorProps = { memoId?: string | null; returnTo?: string; onLeave?: () => void; + onSaved?: (memo: MemoDetail) => void | Promise; }; export const MobileStandaloneTiptapEditor = ({ memoId: memoIdProp, returnTo: returnToProp, onLeave, + onSaved, }: MobileStandaloneTiptapEditorProps = {}) => { const params = useMemo(() => getMobileEditorParams(), []); const memoId = memoIdProp ?? params.get("memoId"); @@ -236,6 +239,7 @@ export const MobileStandaloneTiptapEditor = ({ memoRef.current = data.memo; setMemo(data.memo); + await onSaved?.(data.memo); lastSavedSnapshotRef.current = currentSnapshot(); dirtyRef.current = false; if (draftKey) { @@ -262,7 +266,7 @@ export const MobileStandaloneTiptapEditor = ({ currentSavePromiseRef.current = null; } }, - [currentSnapshot, draftKey, persistLocalDraft, setSaveStateStable] + [currentSnapshot, draftKey, onSaved, persistLocalDraft, setSaveStateStable] ); useEffect(() => { @@ -357,6 +361,7 @@ export const MobileStandaloneTiptapEditor = ({ memoRef.current = data.memo; setMemo(data.memo); + await onSaved?.(data.memo); setSaveStateStable("saved"); window.setTimeout(() => { if (!dirtyRef.current && !savingRef.current && !leavingRef.current) { diff --git a/apps/web/src/components/WorkspaceApp.tsx b/apps/web/src/components/WorkspaceApp.tsx index 28b3bc8b..574e8378 100644 --- a/apps/web/src/components/WorkspaceApp.tsx +++ b/apps/web/src/components/WorkspaceApp.tsx @@ -27,7 +27,6 @@ import { import { MemoListPane, MemoSelectionActionBar } from "./MemoListPane"; import { AppConfirmDialog, MemoDeleteConfirmDialog, NotebookNameDialog } from "./dialogs/ConfirmDialogs"; import { api } from "@/lib/api"; -import { openStandaloneMobileEditor } from "@/lib/mobile-editor"; import { cn } from "@/lib/utils"; import { createExcerpt, docToText, type Notebook, type AuthUser, type MemoSummary, type MemoDetail } from "@edgeever/shared"; import type { @@ -1259,10 +1258,6 @@ export const WorkspaceApp = ({ setCreatedMemoEditId(data.memo.id); setSelectedMemoId(data.memo.id); setActivePane("editor"); - - if (!isDesktopViewport()) { - openStandaloneMobileEditor(data.memo.id); - } }, }); diff --git a/apps/web/src/mobile-edit.tsx b/apps/web/src/mobile-edit.tsx index a37b0696..1488043a 100644 --- a/apps/web/src/mobile-edit.tsx +++ b/apps/web/src/mobile-edit.tsx @@ -1,7 +1,6 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { MobileStandaloneTiptapEditor } from "@/components/MobileStandaloneTiptapEditor"; -import "./styles/mobile-markdown-editor.css"; const root = document.getElementById("mobile-editor-root");