@bifold/core 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/lib/commonjs/components/inputs/BiometryControl.js.map +1 -1
  2. package/lib/commonjs/components/misc/CredentialCard.js +3 -2
  3. package/lib/commonjs/components/misc/CredentialCard.js.map +1 -1
  4. package/lib/commonjs/components/misc/FauxHeader.js +89 -0
  5. package/lib/commonjs/components/misc/FauxHeader.js.map +1 -0
  6. package/lib/commonjs/components/misc/QRScanner.js +1 -1
  7. package/lib/commonjs/components/misc/QRScanner.js.map +1 -1
  8. package/lib/commonjs/components/modals/DeveloperModal.js +43 -0
  9. package/lib/commonjs/components/modals/DeveloperModal.js.map +1 -0
  10. package/lib/commonjs/components/views/PushNotificationsContent.js.map +1 -1
  11. package/lib/commonjs/components/views/PushNotificationsDisabledContent.js.map +1 -1
  12. package/lib/commonjs/contexts/auth.js +24 -3
  13. package/lib/commonjs/contexts/auth.js.map +1 -1
  14. package/lib/commonjs/hooks/chat-messages.js +1 -1
  15. package/lib/commonjs/hooks/chat-messages.js.map +1 -1
  16. package/lib/commonjs/hooks/developer-mode.js +31 -0
  17. package/lib/commonjs/hooks/developer-mode.js.map +1 -0
  18. package/lib/commonjs/hooks/lockout.js +80 -0
  19. package/lib/commonjs/hooks/lockout.js.map +1 -0
  20. package/lib/commonjs/hooks/onboarding.js +23 -0
  21. package/lib/commonjs/hooks/onboarding.js.map +1 -0
  22. package/lib/commonjs/index.js +24 -0
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/commonjs/localization/en/index.js +2 -1
  25. package/lib/commonjs/localization/en/index.js.map +1 -1
  26. package/lib/commonjs/localization/fr/index.js +2 -1
  27. package/lib/commonjs/localization/fr/index.js.map +1 -1
  28. package/lib/commonjs/localization/pt-br/index.js +2 -1
  29. package/lib/commonjs/localization/pt-br/index.js.map +1 -1
  30. package/lib/commonjs/modules/openid/components/OpenIDCredentialCard.js +4 -5
  31. package/lib/commonjs/modules/openid/components/OpenIDCredentialCard.js.map +1 -1
  32. package/lib/commonjs/modules/openid/display.js +6 -3
  33. package/lib/commonjs/modules/openid/display.js.map +1 -1
  34. package/lib/commonjs/modules/openid/metadata.js +2 -1
  35. package/lib/commonjs/modules/openid/metadata.js.map +1 -1
  36. package/lib/commonjs/modules/openid/screens/OpenIDProofChangeCredential.js +128 -0
  37. package/lib/commonjs/modules/openid/screens/OpenIDProofChangeCredential.js.map +1 -0
  38. package/lib/commonjs/modules/openid/screens/OpenIDProofPresentation.js +99 -44
  39. package/lib/commonjs/modules/openid/screens/OpenIDProofPresentation.js.map +1 -1
  40. package/lib/commonjs/modules/openid/types.js.map +1 -1
  41. package/lib/commonjs/modules/openid/utils/utils.js +0 -14
  42. package/lib/commonjs/modules/openid/utils/utils.js.map +1 -1
  43. package/lib/commonjs/navigators/DeliveryStack.js +8 -0
  44. package/lib/commonjs/navigators/DeliveryStack.js.map +1 -1
  45. package/lib/commonjs/navigators/OnboardingScreens.js +0 -8
  46. package/lib/commonjs/navigators/OnboardingScreens.js.map +1 -1
  47. package/lib/commonjs/navigators/OnboardingStack.js +3 -4
  48. package/lib/commonjs/navigators/OnboardingStack.js.map +1 -1
  49. package/lib/commonjs/navigators/TabStack.js +11 -4
  50. package/lib/commonjs/navigators/TabStack.js.map +1 -1
  51. package/lib/commonjs/navigators/defaultStackOptions.js +2 -1
  52. package/lib/commonjs/navigators/defaultStackOptions.js.map +1 -1
  53. package/lib/commonjs/screens/Biometry.js.map +1 -1
  54. package/lib/commonjs/screens/NameWallet.js +4 -3
  55. package/lib/commonjs/screens/NameWallet.js.map +1 -1
  56. package/lib/commonjs/screens/OnboardingPages.js +8 -38
  57. package/lib/commonjs/screens/OnboardingPages.js.map +1 -1
  58. package/lib/commonjs/screens/PINChange.js +5 -1
  59. package/lib/commonjs/screens/PINChange.js.map +1 -1
  60. package/lib/commonjs/screens/PINCreate.js +4 -1
  61. package/lib/commonjs/screens/PINCreate.js.map +1 -1
  62. package/lib/commonjs/screens/PINEnter.js +114 -292
  63. package/lib/commonjs/screens/PINEnter.js.map +1 -1
  64. package/lib/commonjs/screens/PINVerify.js +181 -0
  65. package/lib/commonjs/screens/PINVerify.js.map +1 -0
  66. package/lib/commonjs/screens/PushNotifications.js.map +1 -1
  67. package/lib/commonjs/screens/Settings.js +9 -18
  68. package/lib/commonjs/screens/Settings.js.map +1 -1
  69. package/lib/commonjs/screens/ToggleBiometry.js +16 -24
  70. package/lib/commonjs/screens/ToggleBiometry.js.map +1 -1
  71. package/lib/commonjs/theme.js +2 -1
  72. package/lib/commonjs/theme.js.map +1 -1
  73. package/lib/commonjs/types/navigators.js +1 -0
  74. package/lib/commonjs/types/navigators.js.map +1 -1
  75. package/lib/commonjs/utils/oca.js +46 -17
  76. package/lib/commonjs/utils/oca.js.map +1 -1
  77. package/lib/module/components/inputs/BiometryControl.js.map +1 -1
  78. package/lib/module/components/misc/CredentialCard.js +3 -2
  79. package/lib/module/components/misc/CredentialCard.js.map +1 -1
  80. package/lib/module/components/misc/FauxHeader.js +80 -0
  81. package/lib/module/components/misc/FauxHeader.js.map +1 -0
  82. package/lib/module/components/misc/QRScanner.js +1 -1
  83. package/lib/module/components/misc/QRScanner.js.map +1 -1
  84. package/lib/module/components/modals/DeveloperModal.js +36 -0
  85. package/lib/module/components/modals/DeveloperModal.js.map +1 -0
  86. package/lib/module/components/views/PushNotificationsContent.js.map +1 -1
  87. package/lib/module/components/views/PushNotificationsDisabledContent.js.map +1 -1
  88. package/lib/module/contexts/auth.js +22 -1
  89. package/lib/module/contexts/auth.js.map +1 -1
  90. package/lib/module/hooks/chat-messages.js +1 -1
  91. package/lib/module/hooks/chat-messages.js.map +1 -1
  92. package/lib/module/hooks/developer-mode.js +24 -0
  93. package/lib/module/hooks/developer-mode.js.map +1 -0
  94. package/lib/module/hooks/lockout.js +70 -0
  95. package/lib/module/hooks/lockout.js.map +1 -0
  96. package/lib/module/hooks/onboarding.js +16 -0
  97. package/lib/module/hooks/onboarding.js.map +1 -0
  98. package/lib/module/index.js +4 -1
  99. package/lib/module/index.js.map +1 -1
  100. package/lib/module/localization/en/index.js +2 -1
  101. package/lib/module/localization/en/index.js.map +1 -1
  102. package/lib/module/localization/fr/index.js +2 -1
  103. package/lib/module/localization/fr/index.js.map +1 -1
  104. package/lib/module/localization/pt-br/index.js +2 -1
  105. package/lib/module/localization/pt-br/index.js.map +1 -1
  106. package/lib/module/modules/openid/components/OpenIDCredentialCard.js +4 -4
  107. package/lib/module/modules/openid/components/OpenIDCredentialCard.js.map +1 -1
  108. package/lib/module/modules/openid/display.js +6 -3
  109. package/lib/module/modules/openid/display.js.map +1 -1
  110. package/lib/module/modules/openid/metadata.js +2 -1
  111. package/lib/module/modules/openid/metadata.js.map +1 -1
  112. package/lib/module/modules/openid/screens/OpenIDProofChangeCredential.js +121 -0
  113. package/lib/module/modules/openid/screens/OpenIDProofChangeCredential.js.map +1 -0
  114. package/lib/module/modules/openid/screens/OpenIDProofPresentation.js +100 -45
  115. package/lib/module/modules/openid/screens/OpenIDProofPresentation.js.map +1 -1
  116. package/lib/module/modules/openid/types.js.map +1 -1
  117. package/lib/module/modules/openid/utils/utils.js +1 -12
  118. package/lib/module/modules/openid/utils/utils.js.map +1 -1
  119. package/lib/module/navigators/DeliveryStack.js +8 -0
  120. package/lib/module/navigators/DeliveryStack.js.map +1 -1
  121. package/lib/module/navigators/OnboardingScreens.js +0 -8
  122. package/lib/module/navigators/OnboardingScreens.js.map +1 -1
  123. package/lib/module/navigators/OnboardingStack.js +4 -5
  124. package/lib/module/navigators/OnboardingStack.js.map +1 -1
  125. package/lib/module/navigators/TabStack.js +11 -4
  126. package/lib/module/navigators/TabStack.js.map +1 -1
  127. package/lib/module/navigators/defaultStackOptions.js +2 -1
  128. package/lib/module/navigators/defaultStackOptions.js.map +1 -1
  129. package/lib/module/screens/Biometry.js.map +1 -1
  130. package/lib/module/screens/NameWallet.js +4 -3
  131. package/lib/module/screens/NameWallet.js.map +1 -1
  132. package/lib/module/screens/OnboardingPages.js +8 -38
  133. package/lib/module/screens/OnboardingPages.js.map +1 -1
  134. package/lib/module/screens/PINChange.js +5 -1
  135. package/lib/module/screens/PINChange.js.map +1 -1
  136. package/lib/module/screens/PINCreate.js +4 -1
  137. package/lib/module/screens/PINCreate.js.map +1 -1
  138. package/lib/module/screens/PINEnter.js +116 -294
  139. package/lib/module/screens/PINEnter.js.map +1 -1
  140. package/lib/module/screens/PINVerify.js +172 -0
  141. package/lib/module/screens/PINVerify.js.map +1 -0
  142. package/lib/module/screens/PushNotifications.js.map +1 -1
  143. package/lib/module/screens/Settings.js +7 -16
  144. package/lib/module/screens/Settings.js.map +1 -1
  145. package/lib/module/screens/ToggleBiometry.js +15 -23
  146. package/lib/module/screens/ToggleBiometry.js.map +1 -1
  147. package/lib/module/theme.js +2 -1
  148. package/lib/module/theme.js.map +1 -1
  149. package/lib/module/types/navigators.js +1 -0
  150. package/lib/module/types/navigators.js.map +1 -1
  151. package/lib/module/utils/oca.js +43 -15
  152. package/lib/module/utils/oca.js.map +1 -1
  153. package/lib/typescript/src/components/inputs/BiometryControl.d.ts.map +1 -1
  154. package/lib/typescript/src/components/misc/CredentialCard.d.ts.map +1 -1
  155. package/lib/typescript/src/components/misc/FauxHeader.d.ts +8 -0
  156. package/lib/typescript/src/components/misc/FauxHeader.d.ts.map +1 -0
  157. package/lib/typescript/src/components/modals/DeveloperModal.d.ts +7 -0
  158. package/lib/typescript/src/components/modals/DeveloperModal.d.ts.map +1 -0
  159. package/lib/typescript/src/contexts/auth.d.ts +1 -0
  160. package/lib/typescript/src/contexts/auth.d.ts.map +1 -1
  161. package/lib/typescript/src/hooks/developer-mode.d.ts +4 -0
  162. package/lib/typescript/src/hooks/developer-mode.d.ts.map +1 -0
  163. package/lib/typescript/src/hooks/lockout.d.ts +9 -0
  164. package/lib/typescript/src/hooks/lockout.d.ts.map +1 -0
  165. package/lib/typescript/src/hooks/onboarding.d.ts +2 -0
  166. package/lib/typescript/src/hooks/onboarding.d.ts.map +1 -0
  167. package/lib/typescript/src/index.d.ts +5 -2
  168. package/lib/typescript/src/index.d.ts.map +1 -1
  169. package/lib/typescript/src/localization/en/index.d.ts +1 -0
  170. package/lib/typescript/src/localization/en/index.d.ts.map +1 -1
  171. package/lib/typescript/src/localization/fr/index.d.ts +1 -0
  172. package/lib/typescript/src/localization/fr/index.d.ts.map +1 -1
  173. package/lib/typescript/src/localization/pt-br/index.d.ts +1 -0
  174. package/lib/typescript/src/localization/pt-br/index.d.ts.map +1 -1
  175. package/lib/typescript/src/modules/openid/components/OpenIDCredentialCard.d.ts.map +1 -1
  176. package/lib/typescript/src/modules/openid/display.d.ts.map +1 -1
  177. package/lib/typescript/src/modules/openid/metadata.d.ts +8 -1
  178. package/lib/typescript/src/modules/openid/metadata.d.ts.map +1 -1
  179. package/lib/typescript/src/modules/openid/screens/OpenIDProofChangeCredential.d.ts +6 -0
  180. package/lib/typescript/src/modules/openid/screens/OpenIDProofChangeCredential.d.ts.map +1 -0
  181. package/lib/typescript/src/modules/openid/screens/OpenIDProofPresentation.d.ts.map +1 -1
  182. package/lib/typescript/src/modules/openid/types.d.ts +9 -0
  183. package/lib/typescript/src/modules/openid/types.d.ts.map +1 -1
  184. package/lib/typescript/src/modules/openid/utils/utils.d.ts +1 -3
  185. package/lib/typescript/src/modules/openid/utils/utils.d.ts.map +1 -1
  186. package/lib/typescript/src/navigators/DeliveryStack.d.ts.map +1 -1
  187. package/lib/typescript/src/navigators/OnboardingScreens.d.ts +0 -1
  188. package/lib/typescript/src/navigators/OnboardingScreens.d.ts.map +1 -1
  189. package/lib/typescript/src/navigators/OnboardingStack.d.ts.map +1 -1
  190. package/lib/typescript/src/navigators/TabStack.d.ts.map +1 -1
  191. package/lib/typescript/src/navigators/defaultStackOptions.d.ts.map +1 -1
  192. package/lib/typescript/src/screens/Biometry.d.ts.map +1 -1
  193. package/lib/typescript/src/screens/OnboardingPages.d.ts +1 -1
  194. package/lib/typescript/src/screens/OnboardingPages.d.ts.map +1 -1
  195. package/lib/typescript/src/screens/PINChange.d.ts.map +1 -1
  196. package/lib/typescript/src/screens/PINCreate.d.ts.map +1 -1
  197. package/lib/typescript/src/screens/PINEnter.d.ts +0 -7
  198. package/lib/typescript/src/screens/PINEnter.d.ts.map +1 -1
  199. package/lib/typescript/src/screens/PINVerify.d.ts +13 -0
  200. package/lib/typescript/src/screens/PINVerify.d.ts.map +1 -0
  201. package/lib/typescript/src/screens/Settings.d.ts.map +1 -1
  202. package/lib/typescript/src/screens/ToggleBiometry.d.ts.map +1 -1
  203. package/lib/typescript/src/theme.d.ts +10 -25
  204. package/lib/typescript/src/theme.d.ts.map +1 -1
  205. package/lib/typescript/src/types/navigators.d.ts +14 -1
  206. package/lib/typescript/src/types/navigators.d.ts.map +1 -1
  207. package/lib/typescript/src/utils/oca.d.ts +7 -2
  208. package/lib/typescript/src/utils/oca.d.ts.map +1 -1
  209. package/package.json +3 -3
  210. package/src/components/inputs/BiometryControl.tsx +16 -13
  211. package/src/components/misc/CredentialCard.tsx +5 -2
  212. package/src/components/misc/FauxHeader.tsx +75 -0
  213. package/src/components/misc/QRScanner.tsx +1 -1
  214. package/src/components/modals/DeveloperModal.tsx +30 -0
  215. package/src/components/views/PushNotificationsContent.tsx +15 -15
  216. package/src/components/views/PushNotificationsDisabledContent.tsx +10 -10
  217. package/src/contexts/auth.tsx +33 -1
  218. package/src/hooks/chat-messages.tsx +1 -1
  219. package/src/hooks/developer-mode.ts +25 -0
  220. package/src/hooks/lockout.ts +77 -0
  221. package/src/hooks/onboarding.ts +16 -0
  222. package/src/hooks/usePINValidation.ts +3 -3
  223. package/src/index.ts +7 -0
  224. package/src/localization/en/index.ts +1 -0
  225. package/src/localization/fr/index.ts +1 -0
  226. package/src/localization/pt-br/index.ts +1 -0
  227. package/src/modules/openid/components/OpenIDCredentialCard.tsx +3 -4
  228. package/src/modules/openid/display.tsx +3 -0
  229. package/src/modules/openid/metadata.tsx +7 -1
  230. package/src/modules/openid/screens/OpenIDProofChangeCredential.tsx +132 -0
  231. package/src/modules/openid/screens/OpenIDProofPresentation.tsx +131 -59
  232. package/src/modules/openid/types.tsx +8 -0
  233. package/src/modules/openid/utils/utils.tsx +0 -14
  234. package/src/navigators/DeliveryStack.tsx +9 -0
  235. package/src/navigators/OnboardingScreens.ts +0 -10
  236. package/src/navigators/OnboardingStack.tsx +2 -6
  237. package/src/navigators/RootStack.tsx +1 -1
  238. package/src/navigators/TabStack.tsx +3 -2
  239. package/src/navigators/defaultStackOptions.tsx +1 -0
  240. package/src/screens/Biometry.tsx +1 -4
  241. package/src/screens/NameWallet.tsx +2 -2
  242. package/src/screens/OnboardingPages.tsx +9 -61
  243. package/src/screens/PINChange.tsx +6 -9
  244. package/src/screens/PINCreate.tsx +7 -18
  245. package/src/screens/PINEnter.tsx +114 -361
  246. package/src/screens/PINVerify.tsx +193 -0
  247. package/src/screens/PushNotifications.tsx +2 -2
  248. package/src/screens/Settings.tsx +6 -21
  249. package/src/screens/ToggleBiometry.tsx +20 -34
  250. package/src/theme.ts +34 -3
  251. package/src/types/navigators.ts +18 -1
  252. package/src/utils/oca.ts +60 -19
