diff --git a/apps/web/src/components/editor/index.tsx b/apps/web/src/components/editor/index.tsx
index d20dd1143..6c4a5f0c2 100644
--- a/apps/web/src/components/editor/index.tsx
+++ b/apps/web/src/components/editor/index.tsx
@@ -27,7 +27,15 @@ import React, {
import ReactDOM from "react-dom";
import { Box, Flex, Progress, Text } from "@theme-ui/components";
import Properties from "../properties";
-import { useEditorStore, SaveState } from "../../stores/editor-store";
+import {
+ useEditorStore,
+ SaveState,
+ DefaultEditorSession,
+ DeletedEditorSession,
+ NewEditorSession,
+ ReadonlyEditorSession,
+ EditorSession
+} from "../../stores/editor-store";
import {
useStore as useAppStore,
store as appstore
@@ -65,6 +73,7 @@ import DiffViewer from "../diff-viewer";
import TableOfContents from "./table-of-contents";
import { showNoteLinkingDialog } from "../../common/dialog-controller";
import { scrollIntoViewById } from "@notesnook/editor";
+import { IEditor } from "./types";
const PDFPreview = React.lazy(() => import("../pdf-preview"));
@@ -122,7 +131,7 @@ export default function TabsView() {
) : session.type === "conflicted" || session.type === "diff" ? (
) : (
-
+
)}
))}
@@ -132,10 +141,20 @@ export default function TabsView() {
const MemoizedEditorView = React.memo(
EditorView,
- (prev, next) => prev.id === next.id
+ (prev, next) =>
+ prev.session.id === next.session.id &&
+ prev.session.type === next.session.type
);
-function EditorView({ id }: { id: string }) {
- const lastSavedTime = useRef(Date.now());
+function EditorView({
+ session
+}: {
+ session:
+ | DefaultEditorSession
+ | NewEditorSession
+ | ReadonlyEditorSession
+ | DeletedEditorSession;
+}) {
+ const lastChangedTime = useRef(Date.now());
const [docPreview, setDocPreview] = useState();
const previewSession = useRef();
@@ -150,7 +169,7 @@ function EditorView({ id }: { id: string }) {
(store) => store.getSession(id, ["default", "readonly"])?.note?.readonly
);
const isFocusMode = useAppStore((store) => store.isFocusMode);
- const isPreviewSession = !!previewSession.current;
+ const editor = useEditorManager((store) => store.editors[session.id]?.editor);
const isMobile = useMobile();
const isTablet = useTablet();
@@ -159,25 +178,21 @@ function EditorView({ id }: { id: string }) {
const event = db.eventManager.subscribe(
EVENTS.syncItemMerged,
async (item?: MaybeDeletedItem- ) => {
- const session = useEditorStore
- .getState()
- .getSession(id, ["unlocked", "default"]);
- const editor = useEditorManager.getState().getEditor(id)?.editor;
if (
+ session.type === "new" ||
!editor ||
- !session?.note ||
+ !session.note ||
!item ||
isDeleted(item) ||
(item.type !== "tiptap" && item.type !== "note") ||
- lastSavedTime.current >= (item.dateEdited as number) ||
- isPreviewSession ||
+ lastChangedTime.current >= (item.dateEdited as number) ||
!appstore.get().isRealtimeSyncEnabled
)
return;
const { contentId, locked } = session.note;
const isContent = item.type === "tiptap" && item.id === contentId;
- const isNote = item.type === "note" && item.id === id;
+ const isNote = item.type === "note" && item.id === session.note.id;
if (id && isContent) {
let content: string | null = null;
@@ -194,7 +209,7 @@ function EditorView({ id }: { id: string }) {
useEditorStore
.getState()
- .updateSession(id, ["default"], { note: item });
+ .updateSession(session.id, [session.type], { note: item });
if (item.title)
AppEventManager.publish(AppEvents.changeNoteTitle, {
title: item.title,
@@ -206,30 +221,7 @@ function EditorView({ id }: { id: string }) {
return () => {
event.unsubscribe();
};
- }, [id, isPreviewSession]);
-
- // const openSession = useCallback(async (noteId: string) => {
- // await useEditorStore.getState().openSession(noteId);
- // previewSession.current = undefined;
-
- // lastSavedTime.current = Date.now();
- // setTimestamp(Date.now());
- // }, []);
-
- // useEffect(() => {
- // if (!isNewSession) return;
-
- // editorstore.newSession();
-
- // lastSavedTime.current = 0;
- // setTimestamp(Date.now());
- // }, [isNewSession, nonce]);
-
- // useEffect(() => {
- // if (!isOldSession || typeof noteId === "number") return;
-
- // openSession(noteId);
- // }, [noteId]);
+ }, [editor, session]);
return (
@@ -261,26 +253,24 @@ function EditorView({ id }: { id: string }) {
/>
)} */}
- previewSession.current?.content.data ||
- useEditorStore.getState().getSession(id, ["default"])?.content
- ?.data
- }
+ content={() => session.content?.data}
+ editor={editor}
+ session={session}
onPreviewDocument={(url) => setDocPreview(url)}
- onContentChange={() => (lastSavedTime.current = Date.now())}
+ onContentChange={() => (lastChangedTime.current = Date.now())}
onSave={(content, ignoreEdit) => {
deferredSave(session.id, session.id, ignoreEdit, data);
}}
options={{
- readonly: isReadonly || isPreviewSession,
+ readonly: session?.type === "readonly",
onRequestFocus: () => toggleProperties(false),
focusMode: isFocusMode,
isMobile: isMobile || isTablet
}}
/>
-
+ {editor && }
{docPreview && (
@@ -319,8 +309,12 @@ function EditorView({ id }: { id: string }) {
)}
- {arePropertiesVisible && }
- {isTOCVisible && }
+ {session.type !== "new" && (
+ <>
+ {arePropertiesVisible && }
+ {isTOCVisible && }
+ >
+ )}
);
}
@@ -375,7 +369,9 @@ type EditorOptions = {
};
type EditorProps = {
id: string;
+ session: EditorSession;
content: () => string | undefined;
+ editor?: IEditor;
nonce?: number;
options?: EditorOptions;
onContentChange?: () => void;
@@ -385,6 +381,8 @@ type EditorProps = {
export function Editor(props: EditorProps) {
const {
id,
+ editor,
+ session,
content,
onSave,
nonce,
@@ -399,13 +397,12 @@ export function Editor(props: EditorProps) {
isMobile: false
};
const [isLoading, setIsLoading] = useState(true);
- useScrollToBlock(id);
+ useScrollToBlock(session);
useEffect(() => {
const event = AppEventManager.subscribe(
AppEvents.UPDATE_ATTACHMENT_PROGRESS,
({ hash, loaded, total }: AttachmentProgress) => {
- const editor = useEditorManager.getState().getEditor(id)?.editor;
editor?.sendAttachmentProgress(
hash,
Math.round((loaded / total) * 100)
@@ -416,7 +413,7 @@ export function Editor(props: EditorProps) {
return () => {
event.unsubscribe();
};
- }, []);
+ }, [editor]);
return (
@@ -430,8 +427,8 @@ export function Editor(props: EditorProps) {
corsHost: Config.get("corsProxy", "https://cors.notesnook.com")
}}
onLoad={() => {
- restoreSelection(id);
- restoreScrollPosition(id);
+ if (editor) restoreSelection(editor, id);
+ restoreScrollPosition(session);
setIsLoading(false);
}}
onSelectionChange={({ from, to }) =>
@@ -474,7 +471,6 @@ export function Editor(props: EditorProps) {
}
}}
onInsertAttachment={async (type) => {
- const editor = useEditorManager.getState().getEditor(id)?.editor;
const mime = type === "file" ? "*/*" : "image/*";
const attachments = await insertAttachments(mime);
if (!attachments) return;
@@ -490,7 +486,6 @@ export function Editor(props: EditorProps) {
);
}}
onAttachFiles={async (files) => {
- const editor = useEditorManager.getState().getEditor(id)?.editor;
const result = await attachFiles(files);
if (!result) return;
result.forEach((attachment) => editor?.attachFile(attachment));
@@ -707,11 +702,11 @@ function EditorChrome(
// }
type DropZoneProps = {
- id: string;
overlayRef: React.MutableRefObject;
+ editor: IEditor;
};
function DropZone(props: DropZoneProps) {
- const { overlayRef, id } = props;
+ const { overlayRef, editor } = props;
return (
{
- const editor = useEditorManager.getState().getEditor(id)?.editor;
- if (!editor || !e.dataTransfer.files?.length) return;
+ if (!e.dataTransfer.files?.length) return;
e.preventDefault();
const attachments = await attachFiles(Array.from(e.dataTransfer.files));
@@ -801,19 +795,17 @@ function useDragOverlay() {
return [dropElementRef, overlayRef] as const;
}
-function useScrollToBlock(id: string) {
+function useScrollToBlock(session: EditorSession) {
const blockId = useEditorStore(
- (store) => store.getSession(id)?.activeBlockId
+ (store) => store.getSession(session.id)?.activeBlockId
);
useEffect(() => {
if (!blockId) return;
scrollIntoViewById(blockId);
- useEditorStore
- .getState()
- .updateSession(id, ["default", "unlocked", "deleted"], {
- activeBlockId: undefined
- });
- }, [blockId]);
+ useEditorStore.getState().updateSession(session.id, [session.type], {
+ activeBlockId: undefined
+ });
+ }, [session.id, session.type, blockId]);
}
function isFile(e: DragEvent) {
@@ -824,12 +816,11 @@ function isFile(e: DragEvent) {
);
}
-function restoreScrollPosition(id: string) {
- const session = useEditorStore.getState().getActiveSession();
+function restoreScrollPosition(session: EditorSession) {
if (session?.activeBlockId) return scrollIntoViewById(session.activeBlockId);
const scrollContainer = document.getElementById(`${id}_editorScroll`);
- const scrollPosition = Config.get(`${id}:scroll-position`, 0);
+ const scrollPosition = Config.get(`${session.id}:scroll-position`, 0);
if (scrollContainer) {
requestAnimationFrame(() => {
if (scrollContainer.scrollHeight < scrollPosition)
@@ -839,9 +830,8 @@ function restoreScrollPosition(id: string) {
}
}
-function restoreSelection(id: string) {
- const editor = useEditorManager.getState().getEditor(id)?.editor;
- editor?.focus({
+function restoreSelection(editor: IEditor, id: string) {
+ editor.focus({
position: Config.get(`${id}:selection`, { from: 0, to: 0 })
});
}
diff --git a/apps/web/src/components/editor/table-of-contents.tsx b/apps/web/src/components/editor/table-of-contents.tsx
index 318191838..79bfe45ed 100644
--- a/apps/web/src/components/editor/table-of-contents.tsx
+++ b/apps/web/src/components/editor/table-of-contents.tsx
@@ -38,7 +38,12 @@ along with this program. If not, see .
import React, { useEffect, useState } from "react";
import { ArrowLeft } from "../icons";
-import { useEditorStore } from "../../stores/editor-store";
+import {
+ DefaultEditorSession,
+ DeletedEditorSession,
+ ReadonlyEditorSession,
+ useEditorStore
+} from "../../stores/editor-store";
import { AnimatedFlex } from "../animated";
import ScrollContainer from "../scroll-container";
import { ScopedThemeProvider } from "../theme-provider";
@@ -48,24 +53,21 @@ import { Button, Flex } from "@theme-ui/components";
import { useEditorManager } from "./manager";
type TableOfContentsProps = {
- id: string;
+ session: DefaultEditorSession | ReadonlyEditorSession | DeletedEditorSession;
};
function TableOfContents(props: TableOfContentsProps) {
- const { id } = props;
+ const { session } = props;
const [active, setActive] = useState([]);
const toggleTableOfContents = useEditorStore(
(store) => store.toggleTableOfContents
);
- const session = useEditorStore((store) =>
- store.getSession(id, ["default", "unlocked", "readonly"])
- );
const tableOfContents = useEditorManager(
- (store) => store.editors[id].tableOfContents || []
+ (store) => store.editors[session.id]?.tableOfContents || []
);
useEffect(() => {
- const editorScroll = document.getElementById(`${id}_editorScroll`);
+ const editorScroll = document.getElementById(`${session.id}_editorScroll`);
if (!editorScroll) return;
function onScroll() {
const scrollTop = editorScroll?.scrollTop || 0;
@@ -85,7 +87,7 @@ function TableOfContents(props: TableOfContentsProps) {
return () => {
editorScroll.removeEventListener("scroll", onScroll);
};
- }, [id]);
+ }, [session.id, tableOfContents]);
if (!session) return null;
return (
diff --git a/apps/web/src/components/properties/index.tsx b/apps/web/src/components/properties/index.tsx
index 86bf354aa..d05c6ae3d 100644
--- a/apps/web/src/components/properties/index.tsx
+++ b/apps/web/src/components/properties/index.tsx
@@ -34,7 +34,8 @@ import { Box, Button, Flex, Text } from "@theme-ui/components";
import {
useEditorStore,
ReadonlyEditorSession,
- DefaultEditorSession
+ DefaultEditorSession,
+ DeletedEditorSession
} from "../../stores/editor-store";
import { db } from "../../common/db";
import { useStore as useAppStore } from "../../stores/app-store";
@@ -54,7 +55,6 @@ import { VirtualizedList } from "../virtualized-list";
import { SessionItem } from "../session-item";
import {
ContentBlock,
- DefaultColors,
Note,
VirtualizedGrouping,
createInternalLink,
@@ -106,18 +106,15 @@ const metadataItems = [
];
type EditorPropertiesProps = {
- id: string;
+ session: DefaultEditorSession | ReadonlyEditorSession | DeletedEditorSession;
};
function EditorProperties(props: EditorPropertiesProps) {
- const { id } = props;
+ const { session } = props;
const toggleProperties = useEditorStore((store) => store.toggleProperties);
const isFocusMode = useAppStore((store) => store.isFocusMode);
- const session = useEditorStore((store) =>
- store.getSession(id, ["default", "unlocked", "readonly"])
- );
- if (isFocusMode || !session) return null;
+ if (isFocusMode) return null;
return (
}
>
- <>
- {tools.map((tool) => (
- changeToggleState(tool.key, session)}
- testId={`properties-${tool.key}`}
- />
- ))}
- >
+ {session.type === "deleted" ? null : (
+ <>
+ {tools.map((tool) => (
+ changeToggleState(tool.key, session)}
+ testId={`properties-${tool.key}`}
+ />
+ ))}
+ >
+ )}
{metadataItems.map((item) => (
))}
-
+ {session.type === "deleted" ? null : (
+
+ )}
-
-
-
-
-
+
+
+
+
+