mobile: fix all eslint warnings

This commit is contained in:
ammarahm-ed
2022-08-30 18:27:09 +05:00
parent 2d84b79f22
commit be21c4735f
65 changed files with 1075 additions and 887 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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>

View File

@@ -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,

View File

@@ -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);

View File

@@ -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

View File

@@ -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 : (
<> <>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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(

View File

@@ -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);

View File

@@ -105,7 +105,7 @@ const List = ({
screen={screen} screen={screen}
/> />
), ),
[] [headerProps.color, headerProps.heading, screen, type]
); );
const _onRefresh = async () => { const _onRefresh = async () => {

View File

@@ -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 (

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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({

View File

@@ -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) {

View File

@@ -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({

View File

@@ -76,7 +76,7 @@ export const Update = ({ version: appVersion, fwdRef }) => {
} }
})(); })();
} }
}, []); }, [version]);
return ( return (
<View <View

View File

@@ -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);

View File

@@ -96,7 +96,7 @@ export const SideMenu = React.memo(
<TagsSection /> <TagsSection />
</> </>
), ),
[] [noTextMode]
); );
return !loading && introCompleted ? ( return !loading && introCompleted ? (

View File

@@ -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

View File

@@ -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",

View File

@@ -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(

View File

@@ -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 && (

View File

@@ -105,7 +105,7 @@ export const PressableButton = ({
}, },
customStyle customStyle
], ],
[customStyle, noborder, type, colors] [alpha, selectedColor, opacity, primaryColor, noborder, customStyle]
); );
return ( return (

View File

@@ -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();

View File

@@ -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>

View File

@@ -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();

View File

@@ -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;

View File

@@ -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];
}; };

View File

@@ -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 [];
}; };

View File

@@ -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;

View File

@@ -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;
}; };

View File

@@ -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;
}; };

View File

@@ -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;
} }

View File

@@ -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

View File

@@ -113,7 +113,7 @@ export const useTooltipHandler = (
return () => { return () => {
eUnSubscribeEvent(id, callback); eUnSubscribeEvent(id, callback);
}; };
}, []); }, [callback, id]);
return null; return null;
}; };

View File

@@ -54,7 +54,7 @@ export const useVaultStatus = () => {
return () => { return () => {
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus()); eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
}; };
}, []); }, [checkVaultStatus]);
return vaultStatus; return vaultStatus;
}; };

View File

@@ -60,7 +60,7 @@ export const useVaultStatus = () => {
return () => { return () => {
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus()); eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
}; };
}, []); }, [checkVaultStatus]);
return vaultStatus; return vaultStatus;
}; };

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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 : (
<> <>

View File

@@ -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 {

View File

@@ -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;
}; };

View File

@@ -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,

View File

@@ -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({

View File

@@ -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 = ({

View File

@@ -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() {

View File

@@ -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

View File

@@ -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 = ({

View File

@@ -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 = ({

View File

@@ -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";

View File

@@ -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}>

View File

@@ -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.",

View File

@@ -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

View File

@@ -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

View File

@@ -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) => {

View File

@@ -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,

View File

@@ -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;
}; };

View File

@@ -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> {