diff --git a/apps/mobile/app/screens/editor/tiptap/editor-events.ts b/apps/mobile/app/screens/editor/tiptap/editor-events.ts new file mode 100644 index 000000000..a9af5961b --- /dev/null +++ b/apps/mobile/app/screens/editor/tiptap/editor-events.ts @@ -0,0 +1,19 @@ +export const EventTypes = { + selection: "editor-event:selection", + content: "editor-event:content", + title: "editor-event:title", + scroll: "editor-event:scroll", + history: "editor-event:history", + newtag: "editor-event:newtag", + tag: "editor-event:tag", + filepicker: "editor-event:picker", + download: "editor-event:download-attachment", + logger: "native:logger", + back: "editor-event:back", + pro: "editor-event:pro", + monograph: "editor-event:monograph", + properties: "editor-event:properties", + fullscreen: "editor-event:fullscreen", + link: "editor-event:link", + contentchange: "editor-event:content-change" +}; diff --git a/apps/mobile/app/screens/editor/tiptap/use-editor-events.ts b/apps/mobile/app/screens/editor/tiptap/use-editor-events.ts index 977f5a110..b7741f360 100644 --- a/apps/mobile/app/screens/editor/tiptap/use-editor-events.ts +++ b/apps/mobile/app/screens/editor/tiptap/use-editor-events.ts @@ -59,30 +59,10 @@ import { useDragState } from "../../settings/editor/state"; import { EditorMessage, EditorProps, useEditorType } from "./types"; import { EditorEvents, editorState } from "./utils"; import { openLinkInBrowser } from "../../../utils/functions"; +import { EventTypes } from "./editor-events"; import { RelationsList } from "../../../components/sheets/relations-list"; import ReminderSheet from "../../../components/sheets/reminder"; -export const EventTypes = { - selection: "editor-event:selection", - content: "editor-event:content", - title: "editor-event:title", - scroll: "editor-event:scroll", - history: "editor-event:history", - newtag: "editor-event:newtag", - tag: "editor-event:tag", - filepicker: "editor-event:picker", - download: "editor-event:download-attachment", - logger: "native:logger", - back: "editor-event:back", - pro: "editor-event:pro", - monograph: "editor-event:monograph", - properties: "editor-event:properties", - fullscreen: "editor-event:fullscreen", - link: "editor-event:link", - contentchange: "editor-event:content-change", - reminders: "editor-event:reminders" -}; - const publishNote = async (editor: useEditorType) => { const user = useUserStore.getState().user; if (!user) { diff --git a/apps/mobile/share/editor.js b/apps/mobile/share/editor.js new file mode 100644 index 000000000..1f7f66278 --- /dev/null +++ b/apps/mobile/share/editor.js @@ -0,0 +1,163 @@ +import React, { + useRef, + useState, + useMemo, + useCallback, + useEffect, + useLayoutEffect +} from "react"; +import { WebView } from "react-native-webview"; +import { EDITOR_URI } from "../app/screens/editor/source"; +import { Linking } from "react-native"; +import { EditorEvents, post } from "../app/screens/editor/tiptap/utils"; +import Commands from "../app/screens/editor/tiptap/commands"; +import { useShareStore } from "./store"; +import { + eSubscribeEvent, + eUnSubscribeEvent +} from "../app/services/event-manager"; +import { eOnLoadNote } from "../app/utils/events"; +import { getDefaultPresets } from "@notesnook/editor/dist/toolbar/tool-definitions"; +import { useSettingStore } from "../app/stores/use-setting-store"; +import { EventTypes } from "../app/screens/editor/tiptap/editor-events"; + +const useEditor = () => { + const ref = useRef(); + const [sessionId, setSessionId] = useState("share-editor-session"); + const colors = useShareStore((state) => state.colors); + const accent = useShareStore((state) => state.accent); + const commands = useMemo(() => new Commands(ref), [ref]); + const currentNote = useRef(); + + const postMessage = useCallback( + async (type, data) => post(ref, sessionId, type, data), + [] + ); + + const loadNote = (note) => { + postMessage(EditorEvents.html, note.content.data); + currentNote.current = note; + }; + + useEffect(() => { + eSubscribeEvent(eOnLoadNote + "shareEditor", loadNote); + return () => { + eUnSubscribeEvent(eOnLoadNote + "shareEditor", loadNote); + }; + }, [loadNote]); + + const onLoad = () => { + postMessage(EditorEvents.theme, { ...colors, accent }); + commands.setInsets({ top: 0, left: 0, right: 0, bottom: 0 }); + }; + + return { ref, onLoad, sessionId, currentNote, commands }; +}; + +const useEditorEvents = (editor,onChange) => { + const doubleSpacedLines = useSettingStore( + (state) => state.settings?.doubleSpacedLines + ); + useEffect(() => { + editor.commands.setSettings({ + deviceMode: "mobile", + fullscreen: false, + premium: false, + readonly: false, + tools: getDefaultPresets().default, + noHeader: true, + noToolbar: true, + keyboardShown: false, + doubleSpacedLines: doubleSpacedLines + }); + }, [editor, doubleSpacedLines]); + + const onMessage = (event) => { + const data = event.nativeEvent.data; + const editorMessage = JSON.parse(data); + if ( + editorMessage.sessionId !== editor.sessionId && + editorMessage.type !== EditorEvents.status + ) { + return; + } + + switch (editorMessage.type) { + case EventTypes.logger: + logger.info("[WEBVIEW LOG]", editorMessage.value); + break; + case EventTypes.content: + logger.info("[WEBVIEW LOG]", "EditorTypes.content"); + onChange(editorMessage.value); + break; + } + }; + return onMessage; +}; + +const onShouldStartLoadWithRequest = (request) => { + if (request.url.includes("https")) { + if (Platform.OS === "ios" && !request.isTopFrame) return true; + Linking.openURL(request.url); + return false; + } else { + return true; + } +}; + +const style = { + height: "100%", + maxHeight: "100%", + width: "100%", + alignSelf: "center", + backgroundColor: "transparent" +}; + +export const Editor = ({ onChange, onLoad }) => { + const editor = useEditor(); + const onMessage = useEditorEvents(editor, onChange); + + useLayoutEffect(() => { + onLoad?.(); + }, [onLoad]); + + return ( + + ); +}; diff --git a/apps/mobile/share/share.js b/apps/mobile/share/share.js index cb0ee99b4..165d95f0e 100644 --- a/apps/mobile/share/share.js +++ b/apps/mobile/share/share.js @@ -19,7 +19,7 @@ along with this program. If not, see . import { getPreviewData } from "@flyerhq/react-native-link-preview"; import { parseHTML } from "@notesnook/core/utils/html-parser"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import { ActivityIndicator, Alert, @@ -42,14 +42,13 @@ import ShareExtension from "rn-extensions-share"; import isURL from "validator/lib/isURL"; import { db } from "../app/common/database"; import Storage from "../app/common/database/storage"; -import Editor from "../app/screens/editor"; import { eSendEvent } from "../app/services/event-manager"; import { getElevation } from "../app/utils"; import { eOnLoadNote } from "../app/utils/events"; +import { sleep } from "../app/utils/time"; import { Search } from "./search"; import { useShareStore } from "./store"; -import { useCallback } from "react"; -import { sleep } from "../app/utils/time"; +import { Editor } from "./editor"; const getLinkPreview = (url) => { return getPreviewData(url, 5000); }; @@ -598,15 +597,6 @@ const ShareView = ({ quicknote = false }) => { > {!loadingExtension && ( { noteContent.current = html;