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");