diff --git a/apps/web/src/components/MobileStandaloneEditorParts.tsx b/apps/web/src/components/MobileStandaloneEditorParts.tsx
new file mode 100644
index 00000000..c80deb59
--- /dev/null
+++ b/apps/web/src/components/MobileStandaloneEditorParts.tsx
@@ -0,0 +1,184 @@
+import { Bold, Check, ChevronDown, ImagePlus, List, Minus, Quote } from "lucide-react";
+import type { NotebookMoveOption } from "@/lib/app-helpers";
+import type { MobileEditorSaveState } from "@/lib/mobile-editor-standalone";
+
+export const MobileEditorHeader = ({
+ saveLabel,
+ statusClassName,
+ saveState,
+ onLeave,
+}: {
+ saveLabel: string;
+ statusClassName: string;
+ saveState: MobileEditorSaveState;
+ onLeave: () => void;
+}) => (
+
+
+
+ {saveLabel}
+
+
+
+);
+
+export const MobileEditorToolbar = ({
+ disabled,
+ boldActive,
+ bulletListActive,
+ blockquoteActive,
+ onPickImage,
+ onToggleBold,
+ onToggleBulletList,
+ onToggleBlockquote,
+ onSetHorizontalRule,
+}: {
+ disabled: boolean;
+ boldActive: boolean;
+ bulletListActive: boolean;
+ blockquoteActive: boolean;
+ onPickImage: () => void;
+ onToggleBold: () => void;
+ onToggleBulletList: () => void;
+ onToggleBlockquote: () => void;
+ onSetHorizontalRule: () => void;
+}) => (
+
+
+
+
+
+
+
+);
+
+export const MobileEditorNotebookButton = ({
+ label,
+ disabled,
+ onOpen,
+}: {
+ label: string;
+ disabled: boolean;
+ onOpen: () => void;
+}) => (
+
+);
+
+export const MobileEditorNotebookSheet = ({
+ options,
+ selectedNotebookId,
+ updating,
+ onClose,
+ onSelect,
+}: {
+ options: NotebookMoveOption[];
+ selectedNotebookId?: string;
+ updating: boolean;
+ onClose: () => void;
+ onSelect: (notebookId: string) => void;
+}) => (
+
+
event.stopPropagation()}
+ >
+
+
+
所在笔记本
+
+
+
+ {options.map((notebook) => {
+ const selected = notebook.id === selectedNotebookId;
+
+ return (
+
+ );
+ })}
+
+
+
+);
+
+export const MobileEditorFallback = ({ markdown }: { markdown: string }) => (
+
+ 查看当前正文 Markdown 备份
+ {markdown}
+
+);
diff --git a/apps/web/src/lib/mobile-editor-standalone.ts b/apps/web/src/lib/mobile-editor-standalone.ts
index 5e83b603..c69b22b4 100644
--- a/apps/web/src/lib/mobile-editor-standalone.ts
+++ b/apps/web/src/lib/mobile-editor-standalone.ts
@@ -33,6 +33,34 @@ export type MobileEditorSaveState =
| "local-draft"
| "leaving";
+export const getMobileEditorSaveLabel = (saveState: MobileEditorSaveState) =>
+ saveState === "loading"
+ ? "加载中"
+ : saveState === "saving"
+ ? "保存中"
+ : saveState === "compressing"
+ ? "压缩中"
+ : saveState === "uploading"
+ ? "上传中"
+ : saveState === "dirty"
+ ? "未保存"
+ : saveState === "saved"
+ ? "已保存"
+ : saveState === "local-draft"
+ ? "本地草稿"
+ : saveState === "leaving"
+ ? "返回中"
+ : saveState === "error"
+ ? "保存失败"
+ : "已保存";
+
+export const getMobileEditorStatusClassName = (saveState: MobileEditorSaveState) =>
+ saveState === "error"
+ ? "error"
+ : saveState === "dirty" || saveState === "saving" || saveState === "compressing" || saveState === "uploading" || saveState === "leaving"
+ ? "active"
+ : "";
+
export const getMobileEditorParams = () =>
new URLSearchParams(window.location.hash ? window.location.hash.slice(1) : window.location.search);
diff --git a/apps/web/src/mobile-edit.tsx b/apps/web/src/mobile-edit.tsx
index 52b8a083..23fda3d5 100644
--- a/apps/web/src/mobile-edit.tsx
+++ b/apps/web/src/mobile-edit.tsx
@@ -4,8 +4,14 @@ import { EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Image from "@tiptap/extension-image";
import Placeholder from "@tiptap/extension-placeholder";
-import { Bold, Check, ChevronDown, ImagePlus, List, Minus, Quote } from "lucide-react";
import { docToMarkdown, emptyDoc, type MemoDetail, type Notebook, type TiptapDoc } from "@edgeever/shared";
+import {
+ MobileEditorFallback,
+ MobileEditorHeader,
+ MobileEditorNotebookButton,
+ MobileEditorNotebookSheet,
+ MobileEditorToolbar,
+} from "@/components/MobileStandaloneEditorParts";
import { getNotebookMoveOptions } from "@/lib/app-helpers";
import { compressImageForUpload } from "@/lib/image-compression";
import {
@@ -15,6 +21,8 @@ import {
MOBILE_EDITOR_LEAVE_SAVE_TIMEOUT_MS,
getMobileEditorDraftKey,
getMobileEditorParams,
+ getMobileEditorSaveLabel,
+ getMobileEditorStatusClassName,
normalizeMobileEditorDoc,
parseMobileEditorTags,
requestMobileEditorJson,
@@ -532,33 +540,8 @@ const MobileTiptapEditorApp = () => {
};
}, [leavePage, persistLocalDraft, saveNow]);
- const saveLabel =
- saveState === "loading"
- ? "加载中"
- : saveState === "saving"
- ? "保存中"
- : saveState === "compressing"
- ? "压缩中"
- : saveState === "uploading"
- ? "上传中"
- : saveState === "dirty"
- ? "未保存"
- : saveState === "saved"
- ? "已保存"
- : saveState === "local-draft"
- ? "本地草稿"
- : saveState === "leaving"
- ? "返回中"
- : saveState === "error"
- ? "保存失败"
- : "已保存";
-
- const statusClassName =
- saveState === "error"
- ? "error"
- : saveState === "dirty" || saveState === "saving" || saveState === "compressing" || saveState === "uploading" || saveState === "leaving"
- ? "active"
- : "";
+ const saveLabel = getMobileEditorSaveLabel(saveState);
+ const statusClassName = getMobileEditorStatusClassName(saveState);
const editorActionDisabled =
!memo || !editor || saveState === "loading" || saveState === "compressing" || saveState === "uploading" || saveState === "leaving";
const currentNotebookLabel =
@@ -577,17 +560,7 @@ const MobileTiptapEditorApp = () => {
return (
-
+
void leavePage()} />
{error && {error}
}
@@ -601,16 +574,11 @@ const MobileTiptapEditorApp = () => {
onChange={(event) => handleTitleChange(event.target.value)}
/>
-
+ onOpen={() => setNotebookSheetOpen(true)}
+ />
{
/>
-
-
-
-
-
-
-
+ imageInputRef.current?.click()}
+ onToggleBold={() => runEditorCommand(() => editor?.chain().focus().toggleBold().run() ?? false)}
+ onToggleBulletList={() => runEditorCommand(() => editor?.chain().focus().toggleBulletList().run() ?? false)}
+ onToggleBlockquote={() => runEditorCommand(() => editor?.chain().focus().toggleBlockquote().run() ?? false)}
+ onSetHorizontalRule={() => runEditorCommand(() => editor?.chain().focus().setHorizontalRule().run() ?? false)}
+ />
{
/>
{notebookSheetOpen && (
- setNotebookSheetOpen(false)}>
-
event.stopPropagation()}
- >
-
-
-
所在笔记本
-
-
-
- {notebookOptions.map((notebook) => {
- const selected = notebook.id === memo?.notebookId;
-
- return (
-
- );
- })}
-
-
-
+ setNotebookSheetOpen(false)}
+ onSelect={(notebookId) => void handleNotebookChange(notebookId)}
+ />
)}
- {saveState === "error" && fallbackMarkdown && (
-
- 查看当前正文 Markdown 备份
- {fallbackMarkdown}
-
- )}
+ {saveState === "error" && fallbackMarkdown && }
);