@@ -1,40 +1,34 @@
1
- import { useNavigation } from '@react-navigation/native'
2
- import React, { useCallback, useEffect, useRef, useState } from 'react'
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react'
3
2
  import { useTranslation } from 'react-i18next'
4
- import { Keyboard, StyleSheet, View, DeviceEventEmitter, InteractionManager, Pressable } from 'react-native'
3
+ import { DeviceEventEmitter, InteractionManager, Keyboard, Pressable, StyleSheet, View } from 'react-native'
5
4
 
6
5
  import Button, { ButtonType } from '../components/buttons/Button'
6
+ import { InlineErrorType, InlineMessageProps } from '../components/inputs/InlineErrorText'
7
7
  import PINInput from '../components/inputs/PINInput'
8
8
  import { InfoBoxType } from '../components/misc/InfoBox'
9
+ import DeveloperModal from '../components/modals/DeveloperModal'
9
10
  import PopupModal from '../components/modals/PopupModal'
11
+ import { ThemedText } from '../components/texts/ThemedText'
10
12
  import KeyboardView from '../components/views/KeyboardView'
11
- import { minPINLength, EventTypes, defaultAutoLockTime, attemptLockoutConfig } from '../constants'
13
+ import { EventTypes, attemptLockoutConfig, defaultAutoLockTime, minPINLength } from '../constants'
12
14
  import { TOKENS, useServices } from '../container-api'
