diff --git a/apps/web/src/components/diff-viewer/diff.css b/apps/web/src/components/diff-viewer/diff.css
deleted file mode 100644
index 01b2d8734..000000000
--- a/apps/web/src/components/diff-viewer/diff.css
+++ /dev/null
@@ -1,14 +0,0 @@
-span.diff-del {
- background-color: #fdb0c0;
-}
-
-span.diff-ins {
- background-color: #cafffb;
-}
-
-.diffviewer img {
- height: auto !important;
- max-width: 100% !important;
- background-color: var(--bgSecondary);
- border-radius: 5px;
-}
diff --git a/apps/web/src/components/diff-viewer/differ.js b/apps/web/src/components/diff-viewer/differ.js
deleted file mode 100644
index d5b300df3..000000000
--- a/apps/web/src/components/diff-viewer/differ.js
+++ /dev/null
@@ -1,50 +0,0 @@
-export default class HTMLDiffer {
- constructor() {
- this.isReady = false;
- this.initializing = false;
- this.promiseQueue = [];
- }
-
- async _initialize() {
- if (this.isReady) return;
- this.initializing = true;
- this.worker = new Worker("/diff.worker.js");
- this.isReady = true;
- this.initializing = false;
- }
-
- _communicate(type, data, transferables = [], init = true) {
- return new Promise(async (resolve, reject) => {
- if (init) await this._initialize();
- const messageId = Math.random().toString(36).substr(2, 9);
- const onMessage = (e) => {
- const { type: _type, messageId: _mId, data } = e.data;
- if (_type === type && _mId === messageId) {
- this.worker.removeEventListener("message", onMessage);
- if (data.error) {
- console.error(data.error);
- return reject(data.error);
- }
- resolve(data);
- }
- };
- this.worker.addEventListener("message", onMessage);
- this.worker.postMessage(
- {
- type,
- data,
- messageId,
- },
- transferables
- );
- });
- }
-
- generate = (before, after) => {
- return this._communicate("generate", { before, after });
- };
-
- clean = (html) => {
- return this._communicate("clean", { html });
- };
-}
diff --git a/apps/web/src/components/diff-viewer/index.js b/apps/web/src/components/diff-viewer/index.js
index e5812289c..be8650b67 100644
--- a/apps/web/src/components/diff-viewer/index.js
+++ b/apps/web/src/components/diff-viewer/index.js
@@ -1,48 +1,20 @@
-import "./diff.css";
-import "../editor/plugins/attachmentshandler.css";
import { useState, useEffect, useCallback } from "react";
-import { Flex, Box, Text, Button } from "rebass";
+import { Flex, Text, Button } from "rebass";
import * as Icon from "../icons";
import ContentToggle from "./content-toggle";
import { store as notesStore } from "../../stores/note-store";
import { db } from "../../common/db";
import { useStore as useAppStore } from "../../stores/app-store";
-import { useStore as useThemeStore } from "../../stores/theme-store";
import { useStore as useEditorStore } from "../../stores/editor-store";
import { hashNavigate } from "../../navigation";
-import HTMLDiffer from "./differ";
import { showToast } from "../../utils/toast";
import { ScrollSync, ScrollSyncPane } from "react-scroll-sync";
-import { injectCssSrc, removeCss } from "../../utils/css";
-import { EV, EVENTS } from "notes-core/common";
-
-const differ = new HTMLDiffer();
-var conflicts = undefined;
-var currentConflict = undefined;
-
-function navigateConflicts(prev) {
- if (!conflicts)
- conflicts = [
- ...document.querySelectorAll("span.diff-ins"),
- ...document.querySelectorAll("span.diff-del"),
- ];
- let nextConflict;
- if (currentConflict) {
- const scrollTop = document.getElementById("diffViewAfter").scrollTop;
- nextConflict = conflicts.find((conflict) =>
- prev ? conflict.offsetTop < scrollTop : conflict.offsetTop > scrollTop
- );
- } else nextConflict = conflicts[0];
- if (!nextConflict) return false;
- currentConflict = nextConflict;
- currentConflict.scrollIntoView({ block: "center" });
-}
+import { Editor } from "../editor";
function DiffViewer(props) {
const { noteId } = props;
const setIsEditorOpen = useAppStore((store) => store.setIsEditorOpen);
- const theme = useThemeStore((store) => store.theme);
const sync = useAppStore((store) => store.sync);
const clearSession = useEditorStore((store) => store.clearSession);
const [conflictedNote, setConflictedNote] = useState();
@@ -50,6 +22,7 @@ function DiffViewer(props) {
const [localContent, setLocalContent] = useState();
const [isDownloadingImages, setIsDownloadingImages] = useState(false);
const [htmlDiff, setHtmlDiff] = useState({});
+ const [selectedContent, setSelectedContent] = useState(-1);
const resolveConflict = useCallback(
async ({ toKeep, toCopy, toKeepDateEdited, dateResolved }) => {
@@ -125,39 +98,15 @@ function DiffViewer(props) {
setLocalContent({ ...content, conflicted: false });
setRemoteContent(content.conflicted);
- differ
- .generate(content.data, content.conflicted.data)
- .then(async ({ before, after }) => {
- setHtmlDiff({ before, after });
- conflicts = undefined;
- currentConflict = undefined;
- });
-
setHtmlDiff({ before: content.data, after: content.conflicted.data });
-
- conflicts = undefined;
- currentConflict = undefined;
})();
}, [noteId, resolveConflict]);
- useEffect(() => {
- let cssPath = "";
- if (theme === "dark")
- cssPath = "/skins/notesnook-dark/content.inline.min.css";
- else cssPath = "/skins/notesnook/content.inline.min.css";
- injectCssSrc("tmce", cssPath);
- return () => {
- removeCss("tmce");
- };
- }, [theme]);
-
useEffect(() => {
clearSession(false);
setIsEditorOpen(true);
}, [setIsEditorOpen, clearSession]);
- const [selectedContent, setSelectedContent] = useState(-1);
-
if (!conflictedNote || !localContent || !remoteContent) return null;
return (
-
-
-
+ >
+
+
-
+
+
+
diff --git a/apps/web/src/components/editor/index.tsx b/apps/web/src/components/editor/index.tsx
index 6db6490b8..bfd67bbab 100644
--- a/apps/web/src/components/editor/index.tsx
+++ b/apps/web/src/components/editor/index.tsx
@@ -1,4 +1,10 @@
-import { useEffect, useCallback, useState, useRef } from "react";
+import {
+ useEffect,
+ useCallback,
+ useState,
+ useRef,
+ PropsWithChildren,
+} from "react";
import { Box, Button, Flex, Text } from "rebass";
import Properties from "../properties";
import { useStore, store as editorstore } from "../../stores/editor-store";
@@ -132,8 +138,10 @@ export default function EditorManager({
nonce={timestamp}
title={title}
content={content}
- readonly={isReadonly}
- onRequestFocus={() => toggleProperties(false)}
+ options={{
+ readonly: isReadonly,
+ onRequestFocus: () => toggleProperties(false),
+ }}
/>
{arePropertiesVisible && }
@@ -141,18 +149,27 @@ export default function EditorManager({
);
}
-type EditorProps = {
- title: string;
+type EditorOptions = {
+ headless?: boolean;
readonly?: boolean;
focusMode?: boolean;
- nonce?: number;
- content: string;
onRequestFocus?: () => void;
};
-function Editor(props: EditorProps) {
- const { content, readonly, focusMode, onRequestFocus, title, nonce } = props;
+type EditorProps = {
+ title?: string;
+ nonce?: number;
+ content: string;
+ options?: EditorOptions;
+};
+export function Editor(props: EditorProps) {
+ const { content, nonce, options } = props;
+ const { readonly, headless } = options || {
+ headless: false,
+ readonly: false,
+ focusMode: false,
+ };
+
const editor = useEditorInstance();
- const isMobile = useMobile();
useEffect(() => {
if (!editor) return;
@@ -190,6 +207,44 @@ function Editor(props: EditorProps) {
};
}, [editor]);
+ return (
+
+ {
+ const { id, sessionId } = editorstore.get().session;
+ debouncedOnEditorChange(sessionId, id, sessionId, content);
+ if (counter) debouncedUpdateWordCount(counter);
+ }}
+ onDownloadAttachment={(attachment) =>
+ downloadAttachment(attachment.hash)
+ }
+ onInsertAttachment={(type) => {
+ const mime = type === "file" ? "*/*" : "image/*";
+ insertAttachment(mime).then((file) => {
+ if (!file) return;
+ editor?.attachFile(file);
+ });
+ }}
+ />
+
+ );
+}
+
+function EditorChrome(props: PropsWithChildren) {
+ const { title, nonce, options, children } = props;
+ const { readonly, focusMode, headless, onRequestFocus } = options || {
+ headless: false,
+ readonly: false,
+ focusMode: false,
+ };
+ const isMobile: boolean | null = useMobile();
+
+ if (headless) return <>{children}>;
+
return (
<>
@@ -223,37 +278,19 @@ function Editor(props: EditorProps) {
}}
/>
)}
- {
- const { sessionId, id } = editorstore.get().session;
- debouncedOnTitleChange(sessionId, id, title);
- }}
- title={title}
- />
+ {title !== undefined ? (
+ {
+ const { sessionId, id } = editorstore.get().session;
+ debouncedOnTitleChange(sessionId, id, title);
+ }}
+ title={title}
+ />
+ ) : null}
- {
- const { id, sessionId } = editorstore.get().session;
- debouncedOnEditorChange(sessionId, id, sessionId, content);
- if (counter) debouncedUpdateWordCount(counter);
- }}
- onDownloadAttachment={(attachment) =>
- downloadAttachment(attachment.hash)
- }
- onInsertAttachment={(type) => {
- const mime = type === "file" ? "*/*" : "image/*";
- insertAttachment(mime).then((file) => {
- if (!file) return;
- editor?.attachFile(file);
- });
- }}
- />
+ {children}
diff --git a/apps/web/src/components/editor/tiptap.tsx b/apps/web/src/components/editor/tiptap.tsx
index 4ad00301d..cc3e3f39f 100644
--- a/apps/web/src/components/editor/tiptap.tsx
+++ b/apps/web/src/components/editor/tiptap.tsx
@@ -100,6 +100,8 @@ function TipTap(props: TipTapProps) {
if (isSearching && !isEditorSearching) toggleSearch();
}, [toggleSearch, editor?.storage.searchreplace?.isSearching]);
+ if (!toolbarContainerId) return null;
+
return (
<>
diff --git a/apps/web/src/views/home.js b/apps/web/src/views/home.js
index 92717d1b5..54c9fbc36 100644
--- a/apps/web/src/views/home.js
+++ b/apps/web/src/views/home.js
@@ -24,10 +24,10 @@ function Home() {
store.refresh();
setIsLoading(false);
}
- // const note = db.notes.note("f90f344ee3c13c2f686bd5c1").data;
+ // const note = db.notes.note("62bc3f28a1a1a10000707077").data;
// const data = await db.content.raw(note.contentId);
- // const note2 = db.notes.note("3e9a515cc63199a101ec49bb").data;
+ // const note2 = db.notes.note("62bc3f1ca1a1a10000707075").data;
// const data2 = await db.content.raw(note2.contentId);
// const data3 = { ...data, conflicted: data2 };