diff --git a/apps/mobile/app/components/dialog-provider/index.js b/apps/mobile/app/components/dialog-provider/index.js
index a3dee1020..6ccb27594 100644
--- a/apps/mobile/app/components/dialog-provider/index.js
+++ b/apps/mobile/app/components/dialog-provider/index.js
@@ -43,6 +43,7 @@ const DialogProvider = () => {
return (
<>
+
@@ -61,7 +62,6 @@ const DialogProvider = () => {
-
>
);
};
diff --git a/apps/mobile/app/components/dialogs/applock-password/index.tsx b/apps/mobile/app/components/dialogs/applock-password/index.tsx
index 3237e9e37..9c22d5c90 100644
--- a/apps/mobile/app/components/dialogs/applock-password/index.tsx
+++ b/apps/mobile/app/components/dialogs/applock-password/index.tsx
@@ -91,7 +91,7 @@ export const AppLockPassword = () => {
setVisible(false);
};
- return (
+ return !visible ? null : (
{
await sleep(100);
diff --git a/apps/mobile/app/screens/settings/functions.js b/apps/mobile/app/screens/settings/functions.js
index e42c3cc90..36c59db0a 100644
--- a/apps/mobile/app/screens/settings/functions.js
+++ b/apps/mobile/app/screens/settings/functions.js
@@ -17,9 +17,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-import { presentDialog } from "../../components/dialog/functions";
-import { ToastManager } from "../../services/event-manager";
import { db } from "../../common/database";
+import { validateAppLockPassword } from "../../common/database/encryption";
+import { presentDialog } from "../../components/dialog/functions";
+import BiometicService from "../../services/biometrics";
+import { ToastManager } from "../../services/event-manager";
+import SettingsService from "../../services/settings";
+import { useUserStore } from "../../stores/use-user-store";
import { sleep } from "../../utils/time";
export async function verifyUser(
@@ -69,3 +73,54 @@ export async function verifyUser(
}
});
}
+
+export async function verifyUserWithApplock() {
+ const keyboardType = SettingsService.getProperty("applockKeyboardType");
+ return new Promise((resolve) => {
+ if (SettingsService.getProperty("appLockHasPasswordSecurity")) {
+ presentDialog({
+ title: "Verify it's you",
+ input: true,
+ inputPlaceholder: `Enter app lock ${
+ keyboardType === "numeric" ? "pin" : "password"
+ }`,
+ paragraph: `Please enter your app lock ${
+ keyboardType === "numeric" ? "pin" : "password"
+ }`,
+ positiveText: "Disable",
+ secureTextEntry: true,
+ negativeText: "Cancel",
+ positivePress: async (value) => {
+ try {
+ const verified = await validateAppLockPassword(value);
+ resolve(verified);
+ } catch (e) {
+ resolve(false);
+ }
+ }
+ });
+ } else {
+ BiometicService.isBiometryAvailable().then((available) => {
+ if (available) {
+ BiometicService.validateUser("Verify it's you").then((verified) => {
+ resolve(verified);
+ });
+ } else if (useUserStore.getState().user) {
+ let verified = false;
+ verifyUser(
+ null,
+ () => {
+ resolve(true);
+ },
+ false,
+ () => {
+ resolve(verified);
+ }
+ );
+ } else {
+ resolve(true);
+ }
+ });
+ }
+ });
+}
diff --git a/apps/mobile/app/screens/settings/picker/index.tsx b/apps/mobile/app/screens/settings/picker/index.tsx
index 4f83b387c..ac18da566 100644
--- a/apps/mobile/app/screens/settings/picker/index.tsx
+++ b/apps/mobile/app/screens/settings/picker/index.tsx
@@ -40,6 +40,7 @@ interface PickerOptions {
premium?: boolean;
onCheckOptionIsPremium?: (item: T) => boolean;
requiresVerification?: () => boolean;
+ onVerify?: () => Promise;
}
export function SettingsPicker({
@@ -51,7 +52,8 @@ export function SettingsPicker({
getItemKey,
premium,
onCheckOptionIsPremium = () => true,
- requiresVerification = () => false
+ requiresVerification = () => false,
+ onVerify
}: PickerOptions) {
const { colors } = useThemeColors("contextMenu");
const menuRef = useRef();
@@ -105,6 +107,7 @@ export function SettingsPicker({
anchor={
{
+ if (onVerify && !(await onVerify())) return;
menuRef.current?.show();
}}
type="grayBg"
diff --git a/apps/mobile/app/screens/settings/picker/pickers.jsx b/apps/mobile/app/screens/settings/picker/pickers.jsx
index 2e117dc0b..17b689580 100644
--- a/apps/mobile/app/screens/settings/picker/pickers.jsx
+++ b/apps/mobile/app/screens/settings/picker/pickers.jsx
@@ -27,6 +27,7 @@ import { getFontById, getFonts } from "@notesnook/editor/dist/utils/font";
import { DATE_FORMATS, TIME_FORMATS } from "@notesnook/core/dist/common";
import dayjs from "dayjs";
import { useUserStore } from "../../../stores/use-user-store";
+import { verifyUserWithApplock } from "../functions";
export const FontPicker = createSettingsPicker({
getValue: () => useSettingStore.getState().settings.defaultFontFamily,
@@ -156,5 +157,7 @@ export const ApplockTimerPicker = createSettingsPicker({
getItemKey: (item) => item.toString(),
options: [-1, 0, 1, 5, 15, 30],
compareValue: (current, item) => current === item,
- premium: true
+ onVerify: () => {
+ return verifyUserWithApplock();
+ }
});
diff --git a/apps/mobile/app/screens/settings/section-item.tsx b/apps/mobile/app/screens/settings/section-item.tsx
index d8c900ae8..297ef2ada 100644
--- a/apps/mobile/app/screens/settings/section-item.tsx
+++ b/apps/mobile/app/screens/settings/section-item.tsx
@@ -104,17 +104,26 @@ const _SectionItem = ({ item }: { item: SettingSection }) => {
borderRadius: 0,
...styles
}}
- onPress={() => {
+ onPress={async () => {
switch (item.type) {
case "screen":
- navigation.dispatch(StackActions.push("SettingsGroup", item));
- useNavigationStore.getState().update("Settings");
+ {
+ if (item.onVerify && !(await item.onVerify())) return;
+ navigation.dispatch(StackActions.push("SettingsGroup", item));
+ useNavigationStore.getState().update("Settings");
+ }
break;
case "switch":
- onChangeSettings();
+ {
+ if (item.onVerify && !(await item.onVerify())) return;
+ onChangeSettings();
+ }
break;
default:
- item.modifer && item.modifer(current);
+ {
+ if (item.onVerify && !(await item.onVerify())) return;
+ item.modifer && item.modifer(current);
+ }
break;
}
}}
diff --git a/apps/mobile/app/screens/settings/settings-data.tsx b/apps/mobile/app/screens/settings/settings-data.tsx
index c518da972..116599a30 100644
--- a/apps/mobile/app/screens/settings/settings-data.tsx
+++ b/apps/mobile/app/screens/settings/settings-data.tsx
@@ -25,7 +25,6 @@ import { getVersion } from "react-native-device-info";
import * as RNIap from "react-native-iap";
import { enabled } from "react-native-privacy-snapshot";
import { db } from "../../common/database";
-import { validateAppLockPassword } from "../../common/database/encryption";
import { MMKV } from "../../common/database/mmkv";
import { AttachmentDialog } from "../../components/attachments";
import { ChangePassword } from "../../components/auth/change-password";
@@ -53,6 +52,7 @@ import PremiumService from "../../services/premium";
import SettingsService from "../../services/settings";
import Sync from "../../services/sync";
import { clearAllStores } from "../../stores";
+import { refreshAllStores } from "../../stores/create-db-collection-store";
import { useThemeStore } from "../../stores/use-theme-store";
import { useUserStore } from "../../stores/use-user-store";
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
@@ -67,10 +67,9 @@ import { NotesnookModule } from "../../utils/notesnook-module";
import { sleep } from "../../utils/time";
import { MFARecoveryCodes, MFASheet } from "./2fa";
import { useDragState } from "./editor/state";
-import { verifyUser } from "./functions";
+import { verifyUser, verifyUserWithApplock } from "./functions";
import { SettingSection } from "./types";
import { getTimeLeft } from "./user-section";
-import { refreshAllStores } from "../../stores/create-db-collection-store";
type User = any;
export const settingsGroups: SettingSection[] = [
@@ -790,94 +789,33 @@ export const settingsGroups: SettingSection[] = [
icon: "lock",
type: "switch",
property: "appLockEnabled",
- onChange: async () => {
+ onVerify: async () => {
+ const verified = await verifyUserWithApplock();
+ if (!verified) return false;
+
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 ${
- 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 {
- const verified = await validateAppLockPassword(value);
- if (!verified) {
- SettingsService.setProperty("appLockEnabled", true);
- return false;
- } else {
- SettingsService.setProperty("appLockEnabled", false);
- }
- } catch (e) {
- SettingsService.setProperty("appLockEnabled", true);
- return false;
- }
- }
- });
- } else {
- if (await BiometicService.isBiometryAvailable()) {
- const verified = await BiometicService.validateUser(
- "Verify it's you"
- );
- if (!verified) {
- SettingsService.setProperty("appLockEnabled", true);
- return;
- } else {
- SettingsService.setProperty("appLockEnabled", false);
- }
- } else if (useUserStore.getState().user) {
- let verified = false;
- verifyUser(
- null,
- () => {
- SettingsService.setProperty("appLockEnabled", false);
- verified = true;
- },
- false,
- () => {
- if (!verified)
- SettingsService.setProperty("appLockEnabled", true);
- }
- );
- }
- }
- return;
- }
-
- if (
- !(await BiometicService.isBiometryAvailable()) &&
- !SettingsService.getProperty("appLockHasPasswordSecurity")
- ) {
- ToastManager.show({
- heading: "Biometrics not enrolled",
- type: "error",
- message:
- "To use app lock, you must enable biometrics such as Fingerprint lock or Face ID on your phone."
- });
- SettingsService.setProperty("appLockEnabled", false);
- return;
- }
-
- if (!SettingsService.getProperty("appLockHasPasswordSecurity")) {
- const verified = await BiometicService.validateUser(
- "Verify it's you"
- );
- if (verified) {
+ if (
+ !SettingsService.getProperty("appLockHasPasswordSecurity") &&
+ (await BiometicService.isBiometryAvailable())
+ ) {
SettingsService.setProperty("biometricsAuthEnabled", true);
- } else {
- SettingsService.setProperty("appLockEnabled", false);
- return;
+ }
+
+ if (
+ !(await BiometicService.isBiometryAvailable()) &&
+ !SettingsService.getProperty("appLockHasPasswordSecurity")
+ ) {
+ ToastManager.show({
+ heading: "Biometrics not enrolled",
+ type: "error",
+ message:
+ "To use app lock, you must enable biometrics such as Fingerprint lock or Face ID on your phone."
+ });
+ return false;
}
}
+
+ return verified;
}
},
{
@@ -907,8 +845,12 @@ export const settingsGroups: SettingSection[] = [
"appLockHasPasswordSecurity"
);
},
+ onVerify: () => {
+ return verifyUserWithApplock();
+ },
property: "appLockHasPasswordSecurity",
modifer: () => {
+ console.log("called modifier..");
AppLockPassword.present("create");
}
},
@@ -962,32 +904,23 @@ export const settingsGroups: SettingSection[] = [
description: "Allow biometric authentication to unlock the app",
type: "switch",
property: "biometricsAuthEnabled",
- onChange: async () => {
- if (await BiometicService.isBiometryAvailable()) {
- const verified = await BiometicService.validateUser(
- "Verify it's you"
- );
- if (!verified) {
- SettingsService.setProperty("biometricsAuthEnabled", false);
+ onVerify: async () => {
+ const verified = await verifyUserWithApplock();
+ if (!verified) return false;
+
+ if (SettingsService.getProperty("biometricsAuthEnabled")) {
+ if (
+ !SettingsService.getProperty("appLockHasPasswordSecurity")
+ ) {
+ SettingsService.setProperty("appLockEnabled", false);
+ ToastManager.show({
+ heading: "App lock disabled",
+ type: "success"
+ });
}
- } else {
- ToastManager.error(
- new Error(
- "Biometric authentication is unavailable on this device."
- )
- );
- SettingsService.setProperty("biometricsAuthEnabled", false);
- }
- if (
- !SettingsService.getProperty("biometricsAuthEnabled") &&
- !SettingsService.getProperty("appLockHasPasswordSecurity")
- ) {
- SettingsService.setProperty("appLockEnabled", false);
- ToastManager.show({
- heading: "App lock disabled",
- type: "success"
- });
}
+
+ return verified;
},
icon: "fingerprint"
}
diff --git a/apps/mobile/app/screens/settings/types.ts b/apps/mobile/app/screens/settings/types.ts
index 43718942a..4876e219c 100644
--- a/apps/mobile/app/screens/settings/types.ts
+++ b/apps/mobile/app/screens/settings/types.ts
@@ -45,6 +45,7 @@ export type SettingSection = {
options?: any[];
minInputValue?: number;
maxInputValue?: number;
+ onVerify?: () => Promise;
};
export type SettingsGroup = {
diff --git a/apps/mobile/app/services/backup.js b/apps/mobile/app/services/backup.js
index 8e60716bf..77f5cdac9 100644
--- a/apps/mobile/app/services/backup.js
+++ b/apps/mobile/app/services/backup.js
@@ -154,7 +154,7 @@ async function updateNextBackupTime() {
* @param {string} context
* @returns {Promise<{path?: string, error?: Error}}>
*/
-async function run(progress, context) {
+async function run(progress, context = "global") {
let androidBackupDirectory = await checkBackupDirExists(false, context);
if (!androidBackupDirectory)
return {