13
15
  import { useAnimatedComponents } from '../contexts/animated-components'
14
16
  import { useAuth } from '../contexts/auth'
15
17
  import { DispatchAction } from '../contexts/reducers/store'
16
18
  import { useStore } from '../contexts/store'
17
19
  import { useTheme } from '../contexts/theme'
20
+ import { useDeveloperMode } from '../hooks/developer-mode'
21
+ import { useLockout } from '../hooks/lockout'
22
+ import { useGotoPostAuthScreens } from '../hooks/onboarding'
23
+ import usePreventScreenCapture from '../hooks/screen-capture'
18
24
  import { BifoldError } from '../types/error'
19
- import { Screens } from '../types/navigators'
20
- import { hashPIN } from '../utils/crypto'
21
25
  import { testIdWithKey } from '../utils/testable'
22
- import { InlineErrorType, InlineMessageProps } from '../components/inputs/InlineErrorText'
23
- import { ThemedText } from '../components/texts/ThemedText'
24
26
 
25
27
  interface PINEnterProps {
26
28
  setAuthenticated: (status: boolean) => void
27
- usage?: PINEntryUsage
28
- onCancelAuth?: React.Dispatch<React.SetStateAction<boolean>>
29
- }
30
-
31
- export enum PINEntryUsage {
32
- PINCheck,
33
- WalletUnlock,
34
- ChangeBiometrics,
35
29
  }
