From 6227e50decfd1ce02129209663d3c4d49a8b512a Mon Sep 17 00:00:00 2001 From: Ammar Ahmed Date: Wed, 7 Feb 2024 13:03:25 +0500 Subject: [PATCH] mobile: applock with pin and password --- .../app/components/app-lock-overlay/index.tsx | 9 +- .../dialogs/applock-password/index.tsx | 102 ++++++++++++++---- .../app/components/sheets/migrate/index.tsx | 46 ++++---- apps/mobile/app/components/ui/sheet/index.js | 3 +- .../app/screens/settings/section-item.tsx | 5 +- .../app/screens/settings/settings-data.tsx | 18 ++-- apps/mobile/app/stores/use-setting-store.ts | 2 + apps/mobile/native/android/gradle.properties | 1 + .../native/fonts/MaterialCommunityIcons.ttf | Bin 24356 -> 24712 bytes apps/mobile/scripts/optimize-fonts.mjs | 4 +- 10 files changed, 139 insertions(+), 51 deletions(-) diff --git a/apps/mobile/app/components/app-lock-overlay/index.tsx b/apps/mobile/app/components/app-lock-overlay/index.tsx index f84d00d01..eab792b61 100644 --- a/apps/mobile/app/components/app-lock-overlay/index.tsx +++ b/apps/mobile/app/components/app-lock-overlay/index.tsx @@ -47,6 +47,9 @@ const AppLockedOverlay = () => { const password = useRef(); const appState = useAppState(); const biometricUnlockAwaitingUserInput = useRef(false); + const keyboardType = useSettingStore( + (state) => state.settings.applockKeyboardType + ); const appLockHasPasswordSecurity = useSettingStore( (state) => state.settings.appLockHasPasswordSecurity ); @@ -186,11 +189,13 @@ const AppLockedOverlay = () => { fwdRef={passwordInputRef} secureTextEntry keyboardType={ - appLockHasPasswordSecurity ? "number-pad" : "default" + appLockHasPasswordSecurity ? keyboardType : "default" } placeholder={`Enter ${ appLockHasPasswordSecurity - ? `app lock pin` + ? `app lock ${ + keyboardType === "numeric" ? "pin" : "password" + }` : "account password" }`} onChangeText={(v) => (password.current = v)} diff --git a/apps/mobile/app/components/dialogs/applock-password/index.tsx b/apps/mobile/app/components/dialogs/applock-password/index.tsx index 2f44b1399..3c72feec3 100644 --- a/apps/mobile/app/components/dialogs/applock-password/index.tsx +++ b/apps/mobile/app/components/dialogs/applock-password/index.tsx @@ -31,22 +31,30 @@ import { eSubscribeEvent } from "../../../services/event-manager"; import SettingsService from "../../../services/settings"; +import { useSettingStore } from "../../../stores/use-setting-store"; import { getElevationStyle } from "../../../utils/elevation"; import { eCloseAppLocKPasswordDailog, eOpenAppLockPasswordDialog } from "../../../utils/events"; +import { SIZE } from "../../../utils/size"; import { sleep } from "../../../utils/time"; import BaseDialog from "../../dialog/base-dialog"; import DialogButtons from "../../dialog/dialog-buttons"; import DialogHeader from "../../dialog/dialog-header"; import { Toast } from "../../toast"; +import { IconButton } from "../../ui/icon-button"; import Input from "../../ui/input"; import Seperator from "../../ui/seperator"; export const AppLockPassword = () => { const { colors } = useThemeColors(); const [mode, setMode] = useState<"create" | "change" | "remove">("create"); + const [keyboardType, setKeyboardType] = useState<"pin" | "password">( + useSettingStore.getState().settings.applockKeyboardType === "default" + ? "password" + : "pin" + ); const [visible, setVisible] = useState(false); const currentPasswordInputRef = useRef(null); const passwordInputRef = useRef(null); @@ -56,6 +64,7 @@ export const AppLockPassword = () => { password?: string; confirmPassword?: string; }>({}); + const [secureTextEntry, setSecureTextEntry] = useState(true); useEffect(() => { const subs = [ @@ -72,7 +81,7 @@ export const AppLockPassword = () => { }) ]; return () => { - subs.forEach((sub) => sub.unsubscribe()); + subs.forEach((sub) => sub?.unsubscribe()); }; }, []); @@ -85,7 +94,11 @@ export const AppLockPassword = () => { { await sleep(100); - passwordInputRef.current?.focus(); + if (mode !== "change") { + passwordInputRef.current?.focus(); + } else { + currentPasswordInputRef.current?.focus(); + } }} statusBarTranslucent={false} onRequestClose={close} @@ -103,17 +116,17 @@ export const AppLockPassword = () => { { onSubmit={() => { passwordInputRef.current?.focus(); }} + defaultValue={values.current.currentPassword} autoComplete="password" returnKeyLabel="Next" - keyboardType="number-pad" + keyboardType={keyboardType === "pin" ? "number-pad" : "default"} returnKeyType="next" - secureTextEntry - placeholder={"Current pin"} + secureTextEntry={secureTextEntry} + placeholder={`Current ${keyboardType}`} /> ) : null} @@ -153,12 +167,37 @@ export const AppLockPassword = () => { onSubmit={() => { confirmPasswordInputRef.current?.focus(); }} - keyboardType="number-pad" + defaultValue={values.current.password} + keyboardType={keyboardType === "pin" ? "number-pad" : "default"} autoComplete="password" returnKeyLabel={mode !== "remove" ? "Next" : "Remove"} returnKeyType={mode !== "remove" ? "next" : "done"} - secureTextEntry - placeholder={mode === "change" ? "New pin" : "Pin"} + secureTextEntry={secureTextEntry} + buttonLeft={ + { + setKeyboardType( + keyboardType === "password" ? "pin" : "password" + ); + setSecureTextEntry(false); + setImmediate(() => { + setSecureTextEntry(true); + }); + }} + customStyle={{ + width: 25, + height: 25, + marginRight: 5 + }} + size={SIZE.lg} + /> + } + placeholder={ + mode === "change" + ? `New ${keyboardType}` + : `${keyboardType === "pin" ? "Pin" : "Password"}` + } /> {mode !== "remove" ? ( @@ -171,14 +210,15 @@ export const AppLockPassword = () => { onSubmit={() => { confirmPasswordInputRef.current?.focus(); }} - keyboardType="number-pad" + defaultValue={values.current.confirmPassword} + keyboardType={keyboardType === "pin" ? "number-pad" : "default"} customValidator={() => values.current.password || ""} validationType="confirmPassword" autoComplete="password" returnKeyLabel="Done" returnKeyType="done" - secureTextEntry - placeholder={"Confirm pin"} + secureTextEntry={secureTextEntry} + placeholder={`Confirm ${keyboardType}`} /> ) : null} @@ -198,7 +238,11 @@ export const AppLockPassword = () => { if (values.current.password !== values.current.confirmPassword) { ToastManager.error( - new Error("Pin does not match"), + new Error( + `${ + keyboardType === "pin" ? "Pin" : "Password" + } does not match` + ), undefined, "local" ); @@ -222,7 +266,11 @@ export const AppLockPassword = () => { if (values.current.password !== values.current.confirmPassword) { ToastManager.error( - new Error("Pin does not match"), + new Error( + `${ + keyboardType === "pin" ? "Pin" : "Password" + } does not match` + ), undefined, "local" ); @@ -235,7 +283,9 @@ export const AppLockPassword = () => { if (!isCurrentPasswordCorrect) { ToastManager.error( - new Error("Pin incorrect"), + new Error( + `${keyboardType === "pin" ? "Pin" : "Password"} incorrect` + ), undefined, "local" ); @@ -259,13 +309,23 @@ export const AppLockPassword = () => { ); if (!isCurrentPasswordCorrect) { - ToastManager.error(new Error("Pin incorrect"), "local"); + ToastManager.error( + new Error( + `${keyboardType === "pin" ? "Pin" : "Password"} incorrect` + ), + "local" + ); return; } clearAppLockVerificationCipher(); SettingsService.setProperty("appLockHasPasswordSecurity", false); } + SettingsService.setProperty( + "applockKeyboardType", + keyboardType === "password" ? "default" : "numeric" + ); + close(); }} positiveTitle="Save" diff --git a/apps/mobile/app/components/sheets/migrate/index.tsx b/apps/mobile/app/components/sheets/migrate/index.tsx index a9d6d4a3f..bffdf2b88 100644 --- a/apps/mobile/app/components/sheets/migrate/index.tsx +++ b/apps/mobile/app/components/sheets/migrate/index.tsx @@ -18,18 +18,18 @@ along with this program. If not, see . */ import { EVENTS } from "@notesnook/core/dist/common"; +import { useThemeColors } from "@notesnook/theme"; import React, { useCallback, useEffect, useState } from "react"; import { Platform, View } from "react-native"; import { db } from "../../../common/database"; import { MMKV } from "../../../common/database/mmkv"; import BackupService from "../../../services/backup"; import { + ToastManager, eSendEvent, - presentSheet, - ToastManager + presentSheet } from "../../../services/event-manager"; import SettingsService from "../../../services/settings"; -import { useThemeColors } from "@notesnook/theme"; import { eCloseSheet } from "../../../utils/events"; import { sleep } from "../../../utils/time"; import { Dialog } from "../../dialog"; @@ -122,10 +122,13 @@ export default function Migrate() { - {!loading ? ( + {!loading && !error ? ( - - - Updating {progress ? progress?.collection : null} + Migrating database{progress ? `(${progress?.collection})` : null} {progress ? `(${progress.current}/${progress.total}) ` : null}... please wait + + + + ) : error ? ( @@ -198,6 +207,7 @@ export default function Migrate() { width={250} onPress={async () => { MMKV.clearStore(); + await db.reset(); setReset(true); }} style={{ diff --git a/apps/mobile/app/components/ui/sheet/index.js b/apps/mobile/app/components/ui/sheet/index.js index 67b4a66dc..3c8e01ab5 100644 --- a/apps/mobile/app/components/ui/sheet/index.js +++ b/apps/mobile/app/components/ui/sheet/index.js @@ -120,7 +120,8 @@ const SheetWrapper = ({ width: 100, backgroundColor: colors.secondary.background }} - drawUnderStatusBar={false} + statusBarTranslucent + drawUnderStatusBar={true} containerStyle={style} gestureEnabled={gestureEnabled} initialOffsetFromBottom={1} diff --git a/apps/mobile/app/screens/settings/section-item.tsx b/apps/mobile/app/screens/settings/section-item.tsx index 664b175e4..191316d0f 100644 --- a/apps/mobile/app/screens/settings/section-item.tsx +++ b/apps/mobile/app/screens/settings/section-item.tsx @@ -57,10 +57,11 @@ const _SectionItem = ({ item }: { item: SettingSection }) => { return; } if (!item.property) return; - item.onChange?.(!settings[item.property]); + const nextValue = !settings[item.property]; SettingsService.set({ - [item.property]: !settings[item.property] + [item.property]: nextValue }); + setImmediate(() => item.onChange?.(nextValue)); }; const styles = diff --git a/apps/mobile/app/screens/settings/settings-data.tsx b/apps/mobile/app/screens/settings/settings-data.tsx index bf5b8f2d4..06809a64e 100644 --- a/apps/mobile/app/screens/settings/settings-data.tsx +++ b/apps/mobile/app/screens/settings/settings-data.tsx @@ -799,19 +799,25 @@ export const settingsGroups: SettingSection[] = [ property: "appLockEnabled", onChange: async () => { if (!SettingsService.getProperty("appLockEnabled")) { + const keyboardType = SettingsService.getProperty( + "applockKeyboardType" + ); if (SettingsService.getProperty("appLockHasPasswordSecurity")) { presentDialog({ title: "Verify it's you", input: true, - inputPlaceholder: "Enter app lock pin", - paragraph: - "Please enter your app lock pin to disable app lock", + inputPlaceholder: `Enter app lock ${ + keyboardType === "numeric" ? "pin" : "password" + }`, + paragraph: `Please enter your app lock ${ + keyboardType === "numeric" ? "pin" : "password" + } to disable app lock`, positiveText: "Disable", secureTextEntry: true, negativeText: "Cancel", positivePress: async (value) => { try { - let verified = await validateAppLockPassword(value); + const verified = await validateAppLockPassword(value); if (!verified) { SettingsService.setProperty("appLockEnabled", true); return false; @@ -892,8 +898,8 @@ export const settingsGroups: SettingSection[] = [ }, { id: "app-lock-pin", - name: "Setup app lock pin", - description: "Set up a new pin for app lock", + name: "Setup app lock password", + description: "Setup a new app lock password for app lock", hidden: () => { return !!SettingsService.getProperty( "appLockHasPasswordSecurity" diff --git a/apps/mobile/app/stores/use-setting-store.ts b/apps/mobile/app/stores/use-setting-store.ts index b85276398..6d9348477 100644 --- a/apps/mobile/app/stores/use-setting-store.ts +++ b/apps/mobile/app/stores/use-setting-store.ts @@ -80,6 +80,7 @@ export type Settings = { appLockHasPasswordSecurity?: boolean; biometricsAuthEnabled?: boolean; backgroundSync?: boolean; + applockKeyboardType: "numeric" | "default"; }; type DimensionsType = { @@ -122,6 +123,7 @@ export interface SettingStore extends State { const { width, height } = Dimensions.get("window"); export const defaultSettings: SettingStore["settings"] = { + applockKeyboardType: "numeric", appLockTimer: 0, showToolbarOnTop: false, showKeyboardOnOpen: false, diff --git a/apps/mobile/native/android/gradle.properties b/apps/mobile/native/android/gradle.properties index dd5532e59..769aa2e62 100644 --- a/apps/mobile/native/android/gradle.properties +++ b/apps/mobile/native/android/gradle.properties @@ -48,5 +48,6 @@ hermesEnabled=true # fdroid fdroidBuild=false +org.gradle.java.home=/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home # -DSQLITE_USER_AUTHENTICATION=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 quickSqliteFlags=-DSQLITE3MC_OMIT_AES_HARDWARE_SUPPORT -DHAVE_CIPHER_AES_128_CBC=0 -DHAVE_CIPHER_AES_256_CBC=0 -DHAVE_CIPHER_SQLCIPHER=0 -DHAVE_CIPHER_RC4=0 -DHAVE_CIPHER_CHACHA20=1 -DSQLITE_ENABLE_FTS5 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_DQS=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_USE_ALLOCA=1 \ No newline at end of file diff --git a/apps/mobile/native/fonts/MaterialCommunityIcons.ttf b/apps/mobile/native/fonts/MaterialCommunityIcons.ttf index 4bc96924ee22a8e20a157296be42e8f9f9a6aaa8..cb039d578d6d18a8cd2af586d889830991a9b7c5 100644 GIT binary patch delta 1989 zcmYk7eQZ-z7>9qiD_ys>z3uJCdbh6YRzTe~$~Ha}1m{G>xG)%Wj4^O!8_cn>IR*>_ z3JWR`9Jql_`~saQ+k!}qA%cjCnh*j?w328L7ex)xe>8?fB>wIzi8gu8^PY3x-h0k_ z&TR)zDBC_%5>NnSVl&bZshoFvN#!q(dpR;f>KoeP9a9^8-GJf%?6a4*u3Prkv8n+e zqYilBWOGxzF&-(~2+R#Je{wSil#i5;*`Lq;*ygsbZVLnU&3n|gwl~DL?Cg&KRbR4S z(-!Y8?od9%QDFY9%!;gxw>7n{8vTa-3cxbb(Y~td?78qLP<@pT-3hDm_uGdDmCSU` zM?QO!ODu~l2?x|PbLeh5PXNm3DFSd0eJ7d9oN{`G0L-M#yfTj8N8c*|_tOswTqiwW z0A|s3WHIy2>s600Ej+Aplos03N2FBRmYKPcS%6-e+eieO3S(=`YB6jyKVl$)ZF87~P5;7JB=l7mdzM!zKhPthj?U_1S( z0PLW@5`d@a?*yQi{z(9KLe0EG0Cv%=3IR;ND*%1;QLZABFERRQmWTkmp=R-v5?~L_ zvp|4n>9qpD1C+&T5MY3QLjazq4+#L@o~%y!;I z@C>*<5CFbrRE-rSz#vp_hXA}zb3p_+0M*B;7O??1 z`)uwN0rP+CwjdAc%jyt1c=pE9!<8ainzU^X&v^7@cR*F8!#+bcyaywXy%*;v8$ zMyEyhr0ix&%A+Icj*PP<%-w>LQVfhi7^T3JN#^s%`D}(Vsnm>3N&=jNEm{)rr*nD} zCr?xU8#NSvtSF|$bWe4)VN~_crRKaI)qE{~L;mTA zBQhs47&%`MET}8!EwmN36kaa87A=Z4M~_4=$$#*0ahLfQM kUt2QlE1K3VZI5?0_W!={kUf3n>b9oNM;em*YkRE!0DF0ArT_o{ delta 1645 zcmW-iTWnNS6o$Vuoes2}nKPYEuhYv=h{i~O_5mv)wOp)-k#ZA|0#Ye;#NI58luDU~ zfT;)w)Jw%1YK7JigbXnR6%m0LLsSR~i3FoT@di)Y5Yh+#Sr6a&*4nerK4-1HPp0on zXYizxzyUJpC5>3!qREwYe{KtF_Con0OU%BN_JCCzPX8kXFQ&w&Mf$``jZbXBxF zXE_cFuWDATwV`Eg^ZH+ZQa%cvL+x$rJ3G>6OoqpX^w4g+&gju2gHERJUt1RXldC-S zobDw=&z4j9EX5DX4;!jYUTnZa@(Qt1bLPmM z2F#V86B{7GBMLSe@Tk1cfO+zHLrs#e7;1=o-B2^+zYWzb-!fnkt~bp9y^J^0P%q?M z1D43+DN9{osggE7M~I)XS;m7b#Y4-WLp5DZefTG`>pyOnk0* zwfwCCPs$g>MUAhKe;0o!UMs5%0dd^)paDT^ODSf@li5%7$xdIdDgO$M~c9R{?@ zn+<4_-!-6J{?UMEf zj4B$_q*%=!bJKus+_8lQJTFf&V3S;7K#%;X0eblie~N?_N+_5jDirt1^F*EEE%KWN zY?a?OV4FN7hBZf9l<~0veey{IUX;%nuwDMafS2T-4cH+kZs>AD3+=?stTJGitgZ-n zS^mU;-STk*QopN10`}r&=|~EFdUB%yugL18fLCQzE#NizprP7zu(A#tFd&~b;0;{A z4vYYOH-2q{0Cgmw?GW%5Zcr^1pzZ{}FyI~BP{;tCjgTr8_HrT37qA~U+o3*nf%kC3 zYN>$tadX-Y_(0a13mC+WsC@!H#Ld_C2snUSpwllvRTa)OU?{mfeBAg>t&T? zon^;k{@AowZ|qELWL)dGi{_s%%y6=3=|U&jzU;E6 Oe}4Vpq;JI*ufzZUTrPkB diff --git a/apps/mobile/scripts/optimize-fonts.mjs b/apps/mobile/scripts/optimize-fonts.mjs index 6befe67bf..e7a048d5b 100644 --- a/apps/mobile/scripts/optimize-fonts.mjs +++ b/apps/mobile/scripts/optimize-fonts.mjs @@ -72,7 +72,9 @@ const EXTRA_ICON_NAMES = [ "qrcode", "text", "cloud", - "restore" + "restore", + "keyboard", + "numeric" ]; const __filename = fileURLToPath(import.meta.url);