mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-29 00:20:04 +01:00
255 lines
7.0 KiB
JavaScript
255 lines
7.0 KiB
JavaScript
/*
|
|
This file is part of the Notesnook project (https://notesnook.com/)
|
|
|
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
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, Platform, View } 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] = 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 doubleSpacedLines = useSettingStore(
|
|
(state) => state.settings?.doubleSpacedLines
|
|
);
|
|
const postMessage = useCallback(
|
|
async (type, data) => post(ref, sessionId, type, data),
|
|
[sessionId]
|
|
);
|
|
|
|
const loadNote = useCallback(
|
|
(note) => {
|
|
postMessage(EditorEvents.html, note.content.data);
|
|
currentNote.current = note;
|
|
},
|
|
[postMessage]
|
|
);
|
|
|
|
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 });
|
|
commands.setSettings({
|
|
deviceMode: "mobile",
|
|
fullscreen: false,
|
|
premium: false,
|
|
readonly: false,
|
|
tools: getDefaultPresets().default,
|
|
noHeader: true,
|
|
noToolbar: true,
|
|
keyboardShown: false,
|
|
doubleSpacedLines: doubleSpacedLines
|
|
});
|
|
};
|
|
|
|
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:
|
|
console.log("[WEBVIEW LOG]", editorMessage.value);
|
|
break;
|
|
case EventTypes.content:
|
|
console.log("[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 colors = useShareStore((state) => state.colors);
|
|
const editor = useEditor();
|
|
const onMessage = useEditorEvents(editor, onChange);
|
|
const [loading, setLoading] = useState(true);
|
|
useLayoutEffect(() => {
|
|
onLoad?.();
|
|
}, [onLoad]);
|
|
|
|
useEffect(() => {
|
|
setTimeout(() => {
|
|
onLoad?.();
|
|
setTimeout(() => setLoading(false));
|
|
}, 1000);
|
|
}, [onLoad]);
|
|
|
|
return (
|
|
<View
|
|
style={{
|
|
flex: 1
|
|
}}
|
|
>
|
|
<WebView
|
|
ref={editor.ref}
|
|
onLoad={editor.onLoad}
|
|
nestedScrollEnabled
|
|
injectedJavaScriptBeforeContentLoaded={`
|
|
globalThis.readonly=${false};
|
|
globalThis.noToolbar=${true};
|
|
globalThis.noHeader=${true};
|
|
`}
|
|
injectedJavaScript={`globalThis.sessionId="${editor.sessionId}";`}
|
|
javaScriptEnabled={true}
|
|
focusable={true}
|
|
setSupportMultipleWindows={false}
|
|
overScrollMode="never"
|
|
scrollEnabled={false}
|
|
keyboardDisplayRequiresUserAction={false}
|
|
cacheMode="LOAD_DEFAULT"
|
|
cacheEnabled={true}
|
|
domStorageEnabled={true}
|
|
bounces={false}
|
|
setBuiltInZoomControls={false}
|
|
setDisplayZoomControls={false}
|
|
allowFileAccess={true}
|
|
scalesPageToFit={true}
|
|
hideKeyboardAccessoryView={false}
|
|
allowsFullscreenVideo={true}
|
|
allowFileAccessFromFileURLs={true}
|
|
allowUniversalAccessFromFileURLs={true}
|
|
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
|
originWhitelist={["*"]}
|
|
source={{
|
|
uri: EDITOR_URI
|
|
}}
|
|
style={style}
|
|
autoManageStatusBarEnabled={false}
|
|
onMessage={onMessage || undefined}
|
|
/>
|
|
{loading ? (
|
|
<View
|
|
style={{
|
|
position: "absolute",
|
|
width: "100%",
|
|
height: "100%",
|
|
backgroundColor: colors.bg,
|
|
alignItems: "flex-start",
|
|
zIndex: 999,
|
|
paddingHorizontal: 12
|
|
}}
|
|
>
|
|
<View
|
|
style={{
|
|
height: 16,
|
|
width: "100%",
|
|
backgroundColor: colors.nav,
|
|
borderRadius: 5,
|
|
marginTop: 10
|
|
}}
|
|
/>
|
|
|
|
<View
|
|
style={{
|
|
height: 16,
|
|
width: "100%",
|
|
backgroundColor: colors.nav,
|
|
borderRadius: 5,
|
|
marginTop: 10
|
|
}}
|
|
/>
|
|
|
|
<View
|
|
style={{
|
|
height: 16,
|
|
width: "60%",
|
|
backgroundColor: colors.nav,
|
|
borderRadius: 5,
|
|
marginTop: 10
|
|
}}
|
|
/>
|
|
</View>
|
|
) : null}
|
|
</View>
|
|
);
|
|
};
|