36
30
 
37
- const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryUsage.WalletUnlock, onCancelAuth }) => {
31
+ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated }) => {
38
32
  const { t } = useTranslation()
39
33
  const { checkWalletPIN, getWalletSecret, isBiometricsActive, disableBiometrics } = useAuth()
40
34
  const [store, dispatch] = useStore()
@@ -42,186 +36,35 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
42
36
  const [continueEnabled, setContinueEnabled] = useState(true)
43
37
  const [displayLockoutWarning, setDisplayLockoutWarning] = useState(false)
44
38
  const [biometricsErr, setBiometricsErr] = useState(false)
45
- const navigation = useNavigation()
46
- const [alertModalVisible, setAlertModalVisible] = useState<boolean>(false)
47
- const [biometricsEnrollmentChange, setBiometricsEnrollmentChange] = useState<boolean>(false)
48
- const { ColorPallet, TextTheme, Assets, PINEnterTheme } = useTheme()
39
+ const [alertModalVisible, setAlertModalVisible] = useState(false)
40
+ const [devModalVisible, setDevModalVisible] = useState(false)
41
+ const [biometricsEnrollmentChange, setBiometricsEnrollmentChange] = useState(false)
42
+ const { ColorPallet } = useTheme()
49
43
  const { ButtonLoading } = useAnimatedComponents()
50
- const [
51
- logger,
52
- { enableHiddenDevModeTrigger, attemptLockoutConfig: { baseRules, thresholdRules } = attemptLockoutConfig },
53
- ] = useServices([TOKENS.UTIL_LOGGER, TOKENS.CONFIG])
54
- const developerOptionCount = useRef(0)
55
- const touchCountToEnableBiometrics = 9
44
+ const [logger, { preventScreenCapture, enableHiddenDevModeTrigger, attemptLockoutConfig: { thresholdRules } = attemptLockoutConfig }] =
45
+ useServices([TOKENS.UTIL_LOGGER, TOKENS.CONFIG])
56
46
  const [inlineMessageField, setInlineMessageField] = useState<InlineMessageProps>()
57
47
  const [inlineMessages] = useServices([TOKENS.INLINE_ERRORS])
58
48
  const [alertModalMessage, setAlertModalMessage] = useState('')
59
- // Temporary until all use cases are built with the new design
60
- const isNewDesign = usage === PINEntryUsage.ChangeBiometrics
61
-
62
- const style = StyleSheet.create({
63
- screenContainer: {
64
- height: '100%',
65
- backgroundColor: ColorPallet.brand.primaryBackground,
66
- padding: 20,
67
- justifyContent: 'space-between',
68
- },
69
- // below used as helpful labels for views, no properties needed atp
70
- contentContainer: {},
71
- controlsContainer: {},
72
- buttonContainer: {
73
- width: '100%',
74
- },
75
- notifyText: {
76
- ...TextTheme.normal,
77
- marginVertical: 5,
78
- },
79
- helpText: {
80
- alignSelf: 'auto',
81
- textAlign: 'left',
82
- marginBottom: isNewDesign ? 40 : 16,
83
- },
84
- parenthesisText: {
85
- ...TextTheme.caption,
86
- },
87
- modalText: {
88
- marginVertical: 5,
89
- },
90
- image: {
91
- ...PINEnterTheme.image,
92
- height: Assets.img.logoSecondary.height,
93
- width: Assets.img.logoSecondary.width,
94
- resizeMode: Assets.img.logoSecondary.resizeMode,
95
- },
96
- title: {
97
- marginTop: isNewDesign ? 20 : 0,
98
- marginBottom: isNewDesign ? 40 : 20,
99
- },
100
- subTitle: {
101
- marginBottom: 20,
102
- },
103
- subText: {
104
- marginBottom: isNewDesign ? 20 : 4,
105
- },
106
- })
107
-
108
- const inputLabelText = {
109
- [PINEntryUsage.ChangeBiometrics]: t('PINEnter.ChangeBiometricsInputLabel'),
110
- [PINEntryUsage.PINCheck]: t('PINEnter.AppSettingChangedEnterPIN'),
111
- [PINEntryUsage.WalletUnlock]: t('PINEnter.EnterPIN'),
112
- }
113
-
114
- const inputTestId = {
115
- [PINEntryUsage.ChangeBiometrics]: 'BiometricChangedEnterPIN',
116
- [PINEntryUsage.PINCheck]: 'AppSettingChangedEnterPIN',
117
- [PINEntryUsage.WalletUnlock]: 'EnterPIN',
118
- }
119
-
120
- const primaryButtonText = {
121
- [PINEntryUsage.ChangeBiometrics]: t('Global.Continue'),
122
- [PINEntryUsage.PINCheck]: t('PINEnter.AppSettingSave'),
123
- [PINEntryUsage.WalletUnlock]: t('PINEnter.Unlock'),
124
- }
125
-
126
- const primaryButtonTestId = {
127
- [PINEntryUsage.ChangeBiometrics]: 'Continue',
128
- [PINEntryUsage.PINCheck]: 'AppSettingSave',
129
- [PINEntryUsage.WalletUnlock]: 'Enter',
130
- }
131
-
132
- const incrementDeveloperMenuCounter = useCallback(() => {
133
- if (developerOptionCount.current >= touchCountToEnableBiometrics) {
134
- developerOptionCount.current = 0
135
- dispatch({
136
- type: DispatchAction.ENABLE_DEVELOPER_MODE,
137
- payload: [true],
138
- })
139
-
140
- navigation.navigate(Screens.Developer as never)
141
-
142
- return
143
- }
144
-
145
- developerOptionCount.current = developerOptionCount.current + 1
146
- }, [dispatch, navigation])
147
-
148
- const gotoPostAuthScreens = useCallback(() => {
149
- if (store.onboarding.postAuthScreens.length) {
150
- const screen = store.onboarding.postAuthScreens[0]
151
- if (screen) {
152
- navigation.navigate(screen as never)
153
- }
154
- }
155
- }, [store.onboarding.postAuthScreens, navigation])
156
-
157
- const isContinueDisabled = (): boolean => {
158
- if (inlineMessages.enabled) {
159
- return !continueEnabled
160
- }
161
-
162
- return !continueEnabled || PIN.length < minPINLength
163
- }
49
+ const { getLockoutPenalty, attemptLockout, unMarkServedPenalty } = useLockout()
50
+ const onBackPressed = () => setDevModalVisible(false)
51
+ const onDevModeTriggered = () => setDevModalVisible(true)
52
+ const { incrementDeveloperMenuCounter } = useDeveloperMode(onDevModeTriggered)
53
+ const gotoPostAuthScreens = useGotoPostAuthScreens()
54
+ const isContinueDisabled = inlineMessages.enabled ? !continueEnabled : !continueEnabled || PIN.length < minPINLength
55
+ usePreventScreenCapture(preventScreenCapture)
164
56
 
165
57
  // listen for biometrics error event
166
58
  useEffect(() => {
167
59
  const handle = DeviceEventEmitter.addListener(EventTypes.BIOMETRY_ERROR, (value?: boolean) => {
168
60
  setBiometricsErr((prev) => value ?? !prev)
169
61
  })
170
-
171
62
  return () => {
172
63
  handle.remove()
173
64
  }
174
65
  }, [])
175
66
 
176
- // This method is used to notify the app that the user is able to receive
177
- // another lockout penalty
178
- const unMarkServedPenalty = useCallback(() => {
179
- dispatch({
180
- type: DispatchAction.ATTEMPT_UPDATED,
181
- payload: [
182
- {
183
- loginAttempts: store.loginAttempt.loginAttempts,
184
- lockoutDate: undefined,
185
- servedPenalty: undefined,
186
- },
187
- ],
188
- })
189
- }, [dispatch, store.loginAttempt.loginAttempts])
190
-
191
- const attemptLockout = useCallback(
192
- async (penalty: number) => {
193
- // set the attempt lockout time
194
- dispatch({
195
- type: DispatchAction.ATTEMPT_UPDATED,
196
- payload: [
197
- {
198
- loginAttempts: store.loginAttempt.loginAttempts + 1,
199
- lockoutDate: Date.now() + penalty,
200
- servedPenalty: false,
201
- },
202
- ],
203
- })
204
- },
205
- [dispatch, store.loginAttempt.loginAttempts]
206
- )
207
-
208
- const getLockoutPenalty = useCallback(
209
- (attempts: number): number | undefined => {
210
- let penalty = baseRules[attempts]
211
- if (!penalty && attempts >= thresholdRules.threshold && !(attempts % thresholdRules.increment)) {
212
- penalty = thresholdRules.thresholdPenaltyDuration
213
- }
214
-
215
- return penalty
216
- },
217
- [baseRules, thresholdRules]
218
- )
219
-
220
67
  const loadWalletCredentials = useCallback(async () => {
221
- if (usage === PINEntryUsage.PINCheck || usage === PINEntryUsage.ChangeBiometrics) {
222
- return
223
- }
224
-
225
68
  const walletSecret = await getWalletSecret()
226
69
  if (walletSecret) {
227
70
  // remove lockout notification
@@ -229,24 +72,21 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
229
72
  type: DispatchAction.LOCKOUT_UPDATED,
230
73
  payload: [{ displayNotification: false }],
231
74
  })
232
-
233
75
  // reset login attempts if login is successful
234
76
  dispatch({
235
77
  type: DispatchAction.ATTEMPT_UPDATED,
236
78
  payload: [{ loginAttempts: 0 }],
237
79
  })
238
-
239
80
  setAuthenticated(true)
240
81
  gotoPostAuthScreens()
241
82
  }
242
- }, [usage, getWalletSecret, dispatch, setAuthenticated, gotoPostAuthScreens])
83
+ }, [getWalletSecret, dispatch, setAuthenticated, gotoPostAuthScreens])
243
84
 
