mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-05-18 05:05:36 +02:00
mobile: tab history
This commit is contained in:
committed by
Abdullah Atta
parent
e85f8b60b0
commit
c80286b587
46
packages/editor-mobile/package-lock.json
generated
46
packages/editor-mobile/package-lock.json
generated
@@ -14,6 +14,7 @@
|
||||
"@lingui/react": "5.1.2",
|
||||
"@mdi/js": "^7.2.96",
|
||||
"@mdi/react": "^1.6.0",
|
||||
"@notesnook/common": "file:../common",
|
||||
"@notesnook/editor": "file:../editor",
|
||||
"@notesnook/intl": "file:../intl",
|
||||
"@notesnook/theme": "file:../theme",
|
||||
@@ -33,6 +34,25 @@
|
||||
"react-scripts": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"../common": {
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@notesnook/core": "file:../core",
|
||||
"pathe": "^1.1.2",
|
||||
"timeago.js": "4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@notesnook/core": "file:../core",
|
||||
"@types/react": "^18.2.39",
|
||||
"react": "18.2.0",
|
||||
"vitest": "^1.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"timeago.js": "4.0.2"
|
||||
}
|
||||
},
|
||||
"../editor": {
|
||||
"name": "@notesnook/editor",
|
||||
"version": "2.1.3",
|
||||
@@ -3766,6 +3786,10 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@notesnook/common": {
|
||||
"resolved": "../common",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@notesnook/editor": {
|
||||
"resolved": "../editor",
|
||||
"link": true
|
||||
@@ -4459,7 +4483,7 @@
|
||||
"version": "15.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/q": {
|
||||
"version": "1.5.8",
|
||||
@@ -4483,7 +4507,7 @@
|
||||
"version": "18.2.39",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.39.tgz",
|
||||
"integrity": "sha512-Oiw+ppED6IremMInLV4HXGbfbG6GyziY3kqAwJYOR0PNbkYDmLWQA3a95EhdSmamsvbkJN96ZNN+YD+fGjzSBA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@@ -4518,7 +4542,7 @@
|
||||
"version": "0.16.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
|
||||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.6",
|
||||
@@ -9780,7 +9804,7 @@
|
||||
"version": "9.0.21",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
|
||||
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/immer"
|
||||
@@ -17874,6 +17898,20 @@
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
"react-freeze": "^1.0.3",
|
||||
"zustand": "^4.4.7",
|
||||
"@lingui/core": "5.1.2",
|
||||
"@lingui/react": "5.1.2"
|
||||
"@lingui/react": "5.1.2",
|
||||
"tinycolor2": "1.6.0",
|
||||
"@notesnook/common": "file:../common"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.37.1",
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
useState
|
||||
} from "react";
|
||||
import { useEditorController } from "../hooks/useEditorController";
|
||||
import { useSafeArea } from "../hooks/useSafeArea";
|
||||
import { useSettings } from "../hooks/useSettings";
|
||||
import {
|
||||
NoteState,
|
||||
@@ -44,7 +45,8 @@ import {
|
||||
useTabContext,
|
||||
useTabStore
|
||||
} from "../hooks/useTabStore";
|
||||
import { EventTypes, postAsyncWithTimeout, Settings } from "../utils";
|
||||
import { postAsyncWithTimeout, Settings } from "../utils";
|
||||
import { EditorEvents } from "../utils/editor-events";
|
||||
import { pendingSaveRequests } from "../utils/pending-saves";
|
||||
import Header from "./header";
|
||||
import StatusBar from "./statusbar";
|
||||
@@ -82,6 +84,7 @@ const Tiptap = ({
|
||||
undo,
|
||||
redo
|
||||
});
|
||||
const insets = useSafeArea();
|
||||
tabRef.current = tab;
|
||||
valueRef.current = {
|
||||
undo,
|
||||
@@ -92,7 +95,7 @@ const Tiptap = ({
|
||||
try {
|
||||
if (!tabRef.current.noteId) return;
|
||||
const noteState =
|
||||
state || useTabStore.getState().noteState[tabRef.current.noteId];
|
||||
state || useTabStore.getState().getNoteState(tabRef.current.noteId);
|
||||
|
||||
if (noteState && (noteState.to || noteState.from)) {
|
||||
const size = editors[tabRef.current.id]?.state.doc.content.size || 0;
|
||||
@@ -124,7 +127,7 @@ const Tiptap = ({
|
||||
premium: settings.premium
|
||||
},
|
||||
onPermissionDenied: () => {
|
||||
post(EventTypes.pro, undefined, tabRef.current.id, tab.noteId);
|
||||
post(EditorEvents.pro, undefined, tabRef.current.id, tab.noteId);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -161,7 +164,7 @@ const Tiptap = ({
|
||||
) as Promise<string | undefined>;
|
||||
},
|
||||
createInternalLink(attributes) {
|
||||
return postAsyncWithTimeout(EventTypes.createInternalLink, {
|
||||
return postAsyncWithTimeout(EditorEvents.createInternalLink, {
|
||||
attributes
|
||||
});
|
||||
},
|
||||
@@ -305,12 +308,12 @@ const Tiptap = ({
|
||||
if (isFocusedRef.current) return;
|
||||
if (state.currentTab === tabRef.current.id) {
|
||||
isFocusedRef.current = true;
|
||||
const noteState = tabRef.current.noteId
|
||||
? state.noteState[tabRef.current.noteId]
|
||||
const noteState = tabRef.current?.noteId
|
||||
? state.getNoteState(tabRef.current.noteId)
|
||||
: undefined;
|
||||
|
||||
post(
|
||||
EventTypes.tabFocused,
|
||||
EditorEvents.tabFocused,
|
||||
!!globalThis.editorControllers[tabRef.current.id]?.content.current &&
|
||||
!editorControllers[tabRef.current.id]?.loading,
|
||||
tabRef.current.id,
|
||||
@@ -438,7 +441,9 @@ const Tiptap = ({
|
||||
display: isFocused ? "flex" : "none",
|
||||
flex: 1,
|
||||
flexDirection: "column",
|
||||
maxWidth: "100vw"
|
||||
maxWidth: "100vw",
|
||||
position: "relative",
|
||||
overflow: "hidden"
|
||||
}}
|
||||
ref={editorRoot}
|
||||
onDoubleClick={onClickEmptyArea}
|
||||
@@ -547,58 +552,83 @@ const Tiptap = ({
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
onScroll={controller.scroll}
|
||||
ref={containerRef}
|
||||
style={{
|
||||
overflowY: controller.loading ? "hidden" : "scroll",
|
||||
height: "100%",
|
||||
display: "block",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
{settings.noHeader || tab.locked ? null : (
|
||||
<>
|
||||
<Tags settings={settings} loading={controller.loading} />
|
||||
<Title
|
||||
titlePlaceholder={controller.titlePlaceholder}
|
||||
readonly={settings.readonly}
|
||||
controller={controllerRef}
|
||||
title={controller.title}
|
||||
fontFamily={settings.fontFamily}
|
||||
dateFormat={settings.dateFormat}
|
||||
timeFormat={settings.timeFormat}
|
||||
loading={controller.loading}
|
||||
/>
|
||||
{controller.loading || tab.locked ? (
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "absolute",
|
||||
zIndex: 800,
|
||||
backgroundColor: colors.primary.background,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: tab.locked ? "center" : "flex-start",
|
||||
justifyContent: tab.locked ? "center" : "flex-start",
|
||||
boxSizing: "border-box",
|
||||
rowGap: 10,
|
||||
marginTop: `${50 + insets.top}px`
|
||||
}}
|
||||
>
|
||||
{tab.locked ? (
|
||||
<div
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
paddingLeft: 12,
|
||||
paddingRight: 12,
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: 10
|
||||
}}
|
||||
>
|
||||
<p
|
||||
style={{
|
||||
color: colors.primary.paragraph,
|
||||
fontSize: 20,
|
||||
fontWeight: "600",
|
||||
textAlign: "center",
|
||||
padding: "0px 20px",
|
||||
marginBottom: 0,
|
||||
userSelect: "none"
|
||||
}}
|
||||
>
|
||||
{controller.title}
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
color: colors.primary.paragraph,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
userSelect: "none"
|
||||
}}
|
||||
>
|
||||
This note is locked.
|
||||
</p>
|
||||
|
||||
<StatusBar
|
||||
container={containerRef}
|
||||
loading={controller.loading}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{controller.loading || tab.locked ? (
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "absolute",
|
||||
zIndex: 999,
|
||||
backgroundColor: colors.primary.background,
|
||||
paddingRight: 12,
|
||||
paddingLeft: 12,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: tab.locked ? "center" : "flex-start",
|
||||
justifyContent: tab.locked ? "center" : "flex-start",
|
||||
boxSizing: "border-box",
|
||||
rowGap: 10
|
||||
}}
|
||||
>
|
||||
{tab.locked ? (
|
||||
<>
|
||||
<p
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
const data = new FormData(e.currentTarget);
|
||||
const password = data.get("password");
|
||||
const biometrics = data.get("enrollBiometrics");
|
||||
post("editor-events:unlock", {
|
||||
password,
|
||||
biometrics: biometrics === "on" ? true : false
|
||||
});
|
||||
}}
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
rowGap: 10
|
||||
}}
|
||||
>
|
||||
<input
|
||||
placeholder="Enter password"
|
||||
ref={controller.passwordInputRef}
|
||||
name="password"
|
||||
type="password"
|
||||
required
|
||||
style={{
|
||||
color: colors.primary.paragraph,
|
||||
fontSize: 20,
|
||||
@@ -771,10 +801,139 @@ const Tiptap = ({
|
||||
width: "94%",
|
||||
backgroundColor: colors.secondary.background,
|
||||
borderRadius: 5,
|
||||
marginTop: 10
|
||||
border: `1px solid ${colors.primary.border}`,
|
||||
paddingLeft: 12,
|
||||
paddingRight: 12,
|
||||
fontSize: "1em",
|
||||
backgroundColor: "transparent",
|
||||
caretColor: colors.primary.accent,
|
||||
color: colors.primary.paragraph
|
||||
}}
|
||||
/>
|
||||
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: colors.primary.accent,
|
||||
borderRadius: 5,
|
||||
boxSizing: "border-box",
|
||||
border: "none",
|
||||
color: colors.static.white,
|
||||
width: 300,
|
||||
fontSize: "0.9em",
|
||||
height: 45,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
if (globalThis.keyboardShown) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<p
|
||||
style={{
|
||||
userSelect: "none"
|
||||
}}
|
||||
>
|
||||
Unlock note
|
||||
</p>
|
||||
</button>
|
||||
|
||||
{biometryAvailable && !biometryEnrolled ? (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: 5
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="enrollBiometrics"
|
||||
style={{
|
||||
accentColor: colors.primary.accent
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
if (globalThis.keyboardShown) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<p
|
||||
style={{
|
||||
color: colors.primary.paragraph,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
userSelect: "none"
|
||||
}}
|
||||
>
|
||||
Enable biometric unlocking
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
</form>
|
||||
|
||||
{biometryEnrolled && biometryAvailable ? (
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
borderRadius: 5,
|
||||
boxSizing: "border-box",
|
||||
border: "none",
|
||||
color: colors.primary.accent,
|
||||
width: 300,
|
||||
fontSize: "0.9em",
|
||||
height: 45,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
columnGap: 5,
|
||||
userSelect: "none"
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
if (globalThis.keyboardShown) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
onClick={() => {
|
||||
post("editor-events:unlock-biometrics");
|
||||
}}
|
||||
>
|
||||
<FingerprintIcon />
|
||||
<p
|
||||
style={{
|
||||
userSelect: "none"
|
||||
}}
|
||||
>
|
||||
Unlock with biometrics
|
||||
</p>
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Tags settings={settings} loading={controller.loading} />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
paddingLeft: 12,
|
||||
paddingRight: 12,
|
||||
width: "100%",
|
||||
gap: 10
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
height: 25,
|
||||
width: "100%",
|
||||
backgroundColor: colors.secondary.background,
|
||||
borderRadius: 5
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
@@ -842,10 +1001,42 @@ const Tiptap = ({
|
||||
marginTop: 10
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div
|
||||
onScroll={controller.scroll}
|
||||
ref={containerRef}
|
||||
style={{
|
||||
overflowY: controller.loading ? "hidden" : "scroll",
|
||||
height: "100%",
|
||||
display: "block",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
{settings.noHeader || tab.locked ? null : (
|
||||
<>
|
||||
<Tags settings={settings} loading={controller.loading} />
|
||||
<Title
|
||||
titlePlaceholder={controller.titlePlaceholder}
|
||||
readonly={settings.readonly}
|
||||
controller={controllerRef}
|
||||
title={controller.title}
|
||||
fontFamily={settings.fontFamily}
|
||||
dateFormat={settings.dateFormat}
|
||||
timeFormat={settings.timeFormat}
|
||||
loading={controller.loading}
|
||||
/>
|
||||
|
||||
<StatusBar
|
||||
container={containerRef}
|
||||
loading={controller.loading}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div
|
||||
style={{
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { ControlledMenu, MenuItem as MenuItemInner } from "@szhsin/react-menu";
|
||||
import ArrowBackIcon from "mdi-react/ArrowBackIcon";
|
||||
import ArrowForwardIcon from "mdi-react/ArrowForwardIcon";
|
||||
import ArrowULeftTopIcon from "mdi-react/ArrowULeftTopIcon";
|
||||
import ArrowURightTopIcon from "mdi-react/ArrowURightTopIcon";
|
||||
import DotsHorizontalIcon from "mdi-react/DotsHorizontalIcon";
|
||||
@@ -30,7 +31,8 @@ import TableOfContentsIcon from "mdi-react/TableOfContentsIcon";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { useSafeArea } from "../hooks/useSafeArea";
|
||||
import { useTabContext, useTabStore } from "../hooks/useTabStore";
|
||||
import { EventTypes, Settings } from "../utils";
|
||||
import { Settings } from "../utils";
|
||||
import { EditorEvents } from "../utils/editor-events";
|
||||
import styles from "./styles.module.css";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
@@ -100,6 +102,10 @@ function Header({
|
||||
const openedTabsCount = useTabStore((state) => state.tabs.length);
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
const btnRef = useRef(null);
|
||||
const [canGoBack, canGoForward] = useTabStore((state) => [
|
||||
state.canGoBack,
|
||||
state.canGoForward
|
||||
]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -131,7 +137,7 @@ function Header({
|
||||
) : (
|
||||
<Button
|
||||
onPress={() => {
|
||||
post(EventTypes.back, undefined, tab.id, tab.noteId);
|
||||
post(EditorEvents.back, undefined, tab.id, tab.noteId);
|
||||
}}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
@@ -233,7 +239,7 @@ function Header({
|
||||
{settings.deviceMode !== "mobile" && !settings.fullscreen ? (
|
||||
<Button
|
||||
onPress={() => {
|
||||
post(EventTypes.fullscreen, undefined, tab.id, tab.noteId);
|
||||
post(EditorEvents.fullscreen, undefined, tab.id, tab.noteId);
|
||||
}}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
@@ -296,7 +302,67 @@ function Header({
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
post(EventTypes.showTabs, undefined, tab.id, tab.noteId);
|
||||
editor?.commands.undo();
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 10,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<ArrowULeftTopIcon
|
||||
color={
|
||||
!hasUndo
|
||||
? "var(--nn_secondary_border)"
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
editor?.commands.redo();
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 10,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<ArrowURightTopIcon
|
||||
color={
|
||||
!hasRedo
|
||||
? "var(--nn_secondary_border)"
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
post(EditorEvents.showTabs, undefined, tab.id, tab.noteId);
|
||||
}}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
@@ -341,7 +407,7 @@ function Header({
|
||||
fwdRef={btnRef}
|
||||
onPress={() => {
|
||||
if (tab.locked) {
|
||||
post(EventTypes.properties, undefined, tab.id, tab.noteId);
|
||||
post(EditorEvents.properties, undefined, tab.id, tab.noteId);
|
||||
} else {
|
||||
setOpen(!isOpen);
|
||||
}
|
||||
@@ -395,7 +461,7 @@ function Header({
|
||||
switch (e.value) {
|
||||
case "toc":
|
||||
post(
|
||||
EventTypes.toc,
|
||||
EditorEvents.toc,
|
||||
editorControllers[tab.id]?.getTableOfContents(),
|
||||
tab.id,
|
||||
tab.noteId
|
||||
@@ -406,7 +472,12 @@ function Header({
|
||||
break;
|
||||
case "properties":
|
||||
logger("info", "post properties...");
|
||||
post(EventTypes.properties, undefined, tab.id, tab.noteId);
|
||||
post(
|
||||
EditorEvents.properties,
|
||||
undefined,
|
||||
tab.id,
|
||||
tab.noteId
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -421,17 +492,85 @@ function Header({
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<MagnifyIcon
|
||||
size={22 * settings.fontScale}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
<span
|
||||
<Button
|
||||
onPress={() => {
|
||||
post(EditorEvents.goBack, undefined, tab.id, tab.noteId);
|
||||
setOpen(false);
|
||||
}}
|
||||
style={{
|
||||
color: "var(--nn_primary_paragraph)"
|
||||
}}
|
||||
>
|
||||
{strings.search()}
|
||||
</span>
|
||||
<ArrowBackIcon
|
||||
color={
|
||||
!canGoBack
|
||||
? "var(--nn_secondary_border)"
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
post(EditorEvents.goForward, undefined, tab.id, tab.noteId);
|
||||
setOpen(false);
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 10,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<ArrowForwardIcon
|
||||
color={
|
||||
!canGoForward
|
||||
? "var(--nn_secondary_border)"
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
editor?.commands.startSearch();
|
||||
setOpen(false);
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 10,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<MagnifyIcon
|
||||
size={28 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
</Button>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
|
||||
@@ -27,7 +27,8 @@ import {
|
||||
useState
|
||||
} from "react";
|
||||
import { useSettings } from "../hooks/useSettings";
|
||||
import { EventTypes, Settings, isReactNative, randId } from "../utils";
|
||||
import { Settings, isReactNative, randId } from "../utils";
|
||||
import { EditorEvents } from "../utils/editor-events";
|
||||
|
||||
export const ReadonlyEditorProvider = (): JSX.Element => {
|
||||
const settings = useSettings();
|
||||
@@ -95,7 +96,7 @@ const Tiptap = ({
|
||||
delete pendingResolvers[resolverId];
|
||||
resolve(data);
|
||||
};
|
||||
post(EventTypes.getAttachmentData, {
|
||||
post(EditorEvents.getAttachmentData, {
|
||||
attachment,
|
||||
resolverId: resolverId
|
||||
});
|
||||
@@ -142,7 +143,7 @@ const Tiptap = ({
|
||||
if (isSafari) {
|
||||
root = window;
|
||||
}
|
||||
post(EventTypes.readonlyEditorLoaded);
|
||||
post(EditorEvents.readonlyEditorLoaded);
|
||||
|
||||
const onMessage = (event: any) => {
|
||||
if (event?.data?.[0] !== "{") return;
|
||||
|
||||
@@ -18,7 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { EventTypes, Settings } from "../utils";
|
||||
import { Settings } from "../utils";
|
||||
import { EditorEvents } from "../utils/editor-events";
|
||||
import styles from "./styles.module.css";
|
||||
import { useTabContext } from "../hooks/useTabStore";
|
||||
import { strings } from "@notesnook/intl";
|
||||
@@ -45,7 +46,7 @@ function Tags(props: { settings: Settings; loading?: boolean }): JSX.Element {
|
||||
editor.commands.blur();
|
||||
editorTitles[tab.id]?.current?.blur();
|
||||
}
|
||||
post(EventTypes.newtag, undefined, tab.id, tab.noteId);
|
||||
post(EditorEvents.newtag, undefined, tab.id, tab.noteId);
|
||||
};
|
||||
const fontScale = props.settings?.fontScale || 1;
|
||||
|
||||
@@ -126,7 +127,7 @@ function Tags(props: { settings: Settings; loading?: boolean }): JSX.Element {
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
post(EventTypes.tag, tag, tab.id, tab.noteId);
|
||||
post(EditorEvents.tag, tag, tab.id, tab.noteId);
|
||||
}}
|
||||
>
|
||||
#{tag.alias}
|
||||
|
||||
@@ -32,7 +32,6 @@ import {
|
||||
useState
|
||||
} from "react";
|
||||
import {
|
||||
EventTypes,
|
||||
getRoot,
|
||||
isReactNative,
|
||||
post,
|
||||
@@ -40,6 +39,7 @@ import {
|
||||
saveTheme
|
||||
} from "../utils";
|
||||
import { injectCss, transform } from "../utils/css";
|
||||
import { EditorEvents } from "../utils/editor-events";
|
||||
import { pendingSaveRequests } from "../utils/pending-saves";
|
||||
import { useTabContext, useTabStore } from "./useTabStore";
|
||||
|
||||
@@ -158,7 +158,11 @@ export function useEditorController({
|
||||
});
|
||||
|
||||
if (!tabRef.current.noteId && loading) {
|
||||
setLoading(false);
|
||||
setTimeout(() => {
|
||||
if (!tabRef.current.noteId && loading) {
|
||||
setLoading(false);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
const selectionChange = useCallback((_editor: Editor) => {}, []);
|
||||
@@ -167,7 +171,7 @@ export function useEditorController({
|
||||
if (!isReactNative()) return;
|
||||
const currentSessionId = globalThis.sessionId;
|
||||
post(
|
||||
EventTypes.contentchange,
|
||||
EditorEvents.contentchange,
|
||||
undefined,
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId
|
||||
@@ -181,7 +185,7 @@ export function useEditorController({
|
||||
currentSessionId
|
||||
];
|
||||
const pendingTitleIds = await pendingSaveRequests.getPendingTitleIds();
|
||||
postAsyncWithTimeout(EventTypes.title, ...params, 1000)
|
||||
postAsyncWithTimeout(EditorEvents.title, ...params, 1000)
|
||||
.then(() => {
|
||||
if (pendingTitleIds.length) {
|
||||
dbLogger(
|
||||
@@ -230,7 +234,7 @@ export function useEditorController({
|
||||
}
|
||||
const currentSessionId = globalThis.sessionId;
|
||||
post(
|
||||
EventTypes.contentchange,
|
||||
EditorEvents.contentchange,
|
||||
undefined,
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId
|
||||
@@ -239,21 +243,22 @@ export function useEditorController({
|
||||
if (typeof timers.current.change === "number") {
|
||||
clearTimeout(timers.current?.change);
|
||||
}
|
||||
|
||||
const params = [
|
||||
{
|
||||
html: htmlContentRef.current,
|
||||
ignoreEdit: ignoreEdit
|
||||
},
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId,
|
||||
currentSessionId
|
||||
];
|
||||
|
||||
timers.current.change = setTimeout(async () => {
|
||||
htmlContentRef.current = editor.getHTML();
|
||||
|
||||
const params = [
|
||||
{
|
||||
html: htmlContentRef.current,
|
||||
ignoreEdit: ignoreEdit
|
||||
},
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId,
|
||||
currentSessionId
|
||||
];
|
||||
const pendingContentIds =
|
||||
await pendingSaveRequests.getPendingContentIds();
|
||||
postAsyncWithTimeout(EventTypes.content, ...params, 5000)
|
||||
postAsyncWithTimeout(EditorEvents.content, ...params, 5000)
|
||||
.then(() => {
|
||||
if (pendingContentIds.length) {
|
||||
dbLogger(
|
||||
@@ -284,12 +289,7 @@ export function useEditorController({
|
||||
}
|
||||
});
|
||||
|
||||
logger(
|
||||
"info",
|
||||
"Editor saving content",
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId
|
||||
);
|
||||
logger("info", "Editor saving content", params[1], params[2]);
|
||||
}, 300);
|
||||
|
||||
countWords(5000);
|
||||
@@ -343,13 +343,13 @@ export function useEditorController({
|
||||
switch (type) {
|
||||
case "native:updatehtml": {
|
||||
htmlContentRef.current = value;
|
||||
logger("info", "UPDATING NOTE HTML");
|
||||
|
||||
if (tabRef.current.id !== useTabStore.getState().currentTab) {
|
||||
updateTabOnFocus.current = true;
|
||||
} else {
|
||||
if (!editor) break;
|
||||
const noteState = tabRef.current?.noteId
|
||||
? useTabStore.getState().noteState[tabRef.current?.noteId]
|
||||
? useTabStore.getState().getNoteState(tabRef.current?.noteId)
|
||||
: null;
|
||||
const top = scrollTop() || noteState?.top || 0;
|
||||
editor?.commands.setContent(htmlContentRef.current, false, {
|
||||
@@ -418,12 +418,17 @@ export function useEditorController({
|
||||
}, [onMessage]);
|
||||
|
||||
const openFilePicker = useCallback((type: "image" | "file" | "camera") => {
|
||||
post(EventTypes.filepicker, type, tabRef.current.id, tabRef.current.noteId);
|
||||
post(
|
||||
EditorEvents.filepicker,
|
||||
type,
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId
|
||||
);
|
||||
}, []);
|
||||
|
||||
const downloadAttachment = useCallback((attachment: Attachment) => {
|
||||
post(
|
||||
EventTypes.download,
|
||||
EditorEvents.download,
|
||||
attachment,
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId
|
||||
@@ -431,23 +436,23 @@ export function useEditorController({
|
||||
}, []);
|
||||
const previewAttachment = useCallback((attachment: Attachment) => {
|
||||
post(
|
||||
EventTypes.previewAttachment,
|
||||
EditorEvents.previewAttachment,
|
||||
attachment,
|
||||
tabRef.current.id,
|
||||
tabRef.current.noteId
|
||||
);
|
||||
}, []);
|
||||
const openLink = useCallback((url: string) => {
|
||||
post(EventTypes.link, url, tabRef.current.id, tabRef.current.noteId);
|
||||
post(EditorEvents.link, url, tabRef.current.id, tabRef.current.noteId);
|
||||
return true;
|
||||
}, []);
|
||||
|
||||
const copyToClipboard = (text: string) => {
|
||||
post(EventTypes.copyToClipboard, text);
|
||||
post(EditorEvents.copyToClipboard, text);
|
||||
};
|
||||
|
||||
const getAttachmentData = (attachment: Partial<Attachment>) => {
|
||||
return postAsyncWithTimeout(EventTypes.getAttachmentData, {
|
||||
return postAsyncWithTimeout(EditorEvents.getAttachmentData, {
|
||||
attachment
|
||||
});
|
||||
};
|
||||
|
||||
@@ -29,6 +29,9 @@ globalThis.statusBars = {};
|
||||
export type TabItem = {
|
||||
id: number;
|
||||
noteId?: string;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
previewTab?: boolean;
|
||||
readonly?: boolean;
|
||||
locked?: boolean;
|
||||
@@ -66,6 +69,10 @@ export type TabStore = {
|
||||
setNoteState: (noteId: string, state: Partial<NoteState>) => void;
|
||||
biometryAvailable?: boolean;
|
||||
biometryEnrolled?: boolean;
|
||||
canGoBack?: boolean;
|
||||
canGoForward?: boolean;
|
||||
sessionId?: string;
|
||||
getNoteState: (noteId: string) => NoteState | undefined;
|
||||
};
|
||||
|
||||
function getId(id: number, tabs: TabItem[]): number {
|
||||
@@ -80,10 +87,21 @@ export const useTabStore = create(
|
||||
persist<TabStore>(
|
||||
(set, get) => ({
|
||||
noteState: {},
|
||||
getNoteState: (noteId: string) => {
|
||||
const sessionId = get().sessionId;
|
||||
const session = sessionId ? global.sessions.get(sessionId) : undefined;
|
||||
if (session?.noteId === noteId) {
|
||||
return {
|
||||
top: session.scrollTop,
|
||||
to: session.to,
|
||||
from: session.from
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
id: 0,
|
||||
previewTab: true
|
||||
id: 0
|
||||
}
|
||||
],
|
||||
currentTab: 0,
|
||||
@@ -91,6 +109,15 @@ export const useTabStore = create(
|
||||
setNoteState: (noteId: string, state: Partial<NoteState>) => {
|
||||
if (editorControllers[get().currentTab]?.loading) return;
|
||||
|
||||
const sessionId = get().sessionId;
|
||||
if (sessionId) {
|
||||
globalThis.sessions.updateSession(sessionId, {
|
||||
from: state.from,
|
||||
to: state.to,
|
||||
scrollTop: state.top
|
||||
});
|
||||
}
|
||||
|
||||
const noteState = {
|
||||
...get().noteState
|
||||
};
|
||||
@@ -127,21 +154,7 @@ export const useTabStore = create(
|
||||
scrollPosition
|
||||
});
|
||||
},
|
||||
focusPreviewTab: (noteId: string, options) => {
|
||||
const index = get().tabs.findIndex((t) => t.previewTab);
|
||||
if (index == -1) return get().newTab(noteId, true);
|
||||
const tabs = [...get().tabs];
|
||||
tabs[index] = {
|
||||
...tabs[index],
|
||||
noteId: noteId,
|
||||
previewTab: true,
|
||||
...options
|
||||
};
|
||||
|
||||
set({
|
||||
currentTab: tabs[index].id
|
||||
});
|
||||
},
|
||||
focusPreviewTab: (noteId: string, options) => {},
|
||||
focusEmptyTab: () => {
|
||||
const index = get().tabs.findIndex((t) => !t.noteId);
|
||||
if (index == -1) return get().newTab();
|
||||
@@ -159,8 +172,7 @@ export const useTabStore = create(
|
||||
...get().tabs,
|
||||
{
|
||||
id: id,
|
||||
noteId,
|
||||
previewTab: previewTab
|
||||
noteId
|
||||
}
|
||||
];
|
||||
set({
|
||||
|
||||
56
packages/editor-mobile/src/utils/editor-events.ts
Normal file
56
packages/editor-mobile/src/utils/editor-events.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
export const EditorEvents = {
|
||||
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",
|
||||
previewAttachment: "editor-event:preview-attachment",
|
||||
copyToClipboard: "editor-events:copy-to-clipboard",
|
||||
getAttachmentData: "editor-events:get-attachment-data",
|
||||
tabsChanged: "editor-events:tabs-changed",
|
||||
showTabs: "editor-events:show-tabs",
|
||||
tabFocused: "editor-events:tab-focused",
|
||||
toc: "editor-events:toc",
|
||||
createInternalLink: "editor-events:create-internal-link",
|
||||
load: "editor-events:load",
|
||||
unlock: "editor-events:unlock",
|
||||
unlockWithBiometrics: "editor-events:unlock-biometrics",
|
||||
disableReadonlyMode: "editor-events:disable-readonly-mode",
|
||||
readonlyEditorLoaded: "readonlyEditorLoaded",
|
||||
error: "editorError",
|
||||
dbLogger: "editor-events:dbLogger",
|
||||
goBack: "editor-events:go-back",
|
||||
goForward: "editor-events:go-forward"
|
||||
} as const;
|
||||
@@ -21,6 +21,8 @@ import { Editor, ToolbarGroupDefinition } from "@notesnook/editor";
|
||||
import { ThemeDefinition } from "@notesnook/theme";
|
||||
import { Dispatch, MutableRefObject, RefObject, SetStateAction } from "react";
|
||||
import { EditorController } from "../hooks/useEditorController";
|
||||
import { EditorSessions } from "@notesnook/common/dist/utils/editor-sessions";
|
||||
import { EditorEvents } from "./editor-events";
|
||||
|
||||
globalThis.sessionId = "notesnook-editor";
|
||||
globalThis.pendingResolvers = {};
|
||||
@@ -61,6 +63,7 @@ declare global {
|
||||
};
|
||||
|
||||
var readonlyEditor: boolean;
|
||||
var sessions: EditorSessions;
|
||||
var statusBars: Record<
|
||||
number,
|
||||
| React.MutableRefObject<{
|
||||
@@ -150,8 +153,8 @@ declare global {
|
||||
* @param value
|
||||
*/
|
||||
|
||||
function post<T extends keyof typeof EventTypes>(
|
||||
type: (typeof EventTypes)[T],
|
||||
function post<T extends keyof typeof EditorEvents>(
|
||||
type: (typeof EditorEvents)[T],
|
||||
value?: unknown,
|
||||
tabId?: number,
|
||||
noteId?: string,
|
||||
@@ -184,44 +187,6 @@ export function getOnMessageListener(callback: () => void) {
|
||||
};
|
||||
}
|
||||
|
||||
/* eslint-enable no-var */
|
||||
|
||||
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",
|
||||
previewAttachment: "editor-event:preview-attachment",
|
||||
copyToClipboard: "editor-events:copy-to-clipboard",
|
||||
getAttachmentData: "editor-events:get-attachment-data",
|
||||
tabsChanged: "editor-events:tabs-changed",
|
||||
showTabs: "editor-events:show-tabs",
|
||||
tabFocused: "editor-events:tab-focused",
|
||||
toc: "editor-events:toc",
|
||||
createInternalLink: "editor-events:create-internal-link",
|
||||
load: "editor-events:load",
|
||||
unlock: "editor-events:unlock",
|
||||
unlockWithBiometrics: "editor-events:unlock-biometrics",
|
||||
disableReadonlyMode: "editor-events:disable-readonly-mode",
|
||||
readonlyEditorLoaded: "readonlyEditorLoaded",
|
||||
error: "editorError",
|
||||
dbLogger: "editor-events:dbLogger"
|
||||
} as const;
|
||||
|
||||
export function randId(prefix: string) {
|
||||
return Math.random()
|
||||
.toString(36)
|
||||
@@ -244,7 +209,7 @@ export function logger(
|
||||
})
|
||||
.join(" ");
|
||||
|
||||
post(EventTypes.logger, `[${type}]: ` + logString);
|
||||
post(EditorEvents.logger, `[${type}]: ` + logString);
|
||||
}
|
||||
|
||||
export function dbLogger(type: "error" | "log", ...logs: unknown[]): void {
|
||||
@@ -254,7 +219,7 @@ export function dbLogger(type: "error" | "log", ...logs: unknown[]): void {
|
||||
})
|
||||
.join(" ");
|
||||
|
||||
post(EventTypes.dbLogger, {
|
||||
post(EditorEvents.dbLogger, {
|
||||
message: `[${type}]: ` + logString,
|
||||
error: logs[0] instanceof Error ? logs[0] : undefined
|
||||
});
|
||||
@@ -335,3 +300,10 @@ export function getTheme() {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const editorSessions = new EditorSessions({
|
||||
getGlobalNoteState: () => {
|
||||
return globalThis.tabStore.getState().noteState;
|
||||
}
|
||||
});
|
||||
globalThis.sessions = editorSessions;
|
||||
|
||||
32
packages/editor-mobile/src/utils/native-events.ts
Normal file
32
packages/editor-mobile/src/utils/native-events.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
export const NativeEvents = {
|
||||
html: "native:html",
|
||||
updatehtml: "native:updatehtml",
|
||||
title: "native:title",
|
||||
theme: "native:theme",
|
||||
titleplaceholder: "native:titleplaceholder",
|
||||
logger: "native:logger",
|
||||
status: "native:status",
|
||||
keyboardShown: "native:keyboardShown",
|
||||
attachmentData: "native:attachment-data",
|
||||
resolve: "native:resolve",
|
||||
session: "native:session"
|
||||
};
|
||||
@@ -16,7 +16,8 @@ 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 { EventTypes, postAsyncWithTimeout, randId } from ".";
|
||||
import { postAsyncWithTimeout, randId } from ".";
|
||||
import { EditorEvents } from "./editor-events";
|
||||
|
||||
class PendingSaveRequests {
|
||||
static TITLES = "pendingTitles";
|
||||
@@ -118,7 +119,7 @@ class PendingSaveRequests {
|
||||
this.remove(PendingSaveRequests.TITLES);
|
||||
for (const pending of pendingTitles) {
|
||||
if (pending.params[0]) pending.params[0].pendingChanges = true;
|
||||
await postAsyncWithTimeout(EventTypes.title, ...pending.params, 5000);
|
||||
await postAsyncWithTimeout(EditorEvents.title, ...pending.params, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -127,7 +128,11 @@ class PendingSaveRequests {
|
||||
this.remove(PendingSaveRequests.CONTENT);
|
||||
for (const pending of pendingContents) {
|
||||
if (pending.params[0]) pending.params[0].pendingChanges = true;
|
||||
await postAsyncWithTimeout(EventTypes.content, ...pending.params, 5000);
|
||||
await postAsyncWithTimeout(
|
||||
EditorEvents.content,
|
||||
...pending.params,
|
||||
5000
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user