diff --git a/apps/mobile/app/screens/settings/components/2fa.tsx b/apps/mobile/app/screens/settings/components/2fa.tsx
index 3fee25cf3..958c56621 100644
--- a/apps/mobile/app/screens/settings/components/2fa.tsx
+++ b/apps/mobile/app/screens/settings/components/2fa.tsx
@@ -19,7 +19,7 @@ along with this program. If not, see .
import { sanitizeFilename, useIsFeatureAvailable } from "@notesnook/common";
import { strings } from "@notesnook/intl";
-import { useThemeColors, VariantsWithStaticColors } from "@notesnook/theme";
+import { useThemeColors } from "@notesnook/theme";
import Clipboard from "@react-native-clipboard/clipboard";
import isMobilePhone from "validator/lib/isMobilePhone";
import React, {
@@ -37,20 +37,20 @@ import {
View
} from "react-native";
import RNFetchBlob from "react-native-blob-util";
-import { FlatList } from "react-native-gesture-handler";
import * as ScopedStorage from "react-native-scoped-storage";
+import { Radius, Spacing } from "../../../common/design/spacing";
import { db } from "../../../common/database";
import filesystem from "../../../common/filesystem";
import DialogHeader from "../../../components/dialog/dialog-header";
+import AppIcon from "../../../components/ui/AppIcon";
import { Button } from "../../../components/ui/button";
-import { IconButton } from "../../../components/ui/icon-button";
import FormInput, {
createFormRef,
validators
} from "../../../components/ui/input/form-input";
+import PinInput from "../../../components/ui/pin-input";
import { Pressable } from "../../../components/ui/pressable";
import Seperator from "../../../components/ui/seperator";
-import { SvgView } from "../../../components/ui/svg";
import Heading from "../../../components/ui/typography/heading";
import Paragraph from "../../../components/ui/typography/paragraph";
import useTimer from "../../../hooks/use-timer";
@@ -63,27 +63,25 @@ import { useUserStore } from "../../../stores/use-user-store";
import { eCloseSheet } from "../../../utils/events";
import { AppFontSize } from "../../../utils/size";
import { sleep } from "../../../utils/time";
-import { DefaultAppStyles } from "../../../utils/styles";
import PaywallSheet from "../../../components/sheets/paywall";
const mfaMethods: MFAMethod[] = [
{
id: "app",
title: strings.mfaAuthAppTitle(),
body: strings.mfaAuthAppDesc(),
- icon: "cellphone-key",
- recommended: true
+ icon: "device-mobile-camera"
},
{
id: "sms",
title: strings.mfaSmsTitle(),
body: strings.mfaSmsDesc(),
- icon: "message-plus-outline"
+ icon: "chat"
},
{
id: "email",
title: strings.mfaEmailTitle(),
body: strings.mfaEmailDesc(),
- icon: "email-outline"
+ icon: "envelope-simple"
}
];
type MFAMethod = {
@@ -116,67 +114,78 @@ export const MFAMethodsPickerStep = ({ recovery, onSuccess }: MFAStepProps) => {
return mfaMethods.filter((m) => m.id !== user?.mfa?.primaryMethod);
};
+ const onMethodPress = (item: MFAMethod) => {
+ if (item.id === "sms" && featureAvailable && !featureAvailable?.isAllowed) {
+ ToastManager.show({
+ message: featureAvailable?.error,
+ type: "info",
+ context: "local",
+ actionText: strings.upgrade(),
+ func: () => {
+ PaywallSheet.present(featureAvailable);
+ }
+ });
+ return;
+ }
+
+ onSuccess && onSuccess(item);
+ };
+
return (
<>
- {getMethods().map((item) => (
+ {getMethods().map((item, index, methods) => (
{
- if (
- item.id === "sms" &&
- featureAvailable &&
- !featureAvailable?.isAllowed
- ) {
- ToastManager.show({
- message: featureAvailable?.error,
- type: "info",
- context: "local",
- actionText: strings.upgrade(),
- func: () => {
- PaywallSheet.present(featureAvailable);
- }
- });
- return;
- }
- onSuccess && onSuccess(item);
- }}
+ onPress={() => onMethodPress(item)}
style={{
- paddingHorizontal: DefaultAppStyles.GAP,
- paddingVertical: DefaultAppStyles.GAP_VERTICAL,
- marginTop: 0,
- marginBottom: DefaultAppStyles.GAP_VERTICAL,
+ paddingHorizontal: Spacing.LEVEL_3,
+ paddingVertical: Spacing.LEVEL_1,
+ marginBottom: index === methods.length - 1 ? 0 : Spacing.LEVEL_0,
flexDirection: "row",
- borderRadius: 0,
- alignItems: "flex-start"
+ borderRadius: Radius.S,
+ alignItems: "center",
+ backgroundColor: colors.primary.background
}}
>
{item.icon && (
-
+ >
+
+
)}
- {item.title}
+
+ {item.title}
+
{item.body}
@@ -211,6 +220,7 @@ export const MFASetup = ({
const [loading, setLoading] = useState(method?.id === "app" ? true : false);
const [enabling, setEnabling] = useState(false);
const [sending, setSending] = useState(false);
+ const [codeValue, setCodeValue] = useState("");
const [generalError, setGeneralError] = useState();
useEffect(() => {
@@ -245,6 +255,7 @@ export const MFASetup = ({
: formRef.current.getValue("target")
);
formRef.current.setValue("code", "");
+ setCodeValue("");
setGeneralError(undefined);
}, [authenticatorDetails.sharedKey, methodId, user?.email]);
@@ -280,11 +291,18 @@ export const MFASetup = ({
];
const onNext = async () => {
- if (formRef.current.validateField("code")) return;
+ const code = codeValue.trim();
+ const codeValidationError = codeValidators
+ .map((validator) => validator(code))
+ .find(Boolean);
+
+ if (codeValidationError) {
+ setGeneralError(codeValidationError);
+ return;
+ }
try {
if (!method) return;
- const code = formRef.current.getValue("code").trim();
setGeneralError(undefined);
setEnabling(true);
@@ -300,7 +318,7 @@ export const MFASetup = ({
setEnabling(false);
} catch (e) {
const error = e as Error;
- formRef.current.setError("code", error.message);
+ setGeneralError(error.message);
setEnabling(false);
}
};
@@ -363,18 +381,34 @@ export const MFASetup = ({
}
};
+ const onChangeMethodPress = () => {
+ setStep &&
+ setStep({
+ id: "mfapick",
+ props: {
+ recovery: recovery
+ }
+ });
+ };
+
return !method ? null : (
-
+
-
{loading ? (
@@ -423,16 +457,27 @@ export const MFASetup = ({
}
onSubmitEditing={onSendCode}
validators={targetValidators}
+ containerStyle={{
+ borderWidth: 0,
+ borderRadius: Radius.XS
+ }}
keyboardType={
method.id === "email" ? "email-address" : "phone-pad"
}
buttons={
-
- {strings.enterSixDigitCode()}
-
- {codeHelpText[method?.id]}
-
- {
+
+
+
+
+
+
+
+
+
+ {strings.enterSixDigitCode()}
+
+
+ {codeHelpText[method?.id]}
+
+
+
+
+ {
+ formRef.current.setValue("code", value);
+ setCodeValue(value);
setGeneralError(undefined);
}}
- onSubmitEditing={onNext}
- returnKeyLabel={strings.next()}
- returnKeyType="done"
- validators={codeValidators}
- inputStyle={{
- fontSize: AppFontSize.lg,
- height: 60,
- textAlign: "center",
- letterSpacing: 10,
- width: undefined
- }}
- containerStyle={{
- height: 60,
- borderWidth: 0,
- width: undefined
- }}
- errorStyle={{
- textAlign: "center"
- }}
+ sanitize={(value) => value.replace(/\D/g, "")}
/>
{generalError ? (
@@ -492,7 +562,7 @@ export const MFASetup = ({
size={AppFontSize.sm}
style={{
color: colors.error.icon,
- marginBottom: DefaultAppStyles.GAP_VERTICAL,
+ marginBottom: Spacing.LEVEL_2,
textAlign: "center",
width: "100%"
}}
@@ -501,33 +571,30 @@ export const MFASetup = ({
) : null}
-
-
+ >
+
-
>
)}
@@ -544,6 +611,11 @@ export const MFARecoveryCodes = ({
const [codes, setCodes] = useState([]);
const [loading, setLoading] = useState(true);
+ const codeRows = [] as string[][];
+ for (let i = 0; i < codes.length; i += 3) {
+ codeRows.push(codes.slice(i, i + 3));
+ }
+
useEffect(() => {
(async () => {
try {
@@ -558,140 +630,208 @@ export const MFARecoveryCodes = ({
})();
}, []);
+ const onCopyCodesPress = () => {
+ const codeString = codes.join("\n");
+ Clipboard.setString(codeString);
+ ToastManager.show({
+ heading: strings.codesCopied(),
+ type: "success",
+ context: "local"
+ });
+ };
+
+ const onSaveToFilePress = async () => {
+ try {
+ let path;
+ let fileName = "notesnook_recoverycodes";
+ fileName = sanitizeFilename(fileName, {
+ replacement: "_"
+ });
+ fileName = fileName + ".txt";
+ const codeString = codes.join("\n");
+ if (Platform.OS === "android") {
+ const file = await ScopedStorage.createDocument(
+ fileName,
+ "text/plain",
+ codeString,
+ "utf8"
+ );
+ if (!file) return;
+ path = file.uri;
+ } else {
+ path = await filesystem.checkAndCreateDir("/");
+ await RNFetchBlob.fs.writeFile(path + fileName, codeString, "utf8");
+ path = path + fileName;
+ }
+
+ ToastManager.show({
+ heading: strings.codesSaved(),
+ type: "success",
+ context: "local"
+ });
+ return path;
+ } catch (e) {
+ console.error(e);
+ }
+ };
+
+ const onCompletePress = () => {
+ if (isSetup) {
+ onSuccess && onSuccess(method);
+ } else {
+ eSendEvent(eCloseSheet);
+ }
+ };
+
return (
-
+
-
-
- {loading ? (
-
-
-
- {strings.gettingRecoveryCodes()}... {strings.pleaseWait()}
-
-
- ) : (
- <>
- (
-
- {item}
-
- )}
- />
-
+
+ {loading ? (
- {
- const codeString = codes.join("\n");
- Clipboard.setString(codeString);
- ToastManager.show({
- heading: strings.codesCopied(),
- type: "success",
- context: "local"
- });
- }}
+
+
+ {strings.gettingRecoveryCodes()}... {strings.pleaseWait()}
+
+
+ ) : (
+ <>
+
+ {codeRows.map((row, rowIndex) => (
+
+ {row.map((code, colIndex) => (
+
+ {code}
+
+ ))}
+ {row.length < 3
+ ? Array.from({ length: 3 - row.length }).map((_, idx) => (
+
+ ))
+ : null}
+
+ ))}
+
+
+
+
+
+
+
+
+
{
- try {
- let path;
- let fileName = "notesnook_recoverycodes";
- fileName = sanitizeFilename(fileName, { replacement: "_" });
- fileName = fileName + ".txt";
- const codeString = codes.join("\n");
- if (Platform.OS === "android") {
- const file = await ScopedStorage.createDocument(
- fileName,
- "text/plain",
- codeString,
- "utf8"
- );
- if (!file) return;
- path = file.uri;
- } else {
- path = await filesystem.checkAndCreateDir("/");
- await RNFetchBlob.fs.writeFile(
- path + fileName,
- codeString,
- "utf8"
- );
- path = path + fileName;
- }
-
- ToastManager.show({
- heading: strings.codesSaved(),
- type: "success",
- context: "local"
- });
- return path;
- } catch (e) {
- console.error(e);
- }
+ title={isSetup ? strings.next() : strings.done()}
+ type="accent"
+ width="100%"
+ onPress={onCompletePress}
+ style={{
+ borderRadius: Radius.S,
+ marginTop: Spacing.LEVEL_2,
+ marginBottom: Spacing.LEVEL_2
}}
/>
-
-
- {
- if (isSetup) {
- onSuccess && onSuccess(method);
- } else {
- eSendEvent(eCloseSheet);
- }
- }}
- style={{
- borderRadius: 100,
- marginBottom: DefaultAppStyles.GAP_VERTICAL
- }}
- />
- >
- )}
+ >
+ )}
+
);
};
@@ -702,61 +842,120 @@ MFARecoveryCodes.present = (methodId: MFAMethod["id"]) => {
});
};
-const mfaSvg = (
- colors: VariantsWithStaticColors
-) => ``;
-
const MFASuccess = ({ recovery }: MFAStepProps) => {
- const { colors } = useThemeColors();
+ const { colors, isDark } = useThemeColors();
+
+ const onDonePress = () => {
+ eSendEvent(eCloseSheet);
+ };
+
+ const onSecondaryMethodPress = () => {
+ MFASheet.present(true);
+ };
+
return (
-
-
-
-
-
-
- {
- eSendEvent(eCloseSheet);
- }}
+
+ >
+
+
+
+
+
+
+
+
- {!recovery ? (
+
+
+ {recovery
+ ? strings.fallbackMethodEnabled()
+ : strings.twoFactorAuthEnabled()}
+
+
+ {strings.accountIsSecure()}
+
+
+
+
{
- MFASheet.present(true);
+ title={strings.done()}
+ type="accent"
+ width="100%"
+ onPress={onDonePress}
+ style={{
+ borderRadius: Radius.S
}}
/>
- ) : null}
+
+ {!recovery ? (
+
+ ) : null}
+
);
};
diff --git a/apps/mobile/app/screens/settings/group.tsx b/apps/mobile/app/screens/settings/group.tsx
index 47221c46d..38f6d8fbc 100644
--- a/apps/mobile/app/screens/settings/group.tsx
+++ b/apps/mobile/app/screens/settings/group.tsx
@@ -47,9 +47,15 @@ const Group = ({
return false;
}
});
- const renderItem = ({ item }: { item: SettingSection; index: number }) =>
+ const renderItem = ({
+ item,
+ index
+ }: {
+ item: SettingSection;
+ index: number;
+ }) =>
item.type === "group" ? (
-
+
) : (
);
diff --git a/apps/mobile/app/screens/settings/groups/account.ts b/apps/mobile/app/screens/settings/groups/account.ts
index e6389e228..2c53cdc7c 100644
--- a/apps/mobile/app/screens/settings/groups/account.ts
+++ b/apps/mobile/app/screens/settings/groups/account.ts
@@ -292,7 +292,6 @@ export const accountGroup: SettingSection = {
name: strings.subscriptionNotActivated(),
icon: "warning-circle",
iconFamily: "notesnook",
- isNavigation: true,
hidden: () => Platform.OS !== "ios",
modifer: async () => {
if (Platform.OS === "android") return;
@@ -355,63 +354,77 @@ export const accountGroup: SettingSection = {
iconFamily: "notesnook",
sections: [
{
- id: "enable-2fa",
- name: strings.change2faMethod(),
- modifer: () => {
- verifyUser("global", async () => {
- MFASheet.present();
- });
- },
- useHook: () => useUserStore((state) => state.user),
- description: strings.change2faMethodDesc()
- },
- {
- id: "2fa-fallback",
- name: strings.addFallback2faMethod(),
- useHook: () => useUserStore((state) => state.user),
- hidden: (user) => {
- return (
- !!(user as User)?.mfa?.secondaryMethod ||
- !(user as User)?.mfa?.isEnabled
- );
- },
- modifer: () => {
- verifyUser("global", async () => {
- MFASheet.present(true);
- });
- },
- description: strings.addFallback2faMethodDesc()
- },
- {
- id: "change-2fa-method",
- name: strings.change2faFallbackMethod(),
- useHook: () => useUserStore((state) => state.user),
- hidden: (user) => {
- return (
- !(user as User)?.mfa?.secondaryMethod ||
- !(user as User)?.mfa?.isEnabled
- );
- },
- modifer: () => {
- verifyUser("global", async () => {
- MFASheet.present(true);
- });
- },
- description: strings.change2faFallbackMethod()
- },
- {
- id: "view-2fa-codes",
- name: strings.viewRecoveryCodes(),
- modifer: () => {
- verifyUser("global", async () => {
- MFARecoveryCodes.present("sms");
- });
- },
- useHook: () => useUserStore((state) => state.user),
- hidden: (user) => {
- return !(user as User)?.mfa?.isEnabled;
- },
- description: strings.viewRecoveryCodesDesc()
+ id: "2fa-settings-group",
+ name: strings.twoFactorAuth(),
+ type: "group",
+ sections: [
+ {
+ id: "enable-2fa",
+ name: strings.change2faMethod(),
+ icon: "shield-check",
+ iconFamily: "notesnook",
+ modifer: () => {
+ verifyUser("global", async () => {
+ MFASheet.present();
+ });
+ },
+ useHook: () => useUserStore((state) => state.user),
+ description: strings.change2faMethodDesc()
+ },
+ {
+ id: "2fa-fallback",
+ name: strings.addFallback2faMethod(),
+ icon: "shield-plus",
+ iconFamily: "notesnook",
+ useHook: () => useUserStore((state) => state.user),
+ hidden: (user) => {
+ return (
+ !!(user as User)?.mfa?.secondaryMethod ||
+ !(user as User)?.mfa?.isEnabled
+ );
+ },
+ modifer: () => {
+ verifyUser("global", async () => {
+ MFASheet.present(true);
+ });
+ },
+ description: strings.addFallback2faMethodDesc()
+ },
+ {
+ id: "change-2fa-method",
+ name: strings.change2faFallbackMethod(),
+ icon: "shield-plus",
+ useHook: () => useUserStore((state) => state.user),
+ hidden: (user) => {
+ return (
+ !(user as User)?.mfa?.secondaryMethod ||
+ !(user as User)?.mfa?.isEnabled
+ );
+ },
+ modifer: () => {
+ verifyUser("global", async () => {
+ MFASheet.present(true);
+ });
+ },
+ description: strings.change2faFallbackMethod()
+ },
+ {
+ id: "view-2fa-codes",
+ name: strings.viewRecoveryCodes(),
+ modifer: () => {
+ verifyUser("global", async () => {
+ MFARecoveryCodes.present("sms");
+ });
+ },
+ icon: "numpad",
+ iconFamily: "notesnook",
+ useHook: () => useUserStore((state) => state.user),
+ hidden: (user) => {
+ return !(user as User)?.mfa?.isEnabled;
+ },
+ description: strings.viewRecoveryCodesDesc()
+ }
+ ]
}
]
},
@@ -419,7 +432,6 @@ export const accountGroup: SettingSection = {
id: "recovery-key",
name: strings.saveDataRecoveryKey(),
iconFamily: "notesnook",
- isNavigation: true,
modifer: async () => {
// if (await verifyUser()) {
@@ -686,7 +698,6 @@ export const accountGroup: SettingSection = {
name: strings.forcePullChanges(),
description: strings.forcePullChangesDesc(),
icon: "git-pull-request",
- isNavigation: true,
iconFamily: "notesnook",
modifer: () => {
presentDialog({
@@ -711,7 +722,6 @@ export const accountGroup: SettingSection = {
description: strings.forcePushChangesDesc(),
icon: "arrow-fat-up",
iconFamily: "notesnook",
- isNavigation: true,
modifer: () => {
presentDialog({
title: strings.forcePushChanges(),
diff --git a/apps/mobile/app/screens/settings/home.tsx b/apps/mobile/app/screens/settings/home.tsx
index c24c5f995..849d8342c 100644
--- a/apps/mobile/app/screens/settings/home.tsx
+++ b/apps/mobile/app/screens/settings/home.tsx
@@ -46,11 +46,17 @@ const Home = ({
focusOnInit: true
});
- const renderItem = ({ item }: { item: SettingSection; index: number }) =>
+ const renderItem = ({
+ item,
+ index
+ }: {
+ item: SettingSection;
+ index: number;
+ }) =>
item.id === "account" ? (
) : (
-
+
);
return (
diff --git a/apps/mobile/app/screens/settings/section-group.tsx b/apps/mobile/app/screens/settings/section-group.tsx
index 07cc8c7fe..2c472dd59 100644
--- a/apps/mobile/app/screens/settings/section-group.tsx
+++ b/apps/mobile/app/screens/settings/section-group.tsx
@@ -25,7 +25,13 @@ import Heading from "../../components/ui/typography/heading";
import { AppFontSize } from "../../utils/size";
import { SectionItem } from "./section-item";
import { SettingSection } from "./types";
-export const SectionGroup = ({ item }: { item: SettingSection }) => {
+export const SectionGroup = ({
+ item,
+ isLast
+}: {
+ item: SettingSection;
+ isLast?: boolean;
+}) => {
const { colors } = useThemeColors();
const current = item.useHook && item.useHook();
const isHidden = item.hidden && item.hidden(current);
@@ -49,28 +55,34 @@ export const SectionGroup = ({ item }: { item: SettingSection }) => {
) : null}
- {item.sections?.map((item) =>
- item.type === "group" ? (
-
+ {item.sections?.map((sectionItem, index) =>
+ sectionItem.type === "group" ? (
+
) : (
-
+
)
)}
-
+ {isLast ? null : (
-
+ >
+
+
+ )}
);
};
diff --git a/apps/mobile/app/screens/settings/section-item.tsx b/apps/mobile/app/screens/settings/section-item.tsx
index 3201b717d..2dd35add7 100644
--- a/apps/mobile/app/screens/settings/section-item.tsx
+++ b/apps/mobile/app/screens/settings/section-item.tsx
@@ -421,7 +421,7 @@ const _SectionItem = ({ item }: { item: SettingSection }) => {
/>
)}
- {item.type === "screen" || item.isNavigation ? (
+ {item.type === "screen" ? (
string);
icon?: string;
iconFamily?: IconProps["iconFamily"];
- isNavigation?: boolean;
iconSize?: number;
property?: keyof Settings;
sections?: SettingSection[];
diff --git a/apps/mobile/fonts/MaterialCommunityIcons.ttf b/apps/mobile/fonts/MaterialCommunityIcons.ttf
index 710a7afd2..bd1228311 100644
Binary files a/apps/mobile/fonts/MaterialCommunityIcons.ttf and b/apps/mobile/fonts/MaterialCommunityIcons.ttf differ
diff --git a/apps/mobile/fonts/notesnook-icons.glyphmap.json b/apps/mobile/fonts/notesnook-icons.glyphmap.json
index 1fe530ea7..c56c4a725 100644
--- a/apps/mobile/fonts/notesnook-icons.glyphmap.json
+++ b/apps/mobile/fonts/notesnook-icons.glyphmap.json
@@ -1 +1 @@
-{"m":{"f":"notesnook-icons","u":1024,"z":1020,"s":59648,"h":"732c10c1b7a68a314543aa54f89c5cc11a6dcf1d4457e785521a86655a4306c0"},"i":{"archive":[1024,[[59648,"#666666"]]],"arrow-back":[1024,[[59649,"rgba(255,255,255,0.7)"]]],"arrow-counter-clockwise":[1024,[[59650,"var(--fill-0, #181818)"]]],"arrow-fat-up":[1024,[[59651,"var(--fill-0, #181818)"]]],"arrow-u-up-left":[1024,[[59652,"var(--fill-0, #181818)"]]],"arrows-clockwise":[1024,[[59653,"var(--fill-0, #181818)"]]],"bag-simple":[1024,[[59654,"var(--fill-0, #181818)"]]],"bell":[1024,[[59655,"#666666"]]],"book-open":[1024,[[59656,"#666666"]]],"bookmark":[1024,[[59657,"#666666"]]],"box-empty":[1024,[[59658,"#B0B0B1"]]],"bug-droid":[1024,[[59659,"var(--fill-0, #181818)"]]],"calendar":[1024,[[59660,"rgba(102,102,102,0.8)"]]],"chart-line-up":[1024,[[59661,"var(--fill-0, #181818)"]]],"chat":[1024,[[59662,"white"]]],"checkbox":[1024,[[59663,"#008836"],[59664,"white"]]],"checks":[1024,[[59665,"#181818"]]],"chevron-down":[1024,[[59666,"#181818"]]],"chevron-right":[1024,[[59667,"#181818"]]],"chevron-up":[1024,[[59668,"#181818"]]],"clock-counter-clockwise":[1024,[[59669,"var(--fill-0, #181818)"]]],"close":[1024,[[59670,"#666666"]]],"cloud-check":[1024,[[59671,"var(--fill-0, #181818)"]]],"cloud":[1024,[[59672,"white"]]],"dark-mode-outline":[1024,[[59673,"currentColor"]]],"device-mobile-camera":[1024,[[59674,"var(--fill-0, #181818)"]]],"discord-logo":[1024,[[59675,"var(--fill-0, #181818)"]]],"dots-three":[1024,[[59676,"#202020"]]],"download-simple":[1024,[[59677,"var(--fill-0, #181818)"]]],"drive-file-move":[1088,[[59678,"#666666"]]],"edit-pencil":[1024,[[59679,"#181818"]]],"envelope-simple":[1024,[[59680,"white"]]],"export":[1024,[[59681,"var(--fill-0, #181818)"]]],"eye-closed":[1024,[[59682,"white"]]],"eye-open":[1024,[[59683,"currentColor"]]],"eye-slash":[1024,[[59684,"var(--fill-0, #181818)"]]],"file-dashed":[1024,[[59685,"var(--fill-0, #181818)"]]],"file-text":[1024,[[59686,"var(--fill-0, #181818)"]]],"file":[1024,[[59687,"white"]]],"funnel":[1024,[[59688,"#666666"]]],"git-pull-request":[1024,[[59689,"var(--fill-0, #181818)"]]],"github-logo":[1024,[[59690,"var(--fill-0, #181818)"]]],"hard-drives":[1024,[[59691,"var(--fill-0, #181818)"]]],"home":[1024,[[59692,"#181818"]]],"image-outline":[1024,[[59693,"white"]]],"key":[1024,[[59694,"var(--fill-0, #181818)"]]],"link":[560,[[59695,"#666666"]]],"lock-simple":[1024,[[59696,"white"]]],"lock":[1024,[[59697,"#181818"]]],"mastodon-logo":[1024,[[59698,"var(--fill-0, #181818)"]]],"menu":[1024,[[59699,"#181818"]]],"network":[1024,[[59700,"var(--fill-0, #181818)"]]],"note":[1024,[[59701,"#181818"]]],"notification":[1024,[[59702,"var(--fill-0, #181818)"]]],"paperclip":[1024,[[59703,"var(--fill-0, #181818)"]]],"pause":[1024,[[59704,"var(--fill-0, #181818)"]]],"pencil-simple-line":[1024,[[59705,"var(--fill-0, #181818)"]]],"pin":[939,[[59706,"#666666"]]],"plus":[1024,[[59707,"#666666"]]],"recovery-key-cloud-arrow-down":[1024,[[59708,"var(--fill-0, #181818)"]]],"recovery-key-copy":[1024,[[59709,"var(--stroke-0, #008836)"]]],"recovery-key-file":[1024,[[59710,"var(--fill-0, #181818)"]]],"recovery-key-key":[1024,[[59711,"var(--fill-0, #181818)"]]],"recovery-key-qr-code":[1024,[[59712,"var(--fill-0, #181818)"]]],"recovery-key-shield-check":[1024,[[59713,"var(--fill-0, #008836)"]]],"search":[1024,[[59714,"#181818"]]],"shield-check":[1024,[[59715,"#181818"]]],"shield":[1024,[[59716,"var(--fill-0, #181818)"]]],"shopping-mode":[1024,[[59717,"#666666"]]],"sliders-horizontal":[1024,[[59718,"var(--fill-0, #181818)"]]],"sliders":[1024,[[59719,"#181818"]]],"sort-ascending":[1024,[[59720,"#666666"]]],"sort-descending":[1024,[[59721,"currentColor"]]],"square-out":[1024,[[59722,"#181818"]]],"squares-four":[1024,[[59723,"var(--fill-0, #181818)"]]],"star-filled":[1024,[[59724,"#E5C131"]]],"star":[1024,[[59725,"#666666"]]],"sun":[1024,[[59726,"#666666"]]],"telegram-logo":[1024,[[59727,"var(--fill-0, #181818)"]]],"toggle-off":[1725,[[59728,"#DADADA"]]],"toggle-on":[1725,[[59729,"#008836"]]],"trash":[1024,[[59730,"#666666"]]],"user-circle-minus":[1024,[[59731,"var(--fill-0, #FF242E)"]]],"user-sheet-docs":[1024,[[59732,"var(--fill-0, #181818)"]]],"user-sheet-logout":[1024,[[59733,"var(--fill-0, #FB2C36)"]]],"user-sheet-settings":[1024,[[59734,"var(--fill-0, #181818)"]]],"user-sheet-support":[1024,[[59735,"var(--fill-0, #181818)"]]],"user-sheet-sync":[1024,[[59736,"var(--fill-0, #181818)"]]],"user":[1024,[[59737,"var(--fill-0, #181818)"]]],"users-three":[1024,[[59738,"var(--fill-0, #181818)"]]],"view-list":[1024,[[59739,"#181818"]]],"warning-circle":[1024,[[59740,"#BB3431"]]],"wifi-slash":[1024,[[59741,"var(--fill-0, #181818)"]]],"x-logo":[1024,[[59742,"var(--fill-0, #181818)"]]]}}
\ No newline at end of file
+{"m":{"f":"notesnook-icons","u":1024,"z":1020,"s":59648,"h":"ed87d51c541700d863c75e1c0ba9f42fa7e5f8cc5549f0049cb3931307de6789"},"i":{"archive":[1024,[[59648,"#666666"]]],"arrow-back":[1024,[[59649,"rgba(255,255,255,0.7)"]]],"arrow-counter-clockwise":[1024,[[59650,"var(--fill-0, #181818)"]]],"arrow-fat-up":[1024,[[59651,"var(--fill-0, #181818)"]]],"arrow-u-up-left":[1024,[[59652,"var(--fill-0, #181818)"]]],"arrows-clockwise":[1024,[[59653,"var(--fill-0, #181818)"]]],"bag-simple":[1024,[[59654,"var(--fill-0, #181818)"]]],"bell":[1024,[[59655,"#666666"]]],"book-open":[1024,[[59656,"#666666"]]],"bookmark":[1024,[[59657,"#666666"]]],"box-empty":[1024,[[59658,"#B0B0B1"]]],"bug-droid":[1024,[[59659,"var(--fill-0, #181818)"]]],"calendar":[1024,[[59660,"rgba(102,102,102,0.8)"]]],"chart-line-up":[1024,[[59661,"var(--fill-0, #181818)"]]],"chat":[1024,[[59662,"white"]]],"checkbox":[1024,[[59663,"#008836"],[59664,"white"]]],"checks":[1024,[[59665,"#181818"]]],"chevron-down":[1024,[[59666,"#181818"]]],"chevron-right":[1024,[[59667,"#181818"]]],"chevron-up":[1024,[[59668,"#181818"]]],"clock-counter-clockwise":[1024,[[59669,"var(--fill-0, #181818)"]]],"close":[1024,[[59670,"#666666"]]],"cloud-check":[1024,[[59671,"var(--fill-0, #181818)"]]],"cloud":[1024,[[59672,"white"]]],"dark-mode-outline":[1024,[[59673,"currentColor"]]],"device-mobile-camera":[1024,[[59674,"var(--fill-0, #181818)"]]],"discord-logo":[1024,[[59675,"var(--fill-0, #181818)"]]],"dots-three":[1024,[[59676,"#202020"]]],"download-simple":[1024,[[59677,"var(--fill-0, #181818)"]]],"drive-file-move":[1088,[[59678,"#666666"]]],"edit-pencil":[1024,[[59679,"#181818"]]],"envelope-simple":[1024,[[59680,"white"]]],"export":[1024,[[59681,"var(--fill-0, #181818)"]]],"eye-closed":[1024,[[59682,"white"]]],"eye-open":[1024,[[59683,"currentColor"]]],"eye-slash":[1024,[[59684,"var(--fill-0, #181818)"]]],"file-dashed":[1024,[[59685,"var(--fill-0, #181818)"]]],"file-text":[1024,[[59686,"var(--fill-0, #181818)"]]],"file":[1024,[[59687,"white"]]],"funnel":[1024,[[59688,"#666666"]]],"git-pull-request":[1024,[[59689,"var(--fill-0, #181818)"]]],"github-logo":[1024,[[59690,"var(--fill-0, #181818)"]]],"hard-drives":[1024,[[59691,"var(--fill-0, #181818)"]]],"home":[1024,[[59692,"#181818"]]],"image-outline":[1024,[[59693,"white"]]],"key":[1024,[[59694,"var(--fill-0, #181818)"]]],"link":[560,[[59695,"#666666"]]],"lock-simple":[1024,[[59696,"white"]]],"lock":[1024,[[59697,"#181818"]]],"mastodon-logo":[1024,[[59698,"var(--fill-0, #181818)"]]],"menu":[1024,[[59699,"#181818"]]],"network":[1024,[[59700,"var(--fill-0, #181818)"]]],"note":[1024,[[59701,"#181818"]]],"notification":[1024,[[59702,"var(--fill-0, #181818)"]]],"numpad":[1024,[[59703,"#181818"]]],"paperclip":[1024,[[59704,"var(--fill-0, #181818)"]]],"pause":[1024,[[59705,"var(--fill-0, #181818)"]]],"pencil-simple-line":[1024,[[59706,"var(--fill-0, #181818)"]]],"pin":[939,[[59707,"#666666"]]],"plus":[1024,[[59708,"#666666"]]],"recovery-key-cloud-arrow-down":[1024,[[59709,"var(--fill-0, #181818)"]]],"recovery-key-copy":[1024,[[59710,"var(--stroke-0, #008836)"]]],"recovery-key-file":[1024,[[59711,"var(--fill-0, #181818)"]]],"recovery-key-key":[1024,[[59712,"var(--fill-0, #181818)"]]],"recovery-key-qr-code":[1024,[[59713,"var(--fill-0, #181818)"]]],"recovery-key-shield-check":[1024,[[59714,"var(--fill-0, #008836)"]]],"search":[1024,[[59715,"#181818"]]],"shield-check":[1024,[[59716,"#181818"]]],"shield-plus":[1024,[[59717,"#181818"]]],"shield":[1024,[[59718,"var(--fill-0, #181818)"]]],"shopping-mode":[1024,[[59719,"#666666"]]],"sliders-horizontal":[1024,[[59720,"var(--fill-0, #181818)"]]],"sliders":[1024,[[59721,"#181818"]]],"sort-ascending":[1024,[[59722,"#666666"]]],"sort-descending":[1024,[[59723,"currentColor"]]],"square-out":[1024,[[59724,"#181818"]]],"squares-four":[1024,[[59725,"var(--fill-0, #181818)"]]],"star-filled":[1024,[[59726,"#E5C131"]]],"star":[1024,[[59727,"#666666"]]],"sun":[1024,[[59728,"#666666"]]],"telegram-logo":[1024,[[59729,"var(--fill-0, #181818)"]]],"toggle-off":[1725,[[59730,"#DADADA"]]],"toggle-on":[1725,[[59731,"#008836"]]],"trash":[1024,[[59732,"#666666"]]],"user-circle-minus":[1024,[[59733,"var(--fill-0, #FF242E)"]]],"user-sheet-docs":[1024,[[59734,"var(--fill-0, #181818)"]]],"user-sheet-logout":[1024,[[59735,"var(--fill-0, #FB2C36)"]]],"user-sheet-settings":[1024,[[59736,"var(--fill-0, #181818)"]]],"user-sheet-support":[1024,[[59737,"var(--fill-0, #181818)"]]],"user-sheet-sync":[1024,[[59738,"var(--fill-0, #181818)"]]],"user":[1024,[[59739,"var(--fill-0, #181818)"]]],"users-three":[1024,[[59740,"var(--fill-0, #181818)"]]],"view-list":[1024,[[59741,"#181818"]]],"warning-circle":[1024,[[59742,"#BB3431"]]],"wifi-slash":[1024,[[59743,"var(--fill-0, #181818)"]]],"x-logo":[1024,[[59744,"var(--fill-0, #181818)"]]]}}
\ No newline at end of file
diff --git a/packages/icons/svgs/numpad.svg b/packages/icons/svgs/numpad.svg
new file mode 100644
index 000000000..8c015865e
--- /dev/null
+++ b/packages/icons/svgs/numpad.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/icons/svgs/shield-plus.svg b/packages/icons/svgs/shield-plus.svg
new file mode 100644
index 000000000..50c4ec151
--- /dev/null
+++ b/packages/icons/svgs/shield-plus.svg
@@ -0,0 +1,3 @@
+