mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
mobile: migrate app lock
This commit is contained in:
@@ -53,10 +53,11 @@ import { themeTrpcClient } from "./screens/settings/theme-selector";
|
||||
const App = () => {
|
||||
const init = useAppEvents();
|
||||
useEffect(() => {
|
||||
const { appLockMode } = SettingsService.get();
|
||||
if (appLockMode && appLockMode !== "none") {
|
||||
const { appLockEnabled, appLockMode } = SettingsService.get();
|
||||
if (appLockEnabled || appLockMode !== "none") {
|
||||
useUserStore.getState().lockApp(true);
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
globalThis["IS_MAIN_APP_RUNNING"] = true;
|
||||
init();
|
||||
|
||||
@@ -87,7 +87,8 @@ const BaseDialog = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (useUserStore.getState().disableAppLockRequests) return;
|
||||
if (SettingsService.get().appLockMode === "background") {
|
||||
|
||||
if (SettingsService.canLockAppInBackground()) {
|
||||
if (appState === "background") {
|
||||
setIntervalVisible(false);
|
||||
if (useUserStore.getState().appLocked) {
|
||||
|
||||
@@ -42,6 +42,7 @@ type DialogInfo = {
|
||||
inputPlaceholder: string;
|
||||
defaultValue: string;
|
||||
context: "global" | "local";
|
||||
secureTextEntry?: boolean;
|
||||
};
|
||||
|
||||
export function presentDialog(data: Partial<DialogInfo>): void {
|
||||
|
||||
@@ -36,6 +36,10 @@ import { SIZE } from "../../utils/size";
|
||||
import { Button } from "../ui/button";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import Navigation from "../../services/navigation";
|
||||
import { eOpenLoginDialog } from "../../utils/events";
|
||||
import { AuthMode } from "../auth";
|
||||
import { eSendEvent } from "../../services/event-manager";
|
||||
|
||||
const Intro = ({ navigation }) => {
|
||||
const { colors } = useThemeColors();
|
||||
@@ -193,9 +197,15 @@ const Intro = ({ navigation }) => {
|
||||
<Button
|
||||
width={250}
|
||||
onPress={async () => {
|
||||
navigation.navigate("AppLock", {
|
||||
welcome: true
|
||||
});
|
||||
eSendEvent(eOpenLoginDialog, AuthMode.welcomeSignup);
|
||||
setTimeout(() => {
|
||||
SettingsService.set({
|
||||
introCompleted: true
|
||||
});
|
||||
Navigation.replace("Notes", {
|
||||
canGoBack: false
|
||||
});
|
||||
}, 1000);
|
||||
}}
|
||||
style={{
|
||||
paddingHorizontal: 24,
|
||||
|
||||
@@ -91,7 +91,7 @@ const SheetWrapper = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (useUserStore.getState().disableAppLockRequests) return;
|
||||
if (SettingsService.get().appLockMode === "background") {
|
||||
if (SettingsService.canLockAppInBackground()) {
|
||||
if (appState === "background") {
|
||||
const ref = fwdRef || localRef;
|
||||
ref?.current?.hide();
|
||||
|
||||
@@ -480,15 +480,20 @@ export const useAppEvents = () => {
|
||||
|
||||
const onAppStateChanged = async (state: AppStateStatus) => {
|
||||
if (state === "active") {
|
||||
if (SettingsService.shouldLockAppOnEnterForeground()) {
|
||||
console.log("Locked app on enter foreground");
|
||||
useUserStore.getState().lockApp(true);
|
||||
}
|
||||
|
||||
notifee.setBadgeCount(0);
|
||||
updateStatusBarColor();
|
||||
if (
|
||||
SettingsService.get().appLockMode !== "background" &&
|
||||
!SettingsService.canLockAppInBackground() &&
|
||||
!SettingsService.get().privacyScreen
|
||||
) {
|
||||
enabled(false);
|
||||
}
|
||||
if (SettingsService.get().appLockMode === "background") {
|
||||
if (SettingsService.canLockAppInBackground()) {
|
||||
if (useSettingStore.getState().requestBiometrics) {
|
||||
useSettingStore.getState().setRequestBiometrics(false);
|
||||
return;
|
||||
@@ -510,22 +515,23 @@ export const useAppEvents = () => {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SettingsService.appEnteredBackground();
|
||||
const id = useEditorStore.getState().currentEditingNote;
|
||||
const note = id ? await db.notes.note(id) : undefined;
|
||||
if (
|
||||
note?.locked &&
|
||||
SettingsService.get().appLockMode === "background"
|
||||
) {
|
||||
if (note?.locked && SettingsService.canLockAppInBackground()) {
|
||||
eSendEvent(eClearEditor);
|
||||
}
|
||||
await saveEditorState();
|
||||
if (
|
||||
SettingsService.get().appLockMode === "background" &&
|
||||
SettingsService.canLockAppInBackground() &&
|
||||
!useSettingStore.getState().requestBiometrics &&
|
||||
!useUserStore.getState().appLocked &&
|
||||
!useUserStore.getState().disableAppLockRequests
|
||||
) {
|
||||
useUserStore.getState().lockApp(true);
|
||||
if (SettingsService.getProperty("appLockTimer") === 0) {
|
||||
useUserStore.getState().lockApp(true);
|
||||
}
|
||||
|
||||
if (Platform.OS === "ios") {
|
||||
editorController.current?.commands.blur();
|
||||
Keyboard.dismiss();
|
||||
@@ -533,7 +539,7 @@ export const useAppEvents = () => {
|
||||
}
|
||||
if (
|
||||
SettingsService.get().privacyScreen ||
|
||||
SettingsService.get().appLockMode === "background"
|
||||
SettingsService.canLockAppInBackground()
|
||||
) {
|
||||
!useSettingStore.getState().requestBiometrics ? enabled(true) : null;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ const IntroStackNavigator = () => {
|
||||
initialRouteName={"Intro"}
|
||||
>
|
||||
<NativeStack.Screen name="Intro" component={Intro} />
|
||||
<NativeStack.Screen name="AppLock" component={AppLock} />
|
||||
</IntroStack.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -17,36 +17,24 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React from "react";
|
||||
import { Platform, ScrollView, View } from "react-native";
|
||||
import Animated, { FadeInDown, FadeOutUp } from "react-native-reanimated";
|
||||
import Animated from "react-native-reanimated";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { AuthMode } from "../../components/auth";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { PressableButton } from "../../components/ui/pressable";
|
||||
import Seperator from "../../components/ui/seperator";
|
||||
import Heading from "../../components/ui/typography/heading";
|
||||
import Paragraph from "../../components/ui/typography/paragraph";
|
||||
import BiometicService from "../../services/biometrics";
|
||||
import { DDS } from "../../services/device-detection";
|
||||
import {
|
||||
ToastManager,
|
||||
eSendEvent,
|
||||
presentSheet
|
||||
} from "../../services/event-manager";
|
||||
import Navigation from "../../services/navigation";
|
||||
import { ToastManager, presentSheet } from "../../services/event-manager";
|
||||
import SettingsService from "../../services/settings";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { useUserStore } from "../../stores/use-user-store";
|
||||
import { getElevationStyle } from "../../utils/elevation";
|
||||
import { eOpenLoginDialog } from "../../utils/events";
|
||||
import { SIZE } from "../../utils/size";
|
||||
const AppLock = ({ route }) => {
|
||||
const AppLock = () => {
|
||||
const { colors } = useThemeColors();
|
||||
const appLockMode = useSettingStore((state) => state.settings.appLockMode);
|
||||
const welcome = route?.params?.welcome;
|
||||
const deviceMode = useSettingStore((state) => state.deviceMode);
|
||||
|
||||
const modes = [
|
||||
{
|
||||
@@ -76,128 +64,51 @@ const AppLock = ({ route }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Animated.View
|
||||
exiting={!welcome ? undefined : FadeOutUp}
|
||||
entering={!welcome ? undefined : FadeInDown}
|
||||
style={{
|
||||
height: !welcome ? undefined : "100%",
|
||||
width: !welcome ? undefined : "100%"
|
||||
}}
|
||||
>
|
||||
<Animated.View>
|
||||
<>
|
||||
{!welcome ? (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-end",
|
||||
justifyContent: "space-between",
|
||||
width: "95%",
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 0,
|
||||
alignSelf: "center",
|
||||
minHeight: 125,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.secondary.background
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
name="shield-lock"
|
||||
color={colors.secondary.icon}
|
||||
size={100}
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
top: 6,
|
||||
opacity: 0.2
|
||||
}}
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-end",
|
||||
justifyContent: "space-between",
|
||||
width: DDS.isTab && welcome ? "50%" : "95%",
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 0,
|
||||
alignSelf: "center",
|
||||
minHeight: 125,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: welcome
|
||||
? "transparent"
|
||||
: colors.secondary.background
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
name="shield-lock"
|
||||
color={colors.secondary.icon}
|
||||
size={100}
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
top: 6,
|
||||
opacity: 0.2
|
||||
}}
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{
|
||||
alignItems: !welcome ? undefined : "center",
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Heading>Protect your notes</Heading>
|
||||
<Paragraph
|
||||
style={{
|
||||
textAlign: !welcome ? undefined : "center"
|
||||
}}
|
||||
size={SIZE.md}
|
||||
>
|
||||
Choose how you want to secure your notes locally.
|
||||
</Paragraph>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
justifyContent: "flex-end",
|
||||
paddingHorizontal: 20,
|
||||
backgroundColor: colors.secondary.background,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.primary.border,
|
||||
alignSelf: deviceMode !== "mobile" ? "center" : undefined,
|
||||
borderWidth: deviceMode !== "mobile" ? 1 : null,
|
||||
borderColor:
|
||||
deviceMode !== "mobile" ? colors.primary.border : null,
|
||||
borderRadius: deviceMode !== "mobile" ? 20 : null,
|
||||
marginTop: deviceMode !== "mobile" ? 50 : null,
|
||||
width: deviceMode === "mobile" ? null : "50%",
|
||||
minHeight: 180
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row"
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
width: 100,
|
||||
height: 5,
|
||||
backgroundColor: colors.primary.accent,
|
||||
borderRadius: 2,
|
||||
marginRight: 7
|
||||
}}
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: 20,
|
||||
height: 5,
|
||||
backgroundColor: colors.secondary.background,
|
||||
borderRadius: 2
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<Heading
|
||||
style={{
|
||||
marginTop: 10
|
||||
}}
|
||||
extraBold
|
||||
size={SIZE.xxl}
|
||||
>
|
||||
Protect your notes
|
||||
</Heading>
|
||||
<Paragraph
|
||||
style={{
|
||||
marginBottom: 25
|
||||
}}
|
||||
>
|
||||
<Heading>Protect your notes</Heading>
|
||||
<Paragraph size={SIZE.md}>
|
||||
Choose how you want to secure your notes locally.
|
||||
</Paragraph>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Seperator />
|
||||
<ScrollView
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
width: DDS.isTab && welcome ? "50%" : "100%",
|
||||
width: "100%",
|
||||
alignSelf: "center",
|
||||
flexGrow: 1
|
||||
}}
|
||||
@@ -284,34 +195,6 @@ const AppLock = ({ route }) => {
|
||||
</Paragraph>
|
||||
</PressableButton>
|
||||
))}
|
||||
|
||||
{welcome && (
|
||||
<Button
|
||||
fontSize={SIZE.md}
|
||||
width={250}
|
||||
onPress={async () => {
|
||||
eSendEvent(eOpenLoginDialog, AuthMode.welcomeSignup);
|
||||
setTimeout(() => {
|
||||
SettingsService.set({
|
||||
introCompleted: true
|
||||
});
|
||||
Navigation.replace("Notes", {
|
||||
canGoBack: false
|
||||
});
|
||||
}, 1000);
|
||||
}}
|
||||
style={{
|
||||
paddingHorizontal: 24,
|
||||
alignSelf: "center",
|
||||
...getElevationStyle(5),
|
||||
marginTop: 30,
|
||||
borderRadius: 100,
|
||||
marginBottom: 30
|
||||
}}
|
||||
type="accent"
|
||||
title="Next"
|
||||
/>
|
||||
)}
|
||||
</ScrollView>
|
||||
</>
|
||||
</Animated.View>
|
||||
@@ -319,10 +202,9 @@ const AppLock = ({ route }) => {
|
||||
);
|
||||
};
|
||||
|
||||
AppLock.present = async (isWelcome) => {
|
||||
AppLock.present = async () => {
|
||||
presentSheet({
|
||||
component: <AppLock welcome={isWelcome} s={0} />,
|
||||
disableClosing: isWelcome
|
||||
component: <AppLock />
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ import {
|
||||
FontPicker,
|
||||
TimeFormatPicker,
|
||||
TrashIntervalPicker,
|
||||
BackupReminderPicker
|
||||
BackupReminderPicker,
|
||||
ApplockTimerPicker
|
||||
} from "./picker/pickers";
|
||||
import ThemeSelector from "./theme-selector";
|
||||
|
||||
@@ -49,5 +50,6 @@ export const components: { [name: string]: ReactElement } = {
|
||||
"title-format": <TitleFormat />,
|
||||
"date-format-selector": <DateFormatPicker />,
|
||||
"time-format-selector": <TimeFormatPicker />,
|
||||
"theme-selector": <ThemeSelector />
|
||||
"theme-selector": <ThemeSelector />,
|
||||
"applock-timer": <ApplockTimerPicker />
|
||||
};
|
||||
|
||||
@@ -138,3 +138,23 @@ export const BackupReminderPicker = createSettingsPicker({
|
||||
return item !== "useroff";
|
||||
}
|
||||
});
|
||||
|
||||
export const ApplockTimerPicker = createSettingsPicker({
|
||||
getValue: () => useSettingStore.getState().settings.appLockTimer,
|
||||
updateValue: (item) => {
|
||||
SettingsService.set({ appLockTimer: item });
|
||||
},
|
||||
formatValue: (item) => {
|
||||
return item === -1
|
||||
? "Never"
|
||||
: item === 0 || item === undefined
|
||||
? "Immediately"
|
||||
: item === 1
|
||||
? "1 minute"
|
||||
: item + " minutes";
|
||||
},
|
||||
getItemKey: (item) => item.toString(),
|
||||
options: [-1, 0, 1, 5, 15, 30],
|
||||
compareValue: (current, item) => current === item,
|
||||
premium: true
|
||||
});
|
||||
|
||||
@@ -69,6 +69,7 @@ import { verifyUser } from "./functions";
|
||||
import { SettingSection } from "./types";
|
||||
import { getTimeLeft } from "./user-section";
|
||||
import { AppLockPassword } from "../../components/dialogs/applock-password";
|
||||
import { validateAppLockPassword } from "../../common/database/encryption";
|
||||
type User = any;
|
||||
|
||||
export const settingsGroups: SettingSection[] = [
|
||||
@@ -767,14 +768,105 @@ export const settingsGroups: SettingSection[] = [
|
||||
sections: [
|
||||
{
|
||||
id: "app-lock-mode",
|
||||
name: "App lock mode",
|
||||
name: "Enable app lock",
|
||||
description:
|
||||
"Select the mode for the desired level of app lock security.",
|
||||
icon: "fingerprint",
|
||||
modifer: () => {
|
||||
AppLock.present();
|
||||
icon: "lock",
|
||||
type: "switch",
|
||||
property: "appLockEnabled",
|
||||
onChange: async () => {
|
||||
if (!SettingsService.getProperty("appLockEnabled")) {
|
||||
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",
|
||||
positiveText: "Disable",
|
||||
secureTextEntry: true,
|
||||
negativeText: "Cancel",
|
||||
positivePress: async (value) => {
|
||||
try {
|
||||
let 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()) &&
|
||||
!useUserStore.getState().user &&
|
||||
!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 or create an account."
|
||||
});
|
||||
SettingsService.setProperty("appLockEnabled", false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SettingsService.getProperty("appLockHasPasswordSecurity")) {
|
||||
const verified = await BiometicService.validateUser(
|
||||
"Verify it's you"
|
||||
);
|
||||
if (verified) {
|
||||
SettingsService.setProperty("biometricsAuthEnabled", true);
|
||||
} else {
|
||||
SettingsService.setProperty("appLockEnabled", false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "app-lock-timer",
|
||||
name: "App lock timeout",
|
||||
description:
|
||||
"Set the time after which the app should lock in background",
|
||||
type: "component",
|
||||
component: "applock-timer"
|
||||
},
|
||||
{
|
||||
id: "app-lock-pin",
|
||||
name: "Setup app lock pin",
|
||||
@@ -836,7 +928,8 @@ export const settingsGroups: SettingSection[] = [
|
||||
);
|
||||
SettingsService.setProperty("biometricsAuthEnabled", false);
|
||||
}
|
||||
}
|
||||
},
|
||||
icon: "fingerprint"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
} from "../stores/use-setting-store";
|
||||
import { NotesnookModule } from "../utils/notesnook-module";
|
||||
import { scale, updateSize } from "../utils/size";
|
||||
import { DatabaseLogger } from "../common/database";
|
||||
function reset() {
|
||||
const settings = get();
|
||||
if (settings.reminder !== "off" && settings.reminder !== "useroff") {
|
||||
@@ -44,6 +45,25 @@ function resetSettings() {
|
||||
init();
|
||||
}
|
||||
|
||||
function migrateAppLock() {
|
||||
const appLockMode = get().appLockMode;
|
||||
if (appLockMode === "none") return;
|
||||
if (appLockMode === "background") {
|
||||
set({
|
||||
appLockEnabled: true,
|
||||
appLockTimer: 0,
|
||||
appLockMode: "none"
|
||||
});
|
||||
} else if (appLockMode === "launch") {
|
||||
set({
|
||||
appLockEnabled: true,
|
||||
appLockTimer: -1,
|
||||
appLockMode: "none"
|
||||
});
|
||||
}
|
||||
DatabaseLogger.debug("App lock Migrated");
|
||||
}
|
||||
|
||||
function init() {
|
||||
scale.fontScale = 1;
|
||||
const settingsJson = MMKV.getString("appSettings");
|
||||
@@ -56,17 +76,17 @@ function init() {
|
||||
...JSON.parse(settingsJson)
|
||||
};
|
||||
}
|
||||
|
||||
if (settings.fontScale) {
|
||||
scale.fontScale = settings.fontScale;
|
||||
}
|
||||
setTimeout(() => setPrivacyScreen(settings), 1);
|
||||
updateSize();
|
||||
useSettingStore.getState().setSettings({ ...settings });
|
||||
migrateAppLock();
|
||||
}
|
||||
|
||||
function setPrivacyScreen(settings: SettingStore["settings"]) {
|
||||
if (settings.privacyScreen || settings.appLockMode === "background") {
|
||||
if (settings.privacyScreen || canLockAppInBackground()) {
|
||||
if (Platform.OS === "android") {
|
||||
NotesnookModule.setSecureMode(true);
|
||||
} else {
|
||||
@@ -153,6 +173,27 @@ function checkOrientation() {
|
||||
//});
|
||||
}
|
||||
|
||||
function canLockAppInBackground() {
|
||||
return get().appLockEnabled && get().appLockTimer !== -1;
|
||||
}
|
||||
let backgroundEnterTime = 0;
|
||||
function appEnteredBackground() {
|
||||
if (canLockAppInBackground()) {
|
||||
backgroundEnterTime = Date.now();
|
||||
}
|
||||
}
|
||||
|
||||
function shouldLockAppOnEnterForeground() {
|
||||
const settings = get();
|
||||
if (!settings.appLockEnabled) return false;
|
||||
if (settings.appLockTimer === -1) return false;
|
||||
if (settings.appLockTimer === 0) return true;
|
||||
const time = Date.now();
|
||||
const diff = time - backgroundEnterTime;
|
||||
|
||||
return diff > settings.appLockTimer * 60000;
|
||||
}
|
||||
|
||||
export const SettingsService = {
|
||||
init,
|
||||
set,
|
||||
@@ -163,7 +204,10 @@ export const SettingsService = {
|
||||
reset,
|
||||
getProperty,
|
||||
setProperty,
|
||||
resetSettings
|
||||
resetSettings,
|
||||
shouldLockAppOnEnterForeground,
|
||||
canLockAppInBackground,
|
||||
appEnteredBackground
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
@@ -39,7 +39,9 @@ export type Settings = {
|
||||
sortOrder?: string;
|
||||
screenshotMode?: boolean;
|
||||
privacyScreen?: boolean;
|
||||
appLockMode?: string;
|
||||
appLockTimer: number;
|
||||
appLockEnabled?: boolean;
|
||||
appLockMode?: "none" | "background" | "launch";
|
||||
telemetry?: boolean;
|
||||
notebooksListMode?: "normal" | "compact";
|
||||
notesListMode?: "normal" | "compact";
|
||||
@@ -118,6 +120,7 @@ export interface SettingStore extends State {
|
||||
const { width, height } = Dimensions.get("window");
|
||||
|
||||
export const defaultSettings: SettingStore["settings"] = {
|
||||
appLockTimer: 0,
|
||||
showToolbarOnTop: false,
|
||||
showKeyboardOnOpen: false,
|
||||
fontScale: 1,
|
||||
|
||||
835
apps/mobile/package-lock.json
generated
835
apps/mobile/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
1129
apps/web/package-lock.json
generated
1129
apps/web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
6
packages/core/package-lock.json
generated
6
packages/core/package-lock.json
generated
@@ -4055,7 +4055,8 @@
|
||||
"ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -6310,7 +6311,8 @@
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
|
||||
22
packages/editor-mobile/package-lock.json
generated
22
packages/editor-mobile/package-lock.json
generated
@@ -4358,7 +4358,7 @@
|
||||
"version": "15.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/q": {
|
||||
"version": "1.5.8",
|
||||
@@ -4382,7 +4382,7 @@
|
||||
"version": "18.2.39",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.39.tgz",
|
||||
"integrity": "sha512-Oiw+ppED6IremMInLV4HXGbfbG6GyziY3kqAwJYOR0PNbkYDmLWQA3a95EhdSmamsvbkJN96ZNN+YD+fGjzSBA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@@ -4417,7 +4417,7 @@
|
||||
"version": "0.16.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
|
||||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.6",
|
||||
@@ -9713,7 +9713,7 @@
|
||||
"version": "9.0.21",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
|
||||
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/immer"
|
||||
@@ -17758,6 +17758,20 @@
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||
|
||||
Reference in New Issue
Block a user