@oxyhq/services 5.17.17 → 5.17.18
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 +32 -38
- package/lib/commonjs/core/CrossDomainAuth.js +277 -0
- package/lib/commonjs/core/CrossDomainAuth.js.map +1 -0
- package/lib/commonjs/core/HttpService.js +82 -15
- package/lib/commonjs/core/HttpService.js.map +1 -1
- package/lib/commonjs/core/OxyServices.base.js +11 -3
- package/lib/commonjs/core/OxyServices.base.js.map +1 -1
- package/lib/commonjs/core/OxyServices.js +4 -1
- package/lib/commonjs/core/OxyServices.js.map +1 -1
- package/lib/commonjs/core/index.js +30 -0
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.assets.js +16 -3
- package/lib/commonjs/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.auth.js +73 -32
- package/lib/commonjs/core/mixins/OxyServices.auth.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.fedcm.js +289 -0
- package/lib/commonjs/core/mixins/OxyServices.fedcm.js.map +1 -0
- package/lib/commonjs/core/mixins/OxyServices.popup.js +352 -0
- package/lib/commonjs/core/mixins/OxyServices.popup.js.map +1 -0
- package/lib/commonjs/core/mixins/OxyServices.redirect.js +378 -0
- package/lib/commonjs/core/mixins/OxyServices.redirect.js.map +1 -0
- package/lib/commonjs/core/mixins/OxyServices.user.js +35 -24
- package/lib/commonjs/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/commonjs/core/mixins/index.js +27 -15
- package/lib/commonjs/core/mixins/index.js.map +1 -1
- package/lib/commonjs/crypto/index.js +30 -0
- package/lib/commonjs/crypto/index.js.map +1 -1
- package/lib/commonjs/crypto/keyManager.js +902 -0
- package/lib/commonjs/crypto/keyManager.js.map +1 -0
- package/lib/commonjs/crypto/polyfill.js +14 -5
- package/lib/commonjs/crypto/polyfill.js.map +1 -1
- package/lib/commonjs/crypto/recoveryPhrase.js +152 -0
- package/lib/commonjs/crypto/recoveryPhrase.js.map +1 -0
- package/lib/commonjs/crypto/signatureService.js +289 -0
- package/lib/commonjs/crypto/signatureService.js.map +1 -0
- package/lib/commonjs/i18n/locales/en-US.json +1 -1
- package/lib/commonjs/index.js +40 -26
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/interfaces.js +0 -15
- package/lib/commonjs/models/interfaces.js.map +1 -1
- package/lib/commonjs/ui/components/BottomSheetRouter.js +9 -1
- package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
- package/lib/commonjs/ui/components/Icon.js.map +1 -1
- package/lib/commonjs/ui/components/IconButton/utils.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +41 -11
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/TextField/Adornment/utils.js.map +1 -1
- package/lib/commonjs/ui/components/TextField/helpers.js.map +1 -1
- package/lib/commonjs/ui/components/TouchableRipple/utils.js.map +1 -1
- package/lib/commonjs/ui/components/Typography/AnimatedText.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +110 -199
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +150 -19
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js +279 -0
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js.map +1 -0
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +79 -72
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +38 -51
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js +3 -3
- package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +18 -12
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/useProfileEditing.js +3 -5
- package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +4 -8
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +162 -315
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/hooks/useStorage.js +24 -58
- package/lib/commonjs/ui/hooks/useStorage.js.map +1 -1
- package/lib/commonjs/ui/index.js +50 -21
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/routes.js +5 -1
- package/lib/commonjs/ui/navigation/routes.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +2 -2
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +29 -24
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +134 -66
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +6 -13
- package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/stores/accountStore.js +2 -4
- package/lib/commonjs/ui/stores/accountStore.js.map +1 -1
- package/lib/commonjs/ui/stores/authStore.js +45 -32
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/styles/spacing.js +54 -2
- package/lib/commonjs/ui/styles/spacing.js.map +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js +37 -41
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/commonjs/ui/utils/storageHelpers.js.map +1 -1
- package/lib/commonjs/utils/errorUtils.js +13 -0
- package/lib/commonjs/utils/errorUtils.js.map +1 -1
- package/lib/commonjs/utils/validationUtils.js +15 -1
- package/lib/commonjs/utils/validationUtils.js.map +1 -1
- package/lib/module/core/CrossDomainAuth.js +271 -0
- package/lib/module/core/CrossDomainAuth.js.map +1 -0
- package/lib/module/core/HttpService.js +82 -15
- package/lib/module/core/HttpService.js.map +1 -1
- package/lib/module/core/OxyServices.base.js +11 -4
- package/lib/module/core/OxyServices.base.js.map +1 -1
- package/lib/module/core/OxyServices.js +4 -1
- package/lib/module/core/OxyServices.js.map +1 -1
- package/lib/module/core/index.js +6 -1
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.assets.js +16 -3
- package/lib/module/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.auth.js +73 -32
- package/lib/module/core/mixins/OxyServices.auth.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.fedcm.js +286 -0
- package/lib/module/core/mixins/OxyServices.fedcm.js.map +1 -0
- package/lib/module/core/mixins/OxyServices.popup.js +349 -0
- package/lib/module/core/mixins/OxyServices.popup.js.map +1 -0
- package/lib/module/core/mixins/OxyServices.redirect.js +375 -0
- package/lib/module/core/mixins/OxyServices.redirect.js.map +1 -0
- package/lib/module/core/mixins/OxyServices.user.js +35 -24
- package/lib/module/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/module/core/mixins/index.js +15 -3
- package/lib/module/core/mixins/index.js.map +1 -1
- package/lib/module/crypto/index.js +8 -4
- package/lib/module/crypto/index.js.map +1 -1
- package/lib/module/crypto/keyManager.js +899 -0
- package/lib/module/crypto/keyManager.js.map +1 -0
- package/lib/module/crypto/polyfill.js +6 -5
- package/lib/module/crypto/polyfill.js.map +1 -1
- package/lib/module/crypto/recoveryPhrase.js +147 -0
- package/lib/module/crypto/recoveryPhrase.js.map +1 -0
- package/lib/module/crypto/signatureService.js +286 -0
- package/lib/module/crypto/signatureService.js.map +1 -0
- package/lib/module/i18n/locales/en-US.json +1 -1
- package/lib/module/index.js +6 -9
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/interfaces.js +0 -15
- package/lib/module/models/interfaces.js.map +1 -1
- package/lib/module/ui/components/BottomSheetRouter.js +6 -2
- package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
- package/lib/module/ui/components/Icon.js.map +1 -1
- package/lib/module/ui/components/IconButton/utils.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +41 -11
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/TextField/Adornment/utils.js.map +1 -1
- package/lib/module/ui/components/TextField/helpers.js.map +1 -1
- package/lib/module/ui/components/TouchableRipple/utils.js.map +1 -1
- package/lib/module/ui/components/Typography/AnimatedText.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +112 -191
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +150 -19
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/hooks/useSessionManagement.js +274 -0
- package/lib/module/ui/context/hooks/useSessionManagement.js.map +1 -0
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +80 -72
- package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js +31 -44
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useSecurityQueries.js +1 -1
- package/lib/module/ui/hooks/queries/useSecurityQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js +13 -7
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/useProfileEditing.js +3 -5
- package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +4 -8
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +162 -315
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/hooks/useStorage.js +25 -59
- package/lib/module/ui/hooks/useStorage.js.map +1 -1
- package/lib/module/ui/index.js +15 -10
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/routes.js +5 -1
- package/lib/module/ui/navigation/routes.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +2 -2
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +29 -24
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +135 -68
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/ui/screens/PrivacySettingsScreen.js +6 -13
- package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
- package/lib/module/ui/stores/accountStore.js +2 -4
- package/lib/module/ui/stores/accountStore.js.map +1 -1
- package/lib/module/ui/stores/authStore.js +45 -32
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/styles/spacing.js +6 -2
- package/lib/module/ui/styles/spacing.js.map +1 -1
- package/lib/module/ui/utils/avatarUtils.js +37 -40
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/ui/utils/storageHelpers.js.map +1 -1
- package/lib/module/utils/errorUtils.js +7 -0
- package/lib/module/utils/errorUtils.js.map +1 -1
- package/lib/module/utils/validationUtils.js +13 -0
- package/lib/module/utils/validationUtils.js.map +1 -1
- package/lib/typescript/core/CrossDomainAuth.d.ts +161 -0
- package/lib/typescript/core/CrossDomainAuth.d.ts.map +1 -0
- package/lib/typescript/core/HttpService.d.ts +1 -1
- package/lib/typescript/core/HttpService.d.ts.map +1 -1
- package/lib/typescript/core/OxyServices.base.d.ts +0 -6
- package/lib/typescript/core/OxyServices.base.d.ts.map +1 -1
- package/lib/typescript/core/OxyServices.d.ts +5 -36
- package/lib/typescript/core/OxyServices.d.ts.map +1 -1
- package/lib/typescript/core/index.d.ts +4 -0
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.analytics.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts +40 -20
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.developer.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.devices.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.fedcm.d.ts +195 -0
- package/lib/typescript/core/mixins/OxyServices.fedcm.d.ts.map +1 -0
- package/lib/typescript/core/mixins/OxyServices.karma.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.language.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.location.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.payment.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.popup.d.ts +206 -0
- package/lib/typescript/core/mixins/OxyServices.popup.d.ts.map +1 -0
- package/lib/typescript/core/mixins/OxyServices.privacy.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.redirect.d.ts +246 -0
- package/lib/typescript/core/mixins/OxyServices.redirect.d.ts.map +1 -0
- package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.user.d.ts +6 -4
- package/lib/typescript/core/mixins/OxyServices.user.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.utility.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +220 -8
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/crypto/index.d.ts +6 -3
- package/lib/typescript/crypto/index.d.ts.map +1 -1
- package/lib/typescript/crypto/keyManager.d.ts +190 -0
- package/lib/typescript/crypto/keyManager.d.ts.map +1 -0
- package/lib/typescript/crypto/polyfill.d.ts +4 -3
- package/lib/typescript/crypto/polyfill.d.ts.map +1 -1
- package/lib/typescript/crypto/recoveryPhrase.d.ts +59 -0
- package/lib/typescript/crypto/recoveryPhrase.d.ts.map +1 -0
- package/lib/typescript/crypto/signatureService.d.ts +87 -0
- package/lib/typescript/crypto/signatureService.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +5 -6
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +2 -14
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/models/session.d.ts +0 -9
- package/lib/typescript/models/session.d.ts.map +1 -1
- package/lib/typescript/types/bip39.d.ts +32 -0
- package/lib/typescript/ui/components/BottomSheetRouter.d.ts +5 -0
- package/lib/typescript/ui/components/BottomSheetRouter.d.ts.map +1 -1
- package/lib/typescript/ui/components/IconButton/utils.d.ts +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/TextField/Addons/Outline.d.ts +2 -2
- package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts +1 -1
- package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts.map +1 -1
- package/lib/typescript/ui/components/TextField/helpers.d.ts +8 -8
- package/lib/typescript/ui/components/TextField/types.d.ts +1 -0
- package/lib/typescript/ui/components/TextField/types.d.ts.map +1 -1
- package/lib/typescript/ui/components/types.d.ts +4 -0
- package/lib/typescript/ui/components/types.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +57 -3
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +10 -3
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts +41 -0
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useProfileEditing.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts +1 -2
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useStorage.d.ts +3 -9
- package/lib/typescript/ui/hooks/useStorage.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +6 -2
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/OxyAuthScreen.d.ts +1 -1
- package/lib/typescript/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts +8 -7
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/styles/spacing.d.ts +5 -0
- package/lib/typescript/ui/styles/spacing.d.ts.map +1 -1
- package/lib/typescript/ui/types/navigation.d.ts +2 -1
- package/lib/typescript/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/ui/utils/avatarUtils.d.ts +2 -13
- package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
- package/lib/typescript/ui/utils/storageHelpers.d.ts +0 -3
- package/lib/typescript/ui/utils/storageHelpers.d.ts.map +1 -1
- package/lib/typescript/utils/errorUtils.d.ts +6 -0
- package/lib/typescript/utils/errorUtils.d.ts.map +1 -1
- package/lib/typescript/utils/validationUtils.d.ts +8 -0
- package/lib/typescript/utils/validationUtils.d.ts.map +1 -1
- package/package.json +8 -7
- package/src/core/CrossDomainAuth.ts +307 -0
- package/src/core/HttpService.ts +99 -16
- package/src/core/OxyServices.base.ts +20 -3
- package/src/core/OxyServices.ts +7 -3
- package/src/core/index.ts +9 -1
- package/src/core/mixins/OxyServices.assets.ts +14 -3
- package/src/core/mixins/OxyServices.auth.ts +105 -36
- package/src/core/mixins/OxyServices.fedcm.ts +315 -0
- package/src/core/mixins/OxyServices.popup.ts +402 -0
- package/src/core/mixins/OxyServices.redirect.ts +397 -0
- package/src/core/mixins/OxyServices.user.ts +39 -24
- package/src/core/mixins/index.ts +19 -3
- package/src/crypto/index.ts +16 -5
- package/src/crypto/keyManager.ts +966 -0
- package/src/crypto/polyfill.ts +6 -5
- package/src/crypto/recoveryPhrase.ts +166 -0
- package/src/crypto/signatureService.ts +323 -0
- package/src/i18n/locales/en-US.json +1 -1
- package/src/index.ts +19 -15
- package/src/models/interfaces.ts +4 -16
- package/src/models/session.ts +2 -11
- package/src/types/bip39.d.ts +32 -0
- package/src/ui/components/BottomSheetRouter.tsx +6 -1
- package/src/ui/components/Icon.tsx +1 -1
- package/src/ui/components/IconButton/utils.ts +1 -1
- package/src/ui/components/OxyProvider.tsx +44 -12
- package/src/ui/components/TextField/Addons/Outline.tsx +2 -2
- package/src/ui/components/TextField/Adornment/utils.ts +2 -2
- package/src/ui/components/TextField/helpers.tsx +10 -10
- package/src/ui/components/TextField/types.tsx +1 -1
- package/src/ui/components/TouchableRipple/utils.ts +2 -2
- package/src/ui/components/Typography/AnimatedText.tsx +2 -2
- package/src/ui/components/types.tsx +6 -0
- package/src/ui/context/OxyContext.tsx +173 -195
- package/src/ui/context/hooks/useAuthOperations.ts +177 -36
- package/src/ui/context/hooks/useSessionManagement.ts +399 -0
- package/src/ui/hooks/mutations/useAccountMutations.ts +83 -76
- package/src/ui/hooks/queries/useAccountQueries.ts +29 -35
- package/src/ui/hooks/queries/useSecurityQueries.ts +1 -1
- package/src/ui/hooks/queries/useServicesQueries.ts +14 -6
- package/src/ui/hooks/useProfileEditing.ts +3 -3
- package/src/ui/hooks/useSessionManagement.ts +5 -10
- package/src/ui/hooks/useSessionSocket.ts +46 -175
- package/src/ui/hooks/useStorage.ts +24 -76
- package/src/ui/index.ts +22 -13
- package/src/ui/navigation/routes.ts +6 -2
- package/src/ui/screens/AccountCenterScreen.tsx +2 -2
- package/src/ui/screens/AccountOverviewScreen.tsx +1 -1
- package/src/ui/screens/AccountSettingsScreen.tsx +34 -37
- package/src/ui/screens/AccountSwitcherScreen.tsx +4 -4
- package/src/ui/screens/OxyAuthScreen.tsx +138 -64
- package/src/ui/screens/PrivacySettingsScreen.tsx +6 -12
- package/src/ui/stores/accountStore.ts +1 -11
- package/src/ui/stores/authStore.ts +43 -44
- package/src/ui/styles/spacing.ts +15 -2
- package/src/ui/types/navigation.ts +2 -2
- package/src/ui/utils/avatarUtils.ts +39 -46
- package/src/ui/utils/storageHelpers.ts +0 -4
- package/src/utils/__tests__/validationUtils.test.ts +16 -1
- package/src/utils/errorUtils.ts +8 -1
- package/src/utils/validationUtils.ts +12 -0
- package/lib/commonjs/core/services/SessionService.js +0 -163
- package/lib/commonjs/core/services/SessionService.js.map +0 -1
- package/lib/commonjs/core/services/TokenService.js +0 -220
- package/lib/commonjs/core/services/TokenService.js.map +0 -1
- package/lib/commonjs/crypto/types.js +0 -2
- package/lib/commonjs/crypto/types.js.map +0 -1
- package/lib/commonjs/ui/context/OxyContextBase.js +0 -21
- package/lib/commonjs/ui/context/OxyContextBase.js.map +0 -1
- package/lib/commonjs/ui/context/hooks/useStorage.js +0 -79
- package/lib/commonjs/ui/context/hooks/useStorage.js.map +0 -1
- package/lib/commonjs/ui/hooks/useAvatarPicker.js +0 -56
- package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +0 -1
- package/lib/module/core/services/SessionService.js +0 -159
- package/lib/module/core/services/SessionService.js.map +0 -1
- package/lib/module/core/services/TokenService.js +0 -217
- package/lib/module/core/services/TokenService.js.map +0 -1
- package/lib/module/crypto/types.js +0 -2
- package/lib/module/crypto/types.js.map +0 -1
- package/lib/module/ui/context/OxyContextBase.js +0 -16
- package/lib/module/ui/context/OxyContextBase.js.map +0 -1
- package/lib/module/ui/context/hooks/useStorage.js +0 -74
- package/lib/module/ui/context/hooks/useStorage.js.map +0 -1
- package/lib/module/ui/hooks/useAvatarPicker.js +0 -50
- package/lib/module/ui/hooks/useAvatarPicker.js.map +0 -1
- package/lib/typescript/core/services/SessionService.d.ts +0 -78
- package/lib/typescript/core/services/SessionService.d.ts.map +0 -1
- package/lib/typescript/core/services/TokenService.d.ts +0 -72
- package/lib/typescript/core/services/TokenService.d.ts.map +0 -1
- package/lib/typescript/crypto/types.d.ts +0 -22
- package/lib/typescript/crypto/types.d.ts.map +0 -1
- package/lib/typescript/ui/context/OxyContextBase.d.ts +0 -63
- package/lib/typescript/ui/context/OxyContextBase.d.ts.map +0 -1
- package/lib/typescript/ui/context/hooks/useStorage.d.ts +0 -22
- package/lib/typescript/ui/context/hooks/useStorage.d.ts.map +0 -1
- package/lib/typescript/ui/hooks/useAvatarPicker.d.ts +0 -19
- package/lib/typescript/ui/hooks/useAvatarPicker.d.ts.map +0 -1
- package/src/core/services/SessionService.ts +0 -173
- package/src/core/services/TokenService.ts +0 -237
- package/src/crypto/types.ts +0 -23
- package/src/ui/context/OxyContextBase.tsx +0 -78
- package/src/ui/context/hooks/useStorage.ts +0 -104
- package/src/ui/hooks/useAvatarPicker.ts +0 -61
|
@@ -22,6 +22,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|
|
22
22
|
import { toast } from '../../lib/sonner';
|
|
23
23
|
import { fontFamilies } from '../styles/fonts';
|
|
24
24
|
import { confirmAction } from '../utils/confirmAction';
|
|
25
|
+
import { useAuthStore } from '../stores/authStore';
|
|
25
26
|
import { Header, GroupedSection, Section } from '../components';
|
|
26
27
|
import { useI18n } from '../hooks/useI18n';
|
|
27
28
|
import { useThemeStyles } from '../hooks/useThemeStyles';
|
|
@@ -76,9 +77,13 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
76
77
|
const normalizedTheme = normalizeTheme(theme);
|
|
77
78
|
|
|
78
79
|
// Use TanStack Query for user data
|
|
79
|
-
const { data:
|
|
80
|
+
const { data: user, isLoading: userLoading } = useCurrentUser({ enabled: isAuthenticated });
|
|
80
81
|
const updateProfileMutation = useUpdateProfile();
|
|
81
82
|
const uploadAvatarMutation = useUploadAvatar();
|
|
83
|
+
|
|
84
|
+
// Fallback to store for backward compatibility
|
|
85
|
+
const userFromStore = useAuthStore((state) => state.user);
|
|
86
|
+
const finalUser = user || userFromStore;
|
|
82
87
|
const [isLoading, setIsLoading] = useState(false);
|
|
83
88
|
const isSaving = updateProfileMutation.isPending;
|
|
84
89
|
const isUpdatingAvatar = uploadAvatarMutation.isPending;
|
|
@@ -215,10 +220,9 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
215
220
|
// Only reset all fields if it's a new user or first load
|
|
216
221
|
// Skip reset if it's just an avatar update
|
|
217
222
|
if (shouldInitialize && !isAvatarOnlyUpdate) {
|
|
218
|
-
// Prioritize name.full over name.first for display name
|
|
219
223
|
const userDisplayName = typeof finalUser.name === 'string'
|
|
220
224
|
? finalUser.name
|
|
221
|
-
: finalUser.name?.
|
|
225
|
+
: finalUser.name?.first || finalUser.name?.full || '';
|
|
222
226
|
const userLastName = typeof finalUser.name === 'object' ? finalUser.name?.last || '' : '';
|
|
223
227
|
setDisplayName(userDisplayName);
|
|
224
228
|
setLastName(userLastName);
|
|
@@ -363,15 +367,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
363
367
|
try {
|
|
364
368
|
switch (field) {
|
|
365
369
|
case 'displayName':
|
|
366
|
-
|
|
367
|
-
const fullName = [tempDisplayName, tempLastName].filter(Boolean).join(' ').trim() || tempDisplayName;
|
|
368
|
-
await updateProfileMutation.mutateAsync({
|
|
369
|
-
name: {
|
|
370
|
-
first: tempDisplayName,
|
|
371
|
-
last: tempLastName,
|
|
372
|
-
full: fullName
|
|
373
|
-
}
|
|
374
|
-
});
|
|
370
|
+
await updateProfileMutation.mutateAsync({ name: { first: tempDisplayName, last: tempLastName } });
|
|
375
371
|
setDisplayName(tempDisplayName);
|
|
376
372
|
setLastName(tempLastName);
|
|
377
373
|
break;
|
|
@@ -476,12 +472,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
476
472
|
|
|
477
473
|
// Handle name field
|
|
478
474
|
if (displayName || lastName) {
|
|
479
|
-
|
|
480
|
-
updates.name = {
|
|
481
|
-
first: displayName,
|
|
482
|
-
last: lastName,
|
|
483
|
-
full: fullName
|
|
484
|
-
};
|
|
475
|
+
updates.name = { first: displayName, last: lastName };
|
|
485
476
|
}
|
|
486
477
|
|
|
487
478
|
// Handle avatar
|
|
@@ -523,40 +514,46 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
523
514
|
const handleOpenLinksModal = useCallback(() => setShowEditLinksModal(true), []);
|
|
524
515
|
|
|
525
516
|
// Handler to refresh data after modal saves
|
|
526
|
-
// Note:
|
|
517
|
+
// Note: Access user directly from store when invoked to get latest value,
|
|
518
|
+
// not from closure which may be stale after modal saves update the backend
|
|
527
519
|
const handleModalSave = useCallback(() => {
|
|
520
|
+
// Get fresh user data from store to ensure we have the latest values
|
|
521
|
+
// after the modal's save operation updates the backend
|
|
522
|
+
// Read from store directly (not from closure) to avoid stale data
|
|
523
|
+
const currentUser = useAuthStore.getState().user;
|
|
524
|
+
|
|
528
525
|
// Reload user data to reflect changes
|
|
529
|
-
if (
|
|
530
|
-
const userDisplayName = typeof
|
|
531
|
-
?
|
|
532
|
-
:
|
|
533
|
-
const userLastName = typeof
|
|
526
|
+
if (currentUser) {
|
|
527
|
+
const userDisplayName = typeof currentUser.name === 'string'
|
|
528
|
+
? currentUser.name
|
|
529
|
+
: currentUser.name?.first || currentUser.name?.full || '';
|
|
530
|
+
const userLastName = typeof currentUser.name === 'object' ? currentUser.name?.last || '' : '';
|
|
534
531
|
setDisplayName(userDisplayName);
|
|
535
532
|
setLastName(userLastName);
|
|
536
|
-
setUsername(
|
|
537
|
-
setEmail(
|
|
538
|
-
setBio(
|
|
533
|
+
setUsername(currentUser.username || '');
|
|
534
|
+
setEmail(currentUser.email || '');
|
|
535
|
+
setBio(currentUser.bio || '');
|
|
539
536
|
|
|
540
537
|
// Reload locations and links
|
|
541
|
-
if (
|
|
542
|
-
setLocations(
|
|
538
|
+
if (currentUser.locations && Array.isArray(currentUser.locations)) {
|
|
539
|
+
setLocations(currentUser.locations.map((loc, index) => ({
|
|
543
540
|
id: loc.id || `existing-${index}`,
|
|
544
541
|
name: loc.name,
|
|
545
542
|
label: loc.label,
|
|
546
543
|
coordinates: loc.coordinates
|
|
547
544
|
})));
|
|
548
|
-
} else if (
|
|
545
|
+
} else if (currentUser.location) {
|
|
549
546
|
setLocations([{
|
|
550
547
|
id: 'existing-0',
|
|
551
|
-
name:
|
|
548
|
+
name: currentUser.location,
|
|
552
549
|
label: 'Location'
|
|
553
550
|
}]);
|
|
554
551
|
} else {
|
|
555
552
|
setLocations([]);
|
|
556
553
|
}
|
|
557
554
|
|
|
558
|
-
if (
|
|
559
|
-
setLinksMetadata(
|
|
555
|
+
if (currentUser.linksMetadata && Array.isArray(currentUser.linksMetadata)) {
|
|
556
|
+
setLinksMetadata(currentUser.linksMetadata.map((link, index) => ({
|
|
560
557
|
...link,
|
|
561
558
|
id: link.id || `existing-${index}`
|
|
562
559
|
})));
|
|
@@ -564,7 +561,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
564
561
|
setLinksMetadata([]);
|
|
565
562
|
}
|
|
566
563
|
}
|
|
567
|
-
}, [
|
|
564
|
+
}, []); // Empty dependency array - callback reads fresh data from store at call time
|
|
568
565
|
|
|
569
566
|
// Handle initialField prop - open appropriate modal
|
|
570
567
|
useEffect(() => {
|
|
@@ -832,7 +829,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
832
829
|
{/* Search results */}
|
|
833
830
|
{locationSearchResults.length > 0 && (
|
|
834
831
|
<View style={styles.searchResults}>
|
|
835
|
-
{locationSearchResults.map((result
|
|
832
|
+
{locationSearchResults.map((result) => (
|
|
836
833
|
<TouchableOpacity
|
|
837
834
|
key={result.place_id}
|
|
838
835
|
style={styles.searchResultItem}
|
|
@@ -863,7 +860,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
863
860
|
{tempLocations.length > 0 && (
|
|
864
861
|
<View style={styles.locationsList}>
|
|
865
862
|
<Text style={styles.locationsListTitle}>Your Locations ({tempLocations.length})</Text>
|
|
866
|
-
{tempLocations.map((location
|
|
863
|
+
{tempLocations.map((location, index) => (
|
|
867
864
|
<View key={location.id} style={styles.locationItem}>
|
|
868
865
|
<View style={styles.locationItemContent}>
|
|
869
866
|
<View style={styles.locationItemDragHandle}>
|
|
@@ -991,7 +988,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
991
988
|
onPress: () => setIsAddingLink(true),
|
|
992
989
|
}]),
|
|
993
990
|
// Existing links
|
|
994
|
-
...tempLinksWithMetadata.map((link
|
|
991
|
+
...tempLinksWithMetadata.map((link, index) => ({
|
|
995
992
|
id: link.id,
|
|
996
993
|
customIcon: link.image ? (
|
|
997
994
|
<Image source={{ uri: link.image }} style={{ width: 36, height: 36, borderRadius: 18 }} />
|
|
@@ -130,7 +130,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
130
130
|
|
|
131
131
|
// Create a map for O(1) lookup
|
|
132
132
|
const userProfileMap = new Map<string, User | null>();
|
|
133
|
-
batchResults.forEach(({ sessionId, user }) => {
|
|
133
|
+
batchResults.forEach(({ sessionId, user }: { sessionId: string; user: any }) => {
|
|
134
134
|
userProfileMap.set(sessionId, user);
|
|
135
135
|
});
|
|
136
136
|
|
|
@@ -460,7 +460,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
460
460
|
iconColor: '#007AFF',
|
|
461
461
|
title: 'Add Another Account',
|
|
462
462
|
subtitle: 'Sign in with a different account',
|
|
463
|
-
onPress: () => navigate?.('
|
|
463
|
+
onPress: () => navigate?.('SignIn'),
|
|
464
464
|
},
|
|
465
465
|
{
|
|
466
466
|
id: 'device-management',
|
|
@@ -561,7 +561,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
561
561
|
iconColor: '#ccc',
|
|
562
562
|
title: t('accountSwitcher.empty.title') || 'No saved accounts',
|
|
563
563
|
subtitle: t('accountSwitcher.empty.subtitle') || 'Add another account to switch between them quickly',
|
|
564
|
-
onPress: () => navigate?.('
|
|
564
|
+
onPress: () => navigate?.('SignIn'),
|
|
565
565
|
customContent: (
|
|
566
566
|
<View style={styles.emptyStateContainer}>
|
|
567
567
|
<OxyIcon name="person-outline" size={48} color="#ccc" />
|
|
@@ -571,7 +571,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
571
571
|
</Text>
|
|
572
572
|
<TouchableOpacity
|
|
573
573
|
style={styles.addAccountButton}
|
|
574
|
-
onPress={() => navigate?.('
|
|
574
|
+
onPress={() => navigate?.('SignIn')}
|
|
575
575
|
>
|
|
576
576
|
<Text style={styles.addAccountButtonText}>{t('accountCenter.sections.addAccount') || 'Add Account'}</Text>
|
|
577
577
|
</TouchableOpacity>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This screen is used by OTHER apps in the Oxy ecosystem to authenticate users.
|
|
5
5
|
* It presents two options:
|
|
6
6
|
* 1. Scan QR code with Oxy Accounts app
|
|
7
|
-
* 2. Open Oxy
|
|
7
|
+
* 2. Open the Oxy Auth web flow
|
|
8
8
|
*
|
|
9
9
|
* Uses WebSocket for real-time authorization updates (with polling fallback).
|
|
10
10
|
* The Oxy Accounts app is where users manage their cryptographic identity.
|
|
@@ -29,9 +29,8 @@ import { useOxy } from '../context/OxyContext';
|
|
|
29
29
|
import QRCode from 'react-native-qrcode-svg';
|
|
30
30
|
import OxyLogo from '../components/OxyLogo';
|
|
31
31
|
|
|
32
|
-
// Deep link scheme for Oxy Accounts app
|
|
33
|
-
const OXY_ACCOUNTS_SCHEME = 'oxyaccounts://';
|
|
34
32
|
const OXY_ACCOUNTS_WEB_URL = 'https://accounts.oxy.so';
|
|
33
|
+
const OXY_AUTH_WEB_URL = 'https://auth.oxy.so';
|
|
35
34
|
|
|
36
35
|
// Auth session expiration (5 minutes)
|
|
37
36
|
const AUTH_SESSION_EXPIRY_MS = 5 * 60 * 1000;
|
|
@@ -52,6 +51,63 @@ interface AuthUpdatePayload {
|
|
|
52
51
|
username?: string;
|
|
53
52
|
}
|
|
54
53
|
|
|
54
|
+
const resolveAuthWebBaseUrl = (baseURL: string, authWebUrl?: string): string => {
|
|
55
|
+
if (authWebUrl) {
|
|
56
|
+
return authWebUrl;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const url = new URL(baseURL);
|
|
61
|
+
if (url.port === '3001') {
|
|
62
|
+
url.port = '3000';
|
|
63
|
+
return url.origin;
|
|
64
|
+
}
|
|
65
|
+
if (url.hostname.startsWith('api.')) {
|
|
66
|
+
url.hostname = `auth.${url.hostname.slice(4)}`;
|
|
67
|
+
return url.origin;
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
// Ignore parsing errors, fall back to default.
|
|
71
|
+
}
|
|
72
|
+
return OXY_AUTH_WEB_URL;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const resolveAuthRedirectUri = async (authRedirectUri?: string): Promise<string | null> => {
|
|
76
|
+
if (authRedirectUri) {
|
|
77
|
+
return authRedirectUri;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const initialUrl = await Linking.getInitialURL();
|
|
82
|
+
if (!initialUrl) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const parsed = new URL(initialUrl);
|
|
87
|
+
parsed.search = '';
|
|
88
|
+
parsed.hash = '';
|
|
89
|
+
return parsed.toString();
|
|
90
|
+
} catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const getRedirectParams = (url: string): { sessionId?: string; error?: string } | null => {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = new URL(url);
|
|
98
|
+
const sessionId = parsed.searchParams.get('session_id') ?? undefined;
|
|
99
|
+
const error = parsed.searchParams.get('error') ?? undefined;
|
|
100
|
+
|
|
101
|
+
if (!sessionId && !error) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { sessionId, error };
|
|
106
|
+
} catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
55
111
|
const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
56
112
|
navigate,
|
|
57
113
|
goBack,
|
|
@@ -60,7 +116,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
60
116
|
}) => {
|
|
61
117
|
const themeValue = (theme === 'light' || theme === 'dark') ? theme : 'light';
|
|
62
118
|
const colors = useThemeColors(themeValue);
|
|
63
|
-
const { oxyServices, switchSession } = useOxy();
|
|
119
|
+
const { oxyServices, signIn, switchSession } = useOxy();
|
|
64
120
|
|
|
65
121
|
const [authSession, setAuthSession] = useState<AuthSession | null>(null);
|
|
66
122
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -71,22 +127,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
71
127
|
const socketRef = useRef<Socket | null>(null);
|
|
72
128
|
const pollingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
73
129
|
const isProcessingRef = useRef(false);
|
|
74
|
-
|
|
75
|
-
const resolveDeviceIdForSession = useCallback(
|
|
76
|
-
async (sessionId: string): Promise<string | undefined> => {
|
|
77
|
-
try {
|
|
78
|
-
const deviceSessions = await oxyServices.getDeviceSessions(sessionId);
|
|
79
|
-
const matchingSession = deviceSessions?.find((session) => session.sessionId === sessionId);
|
|
80
|
-
return matchingSession?.deviceId || undefined;
|
|
81
|
-
} catch (err) {
|
|
82
|
-
if (__DEV__) {
|
|
83
|
-
console.log('Failed to resolve deviceId for session', err);
|
|
84
|
-
}
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
[oxyServices],
|
|
89
|
-
);
|
|
130
|
+
const linkingHandledRef = useRef(false);
|
|
90
131
|
|
|
91
132
|
// Handle successful authorization
|
|
92
133
|
const handleAuthSuccess = useCallback(async (sessionId: string) => {
|
|
@@ -102,8 +143,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
102
143
|
}
|
|
103
144
|
} else {
|
|
104
145
|
// Fallback if switchSession not available (shouldn't happen, but for safety)
|
|
105
|
-
|
|
106
|
-
await oxyServices.getTokenBySession(sessionId, deviceId);
|
|
146
|
+
await oxyServices.getTokenBySession(sessionId);
|
|
107
147
|
const user = await oxyServices.getUserBySession(sessionId);
|
|
108
148
|
if (onAuthenticated) {
|
|
109
149
|
onAuthenticated(user);
|
|
@@ -116,7 +156,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
116
156
|
setError('Authorization successful but failed to complete sign in. Please try again.');
|
|
117
157
|
isProcessingRef.current = false;
|
|
118
158
|
}
|
|
119
|
-
}, [oxyServices,
|
|
159
|
+
}, [oxyServices, switchSession, onAuthenticated]);
|
|
120
160
|
|
|
121
161
|
// Connect to socket for real-time updates
|
|
122
162
|
const connectSocket = useCallback((sessionToken: string) => {
|
|
@@ -188,12 +228,12 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
188
228
|
if (isProcessingRef.current) return;
|
|
189
229
|
|
|
190
230
|
try {
|
|
191
|
-
const response
|
|
231
|
+
const response: {
|
|
192
232
|
authorized: boolean;
|
|
193
233
|
sessionId?: string;
|
|
194
234
|
publicKey?: string;
|
|
195
235
|
status?: string;
|
|
196
|
-
}
|
|
236
|
+
} = await oxyServices.makeRequest('GET', `/api/auth/session/status/${sessionToken}`, undefined, { cache: false });
|
|
197
237
|
|
|
198
238
|
if (response.authorized && response.sessionId) {
|
|
199
239
|
cleanup();
|
|
@@ -298,31 +338,27 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
298
338
|
return `oxyauth://${authSession.sessionToken}`;
|
|
299
339
|
};
|
|
300
340
|
|
|
301
|
-
// Open Oxy
|
|
302
|
-
const
|
|
341
|
+
// Open Oxy Auth web flow
|
|
342
|
+
const handleOpenAuth = useCallback(async () => {
|
|
303
343
|
if (!authSession) return;
|
|
304
344
|
|
|
305
|
-
const
|
|
306
|
-
|
|
345
|
+
const authBaseUrl = resolveAuthWebBaseUrl(
|
|
346
|
+
oxyServices.getBaseURL(),
|
|
347
|
+
oxyServices.config?.authWebUrl
|
|
348
|
+
);
|
|
349
|
+
const webUrl = new URL('/authorize', authBaseUrl);
|
|
350
|
+
webUrl.searchParams.set('token', authSession.sessionToken);
|
|
351
|
+
const redirectUri = await resolveAuthRedirectUri(oxyServices.config?.authRedirectUri);
|
|
352
|
+
if (redirectUri) {
|
|
353
|
+
webUrl.searchParams.set('redirect_uri', redirectUri);
|
|
354
|
+
}
|
|
307
355
|
|
|
308
356
|
try {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (canOpen) {
|
|
312
|
-
await Linking.openURL(deepLinkUrl);
|
|
313
|
-
} else {
|
|
314
|
-
// Fallback to web URL
|
|
315
|
-
await Linking.openURL(webUrl);
|
|
316
|
-
}
|
|
357
|
+
await Linking.openURL(webUrl.toString());
|
|
317
358
|
} catch (err) {
|
|
318
|
-
|
|
319
|
-
try {
|
|
320
|
-
await Linking.openURL(webUrl);
|
|
321
|
-
} catch {
|
|
322
|
-
setError('Unable to open Oxy Accounts. Please install the app or use QR code.');
|
|
323
|
-
}
|
|
359
|
+
setError('Unable to open Oxy Auth. Please try again or use the QR code.');
|
|
324
360
|
}
|
|
325
|
-
}, [authSession]);
|
|
361
|
+
}, [authSession, oxyServices]);
|
|
326
362
|
|
|
327
363
|
// Refresh session
|
|
328
364
|
const handleRefresh = useCallback(() => {
|
|
@@ -330,6 +366,49 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
330
366
|
generateAuthSession();
|
|
331
367
|
}, [generateAuthSession, cleanup]);
|
|
332
368
|
|
|
369
|
+
const handleAuthRedirect = useCallback((url: string) => {
|
|
370
|
+
const params = getRedirectParams(url);
|
|
371
|
+
if (!params) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (params.error) {
|
|
376
|
+
cleanup();
|
|
377
|
+
setError('Authorization was denied.');
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (params.sessionId) {
|
|
382
|
+
cleanup();
|
|
383
|
+
handleAuthSuccess(params.sessionId);
|
|
384
|
+
}
|
|
385
|
+
}, [cleanup, handleAuthSuccess]);
|
|
386
|
+
|
|
387
|
+
useEffect(() => {
|
|
388
|
+
if (Platform.OS === 'web') {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const subscription = Linking.addEventListener('url', ({ url }) => {
|
|
393
|
+
linkingHandledRef.current = true;
|
|
394
|
+
handleAuthRedirect(url);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
Linking.getInitialURL()
|
|
398
|
+
.then((url) => {
|
|
399
|
+
if (url && !linkingHandledRef.current) {
|
|
400
|
+
handleAuthRedirect(url);
|
|
401
|
+
}
|
|
402
|
+
})
|
|
403
|
+
.catch(() => {
|
|
404
|
+
// Ignore linking errors; auth will still resolve via socket/polling.
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
return () => {
|
|
408
|
+
subscription.remove();
|
|
409
|
+
};
|
|
410
|
+
}, [handleAuthRedirect]);
|
|
411
|
+
|
|
333
412
|
if (isLoading) {
|
|
334
413
|
return (
|
|
335
414
|
<View style={[styles.container, { backgroundColor: colors.background }]}>
|
|
@@ -381,26 +460,21 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
381
460
|
</Text>
|
|
382
461
|
</View>
|
|
383
462
|
|
|
384
|
-
{/* Divider
|
|
385
|
-
{
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
<OxyLogo width={20} height={20} fillColor="white" style={styles.buttonIcon} />
|
|
400
|
-
<Text style={styles.buttonText}>Open Oxy Accounts</Text>
|
|
401
|
-
</TouchableOpacity>
|
|
402
|
-
</>
|
|
403
|
-
)}
|
|
463
|
+
{/* Divider */}
|
|
464
|
+
<View style={styles.dividerContainer}>
|
|
465
|
+
<View style={[styles.divider, { backgroundColor: colors.border }]} />
|
|
466
|
+
<Text style={[styles.dividerText, { color: colors.secondaryText }]}>or</Text>
|
|
467
|
+
<View style={[styles.divider, { backgroundColor: colors.border }]} />
|
|
468
|
+
</View>
|
|
469
|
+
|
|
470
|
+
{/* Open Oxy Auth Button */}
|
|
471
|
+
<TouchableOpacity
|
|
472
|
+
style={[styles.button, { backgroundColor: colors.primary }]}
|
|
473
|
+
onPress={handleOpenAuth}
|
|
474
|
+
>
|
|
475
|
+
<OxyLogo width={20} height={20} fillColor="white" style={styles.buttonIcon} />
|
|
476
|
+
<Text style={styles.buttonText}>Open Oxy Auth</Text>
|
|
477
|
+
</TouchableOpacity>
|
|
404
478
|
|
|
405
479
|
{/* Status */}
|
|
406
480
|
{isWaiting && (
|
|
@@ -78,11 +78,8 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
|
|
|
78
78
|
const loadSettings = async () => {
|
|
79
79
|
try {
|
|
80
80
|
setIsLoading(true);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const userId = oxyServices?.getCurrentUserId();
|
|
84
|
-
if (userId && oxyServices) {
|
|
85
|
-
const privacySettings = await oxyServices.getPrivacySettings(userId);
|
|
81
|
+
if (user?.id && oxyServices) {
|
|
82
|
+
const privacySettings = await oxyServices.getPrivacySettings(user.id);
|
|
86
83
|
if (privacySettings) {
|
|
87
84
|
setSettings(privacySettings);
|
|
88
85
|
}
|
|
@@ -96,7 +93,7 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
|
|
|
96
93
|
};
|
|
97
94
|
|
|
98
95
|
loadSettings();
|
|
99
|
-
}, [oxyServices, t]);
|
|
96
|
+
}, [user?.id, oxyServices, t]);
|
|
100
97
|
|
|
101
98
|
// Load blocked and restricted users
|
|
102
99
|
useEffect(() => {
|
|
@@ -126,11 +123,8 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
|
|
|
126
123
|
const newSettings = { ...settings, [key]: value };
|
|
127
124
|
setSettings(newSettings);
|
|
128
125
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const userId = oxyServices?.getCurrentUserId();
|
|
132
|
-
if (userId && oxyServices) {
|
|
133
|
-
await oxyServices.updatePrivacySettings({ [key]: value }, userId);
|
|
126
|
+
if (user?.id && oxyServices) {
|
|
127
|
+
await oxyServices.updatePrivacySettings({ [key]: value }, user.id);
|
|
134
128
|
toast.success(t('privacySettings.updated') || 'Privacy settings updated');
|
|
135
129
|
}
|
|
136
130
|
} catch (error) {
|
|
@@ -141,7 +135,7 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
|
|
|
141
135
|
} finally {
|
|
142
136
|
setIsSaving(false);
|
|
143
137
|
}
|
|
144
|
-
}, [settings, oxyServices, t]);
|
|
138
|
+
}, [settings, user?.id, oxyServices, t]);
|
|
145
139
|
|
|
146
140
|
const handleUnblock = useCallback(async (userId: string) => {
|
|
147
141
|
if (!oxyServices) return;
|
|
@@ -112,8 +112,6 @@ export const useAccountStore = create<AccountState>((set, get) => ({
|
|
|
112
112
|
return existing &&
|
|
113
113
|
existing.sessionId === newAccount.sessionId &&
|
|
114
114
|
existing.userId === newAccount.userId &&
|
|
115
|
-
existing.username === newAccount.username &&
|
|
116
|
-
existing.displayName === newAccount.displayName &&
|
|
117
115
|
existing.avatar === newAccount.avatar &&
|
|
118
116
|
existing.avatarUrl === newAccount.avatarUrl;
|
|
119
117
|
});
|
|
@@ -152,15 +150,7 @@ export const useAccountStore = create<AccountState>((set, get) => ({
|
|
|
152
150
|
if (!existing) return {} as any;
|
|
153
151
|
|
|
154
152
|
const updated = { ...existing, ...updates };
|
|
155
|
-
|
|
156
|
-
const hasChanges =
|
|
157
|
-
existing.username !== updated.username ||
|
|
158
|
-
existing.displayName !== updated.displayName ||
|
|
159
|
-
existing.avatar !== updated.avatar ||
|
|
160
|
-
existing.avatarUrl !== updated.avatarUrl ||
|
|
161
|
-
existing.userId !== updated.userId;
|
|
162
|
-
|
|
163
|
-
if (!hasChanges) {
|
|
153
|
+
if (existing.avatar === updated.avatar && existing.avatarUrl === updated.avatarUrl) {
|
|
164
154
|
return {} as any; // No change
|
|
165
155
|
}
|
|
166
156
|
|
|
@@ -1,65 +1,64 @@
|
|
|
1
|
-
/** Auth store for Services SDK (sessions/tokens only). */
|
|
2
|
-
|
|
3
1
|
import { create } from 'zustand';
|
|
2
|
+
import type { User } from '../../models/interfaces';
|
|
4
3
|
|
|
5
4
|
export interface AuthState {
|
|
5
|
+
user: User | null;
|
|
6
6
|
isAuthenticated: boolean;
|
|
7
|
-
isOnline: boolean;
|
|
8
7
|
isLoading: boolean;
|
|
9
8
|
error: string | null;
|
|
10
|
-
|
|
9
|
+
lastUserFetch: number | null; // Timestamp of last user fetch for caching
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
loginSuccess: () => void;
|
|
11
|
+
loginSuccess: (user: User) => void;
|
|
14
12
|
loginFailure: (error: string) => void;
|
|
15
13
|
logout: () => void;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
canAuthenticate: () => boolean;
|
|
14
|
+
fetchUser: (oxyServices: { getCurrentUser: () => Promise<User> }, forceRefresh?: boolean) => Promise<void>;
|
|
15
|
+
setUser: (user: User) => void; // Direct user setter for caching
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
export const useAuthStore = create<AuthState>((set, get) => ({
|
|
18
|
+
export const useAuthStore = create<AuthState>((set: (state: Partial<AuthState>) => void, get: () => AuthState) => ({
|
|
19
|
+
user: null,
|
|
22
20
|
isAuthenticated: false,
|
|
23
|
-
isOnline: true, // Assume online initially
|
|
24
21
|
isLoading: false,
|
|
25
22
|
error: null,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
setOnline: (online: boolean) => {
|
|
29
|
-
set({ isOnline: online });
|
|
30
|
-
// If we go offline, we can't be authenticated
|
|
31
|
-
if (!online) {
|
|
32
|
-
set({ isAuthenticated: false });
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
loginSuccess: () => set({
|
|
37
|
-
isLoading: false,
|
|
38
|
-
isAuthenticated: get().isOnline, // Only authenticated if online
|
|
39
|
-
error: null,
|
|
40
|
-
}),
|
|
23
|
+
lastUserFetch: null,
|
|
41
24
|
|
|
42
|
-
|
|
25
|
+
loginSuccess: (user: User) => set({
|
|
43
26
|
isLoading: false,
|
|
44
|
-
isAuthenticated:
|
|
45
|
-
|
|
27
|
+
isAuthenticated: true,
|
|
28
|
+
user,
|
|
29
|
+
lastUserFetch: Date.now(),
|
|
46
30
|
}),
|
|
47
|
-
|
|
31
|
+
loginFailure: (error: string) => set({ isLoading: false, error }),
|
|
48
32
|
logout: () => set({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
33
|
+
user: null,
|
|
34
|
+
isAuthenticated: false,
|
|
35
|
+
lastUserFetch: null,
|
|
52
36
|
}),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
setIdentitySynced: (synced: boolean) => set({ identitySynced: synced }),
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Check if user can authenticate
|
|
59
|
-
* Requires both valid tokens (checked by caller) and network
|
|
60
|
-
*/
|
|
61
|
-
canAuthenticate: () => {
|
|
37
|
+
setUser: (user: User) => set({ user, lastUserFetch: Date.now() }),
|
|
38
|
+
fetchUser: async (oxyServices, forceRefresh = false) => {
|
|
62
39
|
const state = get();
|
|
63
|
-
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
const cacheAge = state.lastUserFetch ? now - state.lastUserFetch : Number.POSITIVE_INFINITY;
|
|
42
|
+
const cacheValid = cacheAge < 5 * 60 * 1000; // 5 minutes cache
|
|
43
|
+
|
|
44
|
+
// Use cached data if available and not forcing refresh
|
|
45
|
+
if (!forceRefresh && state.user && cacheValid) {
|
|
46
|
+
if (__DEV__) {
|
|
47
|
+
console.log('AuthStore: Using cached user data (age:', cacheAge, 'ms)');
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
set({ isLoading: true, error: null });
|
|
53
|
+
try {
|
|
54
|
+
const user = await oxyServices.getCurrentUser();
|
|
55
|
+
set({ user, isLoading: false, isAuthenticated: true, lastUserFetch: now });
|
|
56
|
+
} catch (error) {
|
|
57
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to fetch user';
|
|
58
|
+
if (__DEV__) {
|
|
59
|
+
console.error('AuthStore: Error fetching user:', error);
|
|
60
|
+
}
|
|
61
|
+
set({ error: errorMessage, isLoading: false });
|
|
62
|
+
}
|
|
64
63
|
},
|
|
65
|
-
}));
|
|
64
|
+
}));
|