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";
import BaseDialog from "../dialog/base-dialog";
import { allowedOnPlatform, renderItem } from "./functions";
import { useCallback } from "react";
export const AnnouncementDialog = () => {
const colors = useThemeStore((state) => state.colors);
@@ -45,20 +46,20 @@ export const AnnouncementDialog = () => {
eUnSubscribeEvent(eOpenAnnouncementDialog, open);
eUnSubscribeEvent(eCloseAnnouncementDialog, close);
};
}, [visible]);
}, [close, visible]);
const open = (data) => {
setInfo(data);
setVisible(true);
};
const close = () => {
const close = useCallback(() => {
if (visible) {
remove(info.id);
setInfo(null);
setVisible(false);
}
};
}, [info.id, remove, visible]);
return (
<BaseDialog

View File

@@ -48,6 +48,7 @@ import { Notice } from "../ui/notice";
import { PressableButton } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
const Actions = ({ attachment, setAttachments, fwdRef }) => {
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 attachmentNotes = attachment.noteIds?.map((id) => {
let index = allNotes?.findIndex((note) => id === note.id);
@@ -169,11 +170,11 @@ const Actions = ({ attachment, setAttachments, fwdRef }) => {
}
});
return attachmentNotes;
};
}, [attachment.noteIds]);
useEffect(() => {
setNotes(getNotes());
}, [attachment]);
}, [attachment, getNotes]);
return (
<ScrollView

View File

@@ -42,9 +42,9 @@ export const AttachmentItem = ({ attachment, encryption, setAttachments }) => {
attachment,
encryption
);
const encryptionProgress = encryption
? useAttachmentStore((state) => state.encryptionProgress)
: null;
const encryptionProgress = useAttachmentStore(
(state) => state.encryptionProgress
);
const onPress = () => {
Actions.present(attachment, setAttachments, attachment.metadata.hash);

View File

@@ -35,6 +35,7 @@ import { PressableButton } from "../ui/pressable";
import Seperator from "../ui/seperator";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
const TwoFactorVerification = ({ onMfaLogin, mfaInfo }) => {
const colors = useThemeStore((state) => state.colors);
@@ -128,9 +129,9 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo }) => {
if (currentMethod.method === "sms" || currentMethod.method === "email") {
onSendCode();
}
}, [currentMethod.method]);
}, [currentMethod.method, onSendCode]);
const onSendCode = async () => {
const onSendCode = useCallback(async () => {
if (seconds || sending) return;
// TODO
setSending(true);
@@ -143,7 +144,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo }) => {
setSending(false);
ToastEvent.error(e, "Error sending 2FA Code", "local");
}
};
}, [currentMethod.method, mfaInfo.token, seconds, sending, start]);
return (
<View>

View File

@@ -32,6 +32,7 @@ import { useSettingStore } from "../../stores/use-setting-store";
import { getElevation, showTooltip, TOOLTIP_POSITIONS } from "../../utils";
import { normalize, SIZE } from "../../utils/size";
import { PressableButton } from "../ui/pressable";
import { useCallback } from "react";
export const FloatingButton = ({
title,
@@ -58,26 +59,29 @@ export const FloatingButton = ({
useEffect(() => {
animate(selectionMode ? 150 : 0);
}, [selectionMode]);
}, [animate, selectionMode]);
function animate(toValue) {
translate.value = withTiming(toValue, {
duration: 250,
easing: Easing.elastic(1)
});
}
const animate = useCallback(
(toValue) => {
translate.value = withTiming(toValue, {
duration: 250,
easing: Easing.elastic(1)
});
},
[translate]
);
const onKeyboardHide = async () => {
const onKeyboardHide = useCallback(async () => {
editorState().keyboardState = false;
if (deviceMode !== "mobile") return;
animate(0);
};
}, [animate, deviceMode]);
const onKeyboardShow = async () => {
const onKeyboardShow = useCallback(async () => {
editorState().keyboardState = true;
if (deviceMode !== "mobile") return;
animate(150);
};
}, [animate, deviceMode]);
useEffect(() => {
let sub1 = Keyboard.addListener("keyboardDidShow", onKeyboardShow);
@@ -86,7 +90,7 @@ export const FloatingButton = ({
sub1?.remove();
sub2?.remove();
};
}, [deviceMode]);
}, [deviceMode, onKeyboardHide, onKeyboardShow]);
const paddings = {
ios: 20,
android: 20,

View File

@@ -33,6 +33,7 @@ import Seperator from "../ui/seperator";
import BaseDialog from "./base-dialog";
import DialogButtons from "./dialog-buttons";
import DialogHeader from "./dialog-header";
import { useCallback } from "react";
export const Dialog = ({ context = "global" }) => {
const colors = useThemeStore((state) => state.colors);
@@ -63,7 +64,7 @@ export const Dialog = ({ context = "global" }) => {
eUnSubscribeEvent(eOpenSimpleDialog, show);
eUnSubscribeEvent(eCloseSimpleDialog, hide);
};
}, []);
}, [show]);
const onPressPositive = async () => {
if (dialogInfo.positivePress) {
@@ -79,12 +80,15 @@ export const Dialog = ({ context = "global" }) => {
hide();
};
const show = (data) => {
if (!data.context) data.context = "global";
if (data.context !== context) return;
setDialogInfo(data);
setVisible(true);
};
const show = useCallback(
(data) => {
if (!data.context) data.context = "global";
if (data.context !== context) return;
setDialogInfo(data);
setVisible(true);
},
[context]
);
const hide = () => {
setInputValue(null);

View File

@@ -35,6 +35,7 @@ import { SIZE } from "../../../utils/size";
import BaseDialog from "../../dialog/base-dialog";
import { PressableButton } from "../../ui/pressable";
import Paragraph from "../../ui/typography/paragraph";
import { useCallback } from "react";
const offsets = [];
let timeout = null;
@@ -66,7 +67,7 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
eUnSubscribeEvent(eCloseJumpToDialog, close);
eUnSubscribeEvent(eScrollEvent, onScroll);
};
}, []);
}, [open]);
const onScroll = (data) => {
let y = data.y;
@@ -80,10 +81,13 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
}, 200);
};
const open = (_type) => {
if (_type !== type) return;
setVisible(true);
};
const open = useCallback(
(_type) => {
if (_type !== type) return;
setVisible(true);
},
[type]
);
const close = () => {
setVisible(false);
@@ -91,9 +95,9 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
useEffect(() => {
loadOffsets();
}, [notes]);
}, [loadOffsets, notes]);
const loadOffsets = () => {
const loadOffsets = useCallback(() => {
notes
.filter((i) => i.type === "header")
.map((item, index) => {
@@ -108,7 +112,7 @@ const JumpToSectionDialog = ({ scrollRef, data, type }) => {
offset = offset + ind * 100 + msgOffset;
offsets.push(offset);
});
};
}, [notes]);
return !visible ? null : (
<BaseDialog

View File

@@ -31,6 +31,7 @@ import { eScrollEvent } from "../../utils/events";
import { LeftMenus } from "./left-menus";
import { RightMenus } from "./right-menus";
import { Title } from "./title";
import { useCallback } from "react";
const _Header = () => {
const colors = useThemeStore((state) => state.colors);
@@ -41,22 +42,25 @@ const _Header = () => {
(state) => state.currentScreen?.name
);
const onScroll = (data) => {
if (data.y > 150) {
if (!hide) return;
setHide(false);
} else {
if (hide) return;
setHide(true);
}
};
const onScroll = useCallback(
(data) => {
if (data.y > 150) {
if (!hide) return;
setHide(false);
} else {
if (hide) return;
setHide(true);
}
},
[hide]
);
useEffect(() => {
eSubscribeEvent(eScrollEvent, onScroll);
return () => {
eUnSubscribeEvent(eScrollEvent, onScroll);
};
}, [hide]);
}, [hide, onScroll]);
return selectionMode ? null : (
<>

View File

@@ -30,6 +30,7 @@ import { eScrollEvent } from "../../utils/events";
import { SIZE } from "../../utils/size";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
const titleState = {};
@@ -46,7 +47,6 @@ export const Title = () => {
: false
);
const isHidden = titleState[currentScreen.id];
console.log(currentScreen, "header");
const notebook =
isTopic && currentScreen.notebookId
? db.notebooks?.notebook(currentScreen.notebookId)?.data
@@ -54,19 +54,22 @@ export const Title = () => {
const title = currentScreen.title;
const isTag = currentScreen?.name === "TaggedNotes";
const onScroll = (data) => {
if (currentScreen.name !== "Notebook") {
setHide(false);
return;
}
if (data.y > 150) {
if (!hide) return;
setHide(false);
} else {
if (hide) return;
setHide(true);
}
};
const onScroll = useCallback(
(data) => {
if (currentScreen.name !== "Notebook") {
setHide(false);
return;
}
if (data.y > 150) {
if (!hide) return;
setHide(false);
} else {
if (hide) return;
setHide(true);
}
},
[currentScreen.name, hide]
);
useEffect(() => {
if (currentScreen.name === "Notebook") {
@@ -78,18 +81,18 @@ export const Title = () => {
} else {
setHide(titleState[currentScreen.id]);
}
}, [currentScreen.id]);
}, [currentScreen.id, currentScreen.name]);
useEffect(() => {
titleState[currentScreen.id] = hide;
}, [hide]);
}, [currentScreen.id, hide]);
useEffect(() => {
eSubscribeEvent(eScrollEvent, onScroll);
return () => {
eUnSubscribeEvent(eScrollEvent, onScroll);
};
}, [hide]);
}, [hide, onScroll]);
function navigateToNotebook() {
if (!isTopic) return;

View File

@@ -58,6 +58,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { Walkthrough } from "../walkthroughs";
import { useAppState } from "../../hooks/use-app-state";
import { useCallback } from "react";
const Launcher = React.memo(
function Launcher() {
@@ -75,7 +76,7 @@ const Launcher = React.memo(
(state) => state.settings.introCompleted
);
const dbInitCompleted = useRef(false);
const loadNotes = async () => {
const loadNotes = useCallback(async () => {
if (verifyUser) {
return;
}
@@ -94,9 +95,9 @@ const Launcher = React.memo(
});
});
});
};
}, [doAppLoadActions, setLoading, verifyUser]);
const init = async () => {
const init = useCallback(async () => {
if (!dbInitCompleted.current) {
await RNBootSplash.hide({ fade: true });
await loadDatabase();
@@ -121,7 +122,7 @@ const Launcher = React.memo(
} else {
useUserStore.getState().setUser(await db.user?.getUser());
}
};
}, [loadNotes, verifyUser]);
// useEffect(() => {
// hideSplashScreen();
@@ -134,9 +135,9 @@ const Launcher = React.memo(
return () => {
dbInitCompleted.current = false;
};
}, [loading]);
}, [doAppLoadActions, loading]);
const doAppLoadActions = async () => {
const doAppLoadActions = useCallback(async () => {
await sleep(500);
if (SettingsService.get().sessionExpired) {
eSendEvent("session_expired");
@@ -170,7 +171,7 @@ const Launcher = React.memo(
}
});
}
};
}, [introCompleted]);
const checkAppUpdateAvailable = async () => {
if (__DEV__) return;
@@ -237,7 +238,7 @@ const Launcher = React.memo(
// return false;
};
const onUnlockBiometrics = async () => {
const onUnlockBiometrics = useCallback(async () => {
if (!(await BiometricService.isBiometryAvailable())) {
ToastEvent.show({
heading: "Biometrics unavailable",
@@ -254,17 +255,17 @@ const Launcher = React.memo(
enabled(false);
password.current = null;
}
};
}, [setVerifyUser]);
useEffect(() => {
init();
}, [verifyUser]);
}, [init, verifyUser]);
useEffect(() => {
if (verifyUser && appState === "active") {
onUnlockBiometrics();
}
}, [appState]);
}, [appState, onUnlockBiometrics, verifyUser]);
const onSubmit = async () => {
if (!password.current) return;

View File

@@ -36,6 +36,7 @@ import { IconButton } from "../../ui/icon-button";
import { Button } from "../../ui/button";
import Sort from "../../sheets/sort";
import Heading from "../../ui/typography/heading";
import { useCallback } from "react";
export const SectionHeader = React.memo(
function SectionHeader({ item, index, type, color, screen }) {
@@ -63,16 +64,16 @@ export const SectionHeader = React.memo(
? "Default"
: groupBy.slice(0, 1).toUpperCase() + groupBy.slice(1, groupBy.length);
const onUpdate = () => {
const onUpdate = useCallback(() => {
setGroupOptions({ ...db.settings?.getGroupOptions(type) });
};
}, [type]);
useEffect(() => {
eSubscribeEvent("groupOptionsUpdate", onUpdate);
return () => {
eUnSubscribeEvent("groupOptionsUpdate", onUpdate);
};
}, []);
}, [onUpdate]);
return (
<View

View File

@@ -47,7 +47,7 @@ export const ActionStrip = ({ note, setActionStrip }) => {
useEffect(() => {
if (note.type === "note") return;
setIsPinnedToMenu(db.settings.isPinned(note.id));
}, []);
}, [note.id, note.type]);
const updateNotes = () => {
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 = () => {
setSelectedItem(item);

View File

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

View File

@@ -43,11 +43,10 @@ export default function NoteHistory({ note, fwdRef }) {
setHistory([...(await db.noteHistory.get(note.id))]);
setLoading(false);
})();
}, []);
}, [note.id]);
async function preview(item) {
const preview = useCallback(async (item) => {
let content = await db.noteHistory.content(item.id);
presentSheet({
component: (
<NotePreview
@@ -60,7 +59,7 @@ export default function NoteHistory({ note, fwdRef }) {
),
context: "note_history"
});
}
}, []);
const getDate = (start, end) => {
let _start = timeConverter(start);
@@ -94,7 +93,7 @@ export default function NoteHistory({ note, fwdRef }) {
</Paragraph>
</PressableButton>
),
[]
[colors.icon, preview]
);
return (

View File

@@ -38,31 +38,35 @@ import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
export const PremiumToast = ({ context = "global", offset = 0 }) => {
const colors = useThemeStore((state) => state.colors);
const [msg, setMsg] = useState(null);
const timer = useRef();
const open = (event) => {
if (!event) {
clearTimeout(timer);
timer.current = null;
setMsg(null);
return;
}
if (event.context === context && msg?.desc !== event.desc) {
if (timer.current !== null) {
clearTimeout(timer.current);
const open = useCallback(
(event) => {
if (!event) {
clearTimeout(timer);
timer.current = null;
}
setMsg(event);
timer.current = setTimeout(async () => {
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(() => {
eSubscribeEvent(eShowGetPremium, open);
@@ -70,7 +74,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
clearTimeout(timer.current);
eUnSubscribeEvent(eShowGetPremium, open);
};
}, []);
}, [open]);
const onPress = async () => {
open(null);

View File

@@ -47,6 +47,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { Walkthrough } from "../walkthroughs";
import { PricingItem } from "./pricing-item";
import { useCallback } from "react";
const promoCyclesMonthly = {
1: "first month",
@@ -77,7 +78,7 @@ export const PricingPlans = ({
const yearlyPlan = usePricing("yearly");
const monthlyPlan = usePricing("monthly");
const getSkus = async () => {
const getSkus = useCallback(async () => {
try {
setLoading(true);
if (promo?.promoCode) {
@@ -88,7 +89,7 @@ export const PricingPlans = ({
setLoading(false);
console.log("error getting sku", e);
}
};
}, [promo?.promoCode]);
const getPromo = async (code) => {
try {
@@ -129,7 +130,7 @@ export const PricingPlans = ({
useEffect(() => {
getSkus();
}, []);
}, [getSkus]);
const buySubscription = async (product) => {
if (buying) return;

View File

@@ -16,24 +16,23 @@
* 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 { useSafeAreaInsets } from "react-native-safe-area-context";
import { useThemeStore } from "../../stores/use-theme-store";
import { useSelectionStore } from "../../stores/use-selection-store";
import { db } from "../../common/database";
import { eSendEvent, ToastEvent } from "../../services/event-manager";
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 { deleteItems } from "../../utils/functions";
import { tabBarRef } from "../../utils/global-refs";
import layoutmanager from "../../utils/layout-manager";
import { SIZE } from "../../utils/size";
import { sleep } from "../../utils/time";
import { presentDialog } from "../dialog/functions";
import { IconButton } from "../ui/icon-button";
import Heading from "../ui/typography/heading";
import useNavigationStore from "../../stores/use-navigation-store";
export const SelectionHeader = React.memo(() => {
const colors = useThemeStore((state) => state.colors);
@@ -131,11 +130,10 @@ export const SelectionHeader = React.memo(() => {
});
};
const onBackPress = () => {
layoutmanager.withSpringAnimation(500);
const onBackPress = useCallback(() => {
clearSelection();
return true;
};
}, [clearSelection]);
useEffect(() => {
if (selectionMode) {
@@ -143,7 +141,7 @@ export const SelectionHeader = React.memo(() => {
} else {
BackHandler.removeEventListener("hardwareBackPress", onBackPress);
}
}, [selectionMode]);
}, [onBackPress, selectionMode]);
return !selectionMode ? null : (
<View

View File

@@ -32,6 +32,7 @@ import { Button } from "../ui/button";
import SheetWrapper from "../ui/sheet";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
const SheetProvider = ({ context = "global" }) => {
const colors = useThemeStore((state) => state.colors);
const [visible, setVisible] = useState(false);
@@ -48,26 +49,29 @@ const SheetProvider = ({ context = "global" }) => {
eUnSubscribeEvent(eOpenProgressDialog, open);
eUnSubscribeEvent(eCloseProgressDialog, close);
};
}, [visible]);
}, [close, open, visible]);
const open = async (data) => {
if (!data.context) data.context = "global";
if (data.context !== context) return;
if (visible || dialogData) {
setDialogData(null);
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;
const open = useCallback(
async (data) => {
if (!data.context) data.context = "global";
if (data.context !== context) return;
if (visible || dialogData) {
setDialogData(null);
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;
}
}
},
[context, dialogData, visible]
);
useEffect(() => {
(async () => {
@@ -85,11 +89,14 @@ const SheetProvider = ({ context = "global" }) => {
})();
}, [visible, dialogData]);
const close = (ctx) => {
if (!ctx) ctx = "global";
if (ctx !== context) return;
actionSheetRef.current?.setModalVisible(false);
};
const close = useCallback(
(ctx) => {
if (!ctx) ctx = "global";
if (ctx !== context) return;
actionSheetRef.current?.setModalVisible(false);
},
[context]
);
return !visible || !dialogData ? null : (
<SheetWrapper

View File

@@ -45,6 +45,7 @@ import { PressableButton } from "../../ui/pressable";
import SheetWrapper from "../../ui/sheet";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { useCallback } from "react";
let newNotebookTitle = null;
const notebookInput = createRef();
const actionSheetRef = createRef();
@@ -178,9 +179,9 @@ const MoveNoteComponent = ({ note }) => {
useEffect(() => {
updateNoteExists();
}, []);
}, [updateNoteExists]);
const updateNoteExists = () => {
const updateNoteExists = useCallback(() => {
if (!note?.id && selectedItemsList?.length === 0) return;
let notes =
@@ -208,7 +209,7 @@ const MoveNoteComponent = ({ note }) => {
}
console.log("ids: ", ids);
setNoteExists(ids);
};
}, [note?.id, selectedItemsList]);
const openAddTopicDialog = (item) => {
presentDialog({

View File

@@ -36,6 +36,7 @@ import { PressableButton } from "../../ui/pressable";
import SheetWrapper from "../../ui/sheet";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { useCallback } from "react";
const ManageTagsSheet = () => {
const colors = useThemeStore((state) => state.colors);
const [visible, setVisible] = useState(false);
@@ -53,16 +54,16 @@ const ManageTagsSheet = () => {
eUnSubscribeEvent(eOpenTagsDialog, open);
eUnSubscribeEvent(eCloseTagsDialog, close);
};
}, []);
}, [open]);
useEffect(() => {
if (visible) {
console.log("sorting tags");
sortTags();
}
}, [allTags, note, query, visible]);
}, [allTags, note, query, sortTags, visible]);
const sortTags = () => {
const sortTags = useCallback(() => {
let _tags = [...allTags];
_tags = _tags.filter((t) => t.type === "tag");
_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));
let combinedTags = [...noteTags, ..._tags];
setTags(combinedTags);
};
}, [allTags, note, query]);
const open = (item) => {
setNote(item);
useTagStore.getState().setTags();
sortTags();
setVisible(true);
};
const open = useCallback(
(item) => {
setNote(item);
useTagStore.getState().setTags();
sortTags();
setVisible(true);
},
[sortTags]
);
useEffect(() => {
if (visible) {

View File

@@ -16,7 +16,7 @@
* 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 DocumentPicker from "react-native-document-picker";
import { FlatList } from "react-native-gesture-handler";
@@ -54,7 +54,7 @@ const RestoreDataSheet = () => {
eUnSubscribeEvent(eOpenRestoreDialog, open);
eUnSubscribeEvent(eCloseRestoreDialog, close);
};
}, []);
}, [close]);
const open = async () => {
setVisible(true);
@@ -62,7 +62,7 @@ const RestoreDataSheet = () => {
actionSheetRef.current?.setModalVisible(true);
};
const close = () => {
const close = useCallback(() => {
if (restoring) {
showIsWorking();
return;
@@ -71,7 +71,7 @@ const RestoreDataSheet = () => {
setTimeout(() => {
setVisible(false);
}, 300);
};
}, [restoring]);
const showIsWorking = () => {
ToastEvent.show({

View File

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

View File

@@ -31,6 +31,7 @@ import { PressableButton } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { ColoredNotes } from "../../screens/notes/colored";
import { useCallback } from "react";
export const ColorSection = React.memo(
function ColorSection() {
@@ -42,7 +43,7 @@ export const ColorSection = React.memo(
if (!loading) {
setColorNotes();
}
}, [loading]);
}, [loading, setColorNotes]);
return colorNotes.map((item, index) => {
let alias = db.colors.alias(item.id);
@@ -61,25 +62,28 @@ const ColorItem = React.memo(
const [headerTextState, setHeaderTextState] = useState(null);
alias = db.colors.alias(item.id) || "";
const onHeaderStateChange = (state) => {
setTimeout(() => {
let id = state.currentScreen?.id;
if (id === item.id) {
setHeaderTextState({ id: state.currentScreen.id });
} else {
if (headerTextState !== null) {
setHeaderTextState(null);
const onHeaderStateChange = useCallback(
(state) => {
setTimeout(() => {
let id = state.currentScreen?.id;
if (id === item.id) {
setHeaderTextState({ id: state.currentScreen.id });
} else {
if (headerTextState !== null) {
setHeaderTextState(null);
}
}
}
}, 300);
};
}, 300);
},
[headerTextState, item.id]
);
useEffect(() => {
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
return () => {
unsub();
};
}, [headerTextState]);
}, [headerTextState, onHeaderStateChange]);
const onPress = (item) => {
ColoredNotes.navigate(item, false);

View File

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

View File

@@ -28,6 +28,7 @@ import { Button } from "../ui/button";
import { PressableButton } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
export const MenuItem = React.memo(
function MenuItem({ item, index, testID, rightBtn }) {
@@ -51,25 +52,28 @@ export const MenuItem = React.memo(
}
};
const onHeaderStateChange = (state) => {
setTimeout(() => {
let id = state.currentScreen?.id;
if (id === screenId) {
setHeaderTextState({ id: state.currentScreen.id });
} else {
if (headerTextState !== null) {
setHeaderTextState(null);
const onHeaderStateChange = useCallback(
(state) => {
setTimeout(() => {
let id = state.currentScreen?.id;
if (id === screenId) {
setHeaderTextState({ id: state.currentScreen.id });
} else {
if (headerTextState !== null) {
setHeaderTextState(null);
}
}
}
}, 300);
};
}, 300);
},
[headerTextState, screenId]
);
useEffect(() => {
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
return () => {
unsub();
};
}, [headerTextState]);
}, [headerTextState, onHeaderStateChange]);
return (
<PressableButton

View File

@@ -37,6 +37,7 @@ import Seperator from "../ui/seperator";
import SheetWrapper from "../ui/sheet";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
export const TagsSection = React.memo(
function TagsSection() {
@@ -48,7 +49,7 @@ export const TagsSection = React.memo(
if (!loading) {
setMenuPins();
}
}, [loading]);
}, [loading, setMenuPins]);
const onPress = (item) => {
if (item.type === "notebook") {
@@ -109,27 +110,30 @@ export const PinItem = React.memo(
const color = headerTextState?.id === item.id ? colors.accent : colors.pri;
const fwdRef = useRef();
const onHeaderStateChange = (state) => {
setTimeout(() => {
let id = state.currentScreen?.id;
if (id === item.id) {
setHeaderTextState({
id: state.currentScreen.id
});
} else {
if (headerTextState !== null) {
setHeaderTextState(null);
const onHeaderStateChange = useCallback(
(state) => {
setTimeout(() => {
let id = state.currentScreen?.id;
if (id === item.id) {
setHeaderTextState({
id: state.currentScreen.id
});
} else {
if (headerTextState !== null) {
setHeaderTextState(null);
}
}
}
}, 300);
};
}, 300);
},
[headerTextState, item.id]
);
useEffect(() => {
let unsub = useNavigationStore.subscribe(onHeaderStateChange);
return () => {
unsub();
};
}, [headerTextState]);
}, [headerTextState, onHeaderStateChange]);
const icons = {
topic: "bookmark",

View File

@@ -126,7 +126,16 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
return () => {
sub && sub.remove();
};
}, [introCompleted, deviceMode, widths]);
}, [
introCompleted,
deviceMode,
widths,
fullscreen,
translateX,
isDrawerOpen,
homePosition,
onDrawerStateChange
]);
useImperativeHandle(
ref,
@@ -193,7 +202,16 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
setScrollEnabled: () => true,
node: node
}),
[deviceMode, homePosition, editorPosition]
[
currentTab,
deviceMode,
translateX,
onDrawerStateChange,
homePosition,
editorPosition,
forcedLock,
isDrawerOpen
]
);
useAnimatedReaction(

View File

@@ -34,6 +34,7 @@ import { SIZE } from "../../utils/size";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { useCallback } from "react";
let toastMessages = [];
export const Toast = ({ context = "global" }) => {
const colors = useThemeStore((state) => state.colors);
@@ -43,42 +44,46 @@ export const Toast = ({ context = "global" }) => {
const hideTimeout = useRef();
const [visible, setVisible] = useState(false);
const showToastFunc = async (data) => {
console.log("toast show", data.message, toastMessages.length);
if (!data) return;
if (data.context !== context) return;
if (toastMessages.findIndex((m) => m.message === data.message) >= 0) {
console.log("returning from here");
return;
}
toastMessages.push(data);
if (toastMessages?.length > 1) return;
setData(data);
const showToastFunc = useCallback(
async (data) => {
if (!data) return;
if (data.context !== context) return;
if (toastMessages.findIndex((m) => m.message === data.message) >= 0) {
return;
}
toastMessages.push(data);
if (toastMessages?.length > 1) return;
setData(data);
setVisible(true);
if (hideTimeout.current) {
clearTimeout(hideTimeout.current);
}
hideTimeout.current = setTimeout(() => {
hideToastFunc();
}, data.duration);
};
setVisible(true);
if (hideTimeout.current) {
clearTimeout(hideTimeout.current);
}
hideTimeout.current = setTimeout(() => {
hideToastFunc();
}, data.duration);
},
[context, hideToastFunc]
);
const showNext = (data) => {
if (!data) {
hideToastFunc();
return;
}
setData(data);
if (hideTimeout.current) {
clearTimeout(hideTimeout.current);
}
hideTimeout.current = setTimeout(() => {
hideToastFunc();
}, data?.duration);
};
const showNext = useCallback(
(data) => {
if (!data) {
hideToastFunc();
return;
}
setData(data);
if (hideTimeout.current) {
clearTimeout(hideTimeout.current);
}
hideTimeout.current = setTimeout(() => {
hideToastFunc();
}, data?.duration);
},
[hideToastFunc]
);
const hideToastFunc = () => {
const hideToastFunc = useCallback(() => {
if (hideTimeout.current) {
clearTimeout(hideTimeout.current);
}
@@ -100,7 +105,7 @@ export const Toast = ({ context = "global" }) => {
}
}, 100);
}
};
}, [showNext]);
const _onKeyboardShow = () => {
setKeyboard(true);
@@ -127,7 +132,7 @@ export const Toast = ({ context = "global" }) => {
eUnSubscribeEvent(eShowToast, showToastFunc);
eUnSubscribeEvent(eHideToast, hideToastFunc);
};
}, [keyboard]);
}, [hideToastFunc, keyboard, showToastFunc]);
return (
visible && (

View File

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

View File

@@ -65,7 +65,7 @@ const SheetWrapper = ({
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0
};
}, [colors.bg, gestureEnabled]);
}, [colors.bg, largeTablet, smallTablet, width]);
const _onOpen = () => {
onOpen && onOpen();

View File

@@ -49,7 +49,7 @@ export const BouncingView = ({
duration: duration,
easing: Easing.elastic(1)
});
}, []);
}, [animated, duration, initialScale, scale]);
return (
<Animated.View style={[style, animatedStyle]}>{children}</Animated.View>

View File

@@ -55,6 +55,7 @@ import {
} from "../utils/events";
import { deleteItems } from "../utils/functions";
import { sleep } from "../utils/time";
import { useCallback } from "react";
export const useActions = ({ close = () => null, item }) => {
const colors = useThemeStore((state) => state.colors);
@@ -78,9 +79,9 @@ export const useActions = ({ close = () => null, item }) => {
if (item.type !== "note") {
setIsPinnedToMenu(db.settings.isPinned(item.id));
}
}, [item]);
}, [checkNotifPinned, item]);
function checkNotifPinned() {
const checkNotifPinned = useCallback(() => {
let pinned = Notifications.getPinnedNotes();
if (!pinned) {
setNotifPinned(null);
@@ -93,7 +94,7 @@ export const useActions = ({ close = () => null, item }) => {
} else {
setNotifPinned(null);
}
}
}, [item.id]);
const isNoteInTopic = () => {
const currentScreen = useNavigationStore.getState().currentScreen;
@@ -104,13 +105,16 @@ export const useActions = ({ close = () => null, item }) => {
.has(item.id);
};
const onUpdate = async (type) => {
if (type === "unpin") {
await sleep(1000);
await Notifications.get();
checkNotifPinned();
}
};
const onUpdate = useCallback(
async (type) => {
if (type === "unpin") {
await sleep(1000);
await Notifications.get();
checkNotifPinned();
}
},
[checkNotifPinned]
);
useEffect(() => {
eSubscribeEvent("onUpdate", onUpdate);
@@ -118,7 +122,7 @@ export const useActions = ({ close = () => null, item }) => {
return () => {
eUnSubscribeEvent("onUpdate", onUpdate);
};
}, [item]);
}, [item, onUpdate]);
function switchTheme() {
toggleDarkMode();

View File

@@ -62,6 +62,7 @@ import {
} from "../services/event-manager";
import { useEditorStore } from "../stores/use-editor-store";
import { useDragState } from "../screens/settings/editor/state";
import { useCallback } from "react";
const SodiumEventEmitter = new NativeEventEmitter(NativeModules.Sodium);
export const useAppEvents = () => {
@@ -121,7 +122,7 @@ export const useAppEvents = () => {
onRequestPartialSync
);
};
}, [loading]);
}, [loading, onSyncComplete]);
useEffect(() => {
let subs = [
@@ -156,10 +157,10 @@ export const useAppEvents = () => {
subs.forEach((sub) => sub?.remove());
};
}, []);
}, [onEmailVerified, onSyncComplete, onUrlRecieved, onUserUpdated]);
const onSessionExpired = async () => {
await SettingsService.set({
SettingsService.set({
sessionExpired: true
});
eSendEvent("session_expired");
@@ -188,18 +189,26 @@ export const useAppEvents = () => {
}
return () => {
refValues.current?.removeInternetStateListener &&
// eslint-disable-next-line react-hooks/exhaustive-deps
refValues.current?.removeInternetStateListener();
sub?.remove();
unsubIAP();
};
}, [loading, verify]);
}, [
loading,
onAppStateChanged,
onEmailVerified,
onInternetStateChanged,
onUserUpdated,
verify
]);
const onInternetStateChanged = async (state) => {
const onInternetStateChanged = useCallback(async (state) => {
if (!syncedOnLaunch.current) return;
reconnectSSE(state);
};
}, []);
const onSyncComplete = async () => {
const onSyncComplete = useCallback(async () => {
console.log("sync complete");
initAfterSync();
setLastSynced(await db.lastSynced());
@@ -209,22 +218,25 @@ export const useAppEvents = () => {
if (note) {
//await updateNoteInEditor();
}
};
}, [setLastSynced]);
const onUrlRecieved = async (res) => {
let url = res ? res.url : "";
try {
if (url.startsWith("https://app.notesnook.com/account/verified")) {
await onEmailVerified();
} else {
return;
const onUrlRecieved = useCallback(
async (res) => {
let url = res ? res.url : "";
try {
if (url.startsWith("https://app.notesnook.com/account/verified")) {
await onEmailVerified();
} 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();
setUser(user);
if (!user) return;
@@ -236,9 +248,9 @@ export const useAppEvents = () => {
if (user?.isEmailConfirmed) {
clearMessage();
}
};
}, [setUser]);
const attachIAPListeners = async () => {
const attachIAPListeners = useCallback(async () => {
await RNIap.initConnection()
.catch(() => null)
.then(async () => {
@@ -247,7 +259,7 @@ export const useAppEvents = () => {
refValues.current.subsriptionErrorListener =
RNIap.purchaseErrorListener(onSubscriptionError);
});
};
}, []);
const onAccountStatusChange = async (userStatus) => {
if (!PremiumService.get() && userStatus.type === 5) {
@@ -281,59 +293,62 @@ export const useAppEvents = () => {
}
};
const onUserUpdated = async (login) => {
console.log(`onUserUpdated: ${login}`);
let user;
try {
user = await db.user.getUser();
await PremiumService.setPremiumStatus();
setLastSynced(await db.lastSynced());
await useDragState.getState().init();
if (!user) {
return setLoginMessage();
}
const onUserUpdated = useCallback(
async (login) => {
console.log(`onUserUpdated: ${login}`);
let user;
try {
user = await db.user.getUser();
await PremiumService.setPremiumStatus();
setLastSynced(await db.lastSynced());
await useDragState.getState().init();
if (!user) {
return setLoginMessage();
}
let userEmailConfirmed = SettingsService.get().userEmailConfirmed;
setUser(user);
if (SettingsService.get().sessionExpired) {
syncedOnLaunch.current = true;
return;
}
clearMessage();
attachIAPListeners();
if (!login) {
user = await db.user.fetchUser();
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);
}
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();
if (user?.isEmailConfirmed && !userEmailConfirmed) {
setTimeout(() => {
onEmailVerified();
}, 1000);
SettingsService.set({
userEmailConfirmed: true
});
user = await db.user.getUser();
if (
user?.isEmailConfirmed &&
!SettingsService.get().recoveryKeySaved &&
!useMessageStore.getState().message?.visible
) {
setRecoveryKeyMessage();
}
} catch (e) {
ToastEvent.error(e, "An error occured", "global");
}
if (!user?.isEmailConfirmed) setEmailVerifyMessage();
refValues.current.isUserReady = true;
user = await db.user.getUser();
if (
user?.isEmailConfirmed &&
!SettingsService.get().recoveryKeySaved &&
!useMessageStore.getState().message?.visible
) {
setRecoveryKeyMessage();
}
if (!user?.isEmailConfirmed) setEmailVerifyMessage();
refValues.current.isUserReady = true;
syncedOnLaunch.current = true;
};
syncedOnLaunch.current = true;
},
[attachIAPListeners, onEmailVerified, setLastSynced, setUser]
);
const onSuccessfulSubscription = async (subscription) => {
await PremiumService.subscriptions.set(subscription);
@@ -349,59 +364,65 @@ export const useAppEvents = () => {
});
};
const onAppStateChanged = async (state) => {
console.log("onAppStateChanged");
if (state === "active") {
updateStatusBarColor();
if (
SettingsService.get().appLockMode !== "background" &&
!SettingsService.get().privacyScreen
) {
enabled(false);
}
if (SettingsService.get().appLockMode === "background") {
if (useSettingStore.getState().requestBiometrics) {
useSettingStore.getState().setRequestBiometrics(false);
return;
const onAppStateChanged = useCallback(
async (state) => {
console.log("onAppStateChanged");
if (state === "active") {
updateStatusBarColor();
if (
SettingsService.get().appLockMode !== "background" &&
!SettingsService.get().privacyScreen
) {
enabled(false);
}
}
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();
if (SettingsService.get().appLockMode === "background") {
if (useSettingStore.getState().requestBiometrics) {
useSettingStore.getState().setRequestBiometrics(false);
return;
}
} 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;
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;
}
}
};
},
[onEmailVerified]
);
async function reconnectSSE(connection) {
if (refValues.current?.isReconnecting) return;

View File

@@ -46,7 +46,7 @@ export const useAttachmentProgress = (attachment, encryption) => {
} else {
setCurrentProgress(null);
}
}, [progress]);
}, [attachment.metadata.hash, progress]);
return [currentProgress, setCurrentProgress];
};

View File

@@ -22,6 +22,7 @@ import { useEditorStore } from "../stores/use-editor-store";
import { useTagStore } from "../stores/use-tag-store";
import { db } from "../common/database";
import { NoteType } from "app/utils/types";
import { useCallback } from "react";
/**
* 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 [noteTags, setNoteTags] = useState<string[]>([]);
async function refreshNote() {
const refreshNote = useCallback(() => {
const current = useEditorStore.getState().currentEditingNote;
if (!current) {
setNote(null);
@@ -44,23 +45,23 @@ const useEditorTags = () => {
const note = db.notes?.note(current)?.data as NoteType;
setNote(note ? { ...note } : null);
getTags(note);
}
}, []);
useEffect(() => {
refreshNote();
}, [currentEditingNote, tags]);
}, [currentEditingNote, refreshNote, tags]);
function load() {
const load = useCallback(() => {
if (!note) return;
// tiny.call(EditorWebView, renderTags(noteTags));
}
}, [note]);
useEffect(() => {
eSubscribeEvent("updateTags", load);
return () => {
eUnSubscribeEvent("updateTags", load);
};
}, [noteTags]);
}, [load, noteTags]);
function getTags(note: NoteType) {
if (!note || !note.tags) return [];
@@ -72,7 +73,7 @@ const useEditorTags = () => {
useEffect(() => {
load();
}, [noteTags]);
}, [load, noteTags]);
return [];
};

View File

@@ -25,7 +25,9 @@ const useImmediateEffect = (callback: EffectCallback, deps: DependencyList) => {
cleanup = callback();
});
return cleanup;
}, deps);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [callback, ...deps]);
};
export default useImmediateEffect;

View File

@@ -18,6 +18,7 @@
import { useEffect, useState } from "react";
import { Keyboard, KeyboardEvent, useWindowDimensions } from "react-native";
import { useCallback } from "react";
/**
* A hook that detects floating keyboard on iPad
@@ -28,9 +29,12 @@ const useIsFloatingKeyboard = () => {
const [floating, setFloating] = useState<boolean>(false);
const onKeyboardWillChangeFrame = (event: KeyboardEvent) => {
setFloating(event.endCoordinates.width !== width);
};
const onKeyboardWillChangeFrame = useCallback(
(event: KeyboardEvent) => {
setFloating(event.endCoordinates.width !== width);
},
[width]
);
useEffect(() => {
const sub1 = Keyboard.addListener(
@@ -40,7 +44,7 @@ const useIsFloatingKeyboard = () => {
return () => {
sub1?.remove();
};
}, [width]);
}, [onKeyboardWillChangeFrame, width]);
return floating;
};

View File

@@ -47,7 +47,7 @@ export const useNavigationFocus = (
},
isBlurred.current ? 0 : delay || 300
);
}, [onFocus, prev]);
}, [delay, onFocus]);
const _onBlur = useCallback(() => {
isBlurred.current = true;
@@ -58,7 +58,7 @@ export const useNavigationFocus = (
setFocused(false);
}
}, delay || 300);
}, [onBlur, prev]);
}, [delay, onBlur]);
useEffect(() => {
if (!navigation) return;
@@ -69,7 +69,7 @@ export const useNavigationFocus = (
return () => {
subs.forEach((sub) => sub());
};
}, [navigation]);
}, [_onBlur, _onFocus, navigation]);
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
*/
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.
const [current, setCurrent] = useState<T>(data.sample());
const intervalRef = useRef<NodeJS.Timer>();
@@ -39,7 +38,7 @@ function useRotator<T>(data: T[], interval = 3000): T | null {
clearInterval(intervalRef.current);
}
};
});
}, [data, interval]);
return current;
}

View File

@@ -47,7 +47,7 @@ const useSyncProgress = () => {
EV?.unsubscribe(EVENTS.syncProgress, onProgress);
EV?.unsubscribe(EVENTS.syncCompleted, onSyncComplete);
};
}, []);
}, [EV, onProgress]);
return {
progress

View File

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

View File

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

View File

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

View File

@@ -89,7 +89,7 @@ const _Tabs = () => {
setTimeout(() => {
useNavigationStore.getState().update({ name: homepage });
}, 1000);
}, []);
}, [homepage]);
return (
<NativeStack.Navigator
@@ -169,7 +169,7 @@ const _NavigationStack = () => {
}
hideAllTooltips();
eSendEvent("navigate");
});
}, [clearSelection]);
return (
<Container>

View File

@@ -59,6 +59,7 @@ import {
import { editorRef, tabBarRef } from "../utils/global-refs";
import { hideAllTooltips } from "../hooks/use-tooltip";
import { NavigationStack } from "./navigation-stack";
import { useCallback } from "react";
const _TabsHolder = () => {
const colors = useThemeStore((state) => state.colors);
@@ -92,7 +93,7 @@ const _TabsHolder = () => {
};
}, []);
const showFullScreenEditor = () => {
const showFullScreenEditor = useCallback(() => {
setFullscreen(true);
if (deviceMode === "smallTablet") {
tabBarRef.current?.openDrawer();
@@ -107,9 +108,9 @@ const _TabsHolder = () => {
: dimensions.width * 0.15
}
});
};
}, [deviceMode, dimensions.width, setFullscreen]);
const closeFullScreenEditor = () => {
const closeFullScreenEditor = useCallback(() => {
if (deviceMode === "smallTablet") {
tabBarRef.current?.closeDrawer();
}
@@ -132,7 +133,7 @@ const _TabsHolder = () => {
tabBarRef.current?.goToIndex(1);
}, 100);
}
};
}, [deviceMode, dimensions.width, setFullscreen]);
useEffect(() => {
if (!tabBarRef.current?.isDrawerOpen()) {
@@ -145,7 +146,14 @@ const _TabsHolder = () => {
eUnSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
};
}, [deviceMode, dimensions, colors]);
}, [
deviceMode,
dimensions,
colors,
showFullScreenEditor,
closeFullScreenEditor,
toggleView
]);
const _onLayout = async (event) => {
console.log("layout called here");
@@ -259,9 +267,12 @@ const _TabsHolder = () => {
}
};
const toggleView = (show) => {
animatedTranslateY.value = show ? 0 : -9999;
};
const toggleView = useCallback(
(show) => {
animatedTranslateY.value = show ? 0 : -9999;
},
[animatedTranslateY]
);
const valueLimiter = (value, min, max) => {
if (value < min) {

View File

@@ -42,6 +42,7 @@ import { EditorProps, useEditorType } from "./tiptap/types";
import { useEditor } from "./tiptap/use-editor";
import { useEditorEvents } from "./tiptap/use-editor-events";
import { editorController } from "./tiptap/utils";
import { useCallback } from "react";
const style: ViewStyle = {
height: "100%",
@@ -91,23 +92,32 @@ const Editor = React.memo(
get: () => editor
}));
const onMediaDownloaded = ({
hash,
groupId,
src
}: {
hash: string;
groupId: string;
src: string;
}) => {
console.log("onMediaDownoaded", groupId);
const onMediaDownloaded = useCallback(
({
hash,
groupId,
src
}: {
hash: string;
groupId: string;
src: string;
}) => {
console.log("onMediaDownoaded", groupId);
if (groupId !== editor.note.current?.id) return;
editor.commands.updateImage({
hash: hash,
src: src
});
};
if (groupId !== editor.note.current?.id) return;
editor.commands.updateImage({
hash: hash,
src: src
});
},
[editor.commands, editor.note]
);
const onError = useCallback(() => {
console.log("RENDER PROCESS GONE!!!");
editor.setLoading(true);
setTimeout(() => editor.setLoading(false), 10);
}, [editor]);
useEffect(() => {
onLoad && onLoad();
@@ -117,17 +127,12 @@ const Editor = React.memo(
eUnSubscribeEvent("webview_reset", onError);
EV.unsubscribe(EVENTS.mediaAttachmentDownloaded, onMediaDownloaded);
};
}, []);
}, [onError, onLoad, onMediaDownloaded]);
if (withController) {
editorController.current = editor;
}
const onError = () => {
console.log("RENDER PROCESS GONE!!!");
editor.setLoading(true);
setTimeout(() => editor.setLoading(false), 10);
};
console.log(editor.loading, "loading editor");
return editor.loading ? null : (
<>

View File

@@ -36,6 +36,7 @@ import { useThemeStore } from "../../stores/use-theme-store";
import { eClearEditor, eOnLoadNote } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { editorState } from "./tiptap/utils";
import { useCallback } from "react";
const EditorOverlay = ({ editorId = "", editor }) => {
const colors = useThemeStore((state) => state.colors);
const [error, setError] = useState(false);
@@ -55,34 +56,37 @@ const EditorOverlay = ({ editorId = "", editor }) => {
clearTimeout(timers.current.closing);
};
const load = async (_loading) => {
editorState().overlay = true;
clearTimers();
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 {
const load = useCallback(
async (_loading) => {
editorState().overlay = true;
clearTimers();
setTimeout(() => {
setError(false);
editorState().overlay = false;
opacity.value = withTiming(0, {
duration: 500
});
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();
setTimeout(() => {
translateValue.value = 6000;
}, 500);
}, 100);
}
};
setError(false);
editorState().overlay = false;
opacity.value = withTiming(0, {
duration: 500
});
setTimeout(() => {
translateValue.value = 6000;
}, 500);
}, 100);
}
},
[editorId, opacity, translateValue]
);
useEffect(() => {
eSubscribeEvent("loadingNote" + editorId, load);
@@ -90,7 +94,7 @@ const EditorOverlay = ({ editorId = "", editor }) => {
clearTimers();
eUnSubscribeEvent("loadingNote" + editorId, load);
};
}, [editorId]);
}, [editorId, load]);
const animatedStyle = useAnimatedStyle(() => {
return {

View File

@@ -151,10 +151,8 @@ export const useEditorEvents = (
);
const tools = useDragState((state) => state.data);
const { keyboardShown } = useKeyboard();
if (!editor) return null;
useEffect(() => {
console.log("keyboardShown", keyboardShown);
editor.commands.setSettings({
deviceMode: deviceMode || "mobile",
fullscreen: fullscreen || false,
@@ -176,7 +174,10 @@ export const useEditorEvents = (
tools,
editor.commands,
keyboardShown,
doubleSpacedLines
doubleSpacedLines,
editorPropReadonly,
noHeader,
noToolbar
]);
const onBackPress = useCallback(async () => {
@@ -211,14 +212,14 @@ export const useEditorEvents = (
editorState().currentlyEditing = false;
editor.reset();
}, 1);
}, [fullscreen, deviceMode]);
}, [editor, deviceMode, fullscreen]);
const onHardwareBackPress = useCallback(() => {
if (editorState().currentlyEditing) {
onBackPress();
return true;
}
}, []);
}, [onBackPress]);
const onLoadNote = useCallback(async () => {
InteractionManager.runAfterInteractions(() => {
@@ -229,29 +230,32 @@ export const useEditorEvents = (
);
}
});
}, []);
const onCallClear = useCallback(async (value: string) => {
if (value === "removeHandler") {
if (handleBack.current) {
handleBack.current.remove();
}
return;
}
if (value === "addHandler") {
if (handleBack.current) {
handleBack.current.remove();
}, [onHardwareBackPress]);
const onCallClear = useCallback(
async (value: string) => {
if (value === "removeHandler") {
if (handleBack.current) {
handleBack.current.remove();
}
return;
}
if (value === "addHandler") {
if (handleBack.current) {
handleBack.current.remove();
}
handleBack.current = BackHandler.addEventListener(
"hardwareBackPress",
onHardwareBackPress
);
return;
}
if (editorState().currentlyEditing) {
await onBackPress();
}
}, []);
handleBack.current = BackHandler.addEventListener(
"hardwareBackPress",
onHardwareBackPress
);
return;
}
if (editorState().currentlyEditing) {
await onBackPress();
}
},
[onBackPress, onHardwareBackPress]
);
useEffect(() => {
if (fullscreen && DDS.isTab) {
@@ -266,7 +270,7 @@ export const useEditorEvents = (
handleBack.current.remove();
}
};
}, [fullscreen]);
}, [fullscreen, onHardwareBackPress]);
useEffect(() => {
eSubscribeEvent(eOnLoadNote + editor.editorId, onLoadNote);
@@ -275,107 +279,110 @@ export const useEditorEvents = (
eUnSubscribeEvent(eClearEditor, onCallClear);
eUnSubscribeEvent(eOnLoadNote, onLoadNote);
};
}, []);
}, [editor.editorId, onCallClear, onLoadNote]);
const onMessage = (event: WebViewMessageEvent) => {
const data = event.nativeEvent.data;
const editorMessage = JSON.parse(data) as EditorMessage;
const onMessage = useCallback(
(event: WebViewMessageEvent) => {
const data = event.nativeEvent.data;
const editorMessage = JSON.parse(data) as EditorMessage;
logger.info("editor", editorMessage.type);
if (
editorMessage.sessionId !== editor.sessionId &&
editorMessage.type !== EditorEvents.status
) {
logger.error(
"editor",
"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: ",
logger.info("editor", editorMessage.type);
if (
editorMessage.sessionId !== editor.sessionId &&
editorMessage.type !== EditorEvents.status
) {
logger.error(
"editor",
"invalid session",
editorMessage.type,
editorMessage.value
editor.sessionId,
editorMessage.sessionId
);
break;
}
eSendEvent(editorMessage.type, editorMessage);
};
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.value
);
break;
}
eSendEvent(editorMessage.type, editorMessage);
},
[editor, onBackPress]
);
return onMessage;
};

