@oxyhq/services 5.13.0 → 5.13.2
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.
- package/README.md +71 -0
- package/lib/commonjs/core/HttpClient.js +238 -0
- package/lib/commonjs/core/HttpClient.js.map +1 -0
- package/lib/commonjs/core/OxyServices.js +530 -332
- package/lib/commonjs/core/OxyServices.js.map +1 -1
- package/lib/commonjs/core/RequestManager.js +199 -0
- package/lib/commonjs/core/RequestManager.js.map +1 -0
- package/lib/commonjs/core/index.js +38 -1
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/i18n/index.js +37 -1
- package/lib/commonjs/i18n/index.js.map +1 -1
- package/lib/commonjs/i18n/locales/ar-SA.json +128 -0
- package/lib/commonjs/i18n/locales/ca-ES.json +128 -0
- package/lib/commonjs/i18n/locales/de-DE.json +128 -0
- package/lib/commonjs/i18n/locales/en-US.json +85 -12
- package/lib/commonjs/i18n/locales/es-ES.json +58 -6
- package/lib/commonjs/i18n/locales/fr-FR.json +128 -0
- package/lib/commonjs/i18n/locales/it-IT.json +128 -0
- package/lib/commonjs/i18n/locales/ja-JP.json +127 -0
- package/lib/commonjs/i18n/locales/ko-KR.json +128 -0
- package/lib/commonjs/i18n/locales/pt-PT.json +128 -0
- package/lib/commonjs/i18n/locales/zh-CN.json +128 -0
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/Avatar.js +94 -27
- package/lib/commonjs/ui/components/Avatar.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +1 -0
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/FontLoader.js +22 -42
- package/lib/commonjs/ui/components/FontLoader.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +5 -8
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/StepBasedScreen.js +64 -44
- package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +14 -35
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/commonjs/ui/components/internal/PinInput.js +2 -2
- package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
- package/lib/commonjs/ui/components/internal/TextField.js +13 -8
- package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +443 -371
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +80 -22
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/index.js +4 -1
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +32 -2
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +101 -59
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -2
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +75 -117
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +43 -50
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +14 -16
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +188 -142
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +10 -10
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +2 -4
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +45 -25
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +88 -53
- package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +79 -58
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +61 -52
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +218 -39
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +77 -50
- package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +424 -71
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +55 -30
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +64 -46
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +84 -146
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +113 -34
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
- package/lib/commonjs/ui/stores/accountStore.js +237 -0
- package/lib/commonjs/ui/stores/accountStore.js.map +1 -0
- package/lib/commonjs/ui/stores/authStore.js +17 -20
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/styles/authStyles.js +16 -8
- package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
- package/lib/commonjs/ui/styles/index.js +11 -0
- package/lib/commonjs/ui/styles/index.js.map +1 -1
- package/lib/commonjs/ui/styles/spacing.js +51 -0
- package/lib/commonjs/ui/styles/spacing.js.map +1 -0
- package/lib/commonjs/utils/asyncUtils.js +9 -22
- package/lib/commonjs/utils/asyncUtils.js.map +1 -1
- package/lib/commonjs/utils/cache.js +259 -0
- package/lib/commonjs/utils/cache.js.map +1 -0
- package/lib/commonjs/utils/index.js +99 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/utils/languageUtils.js +159 -0
- package/lib/commonjs/utils/languageUtils.js.map +1 -0
- package/lib/commonjs/utils/requestUtils.js +217 -0
- package/lib/commonjs/utils/requestUtils.js.map +1 -0
- package/lib/commonjs/utils/sessionUtils.js +191 -0
- package/lib/commonjs/utils/sessionUtils.js.map +1 -0
- package/lib/commonjs/utils/validationUtils.js +1 -1
- package/lib/module/core/HttpClient.js +232 -0
- package/lib/module/core/HttpClient.js.map +1 -0
- package/lib/module/core/OxyServices.js +528 -326
- package/lib/module/core/OxyServices.js.map +1 -1
- package/lib/module/core/RequestManager.js +194 -0
- package/lib/module/core/RequestManager.js.map +1 -0
- package/lib/module/core/index.js +2 -0
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/i18n/index.js +37 -1
- package/lib/module/i18n/index.js.map +1 -1
- package/lib/module/i18n/locales/ar-SA.json +128 -0
- package/lib/module/i18n/locales/ca-ES.json +128 -0
- package/lib/module/i18n/locales/de-DE.json +128 -0
- package/lib/module/i18n/locales/en-US.json +85 -12
- package/lib/module/i18n/locales/es-ES.json +58 -6
- package/lib/module/i18n/locales/fr-FR.json +128 -0
- package/lib/module/i18n/locales/it-IT.json +128 -0
- package/lib/module/i18n/locales/ja-JP.json +127 -0
- package/lib/module/i18n/locales/ko-KR.json +128 -0
- package/lib/module/i18n/locales/pt-PT.json +128 -0
- package/lib/module/i18n/locales/zh-CN.json +128 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/Avatar.js +94 -27
- package/lib/module/ui/components/Avatar.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +1 -0
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/FontLoader.js +23 -43
- package/lib/module/ui/components/FontLoader.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +6 -8
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/StepBasedScreen.js +65 -45
- package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js +14 -35
- package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/module/ui/components/internal/PinInput.js +2 -2
- package/lib/module/ui/components/internal/PinInput.js.map +1 -1
- package/lib/module/ui/components/internal/TextField.js +13 -8
- package/lib/module/ui/components/internal/TextField.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +442 -370
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +80 -22
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/index.js +4 -2
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +33 -2
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +102 -60
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +3 -2
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +73 -117
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +44 -51
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +14 -16
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +187 -143
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInPasswordStep.js +10 -10
- package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInUsernameStep.js +2 -4
- package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverRequestStep.js +45 -25
- package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +89 -54
- package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js +80 -59
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js +62 -53
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInPasswordStep.js +219 -40
- package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInTotpStep.js +78 -51
- package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInUsernameStep.js +426 -73
- package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js +55 -30
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js +65 -47
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js +84 -146
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +114 -35
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
- package/lib/module/ui/stores/accountStore.js +229 -0
- package/lib/module/ui/stores/accountStore.js.map +1 -0
- package/lib/module/ui/stores/authStore.js +17 -20
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/styles/authStyles.js +16 -8
- package/lib/module/ui/styles/authStyles.js.map +1 -1
- package/lib/module/ui/styles/index.js +1 -0
- package/lib/module/ui/styles/index.js.map +1 -1
- package/lib/module/ui/styles/spacing.js +48 -0
- package/lib/module/ui/styles/spacing.js.map +1 -0
- package/lib/module/utils/asyncUtils.js +10 -22
- package/lib/module/utils/asyncUtils.js.map +1 -1
- package/lib/module/utils/cache.js +250 -0
- package/lib/module/utils/cache.js.map +1 -0
- package/lib/module/utils/index.js +7 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/languageUtils.js +151 -0
- package/lib/module/utils/languageUtils.js.map +1 -0
- package/lib/module/utils/requestUtils.js +210 -0
- package/lib/module/utils/requestUtils.js.map +1 -0
- package/lib/module/utils/sessionUtils.js +180 -0
- package/lib/module/utils/sessionUtils.js.map +1 -0
- package/lib/module/utils/validationUtils.js +1 -1
- package/lib/typescript/core/HttpClient.d.ts +64 -0
- package/lib/typescript/core/HttpClient.d.ts.map +1 -0
- package/lib/typescript/core/OxyServices.d.ts +86 -73
- package/lib/typescript/core/OxyServices.d.ts.map +1 -1
- package/lib/typescript/core/RequestManager.d.ts +67 -0
- package/lib/typescript/core/RequestManager.d.ts.map +1 -0
- package/lib/typescript/core/index.d.ts +2 -0
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/i18n/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +15 -0
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/models/session.d.ts +1 -0
- package/lib/typescript/models/session.d.ts.map +1 -1
- package/lib/typescript/ui/components/Avatar.d.ts +6 -7
- package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
- package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/ui/components/FontLoader.d.ts +3 -3
- package/lib/typescript/ui/components/FontLoader.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts +2 -2
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +5 -0
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +2 -2
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts +3 -3
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +2 -0
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
- package/lib/typescript/ui/stores/accountStore.d.ts +34 -0
- package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -0
- package/lib/typescript/ui/stores/authStore.d.ts +7 -3
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/styles/authStyles.d.ts +19 -2
- package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
- package/lib/typescript/ui/styles/index.d.ts +1 -0
- package/lib/typescript/ui/styles/index.d.ts.map +1 -1
- package/lib/typescript/ui/styles/spacing.d.ts +43 -0
- package/lib/typescript/ui/styles/spacing.d.ts.map +1 -0
- package/lib/typescript/utils/asyncUtils.d.ts +2 -0
- package/lib/typescript/utils/asyncUtils.d.ts.map +1 -1
- package/lib/typescript/utils/cache.d.ts +128 -0
- package/lib/typescript/utils/cache.d.ts.map +1 -0
- package/lib/typescript/utils/index.d.ts +4 -0
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/lib/typescript/utils/languageUtils.d.ts +38 -0
- package/lib/typescript/utils/languageUtils.d.ts.map +1 -0
- package/lib/typescript/utils/requestUtils.d.ts +122 -0
- package/lib/typescript/utils/requestUtils.d.ts.map +1 -0
- package/lib/typescript/utils/sessionUtils.d.ts +55 -0
- package/lib/typescript/utils/sessionUtils.d.ts.map +1 -0
- package/lib/typescript/utils/validationUtils.d.ts +1 -1
- package/package.json +1 -1
- package/src/core/HttpClient.ts +277 -0
- package/src/core/OxyServices.ts +461 -352
- package/src/core/RequestManager.ts +240 -0
- package/src/core/index.ts +10 -0
- package/src/i18n/index.ts +36 -0
- package/src/i18n/locales/ar-SA.json +128 -0
- package/src/i18n/locales/ca-ES.json +128 -0
- package/src/i18n/locales/de-DE.json +128 -0
- package/src/i18n/locales/en-US.json +85 -12
- package/src/i18n/locales/es-ES.json +58 -6
- package/src/i18n/locales/fr-FR.json +128 -0
- package/src/i18n/locales/it-IT.json +128 -0
- package/src/i18n/locales/ja-JP.json +127 -0
- package/src/i18n/locales/ko-KR.json +128 -0
- package/src/i18n/locales/pt-PT.json +128 -0
- package/src/i18n/locales/zh-CN.json +128 -0
- package/src/index.ts +10 -0
- package/src/models/interfaces.ts +19 -0
- package/src/models/session.ts +1 -1
- package/src/ui/components/Avatar.tsx +151 -35
- package/src/ui/components/FollowButton.tsx +1 -0
- package/src/ui/components/FontLoader.tsx +17 -37
- package/src/ui/components/OxyProvider.tsx +14 -13
- package/src/ui/components/StepBasedScreen.tsx +66 -43
- package/src/ui/components/internal/GroupedPillButtons.tsx +15 -31
- package/src/ui/components/internal/PinInput.tsx +2 -2
- package/src/ui/components/internal/TextField.tsx +7 -6
- package/src/ui/context/OxyContext.tsx +441 -326
- package/src/ui/hooks/useSessionSocket.ts +72 -18
- package/src/ui/index.ts +4 -1
- package/src/ui/screens/AccountSettingsScreen.tsx +34 -2
- package/src/ui/screens/AccountSwitcherScreen.tsx +102 -68
- package/src/ui/screens/FileManagementScreen.tsx +16 -16
- package/src/ui/screens/LanguageSelectorScreen.tsx +86 -143
- package/src/ui/screens/SignInScreen.tsx +59 -43
- package/src/ui/screens/SignUpScreen.tsx +14 -15
- package/src/ui/screens/WelcomeNewUserScreen.tsx +153 -105
- package/src/ui/screens/internal/SignInPasswordStep.tsx +4 -6
- package/src/ui/screens/internal/SignInUsernameStep.tsx +1 -1
- package/src/ui/screens/steps/RecoverRequestStep.tsx +34 -24
- package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +65 -36
- package/src/ui/screens/steps/RecoverSuccessStep.tsx +71 -47
- package/src/ui/screens/steps/RecoverVerifyStep.tsx +60 -50
- package/src/ui/screens/steps/SignInPasswordStep.tsx +190 -32
- package/src/ui/screens/steps/SignInTotpStep.tsx +68 -34
- package/src/ui/screens/steps/SignInUsernameStep.tsx +446 -63
- package/src/ui/screens/steps/SignUpIdentityStep.tsx +49 -35
- package/src/ui/screens/steps/SignUpSecurityStep.tsx +56 -39
- package/src/ui/screens/steps/SignUpSummaryStep.tsx +99 -89
- package/src/ui/screens/steps/SignUpWelcomeStep.tsx +88 -20
- package/src/ui/stores/accountStore.ts +285 -0
- package/src/ui/stores/authStore.ts +16 -19
- package/src/ui/styles/authStyles.ts +16 -8
- package/src/ui/styles/index.ts +1 -0
- package/src/ui/styles/spacing.ts +46 -0
- package/src/utils/asyncUtils.ts +10 -24
- package/src/utils/cache.ts +264 -0
- package/src/utils/index.ts +19 -0
- package/src/utils/languageUtils.ts +174 -0
- package/src/utils/requestUtils.ts +234 -0
- package/src/utils/sessionUtils.ts +206 -0
- package/src/utils/validationUtils.ts +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useState } from 'react';
|
|
1
|
+
import React, { useState, useMemo, useCallback } from 'react';
|
|
3
2
|
import {
|
|
4
3
|
View,
|
|
5
4
|
Text,
|
|
@@ -15,101 +14,18 @@ import { Ionicons } from '@expo/vector-icons';
|
|
|
15
14
|
import { toast } from '../../lib/sonner';
|
|
16
15
|
import { Header, Section, GroupedSection } from '../components';
|
|
17
16
|
import { useI18n } from '../hooks/useI18n';
|
|
18
|
-
|
|
19
|
-
// Supported languages with their metadata
|
|
20
|
-
const SUPPORTED_LANGUAGES = [
|
|
21
|
-
{
|
|
22
|
-
id: 'en-US',
|
|
23
|
-
name: 'English',
|
|
24
|
-
nativeName: 'English',
|
|
25
|
-
flag: '🇺🇸',
|
|
26
|
-
icon: 'language-outline',
|
|
27
|
-
color: '#007AFF',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
id: 'es-ES',
|
|
31
|
-
name: 'Spanish',
|
|
32
|
-
nativeName: 'Español',
|
|
33
|
-
flag: '🇪🇸',
|
|
34
|
-
icon: 'language-outline',
|
|
35
|
-
color: '#FF3B30',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: 'ca-ES',
|
|
39
|
-
name: 'Catalan',
|
|
40
|
-
nativeName: 'Català',
|
|
41
|
-
flag: '🇪🇸',
|
|
42
|
-
icon: 'language-outline',
|
|
43
|
-
color: '#0CA678',
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
id: 'fr-FR',
|
|
47
|
-
name: 'French',
|
|
48
|
-
nativeName: 'Français',
|
|
49
|
-
flag: '🇫🇷',
|
|
50
|
-
icon: 'language-outline',
|
|
51
|
-
color: '#5856D6',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
id: 'de-DE',
|
|
55
|
-
name: 'German',
|
|
56
|
-
nativeName: 'Deutsch',
|
|
57
|
-
flag: '🇩🇪',
|
|
58
|
-
icon: 'language-outline',
|
|
59
|
-
color: '#FF9500',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
id: 'it-IT',
|
|
63
|
-
name: 'Italian',
|
|
64
|
-
nativeName: 'Italiano',
|
|
65
|
-
flag: '🇮🇹',
|
|
66
|
-
icon: 'language-outline',
|
|
67
|
-
color: '#34C759',
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: 'pt-PT',
|
|
71
|
-
name: 'Portuguese',
|
|
72
|
-
nativeName: 'Português',
|
|
73
|
-
flag: '🇵🇹',
|
|
74
|
-
icon: 'language-outline',
|
|
75
|
-
color: '#AF52DE',
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
id: 'ja-JP',
|
|
79
|
-
name: 'Japanese',
|
|
80
|
-
nativeName: '日本語',
|
|
81
|
-
flag: '🇯🇵',
|
|
82
|
-
icon: 'language-outline',
|
|
83
|
-
color: '#FF2D92',
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: 'ko-KR',
|
|
87
|
-
name: 'Korean',
|
|
88
|
-
nativeName: '한국어',
|
|
89
|
-
flag: '🇰🇷',
|
|
90
|
-
icon: 'language-outline',
|
|
91
|
-
color: '#32D74B',
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
id: 'zh-CN',
|
|
95
|
-
name: 'Chinese',
|
|
96
|
-
nativeName: '中文',
|
|
97
|
-
flag: '🇨🇳',
|
|
98
|
-
icon: 'language-outline',
|
|
99
|
-
color: '#FF9F0A',
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: 'ar-SA',
|
|
103
|
-
name: 'Arabic',
|
|
104
|
-
nativeName: 'العربية',
|
|
105
|
-
flag: '🇸🇦',
|
|
106
|
-
icon: 'language-outline',
|
|
107
|
-
color: '#30B0C7',
|
|
108
|
-
},
|
|
109
|
-
];
|
|
17
|
+
import { SUPPORTED_LANGUAGES } from '../../utils/languageUtils';
|
|
110
18
|
|
|
111
19
|
interface LanguageSelectorScreenProps extends BaseScreenProps { }
|
|
112
20
|
|
|
21
|
+
/**
|
|
22
|
+
* LanguageSelectorScreen - Optimized for performance
|
|
23
|
+
*
|
|
24
|
+
* Performance optimizations:
|
|
25
|
+
* - useMemo for language items to prevent recreation on every render
|
|
26
|
+
* - useCallback for handlers to prevent unnecessary re-renders
|
|
27
|
+
* - Memoized current language section
|
|
28
|
+
*/
|
|
113
29
|
const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
|
|
114
30
|
goBack,
|
|
115
31
|
onClose,
|
|
@@ -121,20 +37,27 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
|
|
|
121
37
|
const colors = useThemeColors(theme);
|
|
122
38
|
const [isLoading, setIsLoading] = useState(false);
|
|
123
39
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
40
|
+
// Memoize the language select handler to prevent recreation on every render
|
|
41
|
+
const handleLanguageSelect = useCallback(async (languageId: string) => {
|
|
42
|
+
if (languageId === currentLanguage || isLoading) {
|
|
43
|
+
return; // Already selected or loading
|
|
127
44
|
}
|
|
128
45
|
|
|
129
46
|
setIsLoading(true);
|
|
130
47
|
|
|
131
48
|
try {
|
|
49
|
+
let serverSyncFailed = false;
|
|
50
|
+
|
|
132
51
|
// If signed in, persist preference to backend user settings
|
|
133
52
|
if (isAuthenticated && user?.id) {
|
|
134
53
|
try {
|
|
135
54
|
await oxyServices.updateProfile({ language: languageId });
|
|
136
55
|
} catch (e: any) {
|
|
137
|
-
|
|
56
|
+
// Server sync failed, but we'll save locally anyway
|
|
57
|
+
serverSyncFailed = true;
|
|
58
|
+
if (__DEV__) {
|
|
59
|
+
console.warn('Failed to sync language to server (will save locally only):', e?.message || e);
|
|
60
|
+
}
|
|
138
61
|
}
|
|
139
62
|
}
|
|
140
63
|
|
|
@@ -142,34 +65,71 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
|
|
|
142
65
|
await setLanguage(languageId);
|
|
143
66
|
|
|
144
67
|
const selectedLang = SUPPORTED_LANGUAGES.find(lang => lang.id === languageId);
|
|
68
|
+
|
|
69
|
+
// Show success message (language is saved locally regardless of server sync)
|
|
145
70
|
toast.success(t('language.changed', { lang: selectedLang?.name || languageId }));
|
|
71
|
+
|
|
72
|
+
// Log server sync failure only in dev mode (user experience is still good - saved locally)
|
|
73
|
+
if (serverSyncFailed && __DEV__) {
|
|
74
|
+
console.warn('Language saved locally but server sync failed');
|
|
75
|
+
}
|
|
146
76
|
|
|
147
77
|
setIsLoading(false);
|
|
148
78
|
// Close the bottom sheet if possible; otherwise, go back
|
|
149
79
|
if (onClose) onClose(); else goBack();
|
|
150
80
|
|
|
151
81
|
} catch (error) {
|
|
82
|
+
// Only show error if local storage also failed
|
|
152
83
|
console.error('Error saving language preference:', error);
|
|
153
84
|
toast.error('Failed to save language preference');
|
|
154
85
|
setIsLoading(false);
|
|
155
86
|
}
|
|
156
|
-
};
|
|
87
|
+
}, [currentLanguage, isLoading, isAuthenticated, user?.id, oxyServices, setLanguage, t, onClose, goBack]);
|
|
88
|
+
|
|
89
|
+
// Memoize language items to prevent recreation on every render
|
|
90
|
+
const languageItems = useMemo(() =>
|
|
91
|
+
SUPPORTED_LANGUAGES.map(language => ({
|
|
92
|
+
id: language.id,
|
|
93
|
+
title: language.name,
|
|
94
|
+
subtitle: language.nativeName,
|
|
95
|
+
customIcon: (
|
|
96
|
+
<View style={[styles.languageFlag, { backgroundColor: `${language.color}20` }]}>
|
|
97
|
+
<Text style={styles.flagEmoji}>{language.flag}</Text>
|
|
98
|
+
</View>
|
|
99
|
+
),
|
|
100
|
+
iconColor: language.color,
|
|
101
|
+
selected: currentLanguage === language.id,
|
|
102
|
+
onPress: () => handleLanguageSelect(language.id),
|
|
103
|
+
dense: true,
|
|
104
|
+
})),
|
|
105
|
+
[currentLanguage, handleLanguageSelect]
|
|
106
|
+
);
|
|
157
107
|
|
|
158
|
-
//
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
108
|
+
// Memoize current language data to prevent recalculation
|
|
109
|
+
const currentLanguageData = useMemo(() => {
|
|
110
|
+
if (!currentLanguage) return null;
|
|
111
|
+
return SUPPORTED_LANGUAGES.find(lang => lang.id === currentLanguage);
|
|
112
|
+
}, [currentLanguage]);
|
|
113
|
+
|
|
114
|
+
// Memoize current language section items
|
|
115
|
+
const currentLanguageItems = useMemo(() => {
|
|
116
|
+
if (!currentLanguageData) return [];
|
|
117
|
+
return [{
|
|
118
|
+
id: `current-${currentLanguageData.id}`,
|
|
119
|
+
title: currentLanguageData.name,
|
|
120
|
+
subtitle: currentLanguageData.nativeName,
|
|
121
|
+
customIcon: (
|
|
122
|
+
<View style={[styles.languageFlag, { backgroundColor: `${currentLanguageData.color}20` }]}>
|
|
123
|
+
<Text style={styles.flagEmoji}>{currentLanguageData.flag}</Text>
|
|
124
|
+
</View>
|
|
125
|
+
),
|
|
126
|
+
iconColor: currentLanguageData.color,
|
|
127
|
+
selected: false,
|
|
128
|
+
showChevron: false,
|
|
129
|
+
dense: true,
|
|
130
|
+
disabled: true,
|
|
131
|
+
}];
|
|
132
|
+
}, [currentLanguageData]);
|
|
173
133
|
|
|
174
134
|
return (
|
|
175
135
|
<View style={[styles.container, { backgroundColor: '#f2f2f2' }]}>
|
|
@@ -182,36 +142,18 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
|
|
|
182
142
|
elevation="subtle"
|
|
183
143
|
/>
|
|
184
144
|
|
|
185
|
-
<ScrollView
|
|
145
|
+
<ScrollView
|
|
146
|
+
style={styles.content}
|
|
147
|
+
showsVerticalScrollIndicator={false}
|
|
148
|
+
removeClippedSubviews={true}
|
|
149
|
+
>
|
|
186
150
|
{/* Current selection */}
|
|
187
|
-
{currentLanguage && (
|
|
151
|
+
{currentLanguage && currentLanguageItems.length > 0 && (
|
|
188
152
|
<Section title={t('language.current')} theme={theme} isFirst={true}>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
<GroupedSection
|
|
194
|
-
items={[
|
|
195
|
-
{
|
|
196
|
-
id: `current-${current.id}`,
|
|
197
|
-
title: current.name,
|
|
198
|
-
subtitle: current.nativeName,
|
|
199
|
-
customIcon: (
|
|
200
|
-
<View style={[styles.languageFlag, { backgroundColor: `${current.color}20` }]}>
|
|
201
|
-
<Text style={styles.flagEmoji}>{current.flag}</Text>
|
|
202
|
-
</View>
|
|
203
|
-
),
|
|
204
|
-
iconColor: current.color,
|
|
205
|
-
selected: false,
|
|
206
|
-
showChevron: false,
|
|
207
|
-
dense: true,
|
|
208
|
-
disabled: true,
|
|
209
|
-
},
|
|
210
|
-
]}
|
|
211
|
-
theme={theme}
|
|
212
|
-
/>
|
|
213
|
-
);
|
|
214
|
-
})()}
|
|
153
|
+
<GroupedSection
|
|
154
|
+
items={currentLanguageItems}
|
|
155
|
+
theme={theme}
|
|
156
|
+
/>
|
|
215
157
|
</Section>
|
|
216
158
|
)}
|
|
217
159
|
|
|
@@ -348,4 +290,5 @@ const styles = StyleSheet.create({
|
|
|
348
290
|
},
|
|
349
291
|
});
|
|
350
292
|
|
|
351
|
-
|
|
293
|
+
// Export memoized component to prevent unnecessary re-renders
|
|
294
|
+
export default React.memo(LanguageSelectorScreen);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
-
import { useState,
|
|
2
|
+
import { useState, useMemo, useCallback } from 'react';
|
|
3
3
|
import type { BaseScreenProps } from '../navigation/types';
|
|
4
4
|
import { useOxy } from '../context/OxyContext';
|
|
5
5
|
import { useThemeColors } from '../styles';
|
|
@@ -29,18 +29,9 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
29
29
|
const [validationStatus, setValidationStatus] = useState<'idle' | 'validating' | 'valid' | 'invalid'>(
|
|
30
30
|
initialUserProfile ? 'valid' : 'idle'
|
|
31
31
|
);
|
|
32
|
+
const [existingSession, setExistingSession] = useState<any>(null);
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
const validationCache = useRef<Map<string, { profile: any }>>(new Map());
|
|
35
|
-
|
|
36
|
-
const { login, completeMfaLogin, isLoading, user, isAuthenticated, sessions, oxyServices } = useOxy();
|
|
37
|
-
|
|
38
|
-
// Only log props in development mode to reduce console noise
|
|
39
|
-
if (__DEV__) {
|
|
40
|
-
console.log('SignInScreen props:', { initialStep, initialUsername, initialUserProfile });
|
|
41
|
-
console.log('🔧 oxyServices available:', !!oxyServices);
|
|
42
|
-
console.log('🔧 getProfileByUsername available:', typeof oxyServices?.getProfileByUsername);
|
|
43
|
-
}
|
|
34
|
+
const { login, completeMfaLogin, isLoading, user, isAuthenticated, sessions, oxyServices, switchSession } = useOxy();
|
|
44
35
|
const colors = useThemeColors(theme);
|
|
45
36
|
|
|
46
37
|
// Check if this should be treated as "Add Account" mode
|
|
@@ -68,14 +59,13 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
68
59
|
return false;
|
|
69
60
|
}
|
|
70
61
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
if (__DEV__) console.log('
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return true;
|
|
62
|
+
const offlineDetected = typeof navigator !== 'undefined' && navigator.onLine === false;
|
|
63
|
+
|
|
64
|
+
if (offlineDetected) {
|
|
65
|
+
if (__DEV__) console.log('⚠️ Offline detected, skipping username validation');
|
|
66
|
+
setValidationStatus('invalid');
|
|
67
|
+
setErrorMessage('No connection. Check your internet connection and try again.');
|
|
68
|
+
return false;
|
|
79
69
|
}
|
|
80
70
|
|
|
81
71
|
if (__DEV__) console.log('🔄 Validating username with API...');
|
|
@@ -97,14 +87,24 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
97
87
|
|
|
98
88
|
if (__DEV__) console.log('✅ Username is valid:', profileData);
|
|
99
89
|
setUserProfile(profileData);
|
|
90
|
+
|
|
91
|
+
// Check if this account is already signed in
|
|
92
|
+
const profileUserId = profile.id?.toString();
|
|
93
|
+
const existing = sessions?.find(s => {
|
|
94
|
+
const sessionUserId = s.userId?.toString();
|
|
95
|
+
return sessionUserId === profileUserId;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (existing) {
|
|
99
|
+
setExistingSession(existing);
|
|
100
|
+
if (__DEV__) console.log('✅ Account already signed in:', existing);
|
|
101
|
+
} else {
|
|
102
|
+
setExistingSession(null);
|
|
103
|
+
}
|
|
104
|
+
|
|
100
105
|
setValidationStatus('valid');
|
|
101
106
|
setErrorMessage('');
|
|
102
107
|
|
|
103
|
-
// Cache the result
|
|
104
|
-
validationCache.current.set(usernameToValidate, {
|
|
105
|
-
profile: profileData
|
|
106
|
-
});
|
|
107
|
-
|
|
108
108
|
return true;
|
|
109
109
|
} else {
|
|
110
110
|
if (__DEV__) console.log('❌ Username not found');
|
|
@@ -116,25 +116,29 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
116
116
|
if (__DEV__) console.log('🚨 Validation error:', error);
|
|
117
117
|
|
|
118
118
|
// If user not found (404), username doesn't exist
|
|
119
|
-
if (error
|
|
119
|
+
if (error?.status === 404 || error?.code === 'USER_NOT_FOUND') {
|
|
120
120
|
console.log('❌ Username not found (404)');
|
|
121
121
|
setValidationStatus('invalid');
|
|
122
122
|
setErrorMessage('Username not found.');
|
|
123
123
|
return false;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
const isNetworkError =
|
|
127
|
+
error?.status === 0 ||
|
|
128
|
+
error?.code === 'ECONNABORTED' ||
|
|
129
|
+
error?.code === 'ERR_NETWORK' ||
|
|
130
|
+
error?.message?.toLowerCase?.().includes('network request failed') ||
|
|
131
|
+
error?.message?.toLowerCase?.().includes('network error') ||
|
|
132
|
+
error?.name === 'AbortError' ||
|
|
133
|
+
error?.type === 'network';
|
|
133
134
|
|
|
134
|
-
// For other errors, show generic message
|
|
135
135
|
console.error('Username validation error:', error);
|
|
136
136
|
setValidationStatus('invalid');
|
|
137
|
-
setErrorMessage(
|
|
137
|
+
setErrorMessage(
|
|
138
|
+
isNetworkError
|
|
139
|
+
? 'No connection. Check your internet connection and try again.'
|
|
140
|
+
: 'Unable to validate username. Please try again.'
|
|
141
|
+
);
|
|
138
142
|
return false;
|
|
139
143
|
} finally {
|
|
140
144
|
setIsValidating(false);
|
|
@@ -177,6 +181,22 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
177
181
|
|
|
178
182
|
const [mfaToken, setMfaToken] = useState<string | null>(null);
|
|
179
183
|
|
|
184
|
+
const handleContinueWithExistingAccount = useCallback(async () => {
|
|
185
|
+
if (!existingSession) return;
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
setErrorMessage('');
|
|
189
|
+
await switchSession(existingSession.sessionId);
|
|
190
|
+
// Get the user for the authenticated callback
|
|
191
|
+
const currentUser = await oxyServices.getUserBySession(existingSession.sessionId);
|
|
192
|
+
if (onAuthenticated) {
|
|
193
|
+
onAuthenticated(currentUser);
|
|
194
|
+
}
|
|
195
|
+
} catch (error: any) {
|
|
196
|
+
setErrorMessage(error.message || 'Failed to switch account');
|
|
197
|
+
}
|
|
198
|
+
}, [existingSession, switchSession, oxyServices, onAuthenticated]);
|
|
199
|
+
|
|
180
200
|
const handleSignIn = useCallback(async () => {
|
|
181
201
|
if (!password) {
|
|
182
202
|
setErrorMessage('Please enter your password.');
|
|
@@ -186,6 +206,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
186
206
|
setErrorMessage('Please enter a valid username first.');
|
|
187
207
|
return;
|
|
188
208
|
}
|
|
209
|
+
|
|
189
210
|
try {
|
|
190
211
|
setErrorMessage('');
|
|
191
212
|
const user = await login(username, password);
|
|
@@ -201,13 +222,6 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
201
222
|
}
|
|
202
223
|
}, [username, password, login, onAuthenticated, userProfile]);
|
|
203
224
|
|
|
204
|
-
// Simple cleanup on unmount - that's all we need for username validation
|
|
205
|
-
useEffect(() => {
|
|
206
|
-
return () => {
|
|
207
|
-
validationCache.current.clear();
|
|
208
|
-
};
|
|
209
|
-
}, []);
|
|
210
|
-
|
|
211
225
|
// Step configurations
|
|
212
226
|
const steps: StepConfig[] = useMemo(() => {
|
|
213
227
|
const base: StepConfig[] = [
|
|
@@ -259,6 +273,8 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
259
273
|
handleInputBlur,
|
|
260
274
|
handleSignIn, // Add sign-in function for password step
|
|
261
275
|
mfaToken,
|
|
276
|
+
existingSession,
|
|
277
|
+
handleContinueWithExistingAccount,
|
|
262
278
|
},
|
|
263
279
|
...(mfaToken ? [{
|
|
264
280
|
username,
|
|
@@ -272,7 +288,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
272
288
|
username, password, errorMessage, validationStatus, userProfile, mfaToken,
|
|
273
289
|
isValidating, isInputFocused, isAddAccountMode, user, showPassword,
|
|
274
290
|
isLoading, handleUsernameChange, handlePasswordChange, handleInputFocus, handleInputBlur,
|
|
275
|
-
validateUsername, handleSignIn, completeMfaLogin
|
|
291
|
+
validateUsername, handleSignIn, completeMfaLogin, existingSession, handleContinueWithExistingAccount
|
|
276
292
|
]);
|
|
277
293
|
|
|
278
294
|
return (
|
|
@@ -9,6 +9,7 @@ import SignUpWelcomeStep from './steps/SignUpWelcomeStep';
|
|
|
9
9
|
import SignUpIdentityStep from './steps/SignUpIdentityStep';
|
|
10
10
|
import SignUpSecurityStep from './steps/SignUpSecurityStep';
|
|
11
11
|
import SignUpSummaryStep from './steps/SignUpSummaryStep';
|
|
12
|
+
import { TTLCache, registerCacheForCleanup } from '../../utils/cache';
|
|
12
13
|
|
|
13
14
|
// Types for better type safety
|
|
14
15
|
interface ValidationState {
|
|
@@ -51,8 +52,16 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
|
|
|
51
52
|
// Error message state
|
|
52
53
|
const [errorMessage, setErrorMessage] = useState('');
|
|
53
54
|
|
|
54
|
-
// Username validation with caching
|
|
55
|
-
const usernameCache = useRef<
|
|
55
|
+
// Username validation with caching - uses centralized cache
|
|
56
|
+
const usernameCache = useRef(new TTLCache<boolean>(5 * 60 * 1000)); // 5 minutes cache
|
|
57
|
+
|
|
58
|
+
// Register cache for cleanup on mount
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
registerCacheForCleanup(usernameCache.current);
|
|
61
|
+
return () => {
|
|
62
|
+
usernameCache.current.clear();
|
|
63
|
+
};
|
|
64
|
+
}, []);
|
|
56
65
|
|
|
57
66
|
const validateUsername = useCallback(async (usernameToValidate: string): Promise<boolean> => {
|
|
58
67
|
if (!usernameToValidate || usernameToValidate.length < USERNAME_MIN_LENGTH) {
|
|
@@ -62,9 +71,8 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
|
|
|
62
71
|
|
|
63
72
|
// Check cache first
|
|
64
73
|
const cached = usernameCache.current.get(usernameToValidate);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const isValid = cached.available;
|
|
74
|
+
if (cached !== null) {
|
|
75
|
+
const isValid = cached;
|
|
68
76
|
setValidationState({
|
|
69
77
|
status: isValid ? 'valid' : 'invalid',
|
|
70
78
|
message: isValid ? '' : 'Username is already taken'
|
|
@@ -79,10 +87,7 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
|
|
|
79
87
|
const isValid = result.available;
|
|
80
88
|
|
|
81
89
|
// Cache the result
|
|
82
|
-
usernameCache.current.set(usernameToValidate,
|
|
83
|
-
available: isValid,
|
|
84
|
-
timestamp: now
|
|
85
|
-
});
|
|
90
|
+
usernameCache.current.set(usernameToValidate, isValid);
|
|
86
91
|
|
|
87
92
|
setValidationState({
|
|
88
93
|
status: isValid ? 'valid' : 'invalid',
|
|
@@ -146,12 +151,6 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
|
|
|
146
151
|
}
|
|
147
152
|
}, [username, email, password, confirmPassword, validateEmail, validatePassword, signUp, navigate]);
|
|
148
153
|
|
|
149
|
-
// Cleanup cache on unmount
|
|
150
|
-
useEffect(() => {
|
|
151
|
-
return () => {
|
|
152
|
-
usernameCache.current.clear();
|
|
153
|
-
};
|
|
154
|
-
}, []);
|
|
155
154
|
|
|
156
155
|
// Step configurations
|
|
157
156
|
const steps: StepConfig[] = useMemo(() => [
|