244
85
  useEffect(() => {
245
86
  const handle = InteractionManager.runAfterInteractions(async () => {
246
87
  if (!store.preferences.useBiometry) {
247
88
  return
248
89
  }
249
-
250
90
  try {
251
91
  const active = await isBiometricsActive()
252
92
  if (!active) {
@@ -284,74 +124,59 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
284
124
  try {
285
125
  setContinueEnabled(false)
286
126
  const result = await checkWalletPIN(PIN)
287
-
288
127
  if (store.loginAttempt.servedPenalty) {
289
128
  // once the user starts entering their PIN, unMark them as having served their
290
129
  // lockout penalty
291
130
  unMarkServedPenalty()
292
131
  }
293
-
294
132
  if (!result) {
295
133
  const newAttempt = store.loginAttempt.loginAttempts + 1
296
-
134
+ let message = ''
297
135
  const attemptsLeft =
298
136
  (thresholdRules.increment - (newAttempt % thresholdRules.increment)) % thresholdRules.increment
299
-
300
137
  if (!inlineMessages.enabled && !getLockoutPenalty(newAttempt)) {
301
138
  // skip displaying modals if we are going to lockout
302
139
  setAlertModalVisible(true)
303
140
  }
304
141
  if (attemptsLeft > 1) {
305
- if (inlineMessages.enabled) {
306
- setInlineMessageField({
307
- message: t('PINEnter.IncorrectPINTries', { tries: attemptsLeft }), // Example: 'Incorrect PIN: 4 tries before timeout'
308
- inlineType: InlineErrorType.error,
309
- config: inlineMessages,
310
- })
311
- } else {
312
- setAlertModalMessage(t('PINEnter.IncorrectPINTries', { tries: attemptsLeft }))
313
- }
142
+ message = t('PINEnter.IncorrectPINTries', { tries: attemptsLeft })
314
143
  } else if (attemptsLeft === 1) {
315
- if (inlineMessages.enabled) {
316
- setInlineMessageField({
317
- message: t('PINEnter.LastTryBeforeTimeout'), // Show last try warning
318
- inlineType: InlineErrorType.error,
319
- config: inlineMessages,
320
- })
321
- } else {
322
- setAlertModalMessage(t('PINEnter.LastTryBeforeTimeout'))
323
- }
144
+ message = t('PINEnter.LastTryBeforeTimeout')
324
145
  } else {
325
146
  const penalty = getLockoutPenalty(newAttempt)
326
147
  if (penalty !== undefined) {
327
148
  attemptLockout(penalty) // Only call attemptLockout if penalty is defined
328
149
  }
150
+ setContinueEnabled(true)
329
151
  return
330
152
  }
331
-
153
+ if (inlineMessages.enabled) {
154
+ setInlineMessageField({
155
+ message,
156
+ inlineType: InlineErrorType.error,
157
+ config: inlineMessages,
158
+ })
159
+ } else {
160
+ setAlertModalMessage(message)
161
+ }
332
162
  setContinueEnabled(true)
333
-
334
163
  // log incorrect login attempts
335
164
  dispatch({
336
165
  type: DispatchAction.ATTEMPT_UPDATED,
337
166
  payload: [{ loginAttempts: newAttempt }],
338
167
  })
339
-
340
168
  return
341
169
  }
342
-
343
170
  // reset login attempts if login is successful
344
171
  dispatch({
345
172
  type: DispatchAction.ATTEMPT_UPDATED,
346
173
  payload: [{ loginAttempts: 0 }],
347
174
  })
348
-
349
175
  // remove lockout notification if login is successful
350
176
  dispatch({
351
177
  type: DispatchAction.LOCKOUT_UPDATED,
352
178
  payload: [{ displayNotification: false }],
353
179
  })
354
-
355
180
  setAuthenticated(true)
356
181
  gotoPostAuthScreens()
357
182
  } catch (err: unknown) {
@@ -380,54 +205,8 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
380
205
  )
381
206
 
382
207
  const clearAlertModal = useCallback(() => {
383
- switch (usage) {
384
- case PINEntryUsage.PINCheck:
385
- setAlertModalVisible(false)
386
- setAuthenticated(false)
387
- break
388
- case PINEntryUsage.ChangeBiometrics:
389
- setAlertModalVisible(false)
390
- setAuthenticated(false)
391
- break
392
-
393
- default:
394
- setAlertModalVisible(false)
395
-
396
- break
397
- }
398
-
399
208
  setAlertModalVisible(false)
400
- }, [usage, setAuthenticated])
401
-
402
- const verifyPIN = useCallback(
403
- async (PIN: string) => {
404
- try {
405
- const walletSecret = await getWalletSecret()
406
- if (!walletSecret) {
407
- throw new Error('Wallet secret not found')
408
- }
409
-
410
- const key = await hashPIN(PIN, walletSecret.salt)
411
-
412
- if (walletSecret.key !== key) {
413
- setAlertModalVisible(true)
414
-
415
- return
416
- }
417
-
418
- setAuthenticated(true)
419
- } catch (err: unknown) {
420
- const error = new BifoldError(
421
- t('Error.Title1042'),
422
- t('Error.Message1042'),
423
- (err as Error)?.message ?? err,
424
- 1042
425
- )
426
- DeviceEventEmitter.emit(EventTypes.ERROR_ADDED, error)
427
- }
428
- },
429
- [getWalletSecret, setAuthenticated, t]
430
- )
209
+ }, [setAlertModalVisible])
431
210
 
432
211
  // both of the async functions called in this function are completely wrapped in try catch
433
212
  const onPINInputCompleted = useCallback(
@@ -438,109 +217,95 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
438
217
  inlineType: InlineErrorType.error,
439
218
  config: inlineMessages,
440
219
  })
441
-
442
220
  return
443
221
  }
444
-
445
222
  setContinueEnabled(false)
446
-
447
- if (usage === PINEntryUsage.PINCheck || usage === PINEntryUsage.ChangeBiometrics) {
448
- await verifyPIN(PIN)
449
- }
450
-
451
- if (usage === PINEntryUsage.WalletUnlock) {
452
- await unlockWalletWithPIN(PIN)
453
- }
223
+ await unlockWalletWithPIN(PIN)
454
224
  },
455
- [usage, verifyPIN, unlockWalletWithPIN, t, inlineMessages]
225
+ [unlockWalletWithPIN, t, inlineMessages]
456
226
  )
