mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-20 13:39:33 +01:00
mobile: fix all eslint warnings
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
|||||||
} from "../../utils/events";
|
} from "../../utils/events";
|
||||||
import BaseDialog from "../dialog/base-dialog";
|
import BaseDialog from "../dialog/base-dialog";
|
||||||
import { allowedOnPlatform, renderItem } from "./functions";
|
import { allowedOnPlatform, renderItem } from "./functions";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const AnnouncementDialog = () => {
|
export const AnnouncementDialog = () => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -45,20 +46,20 @@ export const AnnouncementDialog = () => {
|
|||||||
eUnSubscribeEvent(eOpenAnnouncementDialog, open);
|
eUnSubscribeEvent(eOpenAnnouncementDialog, open);
|
||||||
eUnSubscribeEvent(eCloseAnnouncementDialog, close);
|
eUnSubscribeEvent(eCloseAnnouncementDialog, close);
|
||||||
};
|
};
|
||||||
}, [visible]);
|
}, [close, visible]);
|
||||||
|
|
||||||
const open = (data) => {
|
const open = (data) => {
|
||||||
setInfo(data);
|
setInfo(data);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const close = () => {
|
const close = useCallback(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
remove(info.id);
|
remove(info.id);
|
||||||
setInfo(null);
|
setInfo(null);
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
};
|
}, [info.id, remove, visible]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import { Notice } from "../ui/notice";
|
|||||||
import { PressableButton } from "../ui/pressable";
|
import { PressableButton } from "../ui/pressable";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const Actions = ({ attachment, setAttachments, fwdRef }) => {
|
const Actions = ({ attachment, setAttachments, fwdRef }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -154,7 +155,7 @@ const Actions = ({ attachment, setAttachments, fwdRef }) => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const getNotes = () => {
|
const getNotes = useCallback(() => {
|
||||||
let allNotes = db.notes.all;
|
let allNotes = db.notes.all;
|
||||||
let attachmentNotes = attachment.noteIds?.map((id) => {
|
let attachmentNotes = attachment.noteIds?.map((id) => {
|
||||||
let index = allNotes?.findIndex((note) => id === note.id);
|
let index = allNotes?.findIndex((note) => id === note.id);
|
||||||
@@ -169,11 +170,11 @@ const Actions = ({ attachment, setAttachments, fwdRef }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return attachmentNotes;
|
return attachmentNotes;
|
||||||
};
|
}, [attachment.noteIds]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNotes(getNotes());
|
setNotes(getNotes());
|
||||||
}, [attachment]);
|
}, [attachment, getNotes]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ export const AttachmentItem = ({ attachment, encryption, setAttachments }) => {
|
|||||||
attachment,
|
attachment,
|
||||||
encryption
|
encryption
|
||||||
);
|
);
|
||||||
const encryptionProgress = encryption
|
const encryptionProgress = useAttachmentStore(
|
||||||
? useAttachmentStore((state) => state.encryptionProgress)
|
(state) => state.encryptionProgress
|
||||||
: null;
|
);
|
||||||
|
|
||||||
const onPress = () => {
|
const onPress = () => {
|
||||||
Actions.present(attachment, setAttachments, attachment.metadata.hash);
|
Actions.present(attachment, setAttachments, attachment.metadata.hash);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import { PressableButton } from "../ui/pressable";
|
|||||||
import Seperator from "../ui/seperator";
|
import Seperator from "../ui/seperator";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const TwoFactorVerification = ({ onMfaLogin, mfaInfo }) => {
|
const TwoFactorVerification = ({ onMfaLogin, mfaInfo }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -128,9 +129,9 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo }) => {
|
|||||||
if (currentMethod.method === "sms" || currentMethod.method === "email") {
|
if (currentMethod.method === "sms" || currentMethod.method === "email") {
|
||||||
onSendCode();
|
onSendCode();
|
||||||
}
|
}
|
||||||
}, [currentMethod.method]);
|
}, [currentMethod.method, onSendCode]);
|
||||||
|
|
||||||
const onSendCode = async () => {
|
const onSendCode = useCallback(async () => {
|
||||||
if (seconds || sending) return;
|
if (seconds || sending) return;
|
||||||
// TODO
|
// TODO
|
||||||
setSending(true);
|
setSending(true);
|
||||||
@@ -143,7 +144,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo }) => {
|
|||||||
setSending(false);
|
setSending(false);
|
||||||
ToastEvent.error(e, "Error sending 2FA Code", "local");
|
ToastEvent.error(e, "Error sending 2FA Code", "local");
|
||||||
}
|
}
|
||||||
};
|
}, [currentMethod.method, mfaInfo.token, seconds, sending, start]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import { useSettingStore } from "../../stores/use-setting-store";
|
|||||||
import { getElevation, showTooltip, TOOLTIP_POSITIONS } from "../../utils";
|
import { getElevation, showTooltip, TOOLTIP_POSITIONS } from "../../utils";
|
||||||
import { normalize, SIZE } from "../../utils/size";
|
import { normalize, SIZE } from "../../utils/size";
|
||||||
import { PressableButton } from "../ui/pressable";
|
import { PressableButton } from "../ui/pressable";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const FloatingButton = ({
|
export const FloatingButton = ({
|
||||||
title,
|
title,
|
||||||
@@ -58,26 +59,29 @@ export const FloatingButton = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
animate(selectionMode ? 150 : 0);
|
animate(selectionMode ? 150 : 0);
|
||||||
}, [selectionMode]);
|
}, [animate, selectionMode]);
|
||||||
|
|
||||||
function animate(toValue) {
|
const animate = useCallback(
|
||||||
translate.value = withTiming(toValue, {
|
(toValue) => {
|
||||||
duration: 250,
|
translate.value = withTiming(toValue, {
|
||||||
easing: Easing.elastic(1)
|
duration: 250,
|
||||||
});
|
easing: Easing.elastic(1)
|
||||||
}
|
});
|
||||||
|
},
|
||||||
|
[translate]
|
||||||
|
);
|
||||||
|
|
||||||
const onKeyboardHide = async () => {
|
const onKeyboardHide = useCallback(async () => {
|
||||||
editorState().keyboardState = false;
|
editorState().keyboardState = false;
|
||||||
if (deviceMode !== "mobile") return;
|
if (deviceMode !== "mobile") return;
|
||||||
animate(0);
|
animate(0);
|
||||||
};
|
}, [animate, deviceMode]);
|
||||||
|
|
||||||
const onKeyboardShow = async () => {
|
const onKeyboardShow = useCallback(async () => {
|
||||||
editorState().keyboardState = true;
|
editorState().keyboardState = true;
|
||||||
if (deviceMode !== "mobile") return;
|
if (deviceMode !== "mobile") return;
|
||||||
animate(150);
|
animate(150);
|
||||||
};
|
}, [animate, deviceMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let sub1 = Keyboard.addListener("keyboardDidShow", onKeyboardShow);
|
let sub1 = Keyboard.addListener("keyboardDidShow", onKeyboardShow);
|
||||||
@@ -86,7 +90,7 @@ export const FloatingButton = ({
|
|||||||
sub1?.remove();
|
sub1?.remove();
|
||||||
sub2?.remove();
|
sub2?.remove();
|
||||||
};
|
};
|
||||||
}, [deviceMode]);
|
}, [deviceMode, onKeyboardHide, onKeyboardShow]);
|
||||||
const paddings = {
|
const paddings = {
|
||||||
ios: 20,
|
ios: 20,
|
||||||
android: 20,
|
android: 20,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import Seperator from "../ui/seperator";
|
|||||||
import BaseDialog from "./base-dialog";
|
import BaseDialog from "./base-dialog";
|
||||||
import DialogButtons from "./dialog-buttons";
|
import DialogButtons from "./dialog-buttons";
|
||||||
import DialogHeader from "./dialog-header";
|
import DialogHeader from "./dialog-header";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const Dialog = ({ context = "global" }) => {
|
export const Dialog = ({ context = "global" }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -63,7 +64,7 @@ export const Dialog = ({ context = "global" }) => {
|
|||||||
eUnSubscribeEvent(eOpenSimpleDialog, show);
|
eUnSubscribeEvent(eOpenSimpleDialog, show);
|
||||||
eUnSubscribeEvent(eCloseSimpleDialog, hide);
|
eUnSubscribeEvent(eCloseSimpleDialog, hide);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [show]);
|
||||||
|
|
||||||
const onPressPositive = async () => {
|
const onPressPositive = async () => {
|
||||||
if (dialogInfo.positivePress) {
|
if (dialogInfo.positivePress) {
|
||||||
@@ -79,12 +80,15 @@ export const Dialog = ({ context = "global" }) => {
|
|||||||
hide();
|
hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
const show = (data) => {
|
const show = useCallback(
|
||||||
if (!data.context) data.context = "global";
|
(data) => {
|
||||||
if (data.context !== context) return;
|
if (!data.context) data.context = "global";
|
||||||
setDialogInfo(data);
|
if (data.context !== context) return;
|
||||||
setVisible(true);
|
setDialogInfo(data);
|
||||||
};
|
setVisible(true);
|
||||||
|
},
|
||||||
|
[context]
|
||||||
|
);
|
||||||
|
|
||||||
const hide = () => {
|
const hide = () => {
|
||||||
setInputValue(null);
|
setInputValue(null);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import { SIZE } from "../../../utils/size";
|
|||||||
import BaseDialog from "../../dialog/base-dialog";
|
import BaseDialog from "../../dialog/base-dialog";
|
||||||
import { PressableButton } from "../../ui/pressable";
|
import { PressableButton } from "../../ui/pressable";
|
||||||
import Paragraph from "../../ui/typography/paragraph";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const offsets = [];
|
const offsets = [];
|
||||||
let timeout = null;
|
let timeout = null;
|
||||||
@@ -66,7 +67,7 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
|
|||||||
eUnSubscribeEvent(eCloseJumpToDialog, close);
|
eUnSubscribeEvent(eCloseJumpToDialog, close);
|
||||||
eUnSubscribeEvent(eScrollEvent, onScroll);
|
eUnSubscribeEvent(eScrollEvent, onScroll);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [open]);
|
||||||
|
|
||||||
const onScroll = (data) => {
|
const onScroll = (data) => {
|
||||||
let y = data.y;
|
let y = data.y;
|
||||||
@@ -80,10 +81,13 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
|
|||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
const open = (_type) => {
|
const open = useCallback(
|
||||||
if (_type !== type) return;
|
(_type) => {
|
||||||
setVisible(true);
|
if (_type !== type) return;
|
||||||
};
|
setVisible(true);
|
||||||
|
},
|
||||||
|
[type]
|
||||||
|
);
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
@@ -91,9 +95,9 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadOffsets();
|
loadOffsets();
|
||||||
}, [notes]);
|
}, [loadOffsets, notes]);
|
||||||
|
|
||||||
const loadOffsets = () => {
|
const loadOffsets = useCallback(() => {
|
||||||
notes
|
notes
|
||||||
.filter((i) => i.type === "header")
|
.filter((i) => i.type === "header")
|
||||||
.map((item, index) => {
|
.map((item, index) => {
|
||||||
@@ -108,7 +112,7 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
|
|||||||
offset = offset + ind * 100 + msgOffset;
|
offset = offset + ind * 100 + msgOffset;
|
||||||
offsets.push(offset);
|
offsets.push(offset);
|
||||||
});
|
});
|
||||||
};
|
}, [notes]);
|
||||||
|
|
||||||
return !visible ? null : (
|
return !visible ? null : (
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { eScrollEvent } from "../../utils/events";
|
|||||||
import { LeftMenus } from "./left-menus";
|
import { LeftMenus } from "./left-menus";
|
||||||
import { RightMenus } from "./right-menus";
|
import { RightMenus } from "./right-menus";
|
||||||
import { Title } from "./title";
|
import { Title } from "./title";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const _Header = () => {
|
const _Header = () => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -41,22 +42,25 @@ const _Header = () => {
|
|||||||
(state) => state.currentScreen?.name
|
(state) => state.currentScreen?.name
|
||||||
);
|
);
|
||||||
|
|
||||||
const onScroll = (data) => {
|
const onScroll = useCallback(
|
||||||
if (data.y > 150) {
|
(data) => {
|
||||||
if (!hide) return;
|
if (data.y > 150) {
|
||||||
setHide(false);
|
if (!hide) return;
|
||||||
} else {
|
setHide(false);
|
||||||
if (hide) return;
|
} else {
|
||||||
setHide(true);
|
if (hide) return;
|
||||||
}
|
setHide(true);
|
||||||
};
|
}
|
||||||
|
},
|
||||||
|
[hide]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent(eScrollEvent, onScroll);
|
eSubscribeEvent(eScrollEvent, onScroll);
|
||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent(eScrollEvent, onScroll);
|
eUnSubscribeEvent(eScrollEvent, onScroll);
|
||||||
};
|
};
|
||||||
}, [hide]);
|
}, [hide, onScroll]);
|
||||||
|
|
||||||
return selectionMode ? null : (
|
return selectionMode ? null : (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { eScrollEvent } from "../../utils/events";
|
|||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const titleState = {};
|
const titleState = {};
|
||||||
|
|
||||||
@@ -46,7 +47,6 @@ export const Title = () => {
|
|||||||
: false
|
: false
|
||||||
);
|
);
|
||||||
const isHidden = titleState[currentScreen.id];
|
const isHidden = titleState[currentScreen.id];
|
||||||
console.log(currentScreen, "header");
|
|
||||||
const notebook =
|
const notebook =
|
||||||
isTopic && currentScreen.notebookId
|
isTopic && currentScreen.notebookId
|
||||||
? db.notebooks?.notebook(currentScreen.notebookId)?.data
|
? db.notebooks?.notebook(currentScreen.notebookId)?.data
|
||||||
@@ -54,19 +54,22 @@ export const Title = () => {
|
|||||||
const title = currentScreen.title;
|
const title = currentScreen.title;
|
||||||
const isTag = currentScreen?.name === "TaggedNotes";
|
const isTag = currentScreen?.name === "TaggedNotes";
|
||||||
|
|
||||||
const onScroll = (data) => {
|
const onScroll = useCallback(
|
||||||
if (currentScreen.name !== "Notebook") {
|
(data) => {
|
||||||
setHide(false);
|
if (currentScreen.name !== "Notebook") {
|
||||||
return;
|
setHide(false);
|
||||||
}
|
return;
|
||||||
if (data.y > 150) {
|
}
|
||||||
if (!hide) return;
|
if (data.y > 150) {
|
||||||
setHide(false);
|
if (!hide) return;
|
||||||
} else {
|
setHide(false);
|
||||||
if (hide) return;
|
} else {
|
||||||
setHide(true);
|
if (hide) return;
|
||||||
}
|
setHide(true);
|
||||||
};
|
}
|
||||||
|
},
|
||||||
|
[currentScreen.name, hide]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentScreen.name === "Notebook") {
|
if (currentScreen.name === "Notebook") {
|
||||||
@@ -78,18 +81,18 @@ export const Title = () => {
|
|||||||
} else {
|
} else {
|
||||||
setHide(titleState[currentScreen.id]);
|
setHide(titleState[currentScreen.id]);
|
||||||
}
|
}
|
||||||
}, [currentScreen.id]);
|
}, [currentScreen.id, currentScreen.name]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
titleState[currentScreen.id] = hide;
|
titleState[currentScreen.id] = hide;
|
||||||
}, [hide]);
|
}, [currentScreen.id, hide]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent(eScrollEvent, onScroll);
|
eSubscribeEvent(eScrollEvent, onScroll);
|
||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent(eScrollEvent, onScroll);
|
eUnSubscribeEvent(eScrollEvent, onScroll);
|
||||||
};
|
};
|
||||||
}, [hide]);
|
}, [hide, onScroll]);
|
||||||
|
|
||||||
function navigateToNotebook() {
|
function navigateToNotebook() {
|
||||||
if (!isTopic) return;
|
if (!isTopic) return;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import Heading from "../ui/typography/heading";
|
|||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
import { Walkthrough } from "../walkthroughs";
|
import { Walkthrough } from "../walkthroughs";
|
||||||
import { useAppState } from "../../hooks/use-app-state";
|
import { useAppState } from "../../hooks/use-app-state";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const Launcher = React.memo(
|
const Launcher = React.memo(
|
||||||
function Launcher() {
|
function Launcher() {
|
||||||
@@ -75,7 +76,7 @@ const Launcher = React.memo(
|
|||||||
(state) => state.settings.introCompleted
|
(state) => state.settings.introCompleted
|
||||||
);
|
);
|
||||||
const dbInitCompleted = useRef(false);
|
const dbInitCompleted = useRef(false);
|
||||||
const loadNotes = async () => {
|
const loadNotes = useCallback(async () => {
|
||||||
if (verifyUser) {
|
if (verifyUser) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -94,9 +95,9 @@ const Launcher = React.memo(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}, [doAppLoadActions, setLoading, verifyUser]);
|
||||||
|
|
||||||
const init = async () => {
|
const init = useCallback(async () => {
|
||||||
if (!dbInitCompleted.current) {
|
if (!dbInitCompleted.current) {
|
||||||
await RNBootSplash.hide({ fade: true });
|
await RNBootSplash.hide({ fade: true });
|
||||||
await loadDatabase();
|
await loadDatabase();
|
||||||
@@ -121,7 +122,7 @@ const Launcher = React.memo(
|
|||||||
} else {
|
} else {
|
||||||
useUserStore.getState().setUser(await db.user?.getUser());
|
useUserStore.getState().setUser(await db.user?.getUser());
|
||||||
}
|
}
|
||||||
};
|
}, [loadNotes, verifyUser]);
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// hideSplashScreen();
|
// hideSplashScreen();
|
||||||
@@ -134,9 +135,9 @@ const Launcher = React.memo(
|
|||||||
return () => {
|
return () => {
|
||||||
dbInitCompleted.current = false;
|
dbInitCompleted.current = false;
|
||||||
};
|
};
|
||||||
}, [loading]);
|
}, [doAppLoadActions, loading]);
|
||||||
|
|
||||||
const doAppLoadActions = async () => {
|
const doAppLoadActions = useCallback(async () => {
|
||||||
await sleep(500);
|
await sleep(500);
|
||||||
if (SettingsService.get().sessionExpired) {
|
if (SettingsService.get().sessionExpired) {
|
||||||
eSendEvent("session_expired");
|
eSendEvent("session_expired");
|
||||||
@@ -170,7 +171,7 @@ const Launcher = React.memo(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}, [introCompleted]);
|
||||||
|
|
||||||
const checkAppUpdateAvailable = async () => {
|
const checkAppUpdateAvailable = async () => {
|
||||||
if (__DEV__) return;
|
if (__DEV__) return;
|
||||||
@@ -237,7 +238,7 @@ const Launcher = React.memo(
|
|||||||
// return false;
|
// return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUnlockBiometrics = async () => {
|
const onUnlockBiometrics = useCallback(async () => {
|
||||||
if (!(await BiometricService.isBiometryAvailable())) {
|
if (!(await BiometricService.isBiometryAvailable())) {
|
||||||
ToastEvent.show({
|
ToastEvent.show({
|
||||||
heading: "Biometrics unavailable",
|
heading: "Biometrics unavailable",
|
||||||
@@ -254,17 +255,17 @@ const Launcher = React.memo(
|
|||||||
enabled(false);
|
enabled(false);
|
||||||
password.current = null;
|
password.current = null;
|
||||||
}
|
}
|
||||||
};
|
}, [setVerifyUser]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
init();
|
init();
|
||||||
}, [verifyUser]);
|
}, [init, verifyUser]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (verifyUser && appState === "active") {
|
if (verifyUser && appState === "active") {
|
||||||
onUnlockBiometrics();
|
onUnlockBiometrics();
|
||||||
}
|
}
|
||||||
}, [appState]);
|
}, [appState, onUnlockBiometrics, verifyUser]);
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
if (!password.current) return;
|
if (!password.current) return;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import { IconButton } from "../../ui/icon-button";
|
|||||||
import { Button } from "../../ui/button";
|
import { Button } from "../../ui/button";
|
||||||
import Sort from "../../sheets/sort";
|
import Sort from "../../sheets/sort";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const SectionHeader = React.memo(
|
export const SectionHeader = React.memo(
|
||||||
function SectionHeader({ item, index, type, color, screen }) {
|
function SectionHeader({ item, index, type, color, screen }) {
|
||||||
@@ -63,16 +64,16 @@ export const SectionHeader = React.memo(
|
|||||||
? "Default"
|
? "Default"
|
||||||
: groupBy.slice(0, 1).toUpperCase() + groupBy.slice(1, groupBy.length);
|
: groupBy.slice(0, 1).toUpperCase() + groupBy.slice(1, groupBy.length);
|
||||||
|
|
||||||
const onUpdate = () => {
|
const onUpdate = useCallback(() => {
|
||||||
setGroupOptions({ ...db.settings?.getGroupOptions(type) });
|
setGroupOptions({ ...db.settings?.getGroupOptions(type) });
|
||||||
};
|
}, [type]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent("groupOptionsUpdate", onUpdate);
|
eSubscribeEvent("groupOptionsUpdate", onUpdate);
|
||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent("groupOptionsUpdate", onUpdate);
|
eUnSubscribeEvent("groupOptionsUpdate", onUpdate);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [onUpdate]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const ActionStrip = ({ note, setActionStrip }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (note.type === "note") return;
|
if (note.type === "note") return;
|
||||||
setIsPinnedToMenu(db.settings.isPinned(note.id));
|
setIsPinnedToMenu(db.settings.isPinned(note.id));
|
||||||
}, []);
|
}, [note.id, note.type]);
|
||||||
|
|
||||||
const updateNotes = () => {
|
const updateNotes = () => {
|
||||||
Navigation.queueRoutesForUpdate(
|
Navigation.queueRoutesForUpdate(
|
||||||
|
|||||||
@@ -50,7 +50,14 @@ export const SelectionIcon = ({ setActionStrip, item, compactMode }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedItemsList, item.id]);
|
}, [
|
||||||
|
selectedItemsList,
|
||||||
|
item.id,
|
||||||
|
selectionMode,
|
||||||
|
setActionStrip,
|
||||||
|
item.dateCreated,
|
||||||
|
selected
|
||||||
|
]);
|
||||||
|
|
||||||
const onPress = () => {
|
const onPress = () => {
|
||||||
setSelectedItem(item);
|
setSelectedItem(item);
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ const List = ({
|
|||||||
screen={screen}
|
screen={screen}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[]
|
[headerProps.color, headerProps.heading, screen, type]
|
||||||
);
|
);
|
||||||
|
|
||||||
const _onRefresh = async () => {
|
const _onRefresh = async () => {
|
||||||
|
|||||||
@@ -43,11 +43,10 @@ export default function NoteHistory({ note, fwdRef }) {
|
|||||||
setHistory([...(await db.noteHistory.get(note.id))]);
|
setHistory([...(await db.noteHistory.get(note.id))]);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, [note.id]);
|
||||||
|
|
||||||
async function preview(item) {
|
const preview = useCallback(async (item) => {
|
||||||
let content = await db.noteHistory.content(item.id);
|
let content = await db.noteHistory.content(item.id);
|
||||||
|
|
||||||
presentSheet({
|
presentSheet({
|
||||||
component: (
|
component: (
|
||||||
<NotePreview
|
<NotePreview
|
||||||
@@ -60,7 +59,7 @@ export default function NoteHistory({ note, fwdRef }) {
|
|||||||
),
|
),
|
||||||
context: "note_history"
|
context: "note_history"
|
||||||
});
|
});
|
||||||
}
|
}, []);
|
||||||
|
|
||||||
const getDate = (start, end) => {
|
const getDate = (start, end) => {
|
||||||
let _start = timeConverter(start);
|
let _start = timeConverter(start);
|
||||||
@@ -94,7 +93,7 @@ export default function NoteHistory({ note, fwdRef }) {
|
|||||||
</Paragraph>
|
</Paragraph>
|
||||||
</PressableButton>
|
</PressableButton>
|
||||||
),
|
),
|
||||||
[]
|
[colors.icon, preview]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -38,31 +38,35 @@ import { sleep } from "../../utils/time";
|
|||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const PremiumToast = ({ context = "global", offset = 0 }) => {
|
export const PremiumToast = ({ context = "global", offset = 0 }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
const [msg, setMsg] = useState(null);
|
const [msg, setMsg] = useState(null);
|
||||||
const timer = useRef();
|
const timer = useRef();
|
||||||
|
|
||||||
const open = (event) => {
|
const open = useCallback(
|
||||||
if (!event) {
|
(event) => {
|
||||||
clearTimeout(timer);
|
if (!event) {
|
||||||
timer.current = null;
|
clearTimeout(timer);
|
||||||
setMsg(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.context === context && msg?.desc !== event.desc) {
|
|
||||||
if (timer.current !== null) {
|
|
||||||
clearTimeout(timer.current);
|
|
||||||
timer.current = null;
|
timer.current = null;
|
||||||
}
|
|
||||||
setMsg(event);
|
|
||||||
timer.current = setTimeout(async () => {
|
|
||||||
setMsg(null);
|
setMsg(null);
|
||||||
}, 3000);
|
return;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
if (event.context === context && msg?.desc !== event.desc) {
|
||||||
|
if (timer.current !== null) {
|
||||||
|
clearTimeout(timer.current);
|
||||||
|
timer.current = null;
|
||||||
|
}
|
||||||
|
setMsg(event);
|
||||||
|
timer.current = setTimeout(async () => {
|
||||||
|
setMsg(null);
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[context, msg?.desc]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent(eShowGetPremium, open);
|
eSubscribeEvent(eShowGetPremium, open);
|
||||||
@@ -70,7 +74,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
|
|||||||
clearTimeout(timer.current);
|
clearTimeout(timer.current);
|
||||||
eUnSubscribeEvent(eShowGetPremium, open);
|
eUnSubscribeEvent(eShowGetPremium, open);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [open]);
|
||||||
|
|
||||||
const onPress = async () => {
|
const onPress = async () => {
|
||||||
open(null);
|
open(null);
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import Heading from "../ui/typography/heading";
|
|||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
import { Walkthrough } from "../walkthroughs";
|
import { Walkthrough } from "../walkthroughs";
|
||||||
import { PricingItem } from "./pricing-item";
|
import { PricingItem } from "./pricing-item";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const promoCyclesMonthly = {
|
const promoCyclesMonthly = {
|
||||||
1: "first month",
|
1: "first month",
|
||||||
@@ -77,7 +78,7 @@ export const PricingPlans = ({
|
|||||||
const yearlyPlan = usePricing("yearly");
|
const yearlyPlan = usePricing("yearly");
|
||||||
const monthlyPlan = usePricing("monthly");
|
const monthlyPlan = usePricing("monthly");
|
||||||
|
|
||||||
const getSkus = async () => {
|
const getSkus = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (promo?.promoCode) {
|
if (promo?.promoCode) {
|
||||||
@@ -88,7 +89,7 @@ export const PricingPlans = ({
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
console.log("error getting sku", e);
|
console.log("error getting sku", e);
|
||||||
}
|
}
|
||||||
};
|
}, [promo?.promoCode]);
|
||||||
|
|
||||||
const getPromo = async (code) => {
|
const getPromo = async (code) => {
|
||||||
try {
|
try {
|
||||||
@@ -129,7 +130,7 @@ export const PricingPlans = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getSkus();
|
getSkus();
|
||||||
}, []);
|
}, [getSkus]);
|
||||||
|
|
||||||
const buySubscription = async (product) => {
|
const buySubscription = async (product) => {
|
||||||
if (buying) return;
|
if (buying) return;
|
||||||
|
|||||||
@@ -16,24 +16,23 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useEffect } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
import { BackHandler, Platform, View } from "react-native";
|
import { BackHandler, Platform, View } from "react-native";
|
||||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
import { useThemeStore } from "../../stores/use-theme-store";
|
import { db } from "../../common/database";
|
||||||
import { useSelectionStore } from "../../stores/use-selection-store";
|
|
||||||
import { eSendEvent, ToastEvent } from "../../services/event-manager";
|
import { eSendEvent, ToastEvent } from "../../services/event-manager";
|
||||||
import Navigation from "../../services/navigation";
|
import Navigation from "../../services/navigation";
|
||||||
import { db } from "../../common/database";
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
|
import { useSelectionStore } from "../../stores/use-selection-store";
|
||||||
|
import { useThemeStore } from "../../stores/use-theme-store";
|
||||||
import { eOpenMoveNoteDialog } from "../../utils/events";
|
import { eOpenMoveNoteDialog } from "../../utils/events";
|
||||||
import { deleteItems } from "../../utils/functions";
|
import { deleteItems } from "../../utils/functions";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { tabBarRef } from "../../utils/global-refs";
|
||||||
import layoutmanager from "../../utils/layout-manager";
|
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
import { sleep } from "../../utils/time";
|
import { sleep } from "../../utils/time";
|
||||||
import { presentDialog } from "../dialog/functions";
|
import { presentDialog } from "../dialog/functions";
|
||||||
import { IconButton } from "../ui/icon-button";
|
import { IconButton } from "../ui/icon-button";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
|
||||||
|
|
||||||
export const SelectionHeader = React.memo(() => {
|
export const SelectionHeader = React.memo(() => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -131,11 +130,10 @@ export const SelectionHeader = React.memo(() => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onBackPress = () => {
|
const onBackPress = useCallback(() => {
|
||||||
layoutmanager.withSpringAnimation(500);
|
|
||||||
clearSelection();
|
clearSelection();
|
||||||
return true;
|
return true;
|
||||||
};
|
}, [clearSelection]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectionMode) {
|
if (selectionMode) {
|
||||||
@@ -143,7 +141,7 @@ export const SelectionHeader = React.memo(() => {
|
|||||||
} else {
|
} else {
|
||||||
BackHandler.removeEventListener("hardwareBackPress", onBackPress);
|
BackHandler.removeEventListener("hardwareBackPress", onBackPress);
|
||||||
}
|
}
|
||||||
}, [selectionMode]);
|
}, [onBackPress, selectionMode]);
|
||||||
|
|
||||||
return !selectionMode ? null : (
|
return !selectionMode ? null : (
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import { Button } from "../ui/button";
|
|||||||
import SheetWrapper from "../ui/sheet";
|
import SheetWrapper from "../ui/sheet";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
const SheetProvider = ({ context = "global" }) => {
|
const SheetProvider = ({ context = "global" }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
@@ -48,26 +49,29 @@ const SheetProvider = ({ context = "global" }) => {
|
|||||||
eUnSubscribeEvent(eOpenProgressDialog, open);
|
eUnSubscribeEvent(eOpenProgressDialog, open);
|
||||||
eUnSubscribeEvent(eCloseProgressDialog, close);
|
eUnSubscribeEvent(eCloseProgressDialog, close);
|
||||||
};
|
};
|
||||||
}, [visible]);
|
}, [close, open, visible]);
|
||||||
|
|
||||||
const open = async (data) => {
|
const open = useCallback(
|
||||||
if (!data.context) data.context = "global";
|
async (data) => {
|
||||||
if (data.context !== context) return;
|
if (!data.context) data.context = "global";
|
||||||
if (visible || dialogData) {
|
if (data.context !== context) return;
|
||||||
setDialogData(null);
|
if (visible || dialogData) {
|
||||||
setVisible(false);
|
setDialogData(null);
|
||||||
await sleep(500);
|
setVisible(false);
|
||||||
}
|
await sleep(500);
|
||||||
setDialogData(data);
|
|
||||||
setVisible(true);
|
|
||||||
if (data.editor) {
|
|
||||||
editor.current.refocus = false;
|
|
||||||
if (editorState().keyboardState) {
|
|
||||||
// tiny.call(EditorWebView, tiny.cacheRange + tiny.blur);
|
|
||||||
editor.current.refocus = true;
|
|
||||||
}
|
}
|
||||||
}
|
setDialogData(data);
|
||||||
};
|
setVisible(true);
|
||||||
|
if (data.editor) {
|
||||||
|
editor.current.refocus = false;
|
||||||
|
if (editorState().keyboardState) {
|
||||||
|
// tiny.call(EditorWebView, tiny.cacheRange + tiny.blur);
|
||||||
|
editor.current.refocus = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[context, dialogData, visible]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -85,11 +89,14 @@ const SheetProvider = ({ context = "global" }) => {
|
|||||||
})();
|
})();
|
||||||
}, [visible, dialogData]);
|
}, [visible, dialogData]);
|
||||||
|
|
||||||
const close = (ctx) => {
|
const close = useCallback(
|
||||||
if (!ctx) ctx = "global";
|
(ctx) => {
|
||||||
if (ctx !== context) return;
|
if (!ctx) ctx = "global";
|
||||||
actionSheetRef.current?.setModalVisible(false);
|
if (ctx !== context) return;
|
||||||
};
|
actionSheetRef.current?.setModalVisible(false);
|
||||||
|
},
|
||||||
|
[context]
|
||||||
|
);
|
||||||
|
|
||||||
return !visible || !dialogData ? null : (
|
return !visible || !dialogData ? null : (
|
||||||
<SheetWrapper
|
<SheetWrapper
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import { PressableButton } from "../../ui/pressable";
|
|||||||
import SheetWrapper from "../../ui/sheet";
|
import SheetWrapper from "../../ui/sheet";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
import Paragraph from "../../ui/typography/paragraph";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
let newNotebookTitle = null;
|
let newNotebookTitle = null;
|
||||||
const notebookInput = createRef();
|
const notebookInput = createRef();
|
||||||
const actionSheetRef = createRef();
|
const actionSheetRef = createRef();
|
||||||
@@ -178,9 +179,9 @@ const MoveNoteComponent = ({ note }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateNoteExists();
|
updateNoteExists();
|
||||||
}, []);
|
}, [updateNoteExists]);
|
||||||
|
|
||||||
const updateNoteExists = () => {
|
const updateNoteExists = useCallback(() => {
|
||||||
if (!note?.id && selectedItemsList?.length === 0) return;
|
if (!note?.id && selectedItemsList?.length === 0) return;
|
||||||
|
|
||||||
let notes =
|
let notes =
|
||||||
@@ -208,7 +209,7 @@ const MoveNoteComponent = ({ note }) => {
|
|||||||
}
|
}
|
||||||
console.log("ids: ", ids);
|
console.log("ids: ", ids);
|
||||||
setNoteExists(ids);
|
setNoteExists(ids);
|
||||||
};
|
}, [note?.id, selectedItemsList]);
|
||||||
|
|
||||||
const openAddTopicDialog = (item) => {
|
const openAddTopicDialog = (item) => {
|
||||||
presentDialog({
|
presentDialog({
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import { PressableButton } from "../../ui/pressable";
|
|||||||
import SheetWrapper from "../../ui/sheet";
|
import SheetWrapper from "../../ui/sheet";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
import Paragraph from "../../ui/typography/paragraph";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
const ManageTagsSheet = () => {
|
const ManageTagsSheet = () => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
@@ -53,16 +54,16 @@ const ManageTagsSheet = () => {
|
|||||||
eUnSubscribeEvent(eOpenTagsDialog, open);
|
eUnSubscribeEvent(eOpenTagsDialog, open);
|
||||||
eUnSubscribeEvent(eCloseTagsDialog, close);
|
eUnSubscribeEvent(eCloseTagsDialog, close);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [open]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
console.log("sorting tags");
|
console.log("sorting tags");
|
||||||
sortTags();
|
sortTags();
|
||||||
}
|
}
|
||||||
}, [allTags, note, query, visible]);
|
}, [allTags, note, query, sortTags, visible]);
|
||||||
|
|
||||||
const sortTags = () => {
|
const sortTags = useCallback(() => {
|
||||||
let _tags = [...allTags];
|
let _tags = [...allTags];
|
||||||
_tags = _tags.filter((t) => t.type === "tag");
|
_tags = _tags.filter((t) => t.type === "tag");
|
||||||
_tags = _tags.sort((a, b) => a.title.localeCompare(b.title));
|
_tags = _tags.sort((a, b) => a.title.localeCompare(b.title));
|
||||||
@@ -85,14 +86,17 @@ const ManageTagsSheet = () => {
|
|||||||
noteTags = noteTags.sort((a, b) => a.title.localeCompare(b.title));
|
noteTags = noteTags.sort((a, b) => a.title.localeCompare(b.title));
|
||||||
let combinedTags = [...noteTags, ..._tags];
|
let combinedTags = [...noteTags, ..._tags];
|
||||||
setTags(combinedTags);
|
setTags(combinedTags);
|
||||||
};
|
}, [allTags, note, query]);
|
||||||
|
|
||||||
const open = (item) => {
|
const open = useCallback(
|
||||||
setNote(item);
|
(item) => {
|
||||||
useTagStore.getState().setTags();
|
setNote(item);
|
||||||
sortTags();
|
useTagStore.getState().setTags();
|
||||||
setVisible(true);
|
sortTags();
|
||||||
};
|
setVisible(true);
|
||||||
|
},
|
||||||
|
[sortTags]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { createRef, useEffect, useState } from "react";
|
import React, { createRef, useCallback, useEffect, useState } from "react";
|
||||||
import { ActivityIndicator, Platform, View } from "react-native";
|
import { ActivityIndicator, Platform, View } from "react-native";
|
||||||
import DocumentPicker from "react-native-document-picker";
|
import DocumentPicker from "react-native-document-picker";
|
||||||
import { FlatList } from "react-native-gesture-handler";
|
import { FlatList } from "react-native-gesture-handler";
|
||||||
@@ -54,7 +54,7 @@ const RestoreDataSheet = () => {
|
|||||||
eUnSubscribeEvent(eOpenRestoreDialog, open);
|
eUnSubscribeEvent(eOpenRestoreDialog, open);
|
||||||
eUnSubscribeEvent(eCloseRestoreDialog, close);
|
eUnSubscribeEvent(eCloseRestoreDialog, close);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [close]);
|
||||||
|
|
||||||
const open = async () => {
|
const open = async () => {
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
@@ -62,7 +62,7 @@ const RestoreDataSheet = () => {
|
|||||||
actionSheetRef.current?.setModalVisible(true);
|
actionSheetRef.current?.setModalVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const close = () => {
|
const close = useCallback(() => {
|
||||||
if (restoring) {
|
if (restoring) {
|
||||||
showIsWorking();
|
showIsWorking();
|
||||||
return;
|
return;
|
||||||
@@ -71,7 +71,7 @@ const RestoreDataSheet = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
}, [restoring]);
|
||||||
|
|
||||||
const showIsWorking = () => {
|
const showIsWorking = () => {
|
||||||
ToastEvent.show({
|
ToastEvent.show({
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export const Update = ({ version: appVersion, fwdRef }) => {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}, []);
|
}, [version]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { PressableButton } from "../ui/pressable";
|
|||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
import { ColoredNotes } from "../../screens/notes/colored";
|
import { ColoredNotes } from "../../screens/notes/colored";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const ColorSection = React.memo(
|
export const ColorSection = React.memo(
|
||||||
function ColorSection() {
|
function ColorSection() {
|
||||||
@@ -42,7 +43,7 @@ export const ColorSection = React.memo(
|
|||||||
if (!loading) {
|
if (!loading) {
|
||||||
setColorNotes();
|
setColorNotes();
|
||||||
}
|
}
|
||||||
}, [loading]);
|
}, [loading, setColorNotes]);
|
||||||
|
|
||||||
return colorNotes.map((item, index) => {
|
return colorNotes.map((item, index) => {
|
||||||
let alias = db.colors.alias(item.id);
|
let alias = db.colors.alias(item.id);
|
||||||
@@ -61,25 +62,28 @@ const ColorItem = React.memo(
|
|||||||
const [headerTextState, setHeaderTextState] = useState(null);
|
const [headerTextState, setHeaderTextState] = useState(null);
|
||||||
alias = db.colors.alias(item.id) || "";
|
alias = db.colors.alias(item.id) || "";
|
||||||
|
|
||||||
const onHeaderStateChange = (state) => {
|
const onHeaderStateChange = useCallback(
|
||||||
setTimeout(() => {
|
(state) => {
|
||||||
let id = state.currentScreen?.id;
|
setTimeout(() => {
|
||||||
if (id === item.id) {
|
let id = state.currentScreen?.id;
|
||||||
setHeaderTextState({ id: state.currentScreen.id });
|
if (id === item.id) {
|
||||||
} else {
|
setHeaderTextState({ id: state.currentScreen.id });
|
||||||
if (headerTextState !== null) {
|
} else {
|
||||||
setHeaderTextState(null);
|
if (headerTextState !== null) {
|
||||||
|
setHeaderTextState(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}, 300);
|
||||||
}, 300);
|
},
|
||||||
};
|
[headerTextState, item.id]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
|
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
|
||||||
return () => {
|
return () => {
|
||||||
unsub();
|
unsub();
|
||||||
};
|
};
|
||||||
}, [headerTextState]);
|
}, [headerTextState, onHeaderStateChange]);
|
||||||
|
|
||||||
const onPress = (item) => {
|
const onPress = (item) => {
|
||||||
ColoredNotes.navigate(item, false);
|
ColoredNotes.navigate(item, false);
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export const SideMenu = React.memo(
|
|||||||
<TagsSection />
|
<TagsSection />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
[]
|
[noTextMode]
|
||||||
);
|
);
|
||||||
|
|
||||||
return !loading && introCompleted ? (
|
return !loading && introCompleted ? (
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { Button } from "../ui/button";
|
|||||||
import { PressableButton } from "../ui/pressable";
|
import { PressableButton } from "../ui/pressable";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const MenuItem = React.memo(
|
export const MenuItem = React.memo(
|
||||||
function MenuItem({ item, index, testID, rightBtn }) {
|
function MenuItem({ item, index, testID, rightBtn }) {
|
||||||
@@ -51,25 +52,28 @@ export const MenuItem = React.memo(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onHeaderStateChange = (state) => {
|
const onHeaderStateChange = useCallback(
|
||||||
setTimeout(() => {
|
(state) => {
|
||||||
let id = state.currentScreen?.id;
|
setTimeout(() => {
|
||||||
if (id === screenId) {
|
let id = state.currentScreen?.id;
|
||||||
setHeaderTextState({ id: state.currentScreen.id });
|
if (id === screenId) {
|
||||||
} else {
|
setHeaderTextState({ id: state.currentScreen.id });
|
||||||
if (headerTextState !== null) {
|
} else {
|
||||||
setHeaderTextState(null);
|
if (headerTextState !== null) {
|
||||||
|
setHeaderTextState(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}, 300);
|
||||||
}, 300);
|
},
|
||||||
};
|
[headerTextState, screenId]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
|
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
|
||||||
return () => {
|
return () => {
|
||||||
unsub();
|
unsub();
|
||||||
};
|
};
|
||||||
}, [headerTextState]);
|
}, [headerTextState, onHeaderStateChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PressableButton
|
<PressableButton
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import Seperator from "../ui/seperator";
|
|||||||
import SheetWrapper from "../ui/sheet";
|
import SheetWrapper from "../ui/sheet";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const TagsSection = React.memo(
|
export const TagsSection = React.memo(
|
||||||
function TagsSection() {
|
function TagsSection() {
|
||||||
@@ -48,7 +49,7 @@ export const TagsSection = React.memo(
|
|||||||
if (!loading) {
|
if (!loading) {
|
||||||
setMenuPins();
|
setMenuPins();
|
||||||
}
|
}
|
||||||
}, [loading]);
|
}, [loading, setMenuPins]);
|
||||||
|
|
||||||
const onPress = (item) => {
|
const onPress = (item) => {
|
||||||
if (item.type === "notebook") {
|
if (item.type === "notebook") {
|
||||||
@@ -109,27 +110,30 @@ export const PinItem = React.memo(
|
|||||||
const color = headerTextState?.id === item.id ? colors.accent : colors.pri;
|
const color = headerTextState?.id === item.id ? colors.accent : colors.pri;
|
||||||
const fwdRef = useRef();
|
const fwdRef = useRef();
|
||||||
|
|
||||||
const onHeaderStateChange = (state) => {
|
const onHeaderStateChange = useCallback(
|
||||||
setTimeout(() => {
|
(state) => {
|
||||||
let id = state.currentScreen?.id;
|
setTimeout(() => {
|
||||||
if (id === item.id) {
|
let id = state.currentScreen?.id;
|
||||||
setHeaderTextState({
|
if (id === item.id) {
|
||||||
id: state.currentScreen.id
|
setHeaderTextState({
|
||||||
});
|
id: state.currentScreen.id
|
||||||
} else {
|
});
|
||||||
if (headerTextState !== null) {
|
} else {
|
||||||
setHeaderTextState(null);
|
if (headerTextState !== null) {
|
||||||
|
setHeaderTextState(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}, 300);
|
||||||
}, 300);
|
},
|
||||||
};
|
[headerTextState, item.id]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
|
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
|
||||||
return () => {
|
return () => {
|
||||||
unsub();
|
unsub();
|
||||||
};
|
};
|
||||||
}, [headerTextState]);
|
}, [headerTextState, onHeaderStateChange]);
|
||||||
|
|
||||||
const icons = {
|
const icons = {
|
||||||
topic: "bookmark",
|
topic: "bookmark",
|
||||||
|
|||||||
@@ -126,7 +126,16 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
|||||||
return () => {
|
return () => {
|
||||||
sub && sub.remove();
|
sub && sub.remove();
|
||||||
};
|
};
|
||||||
}, [introCompleted, deviceMode, widths]);
|
}, [
|
||||||
|
introCompleted,
|
||||||
|
deviceMode,
|
||||||
|
widths,
|
||||||
|
fullscreen,
|
||||||
|
translateX,
|
||||||
|
isDrawerOpen,
|
||||||
|
homePosition,
|
||||||
|
onDrawerStateChange
|
||||||
|
]);
|
||||||
|
|
||||||
useImperativeHandle(
|
useImperativeHandle(
|
||||||
ref,
|
ref,
|
||||||
@@ -193,7 +202,16 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
|||||||
setScrollEnabled: () => true,
|
setScrollEnabled: () => true,
|
||||||
node: node
|
node: node
|
||||||
}),
|
}),
|
||||||
[deviceMode, homePosition, editorPosition]
|
[
|
||||||
|
currentTab,
|
||||||
|
deviceMode,
|
||||||
|
translateX,
|
||||||
|
onDrawerStateChange,
|
||||||
|
homePosition,
|
||||||
|
editorPosition,
|
||||||
|
forcedLock,
|
||||||
|
isDrawerOpen
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
useAnimatedReaction(
|
useAnimatedReaction(
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import { SIZE } from "../../utils/size";
|
|||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import Heading from "../ui/typography/heading";
|
import Heading from "../ui/typography/heading";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { useCallback } from "react";
|
||||||
let toastMessages = [];
|
let toastMessages = [];
|
||||||
export const Toast = ({ context = "global" }) => {
|
export const Toast = ({ context = "global" }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -43,42 +44,46 @@ export const Toast = ({ context = "global" }) => {
|
|||||||
const hideTimeout = useRef();
|
const hideTimeout = useRef();
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
const showToastFunc = async (data) => {
|
const showToastFunc = useCallback(
|
||||||
console.log("toast show", data.message, toastMessages.length);
|
async (data) => {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
if (data.context !== context) return;
|
if (data.context !== context) return;
|
||||||
if (toastMessages.findIndex((m) => m.message === data.message) >= 0) {
|
if (toastMessages.findIndex((m) => m.message === data.message) >= 0) {
|
||||||
console.log("returning from here");
|
return;
|
||||||
return;
|
}
|
||||||
}
|
toastMessages.push(data);
|
||||||
toastMessages.push(data);
|
if (toastMessages?.length > 1) return;
|
||||||
if (toastMessages?.length > 1) return;
|
setData(data);
|
||||||
setData(data);
|
|
||||||
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
if (hideTimeout.current) {
|
if (hideTimeout.current) {
|
||||||
clearTimeout(hideTimeout.current);
|
clearTimeout(hideTimeout.current);
|
||||||
}
|
}
|
||||||
hideTimeout.current = setTimeout(() => {
|
hideTimeout.current = setTimeout(() => {
|
||||||
hideToastFunc();
|
hideToastFunc();
|
||||||
}, data.duration);
|
}, data.duration);
|
||||||
};
|
},
|
||||||
|
[context, hideToastFunc]
|
||||||
|
);
|
||||||
|
|
||||||
const showNext = (data) => {
|
const showNext = useCallback(
|
||||||
if (!data) {
|
(data) => {
|
||||||
hideToastFunc();
|
if (!data) {
|
||||||
return;
|
hideToastFunc();
|
||||||
}
|
return;
|
||||||
setData(data);
|
}
|
||||||
if (hideTimeout.current) {
|
setData(data);
|
||||||
clearTimeout(hideTimeout.current);
|
if (hideTimeout.current) {
|
||||||
}
|
clearTimeout(hideTimeout.current);
|
||||||
hideTimeout.current = setTimeout(() => {
|
}
|
||||||
hideToastFunc();
|
hideTimeout.current = setTimeout(() => {
|
||||||
}, data?.duration);
|
hideToastFunc();
|
||||||
};
|
}, data?.duration);
|
||||||
|
},
|
||||||
|
[hideToastFunc]
|
||||||
|
);
|
||||||
|
|
||||||
const hideToastFunc = () => {
|
const hideToastFunc = useCallback(() => {
|
||||||
if (hideTimeout.current) {
|
if (hideTimeout.current) {
|
||||||
clearTimeout(hideTimeout.current);
|
clearTimeout(hideTimeout.current);
|
||||||
}
|
}
|
||||||
@@ -100,7 +105,7 @@ export const Toast = ({ context = "global" }) => {
|
|||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
};
|
}, [showNext]);
|
||||||
|
|
||||||
const _onKeyboardShow = () => {
|
const _onKeyboardShow = () => {
|
||||||
setKeyboard(true);
|
setKeyboard(true);
|
||||||
@@ -127,7 +132,7 @@ export const Toast = ({ context = "global" }) => {
|
|||||||
eUnSubscribeEvent(eShowToast, showToastFunc);
|
eUnSubscribeEvent(eShowToast, showToastFunc);
|
||||||
eUnSubscribeEvent(eHideToast, hideToastFunc);
|
eUnSubscribeEvent(eHideToast, hideToastFunc);
|
||||||
};
|
};
|
||||||
}, [keyboard]);
|
}, [hideToastFunc, keyboard, showToastFunc]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
visible && (
|
visible && (
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export const PressableButton = ({
|
|||||||
},
|
},
|
||||||
customStyle
|
customStyle
|
||||||
],
|
],
|
||||||
[customStyle, noborder, type, colors]
|
[alpha, selectedColor, opacity, primaryColor, noborder, customStyle]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const SheetWrapper = ({
|
|||||||
borderBottomRightRadius: 0,
|
borderBottomRightRadius: 0,
|
||||||
borderBottomLeftRadius: 0
|
borderBottomLeftRadius: 0
|
||||||
};
|
};
|
||||||
}, [colors.bg, gestureEnabled]);
|
}, [colors.bg, largeTablet, smallTablet, width]);
|
||||||
|
|
||||||
const _onOpen = () => {
|
const _onOpen = () => {
|
||||||
onOpen && onOpen();
|
onOpen && onOpen();
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const BouncingView = ({
|
|||||||
duration: duration,
|
duration: duration,
|
||||||
easing: Easing.elastic(1)
|
easing: Easing.elastic(1)
|
||||||
});
|
});
|
||||||
}, []);
|
}, [animated, duration, initialScale, scale]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View style={[style, animatedStyle]}>{children}</Animated.View>
|
<Animated.View style={[style, animatedStyle]}>{children}</Animated.View>
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import {
|
|||||||
} from "../utils/events";
|
} from "../utils/events";
|
||||||
import { deleteItems } from "../utils/functions";
|
import { deleteItems } from "../utils/functions";
|
||||||
import { sleep } from "../utils/time";
|
import { sleep } from "../utils/time";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export const useActions = ({ close = () => null, item }) => {
|
export const useActions = ({ close = () => null, item }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -78,9 +79,9 @@ export const useActions = ({ close = () => null, item }) => {
|
|||||||
if (item.type !== "note") {
|
if (item.type !== "note") {
|
||||||
setIsPinnedToMenu(db.settings.isPinned(item.id));
|
setIsPinnedToMenu(db.settings.isPinned(item.id));
|
||||||
}
|
}
|
||||||
}, [item]);
|
}, [checkNotifPinned, item]);
|
||||||
|
|
||||||
function checkNotifPinned() {
|
const checkNotifPinned = useCallback(() => {
|
||||||
let pinned = Notifications.getPinnedNotes();
|
let pinned = Notifications.getPinnedNotes();
|
||||||
if (!pinned) {
|
if (!pinned) {
|
||||||
setNotifPinned(null);
|
setNotifPinned(null);
|
||||||
@@ -93,7 +94,7 @@ export const useActions = ({ close = () => null, item }) => {
|
|||||||
} else {
|
} else {
|
||||||
setNotifPinned(null);
|
setNotifPinned(null);
|
||||||
}
|
}
|
||||||
}
|
}, [item.id]);
|
||||||
|
|
||||||
const isNoteInTopic = () => {
|
const isNoteInTopic = () => {
|
||||||
const currentScreen = useNavigationStore.getState().currentScreen;
|
const currentScreen = useNavigationStore.getState().currentScreen;
|
||||||
@@ -104,13 +105,16 @@ export const useActions = ({ close = () => null, item }) => {
|
|||||||
.has(item.id);
|
.has(item.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUpdate = async (type) => {
|
const onUpdate = useCallback(
|
||||||
if (type === "unpin") {
|
async (type) => {
|
||||||
await sleep(1000);
|
if (type === "unpin") {
|
||||||
await Notifications.get();
|
await sleep(1000);
|
||||||
checkNotifPinned();
|
await Notifications.get();
|
||||||
}
|
checkNotifPinned();
|
||||||
};
|
}
|
||||||
|
},
|
||||||
|
[checkNotifPinned]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent("onUpdate", onUpdate);
|
eSubscribeEvent("onUpdate", onUpdate);
|
||||||
@@ -118,7 +122,7 @@ export const useActions = ({ close = () => null, item }) => {
|
|||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent("onUpdate", onUpdate);
|
eUnSubscribeEvent("onUpdate", onUpdate);
|
||||||
};
|
};
|
||||||
}, [item]);
|
}, [item, onUpdate]);
|
||||||
|
|
||||||
function switchTheme() {
|
function switchTheme() {
|
||||||
toggleDarkMode();
|
toggleDarkMode();
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import {
|
|||||||
} from "../services/event-manager";
|
} from "../services/event-manager";
|
||||||
import { useEditorStore } from "../stores/use-editor-store";
|
import { useEditorStore } from "../stores/use-editor-store";
|
||||||
import { useDragState } from "../screens/settings/editor/state";
|
import { useDragState } from "../screens/settings/editor/state";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const SodiumEventEmitter = new NativeEventEmitter(NativeModules.Sodium);
|
const SodiumEventEmitter = new NativeEventEmitter(NativeModules.Sodium);
|
||||||
export const useAppEvents = () => {
|
export const useAppEvents = () => {
|
||||||
@@ -121,7 +122,7 @@ export const useAppEvents = () => {
|
|||||||
onRequestPartialSync
|
onRequestPartialSync
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}, [loading]);
|
}, [loading, onSyncComplete]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let subs = [
|
let subs = [
|
||||||
@@ -156,10 +157,10 @@ export const useAppEvents = () => {
|
|||||||
|
|
||||||
subs.forEach((sub) => sub?.remove());
|
subs.forEach((sub) => sub?.remove());
|
||||||
};
|
};
|
||||||
}, []);
|
}, [onEmailVerified, onSyncComplete, onUrlRecieved, onUserUpdated]);
|
||||||
|
|
||||||
const onSessionExpired = async () => {
|
const onSessionExpired = async () => {
|
||||||
await SettingsService.set({
|
SettingsService.set({
|
||||||
sessionExpired: true
|
sessionExpired: true
|
||||||
});
|
});
|
||||||
eSendEvent("session_expired");
|
eSendEvent("session_expired");
|
||||||
@@ -188,18 +189,26 @@ export const useAppEvents = () => {
|
|||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
refValues.current?.removeInternetStateListener &&
|
refValues.current?.removeInternetStateListener &&
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
refValues.current?.removeInternetStateListener();
|
refValues.current?.removeInternetStateListener();
|
||||||
sub?.remove();
|
sub?.remove();
|
||||||
unsubIAP();
|
unsubIAP();
|
||||||
};
|
};
|
||||||
}, [loading, verify]);
|
}, [
|
||||||
|
loading,
|
||||||
|
onAppStateChanged,
|
||||||
|
onEmailVerified,
|
||||||
|
onInternetStateChanged,
|
||||||
|
onUserUpdated,
|
||||||
|
verify
|
||||||
|
]);
|
||||||
|
|
||||||
const onInternetStateChanged = async (state) => {
|
const onInternetStateChanged = useCallback(async (state) => {
|
||||||
if (!syncedOnLaunch.current) return;
|
if (!syncedOnLaunch.current) return;
|
||||||
reconnectSSE(state);
|
reconnectSSE(state);
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const onSyncComplete = async () => {
|
const onSyncComplete = useCallback(async () => {
|
||||||
console.log("sync complete");
|
console.log("sync complete");
|
||||||
initAfterSync();
|
initAfterSync();
|
||||||
setLastSynced(await db.lastSynced());
|
setLastSynced(await db.lastSynced());
|
||||||
@@ -209,22 +218,25 @@ export const useAppEvents = () => {
|
|||||||
if (note) {
|
if (note) {
|
||||||
//await updateNoteInEditor();
|
//await updateNoteInEditor();
|
||||||
}
|
}
|
||||||
};
|
}, [setLastSynced]);
|
||||||
|
|
||||||
const onUrlRecieved = async (res) => {
|
const onUrlRecieved = useCallback(
|
||||||
let url = res ? res.url : "";
|
async (res) => {
|
||||||
try {
|
let url = res ? res.url : "";
|
||||||
if (url.startsWith("https://app.notesnook.com/account/verified")) {
|
try {
|
||||||
await onEmailVerified();
|
if (url.startsWith("https://app.notesnook.com/account/verified")) {
|
||||||
} else {
|
await onEmailVerified();
|
||||||
return;
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
},
|
||||||
console.error(e);
|
[onEmailVerified]
|
||||||
}
|
);
|
||||||
};
|
|
||||||
|
|
||||||
const onEmailVerified = async () => {
|
const onEmailVerified = useCallback(async () => {
|
||||||
let user = await db.user.getUser();
|
let user = await db.user.getUser();
|
||||||
setUser(user);
|
setUser(user);
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
@@ -236,9 +248,9 @@ export const useAppEvents = () => {
|
|||||||
if (user?.isEmailConfirmed) {
|
if (user?.isEmailConfirmed) {
|
||||||
clearMessage();
|
clearMessage();
|
||||||
}
|
}
|
||||||
};
|
}, [setUser]);
|
||||||
|
|
||||||
const attachIAPListeners = async () => {
|
const attachIAPListeners = useCallback(async () => {
|
||||||
await RNIap.initConnection()
|
await RNIap.initConnection()
|
||||||
.catch(() => null)
|
.catch(() => null)
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
@@ -247,7 +259,7 @@ export const useAppEvents = () => {
|
|||||||
refValues.current.subsriptionErrorListener =
|
refValues.current.subsriptionErrorListener =
|
||||||
RNIap.purchaseErrorListener(onSubscriptionError);
|
RNIap.purchaseErrorListener(onSubscriptionError);
|
||||||
});
|
});
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const onAccountStatusChange = async (userStatus) => {
|
const onAccountStatusChange = async (userStatus) => {
|
||||||
if (!PremiumService.get() && userStatus.type === 5) {
|
if (!PremiumService.get() && userStatus.type === 5) {
|
||||||
@@ -281,59 +293,62 @@ export const useAppEvents = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUserUpdated = async (login) => {
|
const onUserUpdated = useCallback(
|
||||||
console.log(`onUserUpdated: ${login}`);
|
async (login) => {
|
||||||
let user;
|
console.log(`onUserUpdated: ${login}`);
|
||||||
try {
|
let user;
|
||||||
user = await db.user.getUser();
|
try {
|
||||||
await PremiumService.setPremiumStatus();
|
user = await db.user.getUser();
|
||||||
setLastSynced(await db.lastSynced());
|
await PremiumService.setPremiumStatus();
|
||||||
await useDragState.getState().init();
|
setLastSynced(await db.lastSynced());
|
||||||
if (!user) {
|
await useDragState.getState().init();
|
||||||
return setLoginMessage();
|
if (!user) {
|
||||||
}
|
return setLoginMessage();
|
||||||
|
}
|
||||||
|
|
||||||
let userEmailConfirmed = SettingsService.get().userEmailConfirmed;
|
let userEmailConfirmed = SettingsService.get().userEmailConfirmed;
|
||||||
setUser(user);
|
|
||||||
if (SettingsService.get().sessionExpired) {
|
|
||||||
syncedOnLaunch.current = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearMessage();
|
|
||||||
attachIAPListeners();
|
|
||||||
|
|
||||||
if (!login) {
|
|
||||||
user = await db.user.fetchUser();
|
|
||||||
setUser(user);
|
setUser(user);
|
||||||
|
if (SettingsService.get().sessionExpired) {
|
||||||
|
syncedOnLaunch.current = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearMessage();
|
||||||
|
attachIAPListeners();
|
||||||
|
|
||||||
|
if (!login) {
|
||||||
|
user = await db.user.fetchUser();
|
||||||
|
setUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
await PremiumService.setPremiumStatus();
|
||||||
|
if (user?.isEmailConfirmed && !userEmailConfirmed) {
|
||||||
|
setTimeout(() => {
|
||||||
|
onEmailVerified();
|
||||||
|
}, 1000);
|
||||||
|
SettingsService.set({
|
||||||
|
userEmailConfirmed: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ToastEvent.error(e, "An error occured", "global");
|
||||||
}
|
}
|
||||||
|
|
||||||
await PremiumService.setPremiumStatus();
|
user = await db.user.getUser();
|
||||||
if (user?.isEmailConfirmed && !userEmailConfirmed) {
|
if (
|
||||||
setTimeout(() => {
|
user?.isEmailConfirmed &&
|
||||||
onEmailVerified();
|
!SettingsService.get().recoveryKeySaved &&
|
||||||
}, 1000);
|
!useMessageStore.getState().message?.visible
|
||||||
SettingsService.set({
|
) {
|
||||||
userEmailConfirmed: true
|
setRecoveryKeyMessage();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
if (!user?.isEmailConfirmed) setEmailVerifyMessage();
|
||||||
ToastEvent.error(e, "An error occured", "global");
|
refValues.current.isUserReady = true;
|
||||||
}
|
|
||||||
|
|
||||||
user = await db.user.getUser();
|
syncedOnLaunch.current = true;
|
||||||
if (
|
},
|
||||||
user?.isEmailConfirmed &&
|
[attachIAPListeners, onEmailVerified, setLastSynced, setUser]
|
||||||
!SettingsService.get().recoveryKeySaved &&
|
);
|
||||||
!useMessageStore.getState().message?.visible
|
|
||||||
) {
|
|
||||||
setRecoveryKeyMessage();
|
|
||||||
}
|
|
||||||
if (!user?.isEmailConfirmed) setEmailVerifyMessage();
|
|
||||||
refValues.current.isUserReady = true;
|
|
||||||
|
|
||||||
syncedOnLaunch.current = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSuccessfulSubscription = async (subscription) => {
|
const onSuccessfulSubscription = async (subscription) => {
|
||||||
await PremiumService.subscriptions.set(subscription);
|
await PremiumService.subscriptions.set(subscription);
|
||||||
@@ -349,59 +364,65 @@ export const useAppEvents = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAppStateChanged = async (state) => {
|
const onAppStateChanged = useCallback(
|
||||||
console.log("onAppStateChanged");
|
async (state) => {
|
||||||
if (state === "active") {
|
console.log("onAppStateChanged");
|
||||||
updateStatusBarColor();
|
if (state === "active") {
|
||||||
if (
|
updateStatusBarColor();
|
||||||
SettingsService.get().appLockMode !== "background" &&
|
if (
|
||||||
!SettingsService.get().privacyScreen
|
SettingsService.get().appLockMode !== "background" &&
|
||||||
) {
|
!SettingsService.get().privacyScreen
|
||||||
enabled(false);
|
) {
|
||||||
}
|
enabled(false);
|
||||||
if (SettingsService.get().appLockMode === "background") {
|
|
||||||
if (useSettingStore.getState().requestBiometrics) {
|
|
||||||
useSettingStore.getState().setRequestBiometrics(false);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
if (SettingsService.get().appLockMode === "background") {
|
||||||
|
if (useSettingStore.getState().requestBiometrics) {
|
||||||
await reconnectSSE();
|
useSettingStore.getState().setRequestBiometrics(false);
|
||||||
await checkIntentState();
|
return;
|
||||||
MMKV.removeItem("appState");
|
|
||||||
let user = await db.user.getUser();
|
|
||||||
if (user && !user?.isEmailConfirmed) {
|
|
||||||
try {
|
|
||||||
let user = await db.user.fetchUser();
|
|
||||||
if (user?.isEmailConfirmed) {
|
|
||||||
onEmailVerified();
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
}
|
||||||
console.error(e);
|
|
||||||
|
await reconnectSSE();
|
||||||
|
await checkIntentState();
|
||||||
|
MMKV.removeItem("appState");
|
||||||
|
let user = await db.user.getUser();
|
||||||
|
if (user && !user?.isEmailConfirmed) {
|
||||||
|
try {
|
||||||
|
let user = await db.user.fetchUser();
|
||||||
|
if (user?.isEmailConfirmed) {
|
||||||
|
onEmailVerified();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let id = useEditorStore.getState().currentEditingNote;
|
||||||
|
let note = id && db.notes.note(id).data;
|
||||||
|
if (
|
||||||
|
note?.locked &&
|
||||||
|
SettingsService.get().appLockMode === "background"
|
||||||
|
) {
|
||||||
|
eSendEvent(eClearEditor);
|
||||||
|
}
|
||||||
|
await storeAppState();
|
||||||
|
if (
|
||||||
|
SettingsService.get().appLockMode === "background" &&
|
||||||
|
!useSettingStore.getState().requestBiometrics &&
|
||||||
|
!useUserStore.getState().verifyUser
|
||||||
|
) {
|
||||||
|
useUserStore.getState().setVerifyUser(true);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
SettingsService.get().privacyScreen ||
|
||||||
|
SettingsService.get().appLockMode === "background"
|
||||||
|
) {
|
||||||
|
!useSettingStore.getState().requestBiometrics ? enabled(true) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
let id = useEditorStore.getState().currentEditingNote;
|
[onEmailVerified]
|
||||||
let note = id && db.notes.note(id).data;
|
);
|
||||||
if (note?.locked && SettingsService.get().appLockMode === "background") {
|
|
||||||
eSendEvent(eClearEditor);
|
|
||||||
}
|
|
||||||
await storeAppState();
|
|
||||||
if (
|
|
||||||
SettingsService.get().appLockMode === "background" &&
|
|
||||||
!useSettingStore.getState().requestBiometrics &&
|
|
||||||
!useUserStore.getState().verifyUser
|
|
||||||
) {
|
|
||||||
useUserStore.getState().setVerifyUser(true);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
SettingsService.get().privacyScreen ||
|
|
||||||
SettingsService.get().appLockMode === "background"
|
|
||||||
) {
|
|
||||||
!useSettingStore.getState().requestBiometrics ? enabled(true) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async function reconnectSSE(connection) {
|
async function reconnectSSE(connection) {
|
||||||
if (refValues.current?.isReconnecting) return;
|
if (refValues.current?.isReconnecting) return;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export const useAttachmentProgress = (attachment, encryption) => {
|
|||||||
} else {
|
} else {
|
||||||
setCurrentProgress(null);
|
setCurrentProgress(null);
|
||||||
}
|
}
|
||||||
}, [progress]);
|
}, [attachment.metadata.hash, progress]);
|
||||||
|
|
||||||
return [currentProgress, setCurrentProgress];
|
return [currentProgress, setCurrentProgress];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { useEditorStore } from "../stores/use-editor-store";
|
|||||||
import { useTagStore } from "../stores/use-tag-store";
|
import { useTagStore } from "../stores/use-tag-store";
|
||||||
import { db } from "../common/database";
|
import { db } from "../common/database";
|
||||||
import { NoteType } from "app/utils/types";
|
import { NoteType } from "app/utils/types";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hook that injects/removes tags from tags bar in editor
|
* A hook that injects/removes tags from tags bar in editor
|
||||||
@@ -34,7 +35,7 @@ const useEditorTags = () => {
|
|||||||
const [note, setNote] = useState<NoteType | null>(null);
|
const [note, setNote] = useState<NoteType | null>(null);
|
||||||
const [noteTags, setNoteTags] = useState<string[]>([]);
|
const [noteTags, setNoteTags] = useState<string[]>([]);
|
||||||
|
|
||||||
async function refreshNote() {
|
const refreshNote = useCallback(() => {
|
||||||
const current = useEditorStore.getState().currentEditingNote;
|
const current = useEditorStore.getState().currentEditingNote;
|
||||||
if (!current) {
|
if (!current) {
|
||||||
setNote(null);
|
setNote(null);
|
||||||
@@ -44,23 +45,23 @@ const useEditorTags = () => {
|
|||||||
const note = db.notes?.note(current)?.data as NoteType;
|
const note = db.notes?.note(current)?.data as NoteType;
|
||||||
setNote(note ? { ...note } : null);
|
setNote(note ? { ...note } : null);
|
||||||
getTags(note);
|
getTags(note);
|
||||||
}
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
refreshNote();
|
refreshNote();
|
||||||
}, [currentEditingNote, tags]);
|
}, [currentEditingNote, refreshNote, tags]);
|
||||||
|
|
||||||
function load() {
|
const load = useCallback(() => {
|
||||||
if (!note) return;
|
if (!note) return;
|
||||||
// tiny.call(EditorWebView, renderTags(noteTags));
|
// tiny.call(EditorWebView, renderTags(noteTags));
|
||||||
}
|
}, [note]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent("updateTags", load);
|
eSubscribeEvent("updateTags", load);
|
||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent("updateTags", load);
|
eUnSubscribeEvent("updateTags", load);
|
||||||
};
|
};
|
||||||
}, [noteTags]);
|
}, [load, noteTags]);
|
||||||
|
|
||||||
function getTags(note: NoteType) {
|
function getTags(note: NoteType) {
|
||||||
if (!note || !note.tags) return [];
|
if (!note || !note.tags) return [];
|
||||||
@@ -72,7 +73,7 @@ const useEditorTags = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
load();
|
load();
|
||||||
}, [noteTags]);
|
}, [load, noteTags]);
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ const useImmediateEffect = (callback: EffectCallback, deps: DependencyList) => {
|
|||||||
cleanup = callback();
|
cleanup = callback();
|
||||||
});
|
});
|
||||||
return cleanup;
|
return cleanup;
|
||||||
}, deps);
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [callback, ...deps]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useImmediateEffect;
|
export default useImmediateEffect;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Keyboard, KeyboardEvent, useWindowDimensions } from "react-native";
|
import { Keyboard, KeyboardEvent, useWindowDimensions } from "react-native";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hook that detects floating keyboard on iPad
|
* A hook that detects floating keyboard on iPad
|
||||||
@@ -28,9 +29,12 @@ const useIsFloatingKeyboard = () => {
|
|||||||
|
|
||||||
const [floating, setFloating] = useState<boolean>(false);
|
const [floating, setFloating] = useState<boolean>(false);
|
||||||
|
|
||||||
const onKeyboardWillChangeFrame = (event: KeyboardEvent) => {
|
const onKeyboardWillChangeFrame = useCallback(
|
||||||
setFloating(event.endCoordinates.width !== width);
|
(event: KeyboardEvent) => {
|
||||||
};
|
setFloating(event.endCoordinates.width !== width);
|
||||||
|
},
|
||||||
|
[width]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sub1 = Keyboard.addListener(
|
const sub1 = Keyboard.addListener(
|
||||||
@@ -40,7 +44,7 @@ const useIsFloatingKeyboard = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
sub1?.remove();
|
sub1?.remove();
|
||||||
};
|
};
|
||||||
}, [width]);
|
}, [onKeyboardWillChangeFrame, width]);
|
||||||
|
|
||||||
return floating;
|
return floating;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const useNavigationFocus = (
|
|||||||
},
|
},
|
||||||
isBlurred.current ? 0 : delay || 300
|
isBlurred.current ? 0 : delay || 300
|
||||||
);
|
);
|
||||||
}, [onFocus, prev]);
|
}, [delay, onFocus]);
|
||||||
|
|
||||||
const _onBlur = useCallback(() => {
|
const _onBlur = useCallback(() => {
|
||||||
isBlurred.current = true;
|
isBlurred.current = true;
|
||||||
@@ -58,7 +58,7 @@ export const useNavigationFocus = (
|
|||||||
setFocused(false);
|
setFocused(false);
|
||||||
}
|
}
|
||||||
}, delay || 300);
|
}, delay || 300);
|
||||||
}, [onBlur, prev]);
|
}, [delay, onBlur]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!navigation) return;
|
if (!navigation) return;
|
||||||
@@ -69,7 +69,7 @@ export const useNavigationFocus = (
|
|||||||
return () => {
|
return () => {
|
||||||
subs.forEach((sub) => sub());
|
subs.forEach((sub) => sub());
|
||||||
};
|
};
|
||||||
}, [navigation]);
|
}, [_onBlur, _onFocus, navigation]);
|
||||||
|
|
||||||
return isFocused;
|
return isFocused;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
* It will return random item in an array after given interval
|
* It will return random item in an array after given interval
|
||||||
*/
|
*/
|
||||||
function useRotator<T>(data: T[], interval = 3000): T | null {
|
function useRotator<T>(data: T[], interval = 3000): T | null {
|
||||||
if (!Array.isArray(data)) return null;
|
|
||||||
//@ts-ignore Added sample() method to Array.prototype to get random value.
|
//@ts-ignore Added sample() method to Array.prototype to get random value.
|
||||||
const [current, setCurrent] = useState<T>(data.sample());
|
const [current, setCurrent] = useState<T>(data.sample());
|
||||||
const intervalRef = useRef<NodeJS.Timer>();
|
const intervalRef = useRef<NodeJS.Timer>();
|
||||||
@@ -39,7 +38,7 @@ function useRotator<T>(data: T[], interval = 3000): T | null {
|
|||||||
clearInterval(intervalRef.current);
|
clearInterval(intervalRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
}, [data, interval]);
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const useSyncProgress = () => {
|
|||||||
EV?.unsubscribe(EVENTS.syncProgress, onProgress);
|
EV?.unsubscribe(EVENTS.syncProgress, onProgress);
|
||||||
EV?.unsubscribe(EVENTS.syncCompleted, onSyncComplete);
|
EV?.unsubscribe(EVENTS.syncCompleted, onSyncComplete);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [EV, onProgress]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
progress
|
progress
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export const useTooltipHandler = (
|
|||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent(id, callback);
|
eUnSubscribeEvent(id, callback);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [callback, id]);
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const useVaultStatus = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
|
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
|
||||||
};
|
};
|
||||||
}, []);
|
}, [checkVaultStatus]);
|
||||||
|
|
||||||
return vaultStatus;
|
return vaultStatus;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const useVaultStatus = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
|
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
|
||||||
};
|
};
|
||||||
}, []);
|
}, [checkVaultStatus]);
|
||||||
|
|
||||||
return vaultStatus;
|
return vaultStatus;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const _Tabs = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
useNavigationStore.getState().update({ name: homepage });
|
useNavigationStore.getState().update({ name: homepage });
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}, []);
|
}, [homepage]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NativeStack.Navigator
|
<NativeStack.Navigator
|
||||||
@@ -169,7 +169,7 @@ const _NavigationStack = () => {
|
|||||||
}
|
}
|
||||||
hideAllTooltips();
|
hideAllTooltips();
|
||||||
eSendEvent("navigate");
|
eSendEvent("navigate");
|
||||||
});
|
}, [clearSelection]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import {
|
|||||||
import { editorRef, tabBarRef } from "../utils/global-refs";
|
import { editorRef, tabBarRef } from "../utils/global-refs";
|
||||||
import { hideAllTooltips } from "../hooks/use-tooltip";
|
import { hideAllTooltips } from "../hooks/use-tooltip";
|
||||||
import { NavigationStack } from "./navigation-stack";
|
import { NavigationStack } from "./navigation-stack";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const _TabsHolder = () => {
|
const _TabsHolder = () => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
@@ -92,7 +93,7 @@ const _TabsHolder = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const showFullScreenEditor = () => {
|
const showFullScreenEditor = useCallback(() => {
|
||||||
setFullscreen(true);
|
setFullscreen(true);
|
||||||
if (deviceMode === "smallTablet") {
|
if (deviceMode === "smallTablet") {
|
||||||
tabBarRef.current?.openDrawer();
|
tabBarRef.current?.openDrawer();
|
||||||
@@ -107,9 +108,9 @@ const _TabsHolder = () => {
|
|||||||
: dimensions.width * 0.15
|
: dimensions.width * 0.15
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}, [deviceMode, dimensions.width, setFullscreen]);
|
||||||
|
|
||||||
const closeFullScreenEditor = () => {
|
const closeFullScreenEditor = useCallback(() => {
|
||||||
if (deviceMode === "smallTablet") {
|
if (deviceMode === "smallTablet") {
|
||||||
tabBarRef.current?.closeDrawer();
|
tabBarRef.current?.closeDrawer();
|
||||||
}
|
}
|
||||||
@@ -132,7 +133,7 @@ const _TabsHolder = () => {
|
|||||||
tabBarRef.current?.goToIndex(1);
|
tabBarRef.current?.goToIndex(1);
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
};
|
}, [deviceMode, dimensions.width, setFullscreen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!tabBarRef.current?.isDrawerOpen()) {
|
if (!tabBarRef.current?.isDrawerOpen()) {
|
||||||
@@ -145,7 +146,14 @@ const _TabsHolder = () => {
|
|||||||
eUnSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
|
eUnSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
|
||||||
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
|
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
|
||||||
};
|
};
|
||||||
}, [deviceMode, dimensions, colors]);
|
}, [
|
||||||
|
deviceMode,
|
||||||
|
dimensions,
|
||||||
|
colors,
|
||||||
|
showFullScreenEditor,
|
||||||
|
closeFullScreenEditor,
|
||||||
|
toggleView
|
||||||
|
]);
|
||||||
|
|
||||||
const _onLayout = async (event) => {
|
const _onLayout = async (event) => {
|
||||||
console.log("layout called here");
|
console.log("layout called here");
|
||||||
@@ -259,9 +267,12 @@ const _TabsHolder = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleView = (show) => {
|
const toggleView = useCallback(
|
||||||
animatedTranslateY.value = show ? 0 : -9999;
|
(show) => {
|
||||||
};
|
animatedTranslateY.value = show ? 0 : -9999;
|
||||||
|
},
|
||||||
|
[animatedTranslateY]
|
||||||
|
);
|
||||||
|
|
||||||
const valueLimiter = (value, min, max) => {
|
const valueLimiter = (value, min, max) => {
|
||||||
if (value < min) {
|
if (value < min) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import { EditorProps, useEditorType } from "./tiptap/types";
|
|||||||
import { useEditor } from "./tiptap/use-editor";
|
import { useEditor } from "./tiptap/use-editor";
|
||||||
import { useEditorEvents } from "./tiptap/use-editor-events";
|
import { useEditorEvents } from "./tiptap/use-editor-events";
|
||||||
import { editorController } from "./tiptap/utils";
|
import { editorController } from "./tiptap/utils";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
const style: ViewStyle = {
|
const style: ViewStyle = {
|
||||||
height: "100%",
|
height: "100%",
|
||||||
@@ -91,23 +92,32 @@ const Editor = React.memo(
|
|||||||
get: () => editor
|
get: () => editor
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const onMediaDownloaded = ({
|
const onMediaDownloaded = useCallback(
|
||||||
hash,
|
({
|
||||||
groupId,
|
hash,
|
||||||
src
|
groupId,
|
||||||
}: {
|
src
|
||||||
hash: string;
|
}: {
|
||||||
groupId: string;
|
hash: string;
|
||||||
src: string;
|
groupId: string;
|
||||||
}) => {
|
src: string;
|
||||||
console.log("onMediaDownoaded", groupId);
|
}) => {
|
||||||
|
console.log("onMediaDownoaded", groupId);
|
||||||
|
|
||||||
if (groupId !== editor.note.current?.id) return;
|
if (groupId !== editor.note.current?.id) return;
|
||||||
editor.commands.updateImage({
|
editor.commands.updateImage({
|
||||||
hash: hash,
|
hash: hash,
|
||||||
src: src
|
src: src
|
||||||
});
|
});
|
||||||
};
|
},
|
||||||
|
[editor.commands, editor.note]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onError = useCallback(() => {
|
||||||
|
console.log("RENDER PROCESS GONE!!!");
|
||||||
|
editor.setLoading(true);
|
||||||
|
setTimeout(() => editor.setLoading(false), 10);
|
||||||
|
}, [editor]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onLoad && onLoad();
|
onLoad && onLoad();
|
||||||
@@ -117,17 +127,12 @@ const Editor = React.memo(
|
|||||||
eUnSubscribeEvent("webview_reset", onError);
|
eUnSubscribeEvent("webview_reset", onError);
|
||||||
EV.unsubscribe(EVENTS.mediaAttachmentDownloaded, onMediaDownloaded);
|
EV.unsubscribe(EVENTS.mediaAttachmentDownloaded, onMediaDownloaded);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [onError, onLoad, onMediaDownloaded]);
|
||||||
|
|
||||||
if (withController) {
|
if (withController) {
|
||||||
editorController.current = editor;
|
editorController.current = editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
const onError = () => {
|
|
||||||
console.log("RENDER PROCESS GONE!!!");
|
|
||||||
editor.setLoading(true);
|
|
||||||
setTimeout(() => editor.setLoading(false), 10);
|
|
||||||
};
|
|
||||||
console.log(editor.loading, "loading editor");
|
console.log(editor.loading, "loading editor");
|
||||||
return editor.loading ? null : (
|
return editor.loading ? null : (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import { useThemeStore } from "../../stores/use-theme-store";
|
|||||||
import { eClearEditor, eOnLoadNote } from "../../utils/events";
|
import { eClearEditor, eOnLoadNote } from "../../utils/events";
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
import { editorState } from "./tiptap/utils";
|
import { editorState } from "./tiptap/utils";
|
||||||
|
import { useCallback } from "react";
|
||||||
const EditorOverlay = ({ editorId = "", editor }) => {
|
const EditorOverlay = ({ editorId = "", editor }) => {
|
||||||
const colors = useThemeStore((state) => state.colors);
|
const colors = useThemeStore((state) => state.colors);
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
@@ -55,34 +56,37 @@ const EditorOverlay = ({ editorId = "", editor }) => {
|
|||||||
clearTimeout(timers.current.closing);
|
clearTimeout(timers.current.closing);
|
||||||
};
|
};
|
||||||
|
|
||||||
const load = async (_loading) => {
|
const load = useCallback(
|
||||||
editorState().overlay = true;
|
async (_loading) => {
|
||||||
clearTimers();
|
editorState().overlay = true;
|
||||||
if (_loading) {
|
|
||||||
opacity.value = 1;
|
|
||||||
translateValue.value = 0;
|
|
||||||
timers.current.error = setTimeout(() => {
|
|
||||||
if (_loading) {
|
|
||||||
let note = _loading;
|
|
||||||
note.forced = true;
|
|
||||||
eSendEvent(eOnLoadNote + editorId, note);
|
|
||||||
}
|
|
||||||
setError(true);
|
|
||||||
}, 4000);
|
|
||||||
} else {
|
|
||||||
clearTimers();
|
clearTimers();
|
||||||
setTimeout(() => {
|
if (_loading) {
|
||||||
setError(false);
|
opacity.value = 1;
|
||||||
editorState().overlay = false;
|
translateValue.value = 0;
|
||||||
opacity.value = withTiming(0, {
|
timers.current.error = setTimeout(() => {
|
||||||
duration: 500
|
if (_loading) {
|
||||||
});
|
let note = _loading;
|
||||||
|
note.forced = true;
|
||||||
|
eSendEvent(eOnLoadNote + editorId, note);
|
||||||
|
}
|
||||||
|
setError(true);
|
||||||
|
}, 4000);
|
||||||
|
} else {
|
||||||
|
clearTimers();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
translateValue.value = 6000;
|
setError(false);
|
||||||
}, 500);
|
editorState().overlay = false;
|
||||||
}, 100);
|
opacity.value = withTiming(0, {
|
||||||
}
|
duration: 500
|
||||||
};
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
translateValue.value = 6000;
|
||||||
|
}, 500);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[editorId, opacity, translateValue]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent("loadingNote" + editorId, load);
|
eSubscribeEvent("loadingNote" + editorId, load);
|
||||||
@@ -90,7 +94,7 @@ const EditorOverlay = ({ editorId = "", editor }) => {
|
|||||||
clearTimers();
|
clearTimers();
|
||||||
eUnSubscribeEvent("loadingNote" + editorId, load);
|
eUnSubscribeEvent("loadingNote" + editorId, load);
|
||||||
};
|
};
|
||||||
}, [editorId]);
|
}, [editorId, load]);
|
||||||
|
|
||||||
const animatedStyle = useAnimatedStyle(() => {
|
const animatedStyle = useAnimatedStyle(() => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -151,10 +151,8 @@ export const useEditorEvents = (
|
|||||||
);
|
);
|
||||||
const tools = useDragState((state) => state.data);
|
const tools = useDragState((state) => state.data);
|
||||||
const { keyboardShown } = useKeyboard();
|
const { keyboardShown } = useKeyboard();
|
||||||
if (!editor) return null;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("keyboardShown", keyboardShown);
|
|
||||||
editor.commands.setSettings({
|
editor.commands.setSettings({
|
||||||
deviceMode: deviceMode || "mobile",
|
deviceMode: deviceMode || "mobile",
|
||||||
fullscreen: fullscreen || false,
|
fullscreen: fullscreen || false,
|
||||||
@@ -176,7 +174,10 @@ export const useEditorEvents = (
|
|||||||
tools,
|
tools,
|
||||||
editor.commands,
|
editor.commands,
|
||||||
keyboardShown,
|
keyboardShown,
|
||||||
doubleSpacedLines
|
doubleSpacedLines,
|
||||||
|
editorPropReadonly,
|
||||||
|
noHeader,
|
||||||
|
noToolbar
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const onBackPress = useCallback(async () => {
|
const onBackPress = useCallback(async () => {
|
||||||
@@ -211,14 +212,14 @@ export const useEditorEvents = (
|
|||||||
editorState().currentlyEditing = false;
|
editorState().currentlyEditing = false;
|
||||||
editor.reset();
|
editor.reset();
|
||||||
}, 1);
|
}, 1);
|
||||||
}, [fullscreen, deviceMode]);
|
}, [editor, deviceMode, fullscreen]);
|
||||||
|
|
||||||
const onHardwareBackPress = useCallback(() => {
|
const onHardwareBackPress = useCallback(() => {
|
||||||
if (editorState().currentlyEditing) {
|
if (editorState().currentlyEditing) {
|
||||||
onBackPress();
|
onBackPress();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}, []);
|
}, [onBackPress]);
|
||||||
|
|
||||||
const onLoadNote = useCallback(async () => {
|
const onLoadNote = useCallback(async () => {
|
||||||
InteractionManager.runAfterInteractions(() => {
|
InteractionManager.runAfterInteractions(() => {
|
||||||
@@ -229,29 +230,32 @@ export const useEditorEvents = (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, []);
|
}, [onHardwareBackPress]);
|
||||||
const onCallClear = useCallback(async (value: string) => {
|
const onCallClear = useCallback(
|
||||||
if (value === "removeHandler") {
|
async (value: string) => {
|
||||||
if (handleBack.current) {
|
if (value === "removeHandler") {
|
||||||
handleBack.current.remove();
|
if (handleBack.current) {
|
||||||
}
|
handleBack.current.remove();
|
||||||
return;
|
}
|
||||||
}
|
return;
|
||||||
if (value === "addHandler") {
|
|
||||||
if (handleBack.current) {
|
|
||||||
handleBack.current.remove();
|
|
||||||
}
|
}
|
||||||
|
if (value === "addHandler") {
|
||||||
|
if (handleBack.current) {
|
||||||
|
handleBack.current.remove();
|
||||||
|
}
|
||||||
|
|
||||||
handleBack.current = BackHandler.addEventListener(
|
handleBack.current = BackHandler.addEventListener(
|
||||||
"hardwareBackPress",
|
"hardwareBackPress",
|
||||||
onHardwareBackPress
|
onHardwareBackPress
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (editorState().currentlyEditing) {
|
if (editorState().currentlyEditing) {
|
||||||
await onBackPress();
|
await onBackPress();
|
||||||
}
|
}
|
||||||
}, []);
|
},
|
||||||
|
[onBackPress, onHardwareBackPress]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (fullscreen && DDS.isTab) {
|
if (fullscreen && DDS.isTab) {
|
||||||
@@ -266,7 +270,7 @@ export const useEditorEvents = (
|
|||||||
handleBack.current.remove();
|
handleBack.current.remove();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [fullscreen]);
|
}, [fullscreen, onHardwareBackPress]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent(eOnLoadNote + editor.editorId, onLoadNote);
|
eSubscribeEvent(eOnLoadNote + editor.editorId, onLoadNote);
|
||||||
@@ -275,107 +279,110 @@ export const useEditorEvents = (
|
|||||||
eUnSubscribeEvent(eClearEditor, onCallClear);
|
eUnSubscribeEvent(eClearEditor, onCallClear);
|
||||||
eUnSubscribeEvent(eOnLoadNote, onLoadNote);
|
eUnSubscribeEvent(eOnLoadNote, onLoadNote);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [editor.editorId, onCallClear, onLoadNote]);
|
||||||
|
|
||||||
const onMessage = (event: WebViewMessageEvent) => {
|
const onMessage = useCallback(
|
||||||
const data = event.nativeEvent.data;
|
(event: WebViewMessageEvent) => {
|
||||||
const editorMessage = JSON.parse(data) as EditorMessage;
|
const data = event.nativeEvent.data;
|
||||||
|
const editorMessage = JSON.parse(data) as EditorMessage;
|
||||||
|
|
||||||
logger.info("editor", editorMessage.type);
|
logger.info("editor", editorMessage.type);
|
||||||
if (
|
if (
|
||||||
editorMessage.sessionId !== editor.sessionId &&
|
editorMessage.sessionId !== editor.sessionId &&
|
||||||
editorMessage.type !== EditorEvents.status
|
editorMessage.type !== EditorEvents.status
|
||||||
) {
|
) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"editor",
|
"editor",
|
||||||
"invalid session",
|
"invalid session",
|
||||||
editorMessage.type,
|
|
||||||
editor.sessionId,
|
|
||||||
editorMessage.sessionId
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (editorMessage.type) {
|
|
||||||
case EventTypes.logger:
|
|
||||||
logger.info("[WEBVIEW LOG]", editorMessage.value);
|
|
||||||
break;
|
|
||||||
case EventTypes.content:
|
|
||||||
editor.saveContent({
|
|
||||||
type: editorMessage.type,
|
|
||||||
content: editorMessage.value as string
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case EventTypes.selection:
|
|
||||||
break;
|
|
||||||
case EventTypes.title:
|
|
||||||
editor.saveContent({
|
|
||||||
type: editorMessage.type,
|
|
||||||
title: editorMessage.value as string
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case EventTypes.newtag:
|
|
||||||
if (!editor.note.current) return;
|
|
||||||
eSendEvent(eOpenTagsDialog, editor.note.current);
|
|
||||||
break;
|
|
||||||
case EventTypes.tag:
|
|
||||||
if (editorMessage.value) {
|
|
||||||
if (!editor.note.current) return;
|
|
||||||
db.notes
|
|
||||||
?.note(editor.note.current?.id)
|
|
||||||
.untag(editorMessage.value)
|
|
||||||
.then(async () => {
|
|
||||||
useTagStore.getState().setTags();
|
|
||||||
await editor.commands.setTags(editor.note.current);
|
|
||||||
Navigation.queueRoutesForUpdate(
|
|
||||||
"ColoredNotes",
|
|
||||||
"Notes",
|
|
||||||
"TaggedNotes",
|
|
||||||
"TopicNotes",
|
|
||||||
"Tags"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EventTypes.filepicker:
|
|
||||||
const { pick } = require("./picker.js").default;
|
|
||||||
pick({ type: editorMessage.value });
|
|
||||||
break;
|
|
||||||
case EventTypes.download:
|
|
||||||
console.log("download attachment request", editorMessage.value);
|
|
||||||
const attachmentInfo = editorMessage.value as Attachment;
|
|
||||||
filesystem.downloadAttachment(attachmentInfo?.hash, true);
|
|
||||||
break;
|
|
||||||
case EventTypes.pro:
|
|
||||||
if (editor.state.current?.isFocused) {
|
|
||||||
editor.state.current.isFocused = true;
|
|
||||||
}
|
|
||||||
umami.pageView("/pro-screen", "/editor");
|
|
||||||
eSendEvent(eOpenPremiumDialog);
|
|
||||||
break;
|
|
||||||
case EventTypes.monograph:
|
|
||||||
publishNote(editor);
|
|
||||||
break;
|
|
||||||
case EventTypes.properties:
|
|
||||||
showActionsheet(editor);
|
|
||||||
break;
|
|
||||||
case EventTypes.fullscreen:
|
|
||||||
editorState().isFullscreen = true;
|
|
||||||
eSendEvent(eOpenFullscreenEditor);
|
|
||||||
break;
|
|
||||||
case EventTypes.back:
|
|
||||||
onBackPress();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(
|
|
||||||
"unhandled event recieved from editor: ",
|
|
||||||
editorMessage.type,
|
editorMessage.type,
|
||||||
editorMessage.value
|
editor.sessionId,
|
||||||
|
editorMessage.sessionId
|
||||||
);
|
);
|
||||||
break;
|
|
||||||
}
|
return;
|
||||||
eSendEvent(editorMessage.type, editorMessage);
|
}
|
||||||
};
|
switch (editorMessage.type) {
|
||||||
|
case EventTypes.logger:
|
||||||
|
logger.info("[WEBVIEW LOG]", editorMessage.value);
|
||||||
|
break;
|
||||||
|
case EventTypes.content:
|
||||||
|
editor.saveContent({
|
||||||
|
type: editorMessage.type,
|
||||||
|
content: editorMessage.value as string
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case EventTypes.selection:
|
||||||
|
break;
|
||||||
|
case EventTypes.title:
|
||||||
|
editor.saveContent({
|
||||||
|
type: editorMessage.type,
|
||||||
|
title: editorMessage.value as string
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case EventTypes.newtag:
|
||||||
|
if (!editor.note.current) return;
|
||||||
|
eSendEvent(eOpenTagsDialog, editor.note.current);
|
||||||
|
break;
|
||||||
|
case EventTypes.tag:
|
||||||
|
if (editorMessage.value) {
|
||||||
|
if (!editor.note.current) return;
|
||||||
|
db.notes
|
||||||
|
?.note(editor.note.current?.id)
|
||||||
|
.untag(editorMessage.value)
|
||||||
|
.then(async () => {
|
||||||
|
useTagStore.getState().setTags();
|
||||||
|
await editor.commands.setTags(editor.note.current);
|
||||||
|
Navigation.queueRoutesForUpdate(
|
||||||
|
"ColoredNotes",
|
||||||
|
"Notes",
|
||||||
|
"TaggedNotes",
|
||||||
|
"TopicNotes",
|
||||||
|
"Tags"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventTypes.filepicker:
|
||||||
|
const { pick } = require("./picker.js").default;
|
||||||
|
pick({ type: editorMessage.value });
|
||||||
|
break;
|
||||||
|
case EventTypes.download:
|
||||||
|
console.log("download attachment request", editorMessage.value);
|
||||||
|
const attachmentInfo = editorMessage.value as Attachment;
|
||||||
|
filesystem.downloadAttachment(attachmentInfo?.hash, true);
|
||||||
|
break;
|
||||||
|
case EventTypes.pro:
|
||||||
|
if (editor.state.current?.isFocused) {
|
||||||
|
editor.state.current.isFocused = true;
|
||||||
|
}
|
||||||
|
umami.pageView("/pro-screen", "/editor");
|
||||||
|
eSendEvent(eOpenPremiumDialog);
|
||||||
|
break;
|
||||||
|
case EventTypes.monograph:
|
||||||
|
publishNote(editor);
|
||||||
|
break;
|
||||||
|
case EventTypes.properties:
|
||||||
|
showActionsheet(editor);
|
||||||
|
break;
|
||||||
|
case EventTypes.fullscreen:
|
||||||
|
editorState().isFullscreen = true;
|
||||||
|
eSendEvent(eOpenFullscreenEditor);
|
||||||
|
break;
|
||||||
|
case EventTypes.back:
|
||||||
|
onBackPress();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(
|
||||||
|
"unhandled event recieved from editor: ",
|
||||||
|
editorMessage.type,
|
||||||
|
editorMessage.value
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
eSendEvent(editorMessage.type, editorMessage);
|
||||||
|
},
|
||||||
|
[editor, onBackPress]
|
||||||
|
);
|
||||||
|
|
||||||
return onMessage;
|
return onMessage;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export const useEditor = (
|
|||||||
commands.setInsets(
|
commands.setInsets(
|
||||||
isDefaultEditor ? insets : { top: 0, left: 0, right: 0, bottom: 0 }
|
isDefaultEditor ? insets : { top: 0, left: 0, right: 0, bottom: 0 }
|
||||||
);
|
);
|
||||||
}, [insets]);
|
}, [commands, insets, isDefaultEditor]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
sessionIdRef.current = sessionId;
|
sessionIdRef.current = sessionId;
|
||||||
@@ -87,7 +87,7 @@ export const useEditor = (
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
commands.setTags(currentNote.current);
|
commands.setTags(currentNote.current);
|
||||||
}, [tags]);
|
}, [commands, tags]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (theme) return;
|
if (theme) return;
|
||||||
@@ -98,28 +98,17 @@ export const useEditor = (
|
|||||||
return () => {
|
return () => {
|
||||||
unsub();
|
unsub();
|
||||||
};
|
};
|
||||||
}, []);
|
}, [postMessage, theme]);
|
||||||
|
|
||||||
useEffect(() => {
|
const overlay = useCallback(
|
||||||
console.log("sessionId:", sessionId);
|
(show: boolean, data = { type: "new" }) => {
|
||||||
async () => {
|
eSendEvent(
|
||||||
await commands.setSessionId(sessionIdRef.current);
|
"loadingNote" + editorId,
|
||||||
if (sessionIdRef.current) {
|
show ? currentNote.current || data : false
|
||||||
if (!state.current?.ready) return;
|
);
|
||||||
await onReady();
|
},
|
||||||
}
|
[editorId]
|
||||||
};
|
);
|
||||||
return () => {
|
|
||||||
state.current.saveCount = 0;
|
|
||||||
};
|
|
||||||
}, [sessionId, loading]);
|
|
||||||
|
|
||||||
const overlay = (show: boolean, data = { type: "new" }) => {
|
|
||||||
eSendEvent(
|
|
||||||
"loadingNote" + editorId,
|
|
||||||
show ? currentNote.current || data : false
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onReady = useCallback(async () => {
|
const onReady = useCallback(async () => {
|
||||||
if (!(await isEditorLoaded(editorRef, sessionIdRef.current))) {
|
if (!(await isEditorLoaded(editorRef, sessionIdRef.current))) {
|
||||||
@@ -127,7 +116,19 @@ export const useEditor = (
|
|||||||
overlay(true);
|
overlay(true);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [overlay]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("sessionId:", sessionId);
|
||||||
|
state.current.saveCount = 0;
|
||||||
|
async () => {
|
||||||
|
await commands.setSessionId(sessionIdRef.current);
|
||||||
|
if (sessionIdRef.current) {
|
||||||
|
if (!state.current?.ready) return;
|
||||||
|
await onReady();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [sessionId, loading, commands, onReady]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -143,24 +144,27 @@ export const useEditor = (
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const reset = useCallback(async (resetState = true) => {
|
const reset = useCallback(
|
||||||
currentNote.current?.id && db.fs.cancel(currentNote.current.id);
|
async (resetState = true) => {
|
||||||
currentNote.current = null;
|
currentNote.current?.id && db.fs.cancel(currentNote.current.id);
|
||||||
currentContent.current = null;
|
currentNote.current = null;
|
||||||
sessionHistoryId.current = undefined;
|
currentContent.current = null;
|
||||||
saveCount.current = 0;
|
sessionHistoryId.current = undefined;
|
||||||
useEditorStore.getState().setReadonly(false);
|
saveCount.current = 0;
|
||||||
postMessage(EditorEvents.title, "");
|
useEditorStore.getState().setReadonly(false);
|
||||||
await commands.clearContent();
|
postMessage(EditorEvents.title, "");
|
||||||
await commands.clearTags();
|
await commands.clearContent();
|
||||||
console.log("reset state: ", resetState);
|
await commands.clearTags();
|
||||||
if (resetState) {
|
console.log("reset state: ", resetState);
|
||||||
isDefaultEditor &&
|
if (resetState) {
|
||||||
useEditorStore.getState().setCurrentlyEditingNote(null);
|
isDefaultEditor &&
|
||||||
placeholderTip.current = TipManager.placeholderTip();
|
useEditorStore.getState().setCurrentlyEditingNote(null);
|
||||||
await commands.setPlaceholder(placeholderTip.current);
|
placeholderTip.current = TipManager.placeholderTip();
|
||||||
}
|
await commands.setPlaceholder(placeholderTip.current);
|
||||||
}, []);
|
}
|
||||||
|
},
|
||||||
|
[commands, isDefaultEditor, postMessage]
|
||||||
|
);
|
||||||
|
|
||||||
const saveNote = useCallback(
|
const saveNote = useCallback(
|
||||||
async ({
|
async ({
|
||||||
@@ -236,6 +240,7 @@ export const useEditor = (
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
noteData.contentId = note?.contentId;
|
noteData.contentId = note?.contentId;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
await db.vault?.save(noteData as any);
|
await db.vault?.save(noteData as any);
|
||||||
}
|
}
|
||||||
console.log(id, sessionIdRef.current, currentSessionId);
|
console.log(id, sessionIdRef.current, currentSessionId);
|
||||||
@@ -265,7 +270,7 @@ export const useEditor = (
|
|||||||
console.log("error saving: ", e);
|
console.log("error saving: ", e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[commands, reset]
|
[commands, isDefaultEditor, postMessage, readonly, reset]
|
||||||
);
|
);
|
||||||
|
|
||||||
const loadContent = useCallback(async (note: NoteType) => {
|
const loadContent = useCallback(async (note: NoteType) => {
|
||||||
@@ -322,7 +327,15 @@ export const useEditor = (
|
|||||||
loadImages();
|
loadImages();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setSessionId]
|
[
|
||||||
|
commands,
|
||||||
|
editorId,
|
||||||
|
isDefaultEditor,
|
||||||
|
loadContent,
|
||||||
|
overlay,
|
||||||
|
postMessage,
|
||||||
|
reset
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const loadImages = () => {
|
const loadImages = () => {
|
||||||
@@ -352,7 +365,7 @@ export const useEditor = (
|
|||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent(eOnLoadNote + editorId, loadNote);
|
eUnSubscribeEvent(eOnLoadNote + editorId, loadNote);
|
||||||
};
|
};
|
||||||
}, [editorId]);
|
}, [editorId, loadNote]);
|
||||||
|
|
||||||
const saveContent = useCallback(
|
const saveContent = useCallback(
|
||||||
({
|
({
|
||||||
@@ -398,28 +411,10 @@ export const useEditor = (
|
|||||||
500
|
500
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[sessionIdRef, sessionId]
|
[sessionId, withTimer, onChange, saveNote]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onLoad = useCallback(async () => {
|
const restoreEditorState = useCallback(async () => {
|
||||||
console.log("on editor load");
|
|
||||||
state.current.ready = true;
|
|
||||||
onReady();
|
|
||||||
postMessage(EditorEvents.theme, theme || useThemeStore.getState().colors);
|
|
||||||
commands.setInsets(
|
|
||||||
isDefaultEditor ? insets : { top: 0, left: 0, right: 0, bottom: 0 }
|
|
||||||
);
|
|
||||||
if (currentNote.current) {
|
|
||||||
console.log("force reload note");
|
|
||||||
loadNote({ ...currentNote.current, forced: true });
|
|
||||||
} else {
|
|
||||||
await commands.setPlaceholder(placeholderTip.current);
|
|
||||||
isDefaultEditor && restoreEditorState();
|
|
||||||
}
|
|
||||||
commands.setSettings();
|
|
||||||
}, [state, currentNote, loadNote]);
|
|
||||||
|
|
||||||
async function restoreEditorState() {
|
|
||||||
const json = await MMKV.getItem("appState");
|
const json = await MMKV.getItem("appState");
|
||||||
if (json) {
|
if (json) {
|
||||||
const appState = JSON.parse(json) as AppState;
|
const appState = JSON.parse(json) as AppState;
|
||||||
@@ -451,7 +446,34 @@ export const useEditor = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.current.isRestoringState = false;
|
state.current.isRestoringState = false;
|
||||||
}
|
}, [loadNote, overlay]);
|
||||||
|
|
||||||
|
const onLoad = useCallback(async () => {
|
||||||
|
console.log("on editor load");
|
||||||
|
state.current.ready = true;
|
||||||
|
onReady();
|
||||||
|
postMessage(EditorEvents.theme, theme || useThemeStore.getState().colors);
|
||||||
|
commands.setInsets(
|
||||||
|
isDefaultEditor ? insets : { top: 0, left: 0, right: 0, bottom: 0 }
|
||||||
|
);
|
||||||
|
if (currentNote.current) {
|
||||||
|
console.log("force reload note");
|
||||||
|
loadNote({ ...currentNote.current, forced: true });
|
||||||
|
} else {
|
||||||
|
await commands.setPlaceholder(placeholderTip.current);
|
||||||
|
isDefaultEditor && restoreEditorState();
|
||||||
|
}
|
||||||
|
commands.setSettings();
|
||||||
|
}, [
|
||||||
|
onReady,
|
||||||
|
postMessage,
|
||||||
|
theme,
|
||||||
|
commands,
|
||||||
|
isDefaultEditor,
|
||||||
|
insets,
|
||||||
|
loadNote,
|
||||||
|
restoreEditorState
|
||||||
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ref: editorRef,
|
ref: editorRef,
|
||||||
|
|||||||
@@ -30,12 +30,11 @@ import {
|
|||||||
eSubscribeEvent,
|
eSubscribeEvent,
|
||||||
eUnSubscribeEvent
|
eUnSubscribeEvent
|
||||||
} from "../../services/event-manager";
|
} from "../../services/event-manager";
|
||||||
import Navigation, {
|
import Navigation, { NavigationProps } from "../../services/navigation";
|
||||||
NavigationProps,
|
|
||||||
NotebookScreenParams
|
|
||||||
} from "../../services/navigation";
|
|
||||||
import SearchService from "../../services/search";
|
import SearchService from "../../services/search";
|
||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
import useNavigationStore, {
|
||||||
|
NotebookScreenParams
|
||||||
|
} from "../../stores/use-navigation-store";
|
||||||
import {
|
import {
|
||||||
eOnNewTopicAdded,
|
eOnNewTopicAdded,
|
||||||
eOpenAddNotebookDialog,
|
eOpenAddNotebookDialog,
|
||||||
@@ -60,7 +59,7 @@ const Notebook = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
|||||||
onBlur: () => false
|
onBlur: () => false
|
||||||
});
|
});
|
||||||
|
|
||||||
const syncWithNavigation = () => {
|
const syncWithNavigation = React.useCallback(() => {
|
||||||
useNavigationStore.getState().update(
|
useNavigationStore.getState().update(
|
||||||
{
|
{
|
||||||
name: route.name,
|
name: route.name,
|
||||||
@@ -71,35 +70,38 @@ const Notebook = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
|||||||
params.current?.canGoBack
|
params.current?.canGoBack
|
||||||
);
|
);
|
||||||
SearchService.prepareSearch = prepareSearch;
|
SearchService.prepareSearch = prepareSearch;
|
||||||
};
|
}, [route.name]);
|
||||||
|
|
||||||
const onRequestUpdate = (data?: NotebookScreenParams) => {
|
const onRequestUpdate = React.useCallback(
|
||||||
if (data) params.current = data;
|
(data?: NotebookScreenParams) => {
|
||||||
params.current.title = params.current.item.title;
|
if (data) params.current = data;
|
||||||
try {
|
params.current.title = params.current.item.title;
|
||||||
const notebook = db.notebooks?.notebook(params?.current?.item?.id)
|
try {
|
||||||
?.data as NotebookType;
|
const notebook = db.notebooks?.notebook(params?.current?.item?.id)
|
||||||
if (notebook) {
|
?.data as NotebookType;
|
||||||
params.current.item = notebook;
|
if (notebook) {
|
||||||
setTopics(
|
params.current.item = notebook;
|
||||||
groupArray(
|
setTopics(
|
||||||
qclone(notebook.topics),
|
groupArray(
|
||||||
db.settings?.getGroupOptions("topics")
|
qclone(notebook.topics),
|
||||||
)
|
db.settings?.getGroupOptions("topics")
|
||||||
);
|
)
|
||||||
syncWithNavigation();
|
);
|
||||||
|
syncWithNavigation();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
},
|
||||||
console.error(e);
|
[syncWithNavigation]
|
||||||
}
|
);
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent(eOnNewTopicAdded, onRequestUpdate);
|
eSubscribeEvent(eOnNewTopicAdded, onRequestUpdate);
|
||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent(eOnNewTopicAdded, onRequestUpdate);
|
eUnSubscribeEvent(eOnNewTopicAdded, onRequestUpdate);
|
||||||
};
|
};
|
||||||
}, [topics]);
|
}, [onRequestUpdate, topics]);
|
||||||
|
|
||||||
const prepareSearch = () => {
|
const prepareSearch = () => {
|
||||||
SearchService.update({
|
SearchService.update({
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ import { groupArray } from "@notesnook/core/utils/grouping";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import NotesPage, { PLACEHOLDER_DATA } from ".";
|
import NotesPage, { PLACEHOLDER_DATA } from ".";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import Navigation, {
|
import Navigation, { NavigationProps } from "../../services/navigation";
|
||||||
NavigationProps,
|
import { NotesScreenParams } from "../../stores/use-navigation-store";
|
||||||
NotesScreenParams
|
|
||||||
} from "../../services/navigation";
|
|
||||||
import { ColorType } from "../../utils/types";
|
import { ColorType } from "../../utils/types";
|
||||||
import { getAlias, openEditor, toCamelCase } from "./common";
|
import { getAlias, openEditor, toCamelCase } from "./common";
|
||||||
export const ColoredNotes = ({
|
export const ColoredNotes = ({
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
import { DDS } from "../../services/device-detection";
|
import { DDS } from "../../services/device-detection";
|
||||||
import { eSendEvent } from "../../services/event-manager";
|
import { eSendEvent } from "../../services/event-manager";
|
||||||
import Navigation, { NotesScreenParams } from "../../services/navigation";
|
import Navigation from "../../services/navigation";
|
||||||
import { useMenuStore } from "../../stores/use-menu-store";
|
import { useMenuStore } from "../../stores/use-menu-store";
|
||||||
import { useTagStore } from "../../stores/use-tag-store";
|
import { useTagStore } from "../../stores/use-tag-store";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
@@ -26,6 +26,8 @@ import { eOnLoadNote } from "../../utils/events";
|
|||||||
import { openLinkInBrowser } from "../../utils/functions";
|
import { openLinkInBrowser } from "../../utils/functions";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { tabBarRef } from "../../utils/global-refs";
|
||||||
import { editorController, editorState } from "../editor/tiptap/utils";
|
import { editorController, editorState } from "../editor/tiptap/utils";
|
||||||
|
import { NotesScreenParams } from "../../stores/use-navigation-store";
|
||||||
|
import { TopicType } from "../../utils/types";
|
||||||
|
|
||||||
export function toCamelCase(title: string) {
|
export function toCamelCase(title: string) {
|
||||||
return title.slice(0, 1).toUpperCase() + title.slice(1);
|
return title.slice(0, 1).toUpperCase() + title.slice(1);
|
||||||
@@ -34,7 +36,7 @@ export function toCamelCase(title: string) {
|
|||||||
export function getAlias(params: Partial<NotesScreenParams>) {
|
export function getAlias(params: Partial<NotesScreenParams>) {
|
||||||
if (!params) return "";
|
if (!params) return "";
|
||||||
const { item } = params;
|
const { item } = params;
|
||||||
return item?.alias || item?.title;
|
return (item as TopicType)?.alias || item?.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openMonographsWebpage() {
|
export function openMonographsWebpage() {
|
||||||
|
|||||||
@@ -25,13 +25,11 @@ import {
|
|||||||
eSubscribeEvent,
|
eSubscribeEvent,
|
||||||
eUnSubscribeEvent
|
eUnSubscribeEvent
|
||||||
} from "../../services/event-manager";
|
} from "../../services/event-manager";
|
||||||
import Navigation, {
|
import Navigation, { NavigationProps } from "../../services/navigation";
|
||||||
NavigationProps,
|
|
||||||
NotesScreenParams
|
|
||||||
} from "../../services/navigation";
|
|
||||||
import SearchService from "../../services/search";
|
import SearchService from "../../services/search";
|
||||||
import useNavigationStore, {
|
import useNavigationStore, {
|
||||||
HeaderRightButton,
|
HeaderRightButton,
|
||||||
|
NotesScreenParams,
|
||||||
RouteName
|
RouteName
|
||||||
} from "../../stores/use-navigation-store";
|
} from "../../stores/use-navigation-store";
|
||||||
import { useNoteStore } from "../../stores/use-notes-store";
|
import { useNoteStore } from "../../stores/use-notes-store";
|
||||||
@@ -117,10 +115,21 @@ const NotesPage = ({
|
|||||||
focusOnInit: !focusControl
|
focusOnInit: !focusControl
|
||||||
});
|
});
|
||||||
|
|
||||||
const syncWithNavigation = () => {
|
const prepareSearch = React.useCallback(() => {
|
||||||
|
const { item } = params.current;
|
||||||
|
SearchService.update({
|
||||||
|
placeholder: `Search in ${alias}`,
|
||||||
|
type: "notes",
|
||||||
|
title: item.type === "tag" ? "#" + alias : toCamelCase(item.title),
|
||||||
|
get: () => {
|
||||||
|
return get(params.current, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [alias, get]);
|
||||||
|
|
||||||
|
const syncWithNavigation = React.useCallback(() => {
|
||||||
const { item, title } = params.current;
|
const { item, title } = params.current;
|
||||||
const alias = getAlias(params.current);
|
const alias = getAlias(params.current);
|
||||||
console.log(alias, title, "syncWithNavigation", params.current);
|
|
||||||
useNavigationStore.getState().update(
|
useNavigationStore.getState().update(
|
||||||
{
|
{
|
||||||
name: route.name,
|
name: route.name,
|
||||||
@@ -146,35 +155,44 @@ const NotesPage = ({
|
|||||||
color: item.title,
|
color: item.title,
|
||||||
notebook: (item as TopicType).notebookId
|
notebook: (item as TopicType).notebookId
|
||||||
});
|
});
|
||||||
};
|
}, [
|
||||||
|
isMonograph,
|
||||||
|
onPressFloatingButton,
|
||||||
|
prepareSearch,
|
||||||
|
rightButtons,
|
||||||
|
route.name
|
||||||
|
]);
|
||||||
|
|
||||||
const onRequestUpdate = (data?: NotesScreenParams) => {
|
const onRequestUpdate = React.useCallback(
|
||||||
const isNew = data && data?.item?.id !== params.current?.item?.id;
|
(data?: NotesScreenParams) => {
|
||||||
if (data) params.current = data;
|
const isNew = data && data?.item?.id !== params.current?.item?.id;
|
||||||
params.current.title = params.current.title || params.current.item.title;
|
if (data) params.current = data;
|
||||||
const { item } = params.current;
|
params.current.title = params.current.title || params.current.item.title;
|
||||||
try {
|
const { item } = params.current;
|
||||||
if (isNew) setLoadingNotes(true);
|
try {
|
||||||
const notes = get(params.current, true) as NoteType[];
|
if (isNew) setLoadingNotes(true);
|
||||||
if (
|
const notes = get(params.current, true) as NoteType[];
|
||||||
(item.type === "tag" || item.type === "color") &&
|
if (
|
||||||
(!notes || notes.length === 0)
|
(item.type === "tag" || item.type === "color") &&
|
||||||
) {
|
(!notes || notes.length === 0)
|
||||||
return Navigation.goBack();
|
) {
|
||||||
|
return Navigation.goBack();
|
||||||
|
}
|
||||||
|
if (item.type === "topic") setWarning(!isSynced(params.current));
|
||||||
|
setNotes(notes);
|
||||||
|
syncWithNavigation();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
if (item.type === "topic") setWarning(!isSynced(params.current));
|
},
|
||||||
setNotes(notes);
|
[get, syncWithNavigation]
|
||||||
syncWithNavigation();
|
);
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loadingNotes) {
|
if (loadingNotes) {
|
||||||
setTimeout(() => setLoadingNotes(false), 300);
|
setTimeout(() => setLoadingNotes(false), 300);
|
||||||
}
|
}
|
||||||
}, [notes]);
|
}, [loadingNotes, notes]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eSubscribeEvent(route.name, onRequestUpdate);
|
eSubscribeEvent(route.name, onRequestUpdate);
|
||||||
@@ -182,19 +200,7 @@ const NotesPage = ({
|
|||||||
setOnFirstSave(null);
|
setOnFirstSave(null);
|
||||||
eUnSubscribeEvent(route.name, onRequestUpdate);
|
eUnSubscribeEvent(route.name, onRequestUpdate);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [onRequestUpdate, route.name]);
|
||||||
|
|
||||||
const prepareSearch = () => {
|
|
||||||
const { item } = params.current;
|
|
||||||
SearchService.update({
|
|
||||||
placeholder: `Search in ${alias}`,
|
|
||||||
type: "notes",
|
|
||||||
title: item.type === "tag" ? "#" + alias : toCamelCase(item.title),
|
|
||||||
get: () => {
|
|
||||||
return get(params.current, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DelayLayout
|
<DelayLayout
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ import { groupArray } from "@notesnook/core/utils/grouping";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import NotesPage, { PLACEHOLDER_DATA } from ".";
|
import NotesPage, { PLACEHOLDER_DATA } from ".";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import Navigation, {
|
import Navigation, { NavigationProps } from "../../services/navigation";
|
||||||
NavigationProps,
|
import { NotesScreenParams } from "../../stores/use-navigation-store";
|
||||||
NotesScreenParams
|
|
||||||
} from "../../services/navigation";
|
|
||||||
import { MonographType } from "../../utils/types";
|
import { MonographType } from "../../utils/types";
|
||||||
import { openMonographsWebpage } from "./common";
|
import { openMonographsWebpage } from "./common";
|
||||||
export const Monographs = ({
|
export const Monographs = ({
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ import { groupArray } from "@notesnook/core/utils/grouping";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import NotesPage, { PLACEHOLDER_DATA } from ".";
|
import NotesPage, { PLACEHOLDER_DATA } from ".";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import Navigation, {
|
import Navigation, { NavigationProps } from "../../services/navigation";
|
||||||
NavigationProps,
|
import { NotesScreenParams } from "../../stores/use-navigation-store";
|
||||||
NotesScreenParams
|
|
||||||
} from "../../services/navigation";
|
|
||||||
import { NoteType, TagType } from "../../utils/types";
|
import { NoteType, TagType } from "../../utils/types";
|
||||||
import { getAlias, openEditor } from "./common";
|
import { getAlias, openEditor } from "./common";
|
||||||
export const TaggedNotes = ({
|
export const TaggedNotes = ({
|
||||||
|
|||||||
@@ -22,10 +22,8 @@ import NotesPage, { PLACEHOLDER_DATA } from ".";
|
|||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import { MoveNotes } from "../../components/sheets/move-notes/movenote";
|
import { MoveNotes } from "../../components/sheets/move-notes/movenote";
|
||||||
import { eSendEvent } from "../../services/event-manager";
|
import { eSendEvent } from "../../services/event-manager";
|
||||||
import Navigation, {
|
import Navigation, { NavigationProps } from "../../services/navigation";
|
||||||
NavigationProps,
|
import { NotesScreenParams } from "../../stores/use-navigation-store";
|
||||||
NotesScreenParams
|
|
||||||
} from "../../services/navigation";
|
|
||||||
import { eOpenAddTopicDialog } from "../../utils/events";
|
import { eOpenAddTopicDialog } from "../../utils/events";
|
||||||
import { NotebookType, TopicType } from "../../utils/types";
|
import { NotebookType, TopicType } from "../../utils/types";
|
||||||
import { openEditor } from "./common";
|
import { openEditor } from "./common";
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export const Search = ({ navigation, route }) => {
|
|||||||
setSearchResults([]);
|
setSearchResults([]);
|
||||||
setSearchStatus(false, null);
|
setSearchStatus(false, null);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [setSearchResults, setSearchStatus]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DelayLayout wait={searching}>
|
<DelayLayout wait={searching}>
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export const MFASetup = ({
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
}, [method?.id]);
|
||||||
|
|
||||||
const codeHelpText = {
|
const codeHelpText = {
|
||||||
app: "After putting the above code in authenticator app, the app will display a code that you can enter below.",
|
app: "After putting the above code in authenticator app, the app will display a code that you can enter below.",
|
||||||
|
|||||||
@@ -78,59 +78,62 @@ export default function DebugLogs() {
|
|||||||
setLogs(logs);
|
setLogs(logs);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, [seconds]);
|
}, [currentLog, seconds, start]);
|
||||||
|
|
||||||
const renderItem = ({ item }: { item: LogMessage; index: number }) => {
|
const renderItem = React.useCallback(
|
||||||
const background =
|
({ item }: { item: LogMessage; index: number }) => {
|
||||||
item.level === LogLevel.Error || item.level === LogLevel.Fatal
|
const background =
|
||||||
? hexToRGBA(colors.red, 0.2)
|
item.level === LogLevel.Error || item.level === LogLevel.Fatal
|
||||||
: item.level === LogLevel.Warn
|
? hexToRGBA(colors.red, 0.2)
|
||||||
? hexToRGBA(colors.orange, 0.2)
|
: item.level === LogLevel.Warn
|
||||||
: "transparent";
|
? hexToRGBA(colors.orange, 0.2)
|
||||||
|
: "transparent";
|
||||||
|
|
||||||
const color =
|
const color =
|
||||||
item.level === LogLevel.Error || item.level === LogLevel.Fatal
|
item.level === LogLevel.Error || item.level === LogLevel.Fatal
|
||||||
? colors.red
|
? colors.red
|
||||||
: item.level === LogLevel.Warn
|
: item.level === LogLevel.Warn
|
||||||
? colors.orange
|
? colors.orange
|
||||||
: colors.pri;
|
: colors.pri;
|
||||||
|
|
||||||
return !item ? null : (
|
return !item ? null : (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
activeOpacity={1}
|
activeOpacity={1}
|
||||||
onLongPress={() => {
|
onLongPress={() => {
|
||||||
Clipboard.setString(format(item));
|
Clipboard.setString(format(item));
|
||||||
ToastEvent.show({
|
ToastEvent.show({
|
||||||
heading: "Debug log copied!",
|
heading: "Debug log copied!",
|
||||||
context: "global",
|
context: "global",
|
||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
paddingVertical: 12,
|
paddingVertical: 12,
|
||||||
backgroundColor: background,
|
backgroundColor: background,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
borderBottomColor: colors.nav
|
borderBottomColor: colors.nav
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Paragraph
|
|
||||||
style={{
|
|
||||||
flexShrink: 1,
|
|
||||||
flexWrap: "wrap",
|
|
||||||
fontFamily: Platform.OS === "ios" ? "Menlo" : "monospace"
|
|
||||||
}}
|
}}
|
||||||
size={12}
|
|
||||||
color={color}
|
|
||||||
>
|
>
|
||||||
{format(item)}
|
<Paragraph
|
||||||
</Paragraph>
|
style={{
|
||||||
</TouchableOpacity>
|
flexShrink: 1,
|
||||||
);
|
flexWrap: "wrap",
|
||||||
};
|
fontFamily: Platform.OS === "ios" ? "Menlo" : "monospace"
|
||||||
|
}}
|
||||||
|
size={12}
|
||||||
|
color={color}
|
||||||
|
>
|
||||||
|
{format(item)}
|
||||||
|
</Paragraph>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[colors.nav, colors.orange, colors.pri, colors.red]
|
||||||
|
);
|
||||||
|
|
||||||
const downloadLogs = async () => {
|
const downloadLogs = React.useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
let path = null;
|
let path = null;
|
||||||
const fileName = sanitizeFilename(`notesnook_logs_${Date.now()}`);
|
const fileName = sanitizeFilename(`notesnook_logs_${Date.now()}`);
|
||||||
@@ -165,9 +168,9 @@ export default function DebugLogs() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
};
|
}, [currentLog?.logs]);
|
||||||
|
|
||||||
const copyLogs = () => {
|
const copyLogs = React.useCallback(() => {
|
||||||
const data = currentLog?.logs
|
const data = currentLog?.logs
|
||||||
.map((log) => {
|
.map((log) => {
|
||||||
return !log ? "" : format(log);
|
return !log ? "" : format(log);
|
||||||
@@ -180,9 +183,9 @@ export default function DebugLogs() {
|
|||||||
context: "global",
|
context: "global",
|
||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
};
|
}, [currentLog?.logs]);
|
||||||
|
|
||||||
const clearLogs = () => {
|
const clearLogs = React.useCallback(() => {
|
||||||
if (!currentLog) return;
|
if (!currentLog) return;
|
||||||
presentDialog({
|
presentDialog({
|
||||||
title: "Clear logs",
|
title: "Clear logs",
|
||||||
@@ -203,7 +206,7 @@ export default function DebugLogs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}, [currentLog, logs]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -45,58 +45,61 @@ export default function ToolSheet({
|
|||||||
const data = useDragState((state) => state.data);
|
const data = useDragState((state) => state.data);
|
||||||
const ungrouped = getUngroupedTools(data) as ToolId[];
|
const ungrouped = getUngroupedTools(data) as ToolId[];
|
||||||
|
|
||||||
const renderTool = React.useCallback((item: ToolId) => {
|
const renderTool = React.useCallback(
|
||||||
const tool = findToolById(item);
|
(item: ToolId) => {
|
||||||
const iconSvgString = tool ? getToolIcon(tool.icon as ToolId) : null;
|
const tool = findToolById(item);
|
||||||
return (
|
const iconSvgString = tool ? getToolIcon(tool.icon as ToolId) : null;
|
||||||
<PressableButton
|
return (
|
||||||
key={item}
|
<PressableButton
|
||||||
type="grayBg"
|
key={item}
|
||||||
onPress={() => {
|
type="grayBg"
|
||||||
const _data = useDragState.getState().data.slice();
|
onPress={() => {
|
||||||
if (group.groupIndex !== undefined) {
|
const _data = useDragState.getState().data.slice();
|
||||||
(_data[group.groupIndex][group.index] as ToolId[]).unshift(
|
if (group.groupIndex !== undefined) {
|
||||||
item as ToolId
|
(_data[group.groupIndex][group.index] as ToolId[]).unshift(
|
||||||
);
|
item as ToolId
|
||||||
} else {
|
);
|
||||||
_data[group.index].unshift(item);
|
} else {
|
||||||
}
|
_data[group.index].unshift(item);
|
||||||
useDragState.getState().setData(_data);
|
}
|
||||||
}}
|
useDragState.getState().setData(_data);
|
||||||
customStyle={{
|
}}
|
||||||
marginBottom: 10,
|
customStyle={{
|
||||||
width: "100%",
|
marginBottom: 10,
|
||||||
height: 50,
|
width: "100%",
|
||||||
paddingHorizontal: 12,
|
height: 50,
|
||||||
paddingRight: 0,
|
paddingHorizontal: 12,
|
||||||
borderRadius: 5,
|
paddingRight: 0,
|
||||||
flexDirection: "row",
|
borderRadius: 5,
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center"
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-start"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{iconSvgString ? (
|
<View
|
||||||
<SvgView width={23} height={23} src={iconSvgString} />
|
|
||||||
) : null}
|
|
||||||
<Paragraph
|
|
||||||
style={{
|
style={{
|
||||||
marginLeft: iconSvgString ? 10 : 0
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
}}
|
}}
|
||||||
color={colors.pri}
|
|
||||||
size={SIZE.sm}
|
|
||||||
>
|
>
|
||||||
{tool?.title}
|
{iconSvgString ? (
|
||||||
</Paragraph>
|
<SvgView width={23} height={23} src={iconSvgString} />
|
||||||
</View>
|
) : null}
|
||||||
</PressableButton>
|
<Paragraph
|
||||||
);
|
style={{
|
||||||
}, []);
|
marginLeft: iconSvgString ? 10 : 0
|
||||||
|
}}
|
||||||
|
color={colors.pri}
|
||||||
|
size={SIZE.sm}
|
||||||
|
>
|
||||||
|
{tool?.title}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
</PressableButton>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[colors.pri, group.groupIndex, group.index]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -64,60 +64,64 @@ export const Tool = ({
|
|||||||
const iconSvgString =
|
const iconSvgString =
|
||||||
isSubgroup || !tool ? null : getToolIcon(tool.icon as ToolId);
|
isSubgroup || !tool ? null : getToolIcon(tool.icon as ToolId);
|
||||||
|
|
||||||
const buttons = isSubgroup
|
const buttons = React.useMemo(
|
||||||
? [
|
() =>
|
||||||
{
|
isSubgroup
|
||||||
name: "minus",
|
? [
|
||||||
onPress: () => {
|
{
|
||||||
presentDialog({
|
name: "minus",
|
||||||
context: "global",
|
onPress: () => {
|
||||||
title: "Delete collapsed section?",
|
presentDialog({
|
||||||
positiveText: "Delete",
|
context: "global",
|
||||||
paragraph:
|
title: "Delete collapsed section?",
|
||||||
"All tools in the collapsed section will also be removed.",
|
positiveText: "Delete",
|
||||||
positivePress: () => {
|
paragraph:
|
||||||
|
"All tools in the collapsed section will also be removed.",
|
||||||
|
positivePress: () => {
|
||||||
|
if (typeof groupIndex !== "number") return;
|
||||||
|
const _data = useDragState.getState().data.slice();
|
||||||
|
_data[groupIndex].splice(index, 1);
|
||||||
|
setData(_data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plus",
|
||||||
|
onPress: () => {
|
||||||
|
ToolSheet.present({
|
||||||
|
item,
|
||||||
|
index,
|
||||||
|
groupIndex,
|
||||||
|
parentIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
name: "minus",
|
||||||
|
onPress: () => {
|
||||||
if (typeof groupIndex !== "number") return;
|
if (typeof groupIndex !== "number") return;
|
||||||
const _data = useDragState.getState().data.slice();
|
const _data = useDragState.getState().data.slice();
|
||||||
_data[groupIndex].splice(index, 1);
|
if (typeof parentIndex !== "number") {
|
||||||
|
const index = _data[groupIndex].findIndex(
|
||||||
|
(tool) => tool === item
|
||||||
|
);
|
||||||
|
_data[groupIndex].splice(index, 1);
|
||||||
|
} else {
|
||||||
|
const index = (
|
||||||
|
_data[parentIndex][groupIndex] as ToolId[]
|
||||||
|
).findIndex((tool: string) => tool === item);
|
||||||
|
(_data[parentIndex][groupIndex] as ToolId[]).splice(index, 1);
|
||||||
|
}
|
||||||
|
console.log(_data[groupIndex]);
|
||||||
setData(_data);
|
setData(_data);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "plus",
|
|
||||||
onPress: () => {
|
|
||||||
ToolSheet.present({
|
|
||||||
item,
|
|
||||||
index,
|
|
||||||
groupIndex,
|
|
||||||
parentIndex
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
{
|
|
||||||
name: "minus",
|
|
||||||
onPress: () => {
|
|
||||||
if (typeof groupIndex !== "number") return;
|
|
||||||
const _data = useDragState.getState().data.slice();
|
|
||||||
if (typeof parentIndex !== "number") {
|
|
||||||
const index = _data[groupIndex].findIndex(
|
|
||||||
(tool) => tool === item
|
|
||||||
);
|
|
||||||
_data[groupIndex].splice(index, 1);
|
|
||||||
} else {
|
|
||||||
const index = (
|
|
||||||
_data[parentIndex][groupIndex] as ToolId[]
|
|
||||||
).findIndex((tool: string) => tool === item);
|
|
||||||
(_data[parentIndex][groupIndex] as ToolId[]).splice(index, 1);
|
|
||||||
}
|
}
|
||||||
console.log(_data[groupIndex]);
|
],
|
||||||
setData(_data);
|
[groupIndex, index, isSubgroup, item, parentIndex, setData]
|
||||||
}
|
);
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
if (parentIndex === undefined && !isSubgroup) {
|
if (parentIndex === undefined && !isSubgroup) {
|
||||||
buttons.unshift({
|
buttons.unshift({
|
||||||
@@ -236,7 +240,20 @@ export const Tool = ({
|
|||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
[]
|
[
|
||||||
|
buttons,
|
||||||
|
colors.bg,
|
||||||
|
colors.icon,
|
||||||
|
colors.nav,
|
||||||
|
colors.pri,
|
||||||
|
groupIndex,
|
||||||
|
iconSvgString,
|
||||||
|
index,
|
||||||
|
isDragged,
|
||||||
|
isSubgroup,
|
||||||
|
item,
|
||||||
|
tool?.title
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onDrop = (data: DraxDragWithReceiverEventData) => {
|
const onDrop = (data: DraxDragWithReceiverEventData) => {
|
||||||
|
|||||||
@@ -24,13 +24,6 @@ import Group from "./group";
|
|||||||
import Home from "./home";
|
import Home from "./home";
|
||||||
import { RouteParams } from "./types";
|
import { RouteParams } from "./types";
|
||||||
const SettingsStack = createNativeStackNavigator<RouteParams>();
|
const SettingsStack = createNativeStackNavigator<RouteParams>();
|
||||||
const screenListeners = {
|
|
||||||
beforeRemove: (e: any) => {
|
|
||||||
if (e.target?.startsWith("SettingsGroup")) {
|
|
||||||
useNavigationStore.getState().update({ name: "Settings" }, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// const Home = React.lazy(() => import(/* webpackChunkName: "settings-home" */ './home'));
|
// const Home = React.lazy(() => import(/* webpackChunkName: "settings-home" */ './home'));
|
||||||
// const Group = React.lazy(() => import(/* webpackChunkName: "settings-group" */ './group'));
|
// const Group = React.lazy(() => import(/* webpackChunkName: "settings-group" */ './group'));
|
||||||
@@ -65,7 +58,13 @@ export const Settings = () => {
|
|||||||
return (
|
return (
|
||||||
<SettingsStack.Navigator
|
<SettingsStack.Navigator
|
||||||
initialRouteName="SettingsHome"
|
initialRouteName="SettingsHome"
|
||||||
screenListeners={screenListeners}
|
screenListeners={{
|
||||||
|
beforeRemove: (e) => {
|
||||||
|
if (e.target?.startsWith("SettingsGroup")) {
|
||||||
|
useNavigationStore.getState().update({ name: "Settings" }, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
animation: "none",
|
animation: "none",
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ export const useTip = (
|
|||||||
return () => {
|
return () => {
|
||||||
clearInterval(intervalRef.current);
|
clearInterval(intervalRef.current);
|
||||||
};
|
};
|
||||||
}, [context, fallback]);
|
}, [context, fallback, options.delay, options?.rotate]);
|
||||||
|
|
||||||
return tip;
|
return tip;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ export type Item =
|
|||||||
|
|
||||||
export type MonographType = {
|
export type MonographType = {
|
||||||
type: "monograph";
|
type: "monograph";
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
dateModified: number;
|
||||||
|
dateCreated: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Entity<TType extends EntityTypes> {
|
export interface Entity<TType extends EntityTypes> {
|
||||||
|
|||||||
Reference in New Issue
Block a user