From 405adff8f4e30fa622a68c4585569780cff457d6 Mon Sep 17 00:00:00 2001 From: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com> Date: Sat, 18 Apr 2026 08:52:39 +0500 Subject: [PATCH] mobile: fix linting not working in vscode and fix lint errors (#9710) --- apps/mobile/app/app.tsx | 8 +- apps/mobile/app/common/database/encryption.ts | 6 +- apps/mobile/app/common/database/index.ts | 2 +- .../app/common/database/sqlite.kysely.ts | 4 +- apps/mobile/app/common/filesystem/io.ts | 8 +- .../components/announcements/announcement.tsx | 2 +- .../app/components/announcements/cta.tsx | 2 +- apps/mobile/app/components/app-lock/index.tsx | 5 +- .../app/components/attachments/actions.tsx | 1 - .../app/components/attachments/index.tsx | 1 - .../app/components/auth/forgot-password.tsx | 2 +- apps/mobile/app/components/auth/login.tsx | 11 +- .../app/components/auth/session-expired.tsx | 6 +- apps/mobile/app/components/auth/signup.tsx | 2 +- .../app/components/date-picker/index.tsx | 19 + .../app/components/dialog/base-dialog.tsx | 9 +- .../app/components/dialog/dialog-header.tsx | 1 - .../app/components/dialogs/vault/index.tsx | 252 +- .../app/components/fluid-panels/index.tsx | 2 - apps/mobile/app/components/list/index.tsx | 10 +- .../app/components/list/reorderable-list.tsx | 4 +- .../app/components/merge-conflicts/index.tsx | 8 +- .../app/components/note-history/index.tsx | 37 +- .../app/components/note-history/preview.tsx | 1 - apps/mobile/app/components/paywall/index.tsx | 13 +- .../app/components/properties/color-tags.tsx | 2 +- .../app/components/properties/date-meta.tsx | 2 +- .../app/components/properties/items.tsx | 18 +- .../mobile/app/components/properties/tags.jsx | 2 +- .../app/components/selection-header/index.tsx | 2 - .../app/components/sheets/buy-plan/index.tsx | 43 +- .../components/sheets/export-notes/share.jsx | 1 - .../app/components/sheets/notebooks/index.tsx | 2 +- .../app/components/sheets/paywall/index.tsx | 19 + .../components/sheets/plan-limits/index.tsx | 27 +- .../components/sheets/publish-note/index.tsx | 5 +- .../mobile/app/components/side-menu/index.tsx | 10 +- .../components/side-menu/pinned-section.tsx | 2 +- apps/mobile/app/components/ui/sheet/index.jsx | 7 +- .../components/walkthroughs/walkthroughs.tsx | 25 +- apps/mobile/app/hooks/use-actions.tsx | 11 +- apps/mobile/app/hooks/use-app-events.tsx | 5 +- apps/mobile/app/hooks/use-db-item.ts | 2 +- apps/mobile/app/hooks/use-feature-manager.ts | 25 +- apps/mobile/app/hooks/use-pricing-plans.ts | 7 +- .../app/navigation/fluid-panels-view.tsx | 18 +- .../app/navigation/navigation-stack.tsx | 1 - .../mobile/app/screens/add-reminder/index.tsx | 123 +- .../app/screens/editor/tiptap/picker.ts | 5 +- .../mobile/app/screens/editor/tiptap/types.ts | 1 - .../editor/tiptap/use-editor-events.tsx | 4 +- .../app/screens/editor/tiptap/use-editor.ts | 6 +- .../mobile/app/screens/editor/tiptap/utils.ts | 5 +- apps/mobile/app/screens/manage-tags/index.tsx | 9 +- apps/mobile/app/screens/notebook/index.tsx | 2 +- .../settings/editor/configure-toolbar.tsx | 12 +- apps/mobile/app/screens/settings/group.tsx | 2 +- apps/mobile/app/screens/settings/logout.ts | 18 + .../app/screens/settings/notesnook-circle.tsx | 21 +- .../app/screens/settings/picker/index.tsx | 6 +- .../screens/settings/restore-backup/index.tsx | 8 +- .../app/screens/settings/section-item.tsx | 4 +- apps/mobile/app/services/message.tsx | 4 +- apps/mobile/app/services/premium.ts | 20 +- apps/mobile/app/services/sync.ts | 1 - apps/mobile/app/share/editor.tsx | 2 +- apps/mobile/app/share/share.tsx | 27 +- apps/mobile/app/share/store.ts | 8 +- apps/mobile/app/stores/index.ts | 2 +- apps/mobile/app/utils/unlock-vault.ts | 1 + apps/mobile/package-lock.json | 2394 +---------------- apps/mobile/package.json | 12 +- 72 files changed, 519 insertions(+), 2830 deletions(-) diff --git a/apps/mobile/app/app.tsx b/apps/mobile/app/app.tsx index 7e92c8042..f936316bb 100644 --- a/apps/mobile/app/app.tsx +++ b/apps/mobile/app/app.tsx @@ -23,7 +23,7 @@ import { THEME_COMPATIBILITY_VERSION, useThemeEngineStore } from "@notesnook/theme"; -import React, { useEffect } from "react"; +import React, { PropsWithChildren, useEffect } from "react"; import { Appearance, I18nManager, Linking, StatusBar } from "react-native"; import "react-native-gesture-handler"; import { GestureHandlerRootView } from "react-native-gesture-handler"; @@ -106,8 +106,10 @@ let currTheme = : SettingsService.getProperty("lighTheme"); useThemeEngineStore.getState().setTheme(currTheme); -export const withTheme = (Element: (props: any) => JSX.Element) => { - return function AppWithThemeProvider(props: any) { +export const withTheme = ( + Element: (props: PropsWithChildren) => JSX.Element +) => { + return function AppWithThemeProvider(props: PropsWithChildren) { const [colorScheme, darkTheme, lightTheme] = useThemeStore((state) => [ state.colorScheme, state.darkTheme, diff --git a/apps/mobile/app/common/database/encryption.ts b/apps/mobile/app/common/database/encryption.ts index 051ade492..4f6308d9f 100644 --- a/apps/mobile/app/common/database/encryption.ts +++ b/apps/mobile/app/common/database/encryption.ts @@ -25,7 +25,6 @@ import * as Keychain from "react-native-keychain"; import { MMKVLoader, ProcessingModes } from "react-native-mmkv-storage"; import { generateSecureRandom } from "react-native-securerandom"; import { DatabaseLogger } from "."; -import { ToastManager } from "../../services/event-manager"; import { MMKV } from "./mmkv"; // Database key cipher is persisted across different user sessions hence it has @@ -205,9 +204,8 @@ export async function getDatabaseKey(appLockPassword?: string) { } if (await Keychain.hasInternetCredentials("notesnook")) { - const userKeyCredentials = await Keychain.getInternetCredentials( - "notesnook" - ); + const userKeyCredentials = + await Keychain.getInternetCredentials("notesnook"); if (userKeyCredentials) { const userKeyCipher: Cipher = (await encrypt( diff --git a/apps/mobile/app/common/database/index.ts b/apps/mobile/app/common/database/index.ts index 63731f200..ec65abff6 100644 --- a/apps/mobile/app/common/database/index.ts +++ b/apps/mobile/app/common/database/index.ts @@ -72,7 +72,7 @@ export async function setupDatabase(password?: string) { ({ compress: Gzip.deflate, decompress: Gzip.inflate - } as ICompressor), + }) as ICompressor, batchSize: 50, sqliteOptions: { dialect: (name) => ({ diff --git a/apps/mobile/app/common/database/sqlite.kysely.ts b/apps/mobile/app/common/database/sqlite.kysely.ts index 04a0c4857..64c259816 100644 --- a/apps/mobile/app/common/database/sqlite.kysely.ts +++ b/apps/mobile/app/common/database/sqlite.kysely.ts @@ -109,8 +109,8 @@ class RNSqliteConnection implements DatabaseConnection { query.kind === "SelectQueryNode" ? "query" : query.kind === "RawNode" - ? "raw" - : "exec"; + ? "raw" + : "exec"; const result = await this.db.executeAsync(sql, parameters as any[]); diff --git a/apps/mobile/app/common/filesystem/io.ts b/apps/mobile/app/common/filesystem/io.ts index c3db265aa..37b9d5d48 100644 --- a/apps/mobile/app/common/filesystem/io.ts +++ b/apps/mobile/app/common/filesystem/io.ts @@ -112,8 +112,8 @@ export async function writeEncryptedBase64( async function deleteLocalFile(filename: string) { try { await createCacheDir(); - let path = cacheDir + `/${filename}`; - let exists = await RNFetchBlob.fs.exists(path); + const path = cacheDir + `/${filename}`; + const exists = await RNFetchBlob.fs.exists(path); if (Platform.OS === "ios" && !exists) { const iosAppGroup = Platform.OS === "ios" @@ -309,7 +309,9 @@ export async function deleteDCacheFiles() { }); } } - } catch (e) {} + } catch (e) { + /** Empty */ + } } export async function getCachePathForFile(filename: string) { diff --git a/apps/mobile/app/components/announcements/announcement.tsx b/apps/mobile/app/components/announcements/announcement.tsx index 329ccc282..47ecabdc0 100644 --- a/apps/mobile/app/components/announcements/announcement.tsx +++ b/apps/mobile/app/components/announcements/announcement.tsx @@ -36,7 +36,7 @@ export const Announcement = () => { state.announcements, state.remove ]); - let announcement = announcements.length > 0 ? announcements[0] : null; + const announcement = announcements.length > 0 ? announcements[0] : null; const selectionMode = useSelectionStore((state) => state.selectionMode); return !announcement || selectionMode ? null : ( diff --git a/apps/mobile/app/components/announcements/cta.tsx b/apps/mobile/app/components/announcements/cta.tsx index 7d2c4938b..2feb2ab66 100644 --- a/apps/mobile/app/components/announcements/cta.tsx +++ b/apps/mobile/app/components/announcements/cta.tsx @@ -32,7 +32,7 @@ import { Action } from "../../stores/use-message-store"; export const Cta = (props: BodyItemProps) => { const { colors } = useThemeColors(); - let buttons = + const buttons = props.item.actions.filter((item) => allowedOnPlatform(item.platforms)) || []; diff --git a/apps/mobile/app/components/app-lock/index.tsx b/apps/mobile/app/components/app-lock/index.tsx index b652e4bc5..bcab38b15 100644 --- a/apps/mobile/app/components/app-lock/index.tsx +++ b/apps/mobile/app/components/app-lock/index.tsx @@ -53,7 +53,6 @@ import Heading from "../ui/typography/heading"; import Paragraph from "../ui/typography/paragraph"; import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; import { strings } from "@notesnook/intl"; -import { AppFontSize } from "../../utils/size"; import { editorController } from "../../screens/editor/tiptap/utils"; import { useTabStore } from "../../screens/editor/tiptap/use-tab-store"; @@ -239,8 +238,8 @@ const AppLocked = () => { deviceMode !== "mobile" ? "50%" : Platform.OS == "ios" - ? "95%" - : "100%", + ? "95%" + : "100%", paddingHorizontal: 12, marginBottom: 30, marginTop: 15, diff --git a/apps/mobile/app/components/attachments/actions.tsx b/apps/mobile/app/components/attachments/actions.tsx index 7adf4490e..811c08a0e 100644 --- a/apps/mobile/app/components/attachments/actions.tsx +++ b/apps/mobile/app/components/attachments/actions.tsx @@ -46,7 +46,6 @@ import { eOnLoadNote } from "../../utils/events"; import { AppFontSize } from "../../utils/size"; -import { sleep } from "../../utils/time"; import { Dialog } from "../dialog"; import { presentDialog } from "../dialog/functions"; import { openNote } from "../list-items/note/wrapper"; diff --git a/apps/mobile/app/components/attachments/index.tsx b/apps/mobile/app/components/attachments/index.tsx index 53a2580a7..b5b7b6943 100644 --- a/apps/mobile/app/components/attachments/index.tsx +++ b/apps/mobile/app/components/attachments/index.tsx @@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { LegendList } from "@legendapp/list"; import { Attachment, FilteredSelector, diff --git a/apps/mobile/app/components/auth/forgot-password.tsx b/apps/mobile/app/components/auth/forgot-password.tsx index 67f82e16e..85ced9c76 100644 --- a/apps/mobile/app/components/auth/forgot-password.tsx +++ b/apps/mobile/app/components/auth/forgot-password.tsx @@ -53,7 +53,7 @@ export const ForgotPassword = ({ userEmail }: { userEmail: string }) => { } setLoading(true); try { - let lastRecoveryEmailTime = SettingsService.get().lastRecoveryEmailTime; + const lastRecoveryEmailTime = SettingsService.get().lastRecoveryEmailTime; if ( lastRecoveryEmailTime && Date.now() - lastRecoveryEmailTime < 60000 * 3 diff --git a/apps/mobile/app/components/auth/login.tsx b/apps/mobile/app/components/auth/login.tsx index e1e2741f4..efa44ba28 100644 --- a/apps/mobile/app/components/auth/login.tsx +++ b/apps/mobile/app/components/auth/login.tsx @@ -22,14 +22,9 @@ import { useThemeColors } from "@notesnook/theme"; import { RouteProp, useRoute } from "@react-navigation/native"; import React, { useEffect, useState } from "react"; import { TouchableOpacity, View, useWindowDimensions } from "react-native"; -import { SheetManager } from "react-native-actions-sheet"; import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; import { DDS } from "../../services/device-detection"; -import { - eSendEvent, - presentSheet, - ToastManager -} from "../../services/event-manager"; +import { eSendEvent, presentSheet } from "../../services/event-manager"; import Navigation from "../../services/navigation"; import PremiumService from "../../services/premium"; import SettingsService from "../../services/settings"; @@ -195,8 +190,8 @@ export const Login = ({ ? "50%" : "49.99%" : focused - ? "100%" - : "99.9%", + ? "100%" + : "99.9%", backgroundColor: colors.primary.background, alignSelf: "center", paddingHorizontal: DDS.isTab ? 0 : DefaultAppStyles.GAP, diff --git a/apps/mobile/app/components/auth/session-expired.tsx b/apps/mobile/app/components/auth/session-expired.tsx index 360f8153e..377bc6d79 100644 --- a/apps/mobile/app/components/auth/session-expired.tsx +++ b/apps/mobile/app/components/auth/session-expired.tsx @@ -92,7 +92,7 @@ export const SessionExpired = () => { const open = React.useCallback(async () => { try { - let res = await db.tokenManager.getToken(); + const res = await db.tokenManager.getToken(); if (!res) throw new Error("no token found"); if (db.tokenManager._isTokenExpired(res)) throw new Error("token expired"); @@ -102,7 +102,7 @@ export const SessionExpired = () => { Sync.run("global", false, "full", async (complete) => { if (!complete) { - let user = await db.user.getUser(); + const user = await db.user.getUser(); if (!user) return; email.current = user.email; setVisible(true); @@ -115,7 +115,7 @@ export const SessionExpired = () => { setVisible(false); }); } catch (e) { - let user = await db.user.getUser(); + const user = await db.user.getUser(); if (!user) return; email.current = user.email; setFocused(false); diff --git a/apps/mobile/app/components/auth/signup.tsx b/apps/mobile/app/components/auth/signup.tsx index f525d4bcf..06f870b21 100644 --- a/apps/mobile/app/components/auth/signup.tsx +++ b/apps/mobile/app/components/auth/signup.tsx @@ -99,7 +99,7 @@ export const Signup = ({ try { setCurrentStep(SignupSteps.createAccount); await db.user.signup(email.current!.toLowerCase(), password.current!); - let user = await db.user.getUser(); + const user = await db.user.getUser(); setUser(user); setLastSynced(await db.lastSynced()); clearMessage(); diff --git a/apps/mobile/app/components/date-picker/index.tsx b/apps/mobile/app/components/date-picker/index.tsx index 7abf8ee47..68f4c14ff 100644 --- a/apps/mobile/app/components/date-picker/index.tsx +++ b/apps/mobile/app/components/date-picker/index.tsx @@ -1,3 +1,22 @@ +/* +This file is part of the Notesnook project (https://notesnook.com/) + +Copyright (C) 2023 Streetwriters (Private) Limited + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +import React from "react"; import { useThemeColors } from "@notesnook/theme"; import { useRef } from "react"; import { View } from "react-native"; diff --git a/apps/mobile/app/components/dialog/base-dialog.tsx b/apps/mobile/app/components/dialog/base-dialog.tsx index 7712c6d4f..f2b0ce4b2 100644 --- a/apps/mobile/app/components/dialog/base-dialog.tsx +++ b/apps/mobile/app/components/dialog/base-dialog.tsx @@ -23,7 +23,6 @@ import { ColorValue, KeyboardAvoidingView, Modal, - Platform, SafeAreaView, StyleSheet, TouchableOpacity, @@ -136,8 +135,8 @@ const BaseDialog = ({ backgroundColor: background ? background : transparent - ? "transparent" - : "rgba(0,0,0,0.3)" + ? "transparent" + : "rgba(0,0,0,0.3)" }} > diff --git a/apps/mobile/app/components/dialog/dialog-header.tsx b/apps/mobile/app/components/dialog/dialog-header.tsx index 311da4630..eff4dad14 100644 --- a/apps/mobile/app/components/dialog/dialog-header.tsx +++ b/apps/mobile/app/components/dialog/dialog-header.tsx @@ -22,7 +22,6 @@ import { Text, View, ViewStyle } from "react-native"; import { useThemeColors } from "@notesnook/theme"; import { AppFontSize } from "../../utils/size"; import { Button, ButtonProps } from "../ui/button"; -import { PressableProps } from "../ui/pressable"; import Heading from "../ui/typography/heading"; import Paragraph from "../ui/typography/paragraph"; import { DefaultAppStyles } from "../../utils/styles"; diff --git a/apps/mobile/app/components/dialogs/vault/index.tsx b/apps/mobile/app/components/dialogs/vault/index.tsx index bf1d65792..0cfdf7661 100644 --- a/apps/mobile/app/components/dialogs/vault/index.tsx +++ b/apps/mobile/app/components/dialogs/vault/index.tsx @@ -110,61 +110,6 @@ export const VaultDialog: React.FC = () => { const confirmPasswordRef = useRef(null); const newPasswordRef = useRef(null); - const open = useCallback(async (data: Vault) => { - const biometry = await BiometricService.isBiometryAvailable(); - const available = !!biometry; - const fingerprint = await BiometricService.hasInternetCredentials(); - - if (data.item) { - const locked = await db.vaults.itemExists(data.item); - noteLockedRef.current = locked; - if (!locked) { - const content = await db.content.findByNoteId(data.item!.id); - if (content && isEncryptedContent(content)) { - noteLockedRef.current = true; - } - } - } - - // Set refs - noteRef.current = data.item; - titleRef.current = data.title || strings.goToEditor(); - descriptionRef.current = data.description || null; - paragraphRef.current = data.paragraph || null; - buttonTitleRef.current = data.buttonTitle || null; - positiveButtonTypeRef.current = data.positiveButtonType || "transparent"; - customActionTitleRef.current = data.customActionTitle || null; - customActionParagraphRef.current = data.customActionParagraph || null; - onUnlockRef.current = data.onUnlock; - requestTypeRef.current = data.requestType; - - // Set UI state - setIsBiometryAvailable(available); - setIsBiometryEnrolled(fingerprint); - setBiometricUnlock(fingerprint); - setWrongPassword(false); - setPasswordsDontMatch(false); - setDeleteAll(false); - setLoading(false); - - // Auto-unlock with fingerprint if applicable - const canAutoUnlock = - fingerprint && - data.requestType !== VaultRequestType.EnableFingerprint && - data.requestType !== VaultRequestType.RevokeFingerprint && - data.requestType !== VaultRequestType.ChangePassword && - data.requestType !== VaultRequestType.ClearVault && - data.requestType !== VaultRequestType.DeleteVault && - data.requestType !== VaultRequestType.CustomAction && - data.requestType !== VaultRequestType.PermanentUnlock; - - if (canAutoUnlock) { - await onPressFingerprintAuth(data.title, data.description); - } else { - setVisible(true); - } - }, []); - const close = useCallback(() => { if (loading) { ToastManager.show({ @@ -292,6 +237,45 @@ export const VaultDialog: React.FC = () => { setLoading(false); }, [close]); + const enrollFingerprint = useCallback( + async (password: string) => { + setLoading(true); + try { + await db.vault.unlock(password); + await BiometricService.storeCredentials(password); + setLoading(false); + eSendEvent("vaultUpdated"); + ToastManager.show({ + heading: strings.biometricUnlockEnabled(), + type: "success", + context: "global" + }); + close(); + } catch (e) { + close(); + ToastManager.show({ + heading: strings.passwordIncorrect(), + type: "error", + context: "local" + }); + setLoading(false); + } + }, + [close] + ); + + const takeErrorAction = useCallback(() => { + setWrongPassword(true); + setVisible(true); + setTimeout(() => { + ToastManager.show({ + heading: strings.passwordIncorrect(), + type: "error", + context: "local" + }); + }, 500); + }, []); + const lockNote = useCallback(async () => { if (!passwordRef.current || passwordRef.current.trim() === "") { ToastManager.show({ @@ -333,7 +317,13 @@ export const VaultDialog: React.FC = () => { .catch((e) => { takeErrorAction(); }); - }, [close, biometricUnlock, isBiometryEnrolled]); + }, [ + biometricUnlock, + isBiometryEnrolled, + close, + enrollFingerprint, + takeErrorAction + ]); const openInEditor = useCallback( (note: Note & { content?: NoteContent }) => { @@ -387,19 +377,7 @@ export const VaultDialog: React.FC = () => { } catch (e) { takeErrorAction(); } - }, [close]); - - const takeErrorAction = useCallback(() => { - setWrongPassword(true); - setVisible(true); - setTimeout(() => { - ToastManager.show({ - heading: strings.passwordIncorrect(), - type: "error", - context: "local" - }); - }, 500); - }, []); + }, [close, takeErrorAction]); const openNote = useCallback(async () => { try { @@ -440,6 +418,7 @@ export const VaultDialog: React.FC = () => { }, [ biometricUnlock, isBiometryEnrolled, + enrollFingerprint, openInEditor, shareNote, deleteNote, @@ -464,33 +443,6 @@ export const VaultDialog: React.FC = () => { } }, [permanantUnlock, openNote]); - const enrollFingerprint = useCallback( - async (password: string) => { - setLoading(true); - try { - await db.vault.unlock(password); - await BiometricService.storeCredentials(password); - setLoading(false); - eSendEvent("vaultUpdated"); - ToastManager.show({ - heading: strings.biometricUnlockEnabled(), - type: "success", - context: "global" - }); - close(); - } catch (e) { - close(); - ToastManager.show({ - heading: strings.passwordIncorrect(), - type: "error", - context: "local" - }); - setLoading(false); - } - }, - [close] - ); - const createVault = useCallback(async () => { await db.vault.create(passwordRef.current || ""); @@ -536,31 +488,6 @@ export const VaultDialog: React.FC = () => { } }, []); - const onPressFingerprintAuth = useCallback( - async (title?: string, description?: string) => { - try { - const credentials = await BiometricService.getCredentials( - title || titleRef.current, - description || descriptionRef.current || "" - ); - - if (!credentials) throw new Error("Failed to get user credentials"); - - if (credentials?.password) { - passwordRef.current = credentials.password; - onPress(); - } else { - eSendEvent(eCloseActionSheet); - await sleep(300); - setVisible(true); - } - } catch (e) { - console.error(e); - } - }, - [] - ); - const onPress = useCallback(async () => { const requestType = requestTypeRef.current; @@ -689,6 +616,89 @@ export const VaultDialog: React.FC = () => { deleteVault ]); + const onPressFingerprintAuth = useCallback( + async (title?: string, description?: string) => { + try { + const credentials = await BiometricService.getCredentials( + title || titleRef.current, + description || descriptionRef.current || "" + ); + + if (!credentials) throw new Error("Failed to get user credentials"); + + if (credentials?.password) { + passwordRef.current = credentials.password; + onPress(); + } else { + eSendEvent(eCloseActionSheet); + await sleep(300); + setVisible(true); + } + } catch (e) { + console.error(e); + } + }, + [onPress] + ); + + const open = useCallback( + async (data: Vault) => { + const biometry = await BiometricService.isBiometryAvailable(); + const available = !!biometry; + const fingerprint = await BiometricService.hasInternetCredentials(); + + if (data.item) { + const locked = await db.vaults.itemExists(data.item); + noteLockedRef.current = locked; + if (!locked) { + const content = await db.content.findByNoteId(data.item!.id); + if (content && isEncryptedContent(content)) { + noteLockedRef.current = true; + } + } + } + + // Set refs + noteRef.current = data.item; + titleRef.current = data.title || strings.goToEditor(); + descriptionRef.current = data.description || null; + paragraphRef.current = data.paragraph || null; + buttonTitleRef.current = data.buttonTitle || null; + positiveButtonTypeRef.current = data.positiveButtonType || "transparent"; + customActionTitleRef.current = data.customActionTitle || null; + customActionParagraphRef.current = data.customActionParagraph || null; + onUnlockRef.current = data.onUnlock; + requestTypeRef.current = data.requestType; + + // Set UI state + setIsBiometryAvailable(available); + setIsBiometryEnrolled(fingerprint); + setBiometricUnlock(fingerprint); + setWrongPassword(false); + setPasswordsDontMatch(false); + setDeleteAll(false); + setLoading(false); + + // Auto-unlock with fingerprint if applicable + const canAutoUnlock = + fingerprint && + data.requestType !== VaultRequestType.EnableFingerprint && + data.requestType !== VaultRequestType.RevokeFingerprint && + data.requestType !== VaultRequestType.ChangePassword && + data.requestType !== VaultRequestType.ClearVault && + data.requestType !== VaultRequestType.DeleteVault && + data.requestType !== VaultRequestType.CustomAction && + data.requestType !== VaultRequestType.PermanentUnlock; + + if (canAutoUnlock) { + await onPressFingerprintAuth(data.title, data.description); + } else { + setVisible(true); + } + }, + [onPressFingerprintAuth] + ); + useEffect(() => { eSubscribeEvent(eOpenVaultDialog, open); eSubscribeEvent(eCloseVaultDialog, close); diff --git a/apps/mobile/app/components/fluid-panels/index.tsx b/apps/mobile/app/components/fluid-panels/index.tsx index 6d2a75159..c2c0d0372 100644 --- a/apps/mobile/app/components/fluid-panels/index.tsx +++ b/apps/mobile/app/components/fluid-panels/index.tsx @@ -22,7 +22,6 @@ import React, { RefObject, useEffect, useImperativeHandle, - useMemo, useRef, useState } from "react"; @@ -39,7 +38,6 @@ import Animated, { WithSpringConfig, withTiming } from "react-native-reanimated"; -import { useTabStore } from "../../screens/editor/tiptap/use-tab-store"; import { eSendEvent } from "../../services/event-manager"; import { useSettingStore } from "../../stores/use-setting-store"; import { eClearEditor } from "../../utils/events"; diff --git a/apps/mobile/app/components/list/index.tsx b/apps/mobile/app/components/list/index.tsx index 54279e358..d33a48c66 100644 --- a/apps/mobile/app/components/list/index.tsx +++ b/apps/mobile/app/components/list/index.tsx @@ -77,10 +77,10 @@ export default function List(props: ListProps) { props.renderedInRoute === "Notes" ? "home" : props.renderedInRoute === "Favorites" - ? "favorites" - : props.renderedInRoute === "Trash" || props.dataType === "trash" - ? "trash" - : `${props.dataType}s`; + ? "favorites" + : props.renderedInRoute === "Trash" || props.dataType === "trash" + ? "trash" + : `${props.dataType}s`; const groupOptions = useGroupOptions(groupType); @@ -94,7 +94,7 @@ export default function List(props: ListProps) { (item: number | boolean, index: number) => { return props.data?.type(index); }, - [] + [props.data] ); const renderItem = React.useCallback( diff --git a/apps/mobile/app/components/list/reorderable-list.tsx b/apps/mobile/app/components/list/reorderable-list.tsx index 6658e072e..3047d024e 100644 --- a/apps/mobile/app/components/list/reorderable-list.tsx +++ b/apps/mobile/app/components/list/reorderable-list.tsx @@ -30,7 +30,7 @@ import { fluidTabsRef } from "../../utils/global-refs"; import { AppFontSize } from "../../utils/size"; import { useSideBarDraggingStore } from "../side-menu/dragging-store"; import { IconButton } from "../ui/icon-button"; -import { isFeatureAvailable, useIsFeatureAvailable } from "@notesnook/common"; +import { useIsFeatureAvailable } from "@notesnook/common"; import PaywallSheet from "../sheets/paywall"; import { strings } from "@notesnook/intl"; import { ToastManager } from "../../services/event-manager"; @@ -142,7 +142,7 @@ function ReorderableList({ items.push(...data.filter((i) => !itemOrderState.includes(i.id))); return items; - }, [data, customizableSidebarFeature?.isAllowed]); + }, [customizableSidebarFeature?.isAllowed, data, itemOrderState]); return ( diff --git a/apps/mobile/app/components/merge-conflicts/index.tsx b/apps/mobile/app/components/merge-conflicts/index.tsx index 8798ac386..80c50f6a4 100644 --- a/apps/mobile/app/components/merge-conflicts/index.tsx +++ b/apps/mobile/app/components/merge-conflicts/index.tsx @@ -20,7 +20,6 @@ along with this program. If not, see . import { getFormattedDate } from "@notesnook/common"; import { EncryptedContentItem, - isEncryptedContent, Note, UnencryptedContentItem } from "@notesnook/core"; @@ -75,9 +74,9 @@ const MergeConflicts = () => { const { height } = useSettingStore((state) => state.dimensions); const applyChanges = async () => { - let contentToSave = selectedContent; + const contentToSave = selectedContent; if (!contentToSave) return; - let note = await db.notes.note(contentToSave.noteId); + const note = await db.notes.note(contentToSave.noteId); if (!note) return; await db.notes.add({ id: note.id, @@ -462,7 +461,8 @@ const MergeConflicts = () => { { - const note = await db.notes.note(content.current?.noteId!); + if (!content.current?.noteId) return; + const note = await db.notes.note(content.current?.noteId); if (!note) return; loadContent({ id: note.id, diff --git a/apps/mobile/app/components/note-history/index.tsx b/apps/mobile/app/components/note-history/index.tsx index a39cd11b8..4b16c191f 100644 --- a/apps/mobile/app/components/note-history/index.tsx +++ b/apps/mobile/app/components/note-history/index.tsx @@ -63,22 +63,25 @@ const HistoryItem = ({ }${_end_time}`; }; - const preview = useCallback(async (item: HistorySession) => { - const content = await db.noteHistory.content(item.id); - presentSheet({ - component: ( - - ), - context: "note_history" - }); - }, []); + const preview = useCallback( + async (item: HistorySession) => { + const content = await db.noteHistory.content(item.id); + presentSheet({ + component: ( + + ), + context: "note_history" + }); + }, + [note] + ); return ( ( ), - [history] + [history, note] ); return ( diff --git a/apps/mobile/app/components/note-history/preview.tsx b/apps/mobile/app/components/note-history/preview.tsx index 647946eea..9124312bc 100644 --- a/apps/mobile/app/components/note-history/preview.tsx +++ b/apps/mobile/app/components/note-history/preview.tsx @@ -42,7 +42,6 @@ import { isEncryptedContent, Note, NoteContent, - SessionContentItem, TrashOrItem } from "@notesnook/core"; diff --git a/apps/mobile/app/components/paywall/index.tsx b/apps/mobile/app/components/paywall/index.tsx index 609b364f0..e1da6a404 100644 --- a/apps/mobile/app/components/paywall/index.tsx +++ b/apps/mobile/app/components/paywall/index.tsx @@ -19,7 +19,6 @@ along with this program. If not, see . import { getFeaturesTable } from "@notesnook/common"; import { - EV, EVENTS, Plan, SKUResponse, @@ -119,7 +118,7 @@ const PayWall = (props: NavigationProps<"PayWall">) => { } setStep(Steps.buy); } - }, [routeParams.state]); + }, [pricingPlans, routeParams.state]); useEffect(() => { let listener: NativeEventSubscription; @@ -137,7 +136,7 @@ const PayWall = (props: NavigationProps<"PayWall">) => { return () => { listener?.remove(); }; - }, [isFocused, step]); + }, [isFocused, routeParams.context, step]); useEffect(() => { const sub = db.eventManager.subscribe( @@ -154,7 +153,7 @@ const PayWall = (props: NavigationProps<"PayWall">) => { return () => { sub?.unsubscribe(); }; - }, []); + }, [routeParams.context]); const is5YearPlanSelected = ( isGithubRelease @@ -971,7 +970,7 @@ const PricingPlanCard = ({ .then((value) => { setRegionaDiscount(value); }); - }, [annualBilling]); + }, [WebPlan?.period, annualBilling, plan.id, pricingPlans]); useEffect(() => { if (!annualBilling) { @@ -1008,8 +1007,8 @@ const PricingPlanCard = ({ : "monthly" }` : pricingPlans.isGithubRelease - ? (WebPlan?.period as string) - : (product?.productId as string) + ? (WebPlan?.period as string) + : (product?.productId as string) ); setStep(Steps.buy); }} diff --git a/apps/mobile/app/components/properties/color-tags.tsx b/apps/mobile/app/components/properties/color-tags.tsx index ba04c98c2..5bcc1ab47 100644 --- a/apps/mobile/app/components/properties/color-tags.tsx +++ b/apps/mobile/app/components/properties/color-tags.tsx @@ -132,7 +132,7 @@ export const ColorTags = ({ item }: { item: Note }) => { } useSettingStore.getState().setSheetKeyboardHandler(false); setVisible(true); - }, []); + }, [colorFeature]); return ( <> diff --git a/apps/mobile/app/components/properties/date-meta.tsx b/apps/mobile/app/components/properties/date-meta.tsx index 8a5da0cba..ab75cab0a 100644 --- a/apps/mobile/app/components/properties/date-meta.tsx +++ b/apps/mobile/app/components/properties/date-meta.tsx @@ -35,7 +35,7 @@ export const DateMeta = ({ item }: { item: Item }) => { const [dateCreated, setDateCreated] = useState(item.dateCreated); function getDateMeta() { - let keys = Object.keys(item); + const keys = Object.keys(item); if (keys.includes("dateEdited")) keys.splice( keys.findIndex((k) => k === "dateModified"), diff --git a/apps/mobile/app/components/properties/items.tsx b/apps/mobile/app/components/properties/items.tsx index ef28b21bd..9f780eca5 100644 --- a/apps/mobile/app/components/properties/items.tsx +++ b/apps/mobile/app/components/properties/items.tsx @@ -173,15 +173,15 @@ export const Items = ({ DDS.isTab ? AppFontSize.xxl : shouldShrink - ? AppFontSize.xxl - : AppFontSize.lg + ? AppFontSize.xxl + : AppFontSize.lg } color={ item.checked ? item.activeColor || colors.primary.accent : item.id.match(/(delete|trash)/g) - ? colors.error.icon - : colors.secondary.icon + ? colors.error.icon + : colors.secondary.icon } /> @@ -212,8 +212,8 @@ export const Items = ({ text: item.checked ? item.activeColor || colors.primary.accent : item.id === "delete" || item.id === "trash" - ? colors.error.paragraph - : colors.primary.paragraph + ? colors.error.paragraph + : colors.primary.paragraph }} testID={"icon-" + item.id} onPress={item.onPress} @@ -277,8 +277,8 @@ export const Items = ({ item.checked ? item.activeColor || colors.primary.accent : item.id === "delete" || item.id === "trash" - ? colors.error.icon - : colors.secondary.icon + ? colors.error.icon + : colors.secondary.icon } /> @@ -318,7 +318,9 @@ export const Items = ({ [ colors.error.icon, colors.primary.accent, + colors.primary.border, colors.secondary.icon, + colors.static.orange, columnItemWidth, topBarSorting ] diff --git a/apps/mobile/app/components/properties/tags.jsx b/apps/mobile/app/components/properties/tags.jsx index 12a8bb261..8e14ccfd3 100644 --- a/apps/mobile/app/components/properties/tags.jsx +++ b/apps/mobile/app/components/properties/tags.jsx @@ -77,7 +77,7 @@ export const TagStrip = ({ item, close }) => { .then((tags) => { setTags(tags); }); - }, []); + }, [item]); return tags?.length > 0 ? ( { - props.pricingPlans - ?.getRegionalDiscount( - props.pricingPlans.currentPlan?.id as string, - props.pricingPlans.isGithubRelease - ? ((product as Plan)?.period as string) - : props.productId - ) - .then((value) => { - if ( - value && - value.sku?.startsWith( - (props.pricingPlans.selectedProduct as RNIap.Subscription) - ?.productId - ) - ) { - props.pricingPlans.selectProduct(value?.sku as string); - } - setRegionaDiscount(value); - }); - }, []); + if (product) { + props.pricingPlans + ?.getRegionalDiscount( + props.pricingPlans.currentPlan?.id as string, + props.pricingPlans.isGithubRelease + ? ((product as Plan)?.period as string) + : props.productId + ) + .then((value) => { + if ( + value && + value.sku?.startsWith( + (props.pricingPlans.selectedProduct as RNIap.Subscription) + ?.productId + ) + ) { + props.pricingPlans.selectProduct(value?.sku as string); + } + setRegionaDiscount(value); + }); + } + }, [product, props.pricingPlans, props.productId]); const discountValue = (isAnnual && !isGithubRelease) || diff --git a/apps/mobile/app/components/sheets/export-notes/share.jsx b/apps/mobile/app/components/sheets/export-notes/share.jsx index 1291f1a1e..a6204193e 100644 --- a/apps/mobile/app/components/sheets/export-notes/share.jsx +++ b/apps/mobile/app/components/sheets/export-notes/share.jsx @@ -21,7 +21,6 @@ import React from "react"; import { View } from "react-native"; import FileViewer from "react-native-file-viewer"; import { ToastManager } from "../../../services/event-manager"; -import { AppFontSize } from "../../../utils/size"; import { Button } from "../../ui/button"; import { strings } from "@notesnook/intl"; import { DefaultAppStyles } from "../../../utils/styles"; diff --git a/apps/mobile/app/components/sheets/notebooks/index.tsx b/apps/mobile/app/components/sheets/notebooks/index.tsx index 5e35eb5ac..328ce2748 100644 --- a/apps/mobile/app/components/sheets/notebooks/index.tsx +++ b/apps/mobile/app/components/sheets/notebooks/index.tsx @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { Notebook, VirtualizedGrouping } from "@notesnook/core"; +import { Notebook } from "@notesnook/core"; import { strings } from "@notesnook/intl"; import { useThemeColors } from "@notesnook/theme"; import React, { useEffect, useState } from "react"; diff --git a/apps/mobile/app/components/sheets/paywall/index.tsx b/apps/mobile/app/components/sheets/paywall/index.tsx index c6c92c82b..1000a2c14 100644 --- a/apps/mobile/app/components/sheets/paywall/index.tsx +++ b/apps/mobile/app/components/sheets/paywall/index.tsx @@ -1,3 +1,22 @@ +/* +This file is part of the Notesnook project (https://notesnook.com/) + +Copyright (C) 2023 Streetwriters (Private) Limited + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +import React from "react"; import { FeatureId, FeatureResult } from "@notesnook/common"; import { SubscriptionPlan, SubscriptionProvider } from "@notesnook/core"; import { strings } from "@notesnook/intl"; diff --git a/apps/mobile/app/components/sheets/plan-limits/index.tsx b/apps/mobile/app/components/sheets/plan-limits/index.tsx index e6a40140f..91667a0c7 100644 --- a/apps/mobile/app/components/sheets/plan-limits/index.tsx +++ b/apps/mobile/app/components/sheets/plan-limits/index.tsx @@ -1,3 +1,22 @@ +/* +This file is part of the Notesnook project (https://notesnook.com/) + +Copyright (C) 2023 Streetwriters (Private) Limited + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +import React from "react"; import { FeatureUsage, formatBytes, @@ -76,10 +95,10 @@ export function PlanLimits() { {item.total === Infinity ? strings.unlimited() : item.id === "storage" - ? `${formatBytes(item.used)}/${formatBytes( - item.total - )} ${strings.used()}` - : `${item.used}/${item.total} ${strings.used()}`} + ? `${formatBytes(item.used)}/${formatBytes( + item.total + )} ${strings.used()}` + : `${item.used}/${item.total} ${strings.used()}`} diff --git a/apps/mobile/app/components/sheets/publish-note/index.tsx b/apps/mobile/app/components/sheets/publish-note/index.tsx index 5f1c96c85..16e8c7b81 100644 --- a/apps/mobile/app/components/sheets/publish-note/index.tsx +++ b/apps/mobile/app/components/sheets/publish-note/index.tsx @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { hosts, Monograph, Note } from "@notesnook/core"; +import { hosts, Note } from "@notesnook/core"; import { strings } from "@notesnook/intl"; import { useThemeColors } from "@notesnook/theme"; import Clipboard from "@react-native-clipboard/clipboard"; @@ -28,7 +28,6 @@ import { TouchableOpacity, View } from "react-native"; -import Icon from "react-native-vector-icons/MaterialCommunityIcons"; //@ts-ignore import ToggleSwitch from "toggle-switch-react-native"; import { db } from "../../../common/database"; @@ -50,8 +49,8 @@ import Input from "../../ui/input"; import Heading from "../../ui/typography/heading"; import Paragraph from "../../ui/typography/paragraph"; import { useAsync } from "react-async-hook"; -import { isFeatureAvailable, useIsFeatureAvailable } from "@notesnook/common"; import { eMenuItemUpdate } from "../../../utils/events"; +import { useIsFeatureAvailable } from "@notesnook/common"; async function fetchMonographData(noteId: string) { const monographId = db.monographs.monograph(noteId); diff --git a/apps/mobile/app/components/side-menu/index.tsx b/apps/mobile/app/components/side-menu/index.tsx index 4d12c9809..a3b31bc50 100644 --- a/apps/mobile/app/components/side-menu/index.tsx +++ b/apps/mobile/app/components/side-menu/index.tsx @@ -79,6 +79,7 @@ type SimpleTabViewProps = { const createSceneMap = ( scenes: Record> ): ((props: { route: SimpleRoute }) => React.ReactNode) => { + // eslint-disable-next-line react/display-name return ({ route }: { route: SimpleRoute }) => { const SceneComponent = scenes[route.key]; if (!SceneComponent) return null; @@ -136,8 +137,8 @@ const SimpleTabView = ({ {loadedKeysRef.current.has(route.key) ? getSceneForRoute(route) : navigationState.index === routeIndex - ? getSceneForRoute(route) - : null} + ? getSceneForRoute(route) + : null} ))} @@ -435,9 +436,8 @@ const TabBar = (props: SimpleTabBarProps) => { color={colors.primary.icon} onPress={async () => { if (props.navigationState.index === 1) { - const notebooksFeature = await isFeatureAvailable( - "notebooks" - ); + const notebooksFeature = + await isFeatureAvailable("notebooks"); if (!notebooksFeature.isAllowed) { PaywallSheet.present(notebooksFeature); return; diff --git a/apps/mobile/app/components/side-menu/pinned-section.tsx b/apps/mobile/app/components/side-menu/pinned-section.tsx index bab4cbac6..128a626a5 100644 --- a/apps/mobile/app/components/side-menu/pinned-section.tsx +++ b/apps/mobile/app/components/side-menu/pinned-section.tsx @@ -76,7 +76,7 @@ export const PinnedSection = React.memo( onPress: onPress, onLongPress: onLongPress })) as SideMenuItem[], - [menuPins, onPress] + [menuPins, onLongPress, onPress] ); const renderItem = React.useCallback(({ item }: { item: SideMenuItem }) => { diff --git a/apps/mobile/app/components/ui/sheet/index.jsx b/apps/mobile/app/components/ui/sheet/index.jsx index 273adf61b..49cbd2fb0 100644 --- a/apps/mobile/app/components/ui/sheet/index.jsx +++ b/apps/mobile/app/components/ui/sheet/index.jsx @@ -83,12 +83,13 @@ const SheetWrapper = ({ : 0 }; }, [ - colors.primary.background, - colors.primary.border, largeTablet, smallTablet, width, - insets.bottom + colors.primary.background, + colors.primary.border, + bottomInsets, + isGestureNavigationEnabled ]); const _onOpen = () => { diff --git a/apps/mobile/app/components/walkthroughs/walkthroughs.tsx b/apps/mobile/app/components/walkthroughs/walkthroughs.tsx index f42ba58e8..3dc6167e5 100644 --- a/apps/mobile/app/components/walkthroughs/walkthroughs.tsx +++ b/apps/mobile/app/components/walkthroughs/walkthroughs.tsx @@ -17,33 +17,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +import { SubscriptionPlan } from "@notesnook/core"; import { strings } from "@notesnook/intl"; -import { useThemeColors } from "@notesnook/theme"; import React from "react"; -import { Linking, View } from "react-native"; -import Icon from "react-native-vector-icons/MaterialCommunityIcons"; -import { - COMMUNITY_SVG, - LAUNCH_ROCKET, - SUPPORT_SVG, - WELCOME_SVG -} from "../../assets/images/assets"; -import useRotator from "../../hooks/use-rotator"; -import { eSendEvent } from "../../services/event-manager"; -import { getContainerBorder } from "../../utils/colors"; -import { getElevationStyle } from "../../utils/elevation"; -import { eOpenAddNotebookDialog } from "../../utils/events"; -import { defaultBorderRadius, AppFontSize } from "../../utils/size"; -import { Button } from "../ui/button"; -import Seperator from "../ui/seperator"; -import { SvgView } from "../ui/svg"; -import Heading from "../ui/typography/heading"; -import Paragraph from "../ui/typography/paragraph"; -import { DefaultAppStyles } from "../../utils/styles"; +import { WELCOME_SVG } from "../../assets/images/assets"; import { useUserStore } from "../../stores/use-user-store"; -import { planToId, SubscriptionPlan } from "@notesnook/core"; import { planToDisplayName } from "../../utils/constants"; import AppIcon from "../ui/AppIcon"; +import { SvgView } from "../ui/svg"; export type TStep = { text?: string; diff --git a/apps/mobile/app/hooks/use-actions.tsx b/apps/mobile/app/hooks/use-actions.tsx index fb24369d0..2e0a685e0 100644 --- a/apps/mobile/app/hooks/use-actions.tsx +++ b/apps/mobile/app/hooks/use-actions.tsx @@ -33,7 +33,7 @@ import { useThemeColors } from "@notesnook/theme"; import { DisplayedNotification } from "@notifee/react-native"; import Clipboard from "@react-native-clipboard/clipboard"; import React, { useEffect, useRef, useState } from "react"; -import { InteractionManager, Platform, View } from "react-native"; +import { InteractionManager, Platform } from "react-native"; import Share from "react-native-share"; import { DatabaseLogger, db } from "../common/database"; import { AttachmentDialog } from "../components/attachments"; @@ -72,8 +72,8 @@ import { useUserStore } from "../stores/use-user-store"; import { eCloseSheet, eUpdateNoteInEditor } from "../utils/events"; import { deleteItems } from "../utils/functions"; import { convertNoteToText } from "../utils/note-to-text"; -import { sleep } from "../utils/time"; import { NotesnookModule } from "../utils/notesnook-module"; +import { sleep } from "../utils/time"; import DatePickerComponent from "../components/date-picker"; @@ -196,7 +196,7 @@ export const useActions = ({ "expiringNotes" ]); const [item, setItem] = useState(propItem); - const { colors, isDark } = useThemeColors(); + const { colors } = useThemeColors(); const setMenuPins = useMenuStore((state) => state.setMenuPins); const [isPinnedToMenu, setIsPinnedToMenu] = useState( db.shortcuts.exists(item.id) @@ -1286,7 +1286,10 @@ export const useActions = ({ (item as Note).headline || (item as Notebook).description || "", (item as Color).colorCode ); - } catch (e) {} + } catch (e) { + /** + empty */ + } } }); } diff --git a/apps/mobile/app/hooks/use-app-events.tsx b/apps/mobile/app/hooks/use-app-events.tsx index ed01aa347..53f1bff0f 100644 --- a/apps/mobile/app/hooks/use-app-events.tsx +++ b/apps/mobile/app/hooks/use-app-events.tsx @@ -352,7 +352,10 @@ async function checkForShareExtensionLaunchedInBackground() { if (note) setTimeout(() => eSendEvent("loadingNote", note), 1); MMKV.removeItem("shareExtensionOpened"); } - } catch (e) {} + } catch (e) { + /** + empty */ + } } const onSuccessfulSubscription = async ( diff --git a/apps/mobile/app/hooks/use-db-item.ts b/apps/mobile/app/hooks/use-db-item.ts index 3c44ca321..6b93a40b5 100644 --- a/apps/mobile/app/hooks/use-db-item.ts +++ b/apps/mobile/app/hooks/use-db-item.ts @@ -135,7 +135,7 @@ export const useNoteLocked = (noteId: string | undefined) => { //@ts-ignore !globalThis["IS_SHARE_EXTENSION"] ) { - let unsub = useSettingStore.subscribe((state) => { + const unsub = useSettingStore.subscribe((state) => { if (!state.isAppLoading) { unsub(); db.vaults diff --git a/apps/mobile/app/hooks/use-feature-manager.ts b/apps/mobile/app/hooks/use-feature-manager.ts index f173477fa..b9db4d6fb 100644 --- a/apps/mobile/app/hooks/use-feature-manager.ts +++ b/apps/mobile/app/hooks/use-feature-manager.ts @@ -1,15 +1,28 @@ +/* +This file is part of the Notesnook project (https://notesnook.com/) + +Copyright (C) 2023 Streetwriters (Private) Limited + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ import { useAreFeaturesAvailable } from "@notesnook/common"; -import { strings } from "@notesnook/intl"; import { useEffect } from "react"; import { db } from "../common/database"; -import { presentDialog } from "../components/dialog/functions"; import { useDragState } from "../screens/settings/editor/state"; -import { eSendEvent } from "../services/event-manager"; -import Navigation from "../services/navigation"; import Notifications from "../services/notifications"; import SettingsService from "../services/settings"; import { useUserStore } from "../stores/use-user-store"; -import { eCloseSimpleDialog } from "../utils/events"; export default function useFeatureManager() { const features = useAreFeaturesAvailable([ @@ -69,7 +82,7 @@ export default function useFeatureManager() { db.settings.setDefaultTag(undefined); } } - }, [features, plan]); + }, [features, plan, user]); return true; } diff --git a/apps/mobile/app/hooks/use-pricing-plans.ts b/apps/mobile/app/hooks/use-pricing-plans.ts index 1ca7a8422..b52fe8e4b 100644 --- a/apps/mobile/app/hooks/use-pricing-plans.ts +++ b/apps/mobile/app/hooks/use-pricing-plans.ts @@ -255,12 +255,15 @@ const usePricingPlans = (options?: PricingPlansOptions) => { const products = WebPlanCache || (await db.pricing.products()); WebPlanCache = products; setWebPricingPlans(products); - } catch (e) {} + } catch (e) { + /** + empty */ + } } setLoadingPlans(false); }; loadPlans(); - }, [options?.promoOffer, cancelPromo]); + }, [options?.promoOffer, cancelPromo, hasTrialOffer]); function getLocalizedPrice( product: RNIap.Subscription | RNIap.Product | Plan diff --git a/apps/mobile/app/navigation/fluid-panels-view.tsx b/apps/mobile/app/navigation/fluid-panels-view.tsx index aebbd13a8..41eafeac7 100644 --- a/apps/mobile/app/navigation/fluid-panels-view.tsx +++ b/apps/mobile/app/navigation/fluid-panels-view.tsx @@ -139,7 +139,7 @@ export const FluidPanelsView = React.memo( if (deviceMode === "smallTablet") { fluidTabsRef.current?.openDrawer(false); } - }, [deviceMode, dimensions.width, setFullscreen]); + }, [deviceMode, setFullscreen]); const closeFullScreenEditor = useCallback( (current: string) => { @@ -158,7 +158,7 @@ export const FluidPanelsView = React.memo( fluidTabsRef.current?.goToIndex(2, false); } }, - [deviceMode, dimensions.width, setFullscreen] + [deviceMode, setFullscreen] ); const toggleView = useCallback( @@ -215,7 +215,7 @@ export const FluidPanelsView = React.memo( } }, 0); }, - [deviceMode, fullscreen, setDeviceModeState] + [fullscreen, setDeviceModeState] ); const checkDeviceType = React.useCallback( @@ -229,14 +229,14 @@ export const FluidPanelsView = React.memo( : "mobile"; setDeviceMode(nextDeviceMode, size); }, - [orientation, setDeviceMode, setDimensions] + [orientation, setDeviceMode] ); useEffect(() => { if (orientation !== "UNKNOWN") { checkDeviceType(dimensions); } - }, [orientation, dimensions]); + }, [orientation, dimensions, checkDeviceType]); const _onLayout = React.useCallback( (event: LayoutChangeEvent) => { @@ -251,13 +251,7 @@ export const FluidPanelsView = React.memo( setOrientation(OrientationType["PORTRAIT"]); } }, - [ - checkDeviceType, - deviceMode, - dimensions.width, - orientation, - setDeviceMode - ] + [setDimensions] ); const PANE_OFFSET = useMemo( diff --git a/apps/mobile/app/navigation/navigation-stack.tsx b/apps/mobile/app/navigation/navigation-stack.tsx index dc4139f6e..3604bce27 100644 --- a/apps/mobile/app/navigation/navigation-stack.tsx +++ b/apps/mobile/app/navigation/navigation-stack.tsx @@ -16,7 +16,6 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ - import { useThemeColors } from "@notesnook/theme"; import { NavigationContainer } from "@react-navigation/native"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; diff --git a/apps/mobile/app/screens/add-reminder/index.tsx b/apps/mobile/app/screens/add-reminder/index.tsx index a8c78d930..b88528f72 100644 --- a/apps/mobile/app/screens/add-reminder/index.tsx +++ b/apps/mobile/app/screens/add-reminder/index.tsx @@ -400,17 +400,45 @@ export default function AddReminder(props: NavigationProps<"AddReminder">) { recurringMode === RecurringModes.Year ? null : recurringMode === RecurringModes.Week - ? (weekFormat === "Mon" ? WeekDaysMon : WeekDays).map( - (item) => ( + ? (weekFormat === "Mon" ? WeekDaysMon : WeekDays).map( + (item) => ( +