457
227
 
458
- const displayHelpText = useCallback(() => {
228
+ const style = StyleSheet.create({
229
+ screenContainer: {
230
+ height: '100%',
231
+ padding: 20,
232
+ justifyContent: 'space-between',
233
+ backgroundColor: ColorPallet.brand.primaryBackground,
234
+ },
235
+ buttonContainer: {
236
+ width: '100%',
237
+ },
238
+ biometricsButtonContainer: {
239
+ width: '100%',
240
+ marginTop: 10,
241
+ },
242
+ biometricsText: {
243
+ alignSelf: 'center',
244
+ marginTop: 10,
245
+ },
246
+ helpText: {
247
+ alignSelf: 'auto',
248
+ textAlign: 'left',
249
+ marginBottom: 16,
250
+ },
251
+ inputLabel: {
252
+ marginBottom: 16,
253
+ },
254
+ modalText: {
255
+ marginVertical: 5,
256
+ },
257
+ subTitle: {
258
+ marginBottom: 20,
259
+ },
260
+ })
261
+
262
+ const HelpText = useMemo(() => {
263
+ const showHelpText = store.lockout.displayNotification || biometricsEnrollmentChange || biometricsErr
264
+ let header = t('PINEnter.Title')
265
+ let subheader = t('PINEnter.SubText')
459
266
  if (store.lockout.displayNotification) {
460
- return (
461
- <>
462
- <ThemedText style={style.helpText}>
463
- {t('PINEnter.LockedOut', { time: String(store.preferences.autoLockTime ?? defaultAutoLockTime) })}
464
- </ThemedText>
465
- <ThemedText style={style.helpText}>{t('PINEnter.ReEnterPIN')}</ThemedText>
466
- </>
467
- )
267
+ header = t('PINEnter.LockedOut', { time: String(store.preferences.autoLockTime ?? defaultAutoLockTime) })
268
+ subheader = t('PINEnter.ReEnterPIN')
468
269
  }
469
-
470
270
  if (biometricsEnrollmentChange) {
471
- return (
472
- <>
473
- <ThemedText style={style.helpText}>{t('PINEnter.BiometricsChanged')}</ThemedText>
474
- <ThemedText style={style.helpText}>{t('PINEnter.BiometricsChangedEnterPIN')}</ThemedText>
475
- </>
476
- )
271
+ header = t('PINEnter.BiometricsChanged')
272
+ subheader = t('PINEnter.BiometricsChangedEnterPIN')
477
273
  }
478
-
479
274
  if (biometricsErr) {
480
- return (
481
- <>
482
- <ThemedText style={style.helpText}>{t('PINEnter.BiometricsError')}</ThemedText>
483
- <ThemedText style={style.helpText}>{t('PINEnter.BiometricsErrorEnterPIN')}</ThemedText>
484
- </>
485
- )
486
- }
487
-
488
- if (usage === PINEntryUsage.PINCheck) {
489
- return <ThemedText style={style.helpText}>{t('PINEnter.AppSettingChanged')}</ThemedText>
275
+ header = t('PINEnter.BiometricsError')
276
+ subheader = t('PINEnter.BiometricsErrorEnterPIN')
490
277
  }
491
-
492
- if (usage === PINEntryUsage.ChangeBiometrics) {
493
- return (
494
- <>
495
- <ThemedText variant="headingTwo" style={style.title}>
496
- {t('PINEnter.ChangeBiometricsHeader')}
497
- </ThemedText>
498
- <ThemedText style={style.helpText}>{t('PINEnter.ChangeBiometricsSubtext')}</ThemedText>
499
- </>
500
- )
501
- }
502
-
503
278
  return (
504
279
  <>
505
- <ThemedText variant="headingTwo" style={style.title}>
506
- {t('PINEnter.Title')}
280
+ <ThemedText variant={showHelpText ? 'normal' : 'headingThree'} style={style.helpText}>
281
+ {header}
507
282
  </ThemedText>
508
- <ThemedText variant="labelSubtitle" style={style.subTitle}>
509
- {t('PINEnter.SubText')}
283
+ <ThemedText variant={showHelpText ? 'normal' : 'labelSubtitle'} style={style.helpText}>
284
+ {subheader}
510
285
  </ThemedText>
511
286
  </>
512
287
  )
513
288
  }, [
514
- store.lockout.displayNotification,
515
289
  style.helpText,
290
+ store.lockout.displayNotification,
516
291
  t,
517
292
  biometricsEnrollmentChange,
518
293
  biometricsErr,
519
- style.title,
520
- style.subTitle,
521
294
  store.preferences.autoLockTime,
522
- usage,
523
295
  ])
524
296
 
525
297
  return (
526
298
  <KeyboardView>
527
299
  <View style={style.screenContainer}>
528
- <View style={style.contentContainer}>
529
- {usage === PINEntryUsage.WalletUnlock && enableHiddenDevModeTrigger ? (
530
- <Pressable onPress={incrementDeveloperMenuCounter} testID={testIdWithKey('DeveloperCounter')}>
531
- {displayHelpText()}
532
- </Pressable>
533
- ) : (
534
- displayHelpText()
535
- )}
536
- <ThemedText variant="bold" style={style.subText}>
537
- {inputLabelText[usage]}
538
- {usage === PINEntryUsage.ChangeBiometrics && (
539
- <ThemedText style={style.parenthesisText}>
540
- {' '}
541
- {t('PINEnter.ChangeBiometricsInputLabelParenthesis')}
542
- </ThemedText>
543
- )}
300
+ <View>
301
+ <Pressable
302
+ onPress={enableHiddenDevModeTrigger ? incrementDeveloperMenuCounter : () => {}}
303
+ testID={testIdWithKey('DeveloperCounter')}
304
+ >
305
+ {HelpText}
306
+ </Pressable>
307
+ <ThemedText variant="bold" style={style.inputLabel}>
308
+ {t('PINEnter.EnterPIN')}
544
309
  </ThemedText>
545
310
  <PINInput
546
311
  onPINChanged={(p: string) => {
@@ -549,20 +314,20 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
549
314
  Keyboard.dismiss()
550
315
  }
551
316
  }}
552
- testID={testIdWithKey(inputTestId[usage])}
553
- accessibilityLabel={inputLabelText[usage]}
317
+ testID={testIdWithKey('EnterPIN')}
318
+ accessibilityLabel={t('PINEnter.EnterPIN')}
554
319
  autoFocus={true}
555
320
  inlineMessage={inlineMessageField}
556
321
  />
557
322
  </View>
558
- <View style={style.controlsContainer}>
323
+ <View>
559
324
  <View style={style.buttonContainer}>
560
325
  <Button
561
- title={primaryButtonText[usage]}
326
+ title={t('PINEnter.Unlock')}
562
327
  buttonType={ButtonType.Primary}
563
- testID={testIdWithKey(primaryButtonTestId[usage])}
564
- disabled={isContinueDisabled()}
565
- accessibilityLabel={primaryButtonText[usage]}
328
+ testID={testIdWithKey('Enter')}
329
+ disabled={isContinueDisabled}
330
+ accessibilityLabel={t('PINEnter.Unlock')}
566
331
  onPress={() => {
567
332
  Keyboard.dismiss()
568
333
  onPINInputCompleted(PIN)
@@ -571,11 +336,10 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
571
336
  {!continueEnabled && <ButtonLoading />}
572
337
  </Button>
573
338
  </View>
574
-
575
- {store.preferences.useBiometry && usage === PINEntryUsage.WalletUnlock && (
339
+ {store.preferences.useBiometry && (
576
340
  <>
577
- <ThemedText style={{ alignSelf: 'center', marginTop: 10 }}>{t('PINEnter.Or')}</ThemedText>
578
- <View style={[style.buttonContainer, { marginTop: 10 }]}>
341
+ <ThemedText style={style.biometricsText}>{t('PINEnter.Or')}</ThemedText>
342
+ <View style={style.biometricsButtonContainer}>
579
343
  <Button
580
344
  title={t('PINEnter.BiometricsUnlock')}
581
345
  buttonType={ButtonType.Secondary}
@@ -587,26 +351,14 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
587
351
  </View>
588
352
  </>
589
353
  )}
590
-
591
- {usage === PINEntryUsage.PINCheck && (
592
- <View style={[style.buttonContainer, { marginTop: 10 }]}>
593
- <Button
594
- title={t('PINEnter.AppSettingCancel')}
595
- buttonType={ButtonType.Secondary}
596
- testID={testIdWithKey('AppSettingCancel')}
597
- accessibilityLabel={t('PINEnter.AppSettingCancel')}
598
- onPress={() => onCancelAuth?.(false)}
599
- />
600
- </View>
601
- )}
602
354
  </View>
603
355
  </View>
604
- {alertModalVisible && (
356
+ {alertModalVisible ? (
605
357
  <PopupModal
606
358
  notificationType={InfoBoxType.Info}
607
359
  title={t('PINEnter.IncorrectPIN')}
608
360
  bodyContent={
609
- <View>
361
+ <>
610
362
  <ThemedText variant="popupModalText" style={style.modalText}>
611
363
  {alertModalMessage}
612
364
  </ThemedText>
@@ -615,12 +367,13 @@ const PINEnter: React.FC<PINEnterProps> = ({ setAuthenticated, usage = PINEntryU
615
367
  {t('PINEnter.AttemptLockoutWarning')}
616
368
  </ThemedText>
617
369
  ) : null}
618
- </View>
370
+ </>
619
371
  }
620
372
  onCallToActionLabel={t('Global.Okay')}
621
373
  onCallToActionPressed={clearAlertModal}
622
374
  />
623
- )}
375
+ ) : null}
376
+ {devModalVisible ? <DeveloperModal onBackPressed={onBackPressed} /> : null}
624
377
  </KeyboardView>
625
378
  )
626
379
  }