mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-23 19:49:56 +01:00
mobile: applock with pin and password
This commit is contained in:
committed by
Abdullah Atta
parent
bad138d2fa
commit
9722fab8f3
@@ -47,6 +47,9 @@ const AppLockedOverlay = () => {
|
||||
const password = useRef<string>();
|
||||
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)}
|
||||
|
||||
@@ -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<TextInput>(null);
|
||||
const passwordInputRef = useRef<TextInput>(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 = () => {
|
||||
<BaseDialog
|
||||
onShow={async () => {
|
||||
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 = () => {
|
||||
<DialogHeader
|
||||
title={
|
||||
mode === "change"
|
||||
? "Change app lock pin"
|
||||
? `Change app lock ${keyboardType}`
|
||||
: mode === "remove"
|
||||
? "Remove app lock pin"
|
||||
: "Set up app lock pin"
|
||||
? `Remove app lock ${keyboardType}`
|
||||
: `Set up app lock ${keyboardType}`
|
||||
}
|
||||
paragraph={
|
||||
mode === "change"
|
||||
? "Change app lock pin"
|
||||
? `Change app lock ${keyboardType}`
|
||||
: mode === "remove"
|
||||
? "Remove app lock pin"
|
||||
: "Set up a custom app lock pin to unlock the app"
|
||||
? `Remove app lock ${keyboardType}`
|
||||
: `Set up a custom app lock ${keyboardType} to unlock the app`
|
||||
}
|
||||
icon="shield"
|
||||
padding={12}
|
||||
@@ -135,12 +148,13 @@ 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={
|
||||
<IconButton
|
||||
name={keyboardType === "password" ? "numeric" : "keyboard"}
|
||||
onPress={() => {
|
||||
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}
|
||||
</View>
|
||||
@@ -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"
|
||||
|
||||
@@ -18,18 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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() {
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
paddingTop: 12
|
||||
paddingTop: 12,
|
||||
height: "100%",
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
}}
|
||||
>
|
||||
{!loading ? (
|
||||
{!loading && !error ? (
|
||||
<DialogHeader
|
||||
title="Save a backup of your notes"
|
||||
centered
|
||||
@@ -140,33 +143,39 @@ export default function Migrate() {
|
||||
<>
|
||||
<View
|
||||
style={{
|
||||
width: 200,
|
||||
height: 100,
|
||||
alignSelf: "center",
|
||||
justifyContent: "center"
|
||||
}}
|
||||
>
|
||||
<ProgressBarComponent
|
||||
height={5}
|
||||
width={200}
|
||||
animated={true}
|
||||
useNativeDriver
|
||||
indeterminate
|
||||
unfilledColor={colors.secondary.background}
|
||||
color={colors.primary.accent}
|
||||
borderWidth={0}
|
||||
/>
|
||||
|
||||
<Paragraph
|
||||
style={{
|
||||
marginTop: 5,
|
||||
marginBottom: 10,
|
||||
textAlign: "center"
|
||||
}}
|
||||
>
|
||||
Updating {progress ? progress?.collection : null}
|
||||
Migrating database{progress ? `(${progress?.collection})` : null}
|
||||
{progress ? `(${progress.current}/${progress.total}) ` : null}...
|
||||
please wait
|
||||
</Paragraph>
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: 200
|
||||
}}
|
||||
>
|
||||
<ProgressBarComponent
|
||||
height={5}
|
||||
width={200}
|
||||
animated={true}
|
||||
useNativeDriver
|
||||
indeterminate
|
||||
unfilledColor={colors.secondary.background}
|
||||
color={colors.primary.accent}
|
||||
borderWidth={0}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
) : error ? (
|
||||
@@ -198,6 +207,7 @@ export default function Migrate() {
|
||||
width={250}
|
||||
onPress={async () => {
|
||||
MMKV.clearStore();
|
||||
await db.reset();
|
||||
setReset(true);
|
||||
}}
|
||||
style={{
|
||||
|
||||
@@ -120,7 +120,8 @@ const SheetWrapper = ({
|
||||
width: 100,
|
||||
backgroundColor: colors.secondary.background
|
||||
}}
|
||||
drawUnderStatusBar={false}
|
||||
statusBarTranslucent
|
||||
drawUnderStatusBar={true}
|
||||
containerStyle={style}
|
||||
gestureEnabled={gestureEnabled}
|
||||
initialOffsetFromBottom={1}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
Binary file not shown.
@@ -72,7 +72,9 @@ const EXTRA_ICON_NAMES = [
|
||||
"qrcode",
|
||||
"text",
|
||||
"cloud",
|
||||
"restore"
|
||||
"restore",
|
||||
"keyboard",
|
||||
"numeric"
|
||||
];
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
|
||||
Reference in New Issue
Block a user