View File

@@ -79,7 +79,7 @@ export const useEditor = (
commands.setInsets(
isDefaultEditor ? insets : { top: 0, left: 0, right: 0, bottom: 0 }
);
}, [insets]);
}, [commands, insets, isDefaultEditor]);
useEffect(() => {
sessionIdRef.current = sessionId;
@@ -87,7 +87,7 @@ export const useEditor = (
useEffect(() => {
commands.setTags(currentNote.current);
}, [tags]);
}, [commands, tags]);
useEffect(() => {
if (theme) return;
@@ -98,28 +98,17 @@ export const useEditor = (
return () => {
unsub();
};
}, []);
}, [postMessage, theme]);
useEffect(() => {
console.log("sessionId:", sessionId);
async () => {
await commands.setSessionId(sessionIdRef.current);
if (sessionIdRef.current) {
if (!state.current?.ready) return;
await onReady();
}
};
return () => {
state.current.saveCount = 0;
};
}, [sessionId, loading]);
const overlay = (show: boolean, data = { type: "new" }) => {
eSendEvent(
"loadingNote" + editorId,
show ? currentNote.current || data : false
);
};
const overlay = useCallback(
(show: boolean, data = { type: "new" }) => {
eSendEvent(
"loadingNote" + editorId,
show ? currentNote.current || data : false
);
},
[editorId]
);
const onReady = useCallback(async () => {
if (!(await isEditorLoaded(editorRef, sessionIdRef.current))) {
@@ -127,7 +116,19 @@ export const useEditor = (
overlay(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(() => {
if (loading) {
@@ -143,24 +144,27 @@ export const useEditor = (
[]
);
const reset = useCallback(async (resetState = true) => {
currentNote.current?.id && db.fs.cancel(currentNote.current.id);
currentNote.current = null;
currentContent.current = null;
sessionHistoryId.current = undefined;
saveCount.current = 0;
useEditorStore.getState().setReadonly(false);
postMessage(EditorEvents.title, "");
await commands.clearContent();
await commands.clearTags();
console.log("reset state: ", resetState);
if (resetState) {
isDefaultEditor &&
useEditorStore.getState().setCurrentlyEditingNote(null);
placeholderTip.current = TipManager.placeholderTip();
await commands.setPlaceholder(placeholderTip.current);
}
}, []);
const reset = useCallback(
async (resetState = true) => {
currentNote.current?.id && db.fs.cancel(currentNote.current.id);
currentNote.current = null;
currentContent.current = null;
sessionHistoryId.current = undefined;
saveCount.current = 0;
useEditorStore.getState().setReadonly(false);
postMessage(EditorEvents.title, "");
await commands.clearContent();
await commands.clearTags();
console.log("reset state: ", resetState);
if (resetState) {
isDefaultEditor &&
useEditorStore.getState().setCurrentlyEditingNote(null);
placeholderTip.current = TipManager.placeholderTip();
await commands.setPlaceholder(placeholderTip.current);
}
},
[commands, isDefaultEditor, postMessage]
);
const saveNote = useCallback(
async ({
@@ -236,6 +240,7 @@ export const useEditor = (
}
} else {
noteData.contentId = note?.contentId;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await db.vault?.save(noteData as any);
}
console.log(id, sessionIdRef.current, currentSessionId);
@@ -265,7 +270,7 @@ export const useEditor = (
console.log("error saving: ", e);
}
},
[commands, reset]
[commands, isDefaultEditor, postMessage, readonly, reset]
);
const loadContent = useCallback(async (note: NoteType) => {
@@ -322,7 +327,15 @@ export const useEditor = (
loadImages();
}
},
[setSessionId]
[
commands,
editorId,
isDefaultEditor,
loadContent,
overlay,
postMessage,
reset
]
);
const loadImages = () => {
@@ -352,7 +365,7 @@ export const useEditor = (
return () => {
eUnSubscribeEvent(eOnLoadNote + editorId, loadNote);
};
}, [editorId]);
}, [editorId, loadNote]);
const saveContent = useCallback(
({
@@ -398,28 +411,10 @@ export const useEditor = (
500
);
},
[sessionIdRef, sessionId]
[sessionId, withTimer, onChange, saveNote]
);
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();
}, [state, currentNote, loadNote]);
async function restoreEditorState() {
const restoreEditorState = useCallback(async () => {
const json = await MMKV.getItem("appState");
if (json) {
const appState = JSON.parse(json) as AppState;
@@ -451,7 +446,34 @@ export const useEditor = (
return;
}
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 {
ref: editorRef,

View File

@@ -30,12 +30,11 @@ import {
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import Navigation, {
NavigationProps,
NotebookScreenParams
} from "../../services/navigation";
import Navigation, { NavigationProps } from "../../services/navigation";
import SearchService from "../../services/search";
import useNavigationStore from "../../stores/use-navigation-store";
import useNavigationStore, {
NotebookScreenParams
} from "../../stores/use-navigation-store";
import {
eOnNewTopicAdded,
eOpenAddNotebookDialog,
@@ -60,7 +59,7 @@ const Notebook = ({ route, navigation }: NavigationProps<"Notebook">) => {
onBlur: () => false
});
const syncWithNavigation = () => {
const syncWithNavigation = React.useCallback(() => {
useNavigationStore.getState().update(
{
name: route.name,
@@ -71,35 +70,38 @@ const Notebook = ({ route, navigation }: NavigationProps<"Notebook">) => {
params.current?.canGoBack
);
SearchService.prepareSearch = prepareSearch;
};
}, [route.name]);
const onRequestUpdate = (data?: NotebookScreenParams) => {
if (data) params.current = data;
params.current.title = params.current.item.title;
try {
const notebook = db.notebooks?.notebook(params?.current?.item?.id)
?.data as NotebookType;
if (notebook) {
params.current.item = notebook;
setTopics(
groupArray(
qclone(notebook.topics),
db.settings?.getGroupOptions("topics")
)
);
syncWithNavigation();
const onRequestUpdate = React.useCallback(
(data?: NotebookScreenParams) => {
if (data) params.current = data;
params.current.title = params.current.item.title;
try {
const notebook = db.notebooks?.notebook(params?.current?.item?.id)
?.data as NotebookType;
if (notebook) {
params.current.item = notebook;
setTopics(
groupArray(
qclone(notebook.topics),
db.settings?.getGroupOptions("topics")
)
);
syncWithNavigation();
}
} catch (e) {
console.error(e);
}
} catch (e) {
console.error(e);
}
};
},
[syncWithNavigation]
);
useEffect(() => {
eSubscribeEvent(eOnNewTopicAdded, onRequestUpdate);
return () => {
eUnSubscribeEvent(eOnNewTopicAdded, onRequestUpdate);
};
}, [topics]);
}, [onRequestUpdate, topics]);
const prepareSearch = () => {
SearchService.update({

View File

@@ -20,10 +20,8 @@ import { groupArray } from "@notesnook/core/utils/grouping";
import React from "react";
import NotesPage, { PLACEHOLDER_DATA } from ".";
import { db } from "../../common/database";
import Navigation, {
NavigationProps,
NotesScreenParams
} from "../../services/navigation";
import Navigation, { NavigationProps } from "../../services/navigation";
import { NotesScreenParams } from "../../stores/use-navigation-store";
import { ColorType } from "../../utils/types";
import { getAlias, openEditor, toCamelCase } from "./common";
export const ColoredNotes = ({

View File

@@ -18,7 +18,7 @@
import { DDS } from "../../services/device-detection";
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 { useTagStore } from "../../stores/use-tag-store";
import { db } from "../../common/database";
@@ -26,6 +26,8 @@ import { eOnLoadNote } from "../../utils/events";
import { openLinkInBrowser } from "../../utils/functions";
import { tabBarRef } from "../../utils/global-refs";
import { editorController, editorState } from "../editor/tiptap/utils";
import { NotesScreenParams } from "../../stores/use-navigation-store";
import { TopicType } from "../../utils/types";
export function toCamelCase(title: string) {
return title.slice(0, 1).toUpperCase() + title.slice(1);
@@ -34,7 +36,7 @@ export function toCamelCase(title: string) {
export function getAlias(params: Partial<NotesScreenParams>) {
if (!params) return "";
const { item } = params;
return item?.alias || item?.title;
return (item as TopicType)?.alias || item?.title;
}
export function openMonographsWebpage() {

View File

@@ -25,13 +25,11 @@ import {
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import Navigation, {
NavigationProps,
NotesScreenParams
} from "../../services/navigation";
import Navigation, { NavigationProps } from "../../services/navigation";
import SearchService from "../../services/search";
import useNavigationStore, {
HeaderRightButton,
NotesScreenParams,
RouteName
} from "../../stores/use-navigation-store";
import { useNoteStore } from "../../stores/use-notes-store";
@@ -117,10 +115,21 @@ const NotesPage = ({
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 alias = getAlias(params.current);
console.log(alias, title, "syncWithNavigation", params.current);
useNavigationStore.getState().update(
{
name: route.name,
@@ -146,35 +155,44 @@ const NotesPage = ({
color: item.title,
notebook: (item as TopicType).notebookId
});
};
}, [
isMonograph,
onPressFloatingButton,
prepareSearch,
rightButtons,
route.name
]);
const onRequestUpdate = (data?: NotesScreenParams) => {
const isNew = data && data?.item?.id !== params.current?.item?.id;
if (data) params.current = data;
params.current.title = params.current.title || params.current.item.title;
const { item } = params.current;
try {
if (isNew) setLoadingNotes(true);
const notes = get(params.current, true) as NoteType[];
if (
(item.type === "tag" || item.type === "color") &&
(!notes || notes.length === 0)
) {
return Navigation.goBack();
const onRequestUpdate = React.useCallback(
(data?: NotesScreenParams) => {
const isNew = data && data?.item?.id !== params.current?.item?.id;
if (data) params.current = data;
params.current.title = params.current.title || params.current.item.title;
const { item } = params.current;
try {
if (isNew) setLoadingNotes(true);
const notes = get(params.current, true) as NoteType[];
if (
(item.type === "tag" || item.type === "color") &&
(!notes || notes.length === 0)
) {
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);
syncWithNavigation();
} catch (e) {
console.error(e);
}
};
},
[get, syncWithNavigation]
);
useEffect(() => {
if (loadingNotes) {
setTimeout(() => setLoadingNotes(false), 300);
}
}, [notes]);
}, [loadingNotes, notes]);
useEffect(() => {
eSubscribeEvent(route.name, onRequestUpdate);
@@ -182,19 +200,7 @@ const NotesPage = ({
setOnFirstSave(null);
eUnSubscribeEvent(route.name, onRequestUpdate);
};
}, []);
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);
}
});
};
}, [onRequestUpdate, route.name]);
return (
<DelayLayout

View File

@@ -20,10 +20,8 @@ import { groupArray } from "@notesnook/core/utils/grouping";
import React from "react";
import NotesPage, { PLACEHOLDER_DATA } from ".";
import { db } from "../../common/database";
import Navigation, {
NavigationProps,
NotesScreenParams
} from "../../services/navigation";
import Navigation, { NavigationProps } from "../../services/navigation";
import { NotesScreenParams } from "../../stores/use-navigation-store";
import { MonographType } from "../../utils/types";
import { openMonographsWebpage } from "./common";
export const Monographs = ({

View File

@@ -20,10 +20,8 @@ import { groupArray } from "@notesnook/core/utils/grouping";
import React from "react";
import NotesPage, { PLACEHOLDER_DATA } from ".";
import { db } from "../../common/database";
import Navigation, {
NavigationProps,
NotesScreenParams
} from "../../services/navigation";
import Navigation, { NavigationProps } from "../../services/navigation";
import { NotesScreenParams } from "../../stores/use-navigation-store";
import { NoteType, TagType } from "../../utils/types";
import { getAlias, openEditor } from "./common";
export const TaggedNotes = ({

View File

@@ -22,10 +22,8 @@ import NotesPage, { PLACEHOLDER_DATA } from ".";
import { db } from "../../common/database";
import { MoveNotes } from "../../components/sheets/move-notes/movenote";
import { eSendEvent } from "../../services/event-manager";
import Navigation, {
NavigationProps,
NotesScreenParams
} from "../../services/navigation";
import Navigation, { NavigationProps } from "../../services/navigation";
import { NotesScreenParams } from "../../stores/use-navigation-store";
import { eOpenAddTopicDialog } from "../../utils/events";
import { NotebookType, TopicType } from "../../utils/types";
import { openEditor } from "./common";

View File

@@ -48,7 +48,7 @@ export const Search = ({ navigation, route }) => {
setSearchResults([]);
setSearchStatus(false, null);
};
}, []);
}, [setSearchResults, setSearchStatus]);
return (
<DelayLayout wait={searching}>

View File

@@ -180,7 +180,7 @@ export const MFASetup = ({
setLoading(false);
});
}
}, []);
}, [method?.id]);
const codeHelpText = {
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);
}
})();
}, [seconds]);
}, [currentLog, seconds, start]);
const renderItem = ({ item }: { item: LogMessage; index: number }) => {
const background =
item.level === LogLevel.Error || item.level === LogLevel.Fatal
? hexToRGBA(colors.red, 0.2)
: item.level === LogLevel.Warn
? hexToRGBA(colors.orange, 0.2)
: "transparent";
const renderItem = React.useCallback(
({ item }: { item: LogMessage; index: number }) => {
const background =
item.level === LogLevel.Error || item.level === LogLevel.Fatal
? hexToRGBA(colors.red, 0.2)
: item.level === LogLevel.Warn
? hexToRGBA(colors.orange, 0.2)
: "transparent";
const color =
item.level === LogLevel.Error || item.level === LogLevel.Fatal
? colors.red
: item.level === LogLevel.Warn
? colors.orange
: colors.pri;
const color =
item.level === LogLevel.Error || item.level === LogLevel.Fatal
? colors.red
: item.level === LogLevel.Warn
? colors.orange
: colors.pri;
return !item ? null : (
<TouchableOpacity
activeOpacity={1}
onLongPress={() => {
Clipboard.setString(format(item));
ToastEvent.show({
heading: "Debug log copied!",
context: "global",
type: "success"
});
}}
style={{
paddingHorizontal: 12,
paddingVertical: 12,
backgroundColor: background,
flexShrink: 1,
borderBottomWidth: 1,
borderBottomColor: colors.nav
}}
>
<Paragraph
style={{
flexShrink: 1,
flexWrap: "wrap",
fontFamily: Platform.OS === "ios" ? "Menlo" : "monospace"
return !item ? null : (
<TouchableOpacity
activeOpacity={1}
onLongPress={() => {
Clipboard.setString(format(item));
ToastEvent.show({
heading: "Debug log copied!",
context: "global",
type: "success"
});
}}
style={{
paddingHorizontal: 12,
paddingVertical: 12,
backgroundColor: background,
flexShrink: 1,
borderBottomWidth: 1,
borderBottomColor: colors.nav
}}
size={12}
color={color}
>
{format(item)}
</Paragraph>
</TouchableOpacity>
);
};
<Paragraph
style={{
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 {
let path = null;
const fileName = sanitizeFilename(`notesnook_logs_${Date.now()}`);
@@ -165,9 +168,9 @@ export default function DebugLogs() {
} catch (e) {
console.log(e);
}
};
}, [currentLog?.logs]);
const copyLogs = () => {
const copyLogs = React.useCallback(() => {
const data = currentLog?.logs
.map((log) => {
return !log ? "" : format(log);
@@ -180,9 +183,9 @@ export default function DebugLogs() {
context: "global",
type: "success"
});
};
}, [currentLog?.logs]);
const clearLogs = () => {
const clearLogs = React.useCallback(() => {
if (!currentLog) return;
presentDialog({
title: "Clear logs",
@@ -203,7 +206,7 @@ export default function DebugLogs() {
}
}
});
};
}, [currentLog, logs]);
return (
<View

View File

@@ -45,58 +45,61 @@ export default function ToolSheet({
const data = useDragState((state) => state.data);
const ungrouped = getUngroupedTools(data) as ToolId[];
const renderTool = React.useCallback((item: ToolId) => {
const tool = findToolById(item);
const iconSvgString = tool ? getToolIcon(tool.icon as ToolId) : null;
return (
<PressableButton
key={item}
type="grayBg"
onPress={() => {
const _data = useDragState.getState().data.slice();
if (group.groupIndex !== undefined) {
(_data[group.groupIndex][group.index] as ToolId[]).unshift(
item as ToolId
);
} else {
_data[group.index].unshift(item);
}
useDragState.getState().setData(_data);
}}
customStyle={{
marginBottom: 10,
width: "100%",
height: 50,
paddingHorizontal: 12,
paddingRight: 0,
borderRadius: 5,
flexDirection: "row",
alignItems: "center",
justifyContent: "flex-start"
}}
>
<View
style={{
const renderTool = React.useCallback(
(item: ToolId) => {
const tool = findToolById(item);
const iconSvgString = tool ? getToolIcon(tool.icon as ToolId) : null;
return (
<PressableButton
key={item}
type="grayBg"
onPress={() => {
const _data = useDragState.getState().data.slice();
if (group.groupIndex !== undefined) {
(_data[group.groupIndex][group.index] as ToolId[]).unshift(
item as ToolId
);
} else {
_data[group.index].unshift(item);
}
useDragState.getState().setData(_data);
}}
customStyle={{
marginBottom: 10,
width: "100%",
height: 50,
paddingHorizontal: 12,
paddingRight: 0,
borderRadius: 5,
flexDirection: "row",
alignItems: "center"
alignItems: "center",
justifyContent: "flex-start"
}}
>
{iconSvgString ? (
<SvgView width={23} height={23} src={iconSvgString} />
) : null}
<Paragraph
<View
style={{
marginLeft: iconSvgString ? 10 : 0
flexDirection: "row",
alignItems: "center"
}}
color={colors.pri}
size={SIZE.sm}
>
{tool?.title}
</Paragraph>
</View>
</PressableButton>
);
}, []);
{iconSvgString ? (
<SvgView width={23} height={23} src={iconSvgString} />
) : null}
<Paragraph
style={{
marginLeft: iconSvgString ? 10 : 0
}}
color={colors.pri}
size={SIZE.sm}
>
{tool?.title}
</Paragraph>
</View>
</PressableButton>
);
},
[colors.pri, group.groupIndex, group.index]
);
return (
<View

View File

@@ -64,60 +64,64 @@ export const Tool = ({
const iconSvgString =
isSubgroup || !tool ? null : getToolIcon(tool.icon as ToolId);
const buttons = isSubgroup
? [
{
name: "minus",
onPress: () => {
presentDialog({
context: "global",
title: "Delete collapsed section?",
positiveText: "Delete",
paragraph:
"All tools in the collapsed section will also be removed.",
positivePress: () => {
const buttons = React.useMemo(
() =>
isSubgroup
? [
{
name: "minus",
onPress: () => {
presentDialog({
context: "global",
title: "Delete collapsed section?",
positiveText: "Delete",
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;
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);
}
});
}
},
{
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) {
buttons.unshift({
@@ -236,7 +240,20 @@ export const Tool = ({
) : null}
</>
),
[]
[
buttons,
colors.bg,
colors.icon,
colors.nav,
colors.pri,
groupIndex,
iconSvgString,
index,
isDragged,
isSubgroup,
item,
tool?.title
]
);
const onDrop = (data: DraxDragWithReceiverEventData) => {

View File

@@ -24,13 +24,6 @@ import Group from "./group";
import Home from "./home";
import { RouteParams } from "./types";
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 Group = React.lazy(() => import(/* webpackChunkName: "settings-group" */ './group'));
@@ -65,7 +58,13 @@ export const Settings = () => {
return (
<SettingsStack.Navigator
initialRouteName="SettingsHome"
screenListeners={screenListeners}
screenListeners={{
beforeRemove: (e) => {
if (e.target?.startsWith("SettingsGroup")) {
useNavigationStore.getState().update({ name: "Settings" }, false);
}
}
}}
screenOptions={{
animation: "none",
headerShown: false,

View File

@@ -137,7 +137,7 @@ export const useTip = (
return () => {
clearInterval(intervalRef.current);
};
}, [context, fallback]);
}, [context, fallback, options.delay, options?.rotate]);
return tip;
};

View File

@@ -58,6 +58,10 @@ export type Item =
export type MonographType = {
type: "monograph";
id: string;
title: string;
dateModified: number;
dateCreated: number;
};
export interface Entity<TType extends EntityTypes> {