Use Tiptap mobile editor inside workspace
This commit is contained in:
1 parent
241b061ccc
commit
b48b0c68d6
4 files changed
+25
-20
No files matched your search
@@ -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 (
|
||||
<div className="flex h-full min-h-0 items-center justify-center bg-white text-sm font-medium text-slate-400">
|
||||
打开编辑器
|
||||
</div>
|
||||
<Suspense fallback={<div className="flex h-full min-h-0 items-center justify-center bg-white text-sm font-medium text-slate-400">加载编辑器</div>}>
|
||||
<MobileStandaloneTiptapEditor
|
||||
memoId={activeMemoId}
|
||||
onSaved={props.onSaved}
|
||||
onLeave={() => {
|
||||
props.onMobileDefaultEditConsumed();
|
||||
setMobileNativeEditMemoId(null);
|
||||
props.onBackToList();
|
||||
}}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -981,7 +988,6 @@ export const EditorPane = (props: EditorPaneProps) => {
|
||||
onRequestMobileNativeEdit={() => {
|
||||
if (props.memo?.id && !readOnly) {
|
||||
setMobileNativeEditMemoId(props.memo.id);
|
||||
openStandaloneMobileEditor(props.memo.id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -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<void>;
|
||||
};
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in new issue
Block a user