@oxyhq/services 22.12.5 → 22.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -46
- package/lib/commonjs/index.js +18 -12
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/boot/runProviderColdBoot.js +51 -9
- package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/commonjs/ui/client.js +0 -13
- package/lib/commonjs/ui/client.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +27 -4
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAuthChooser.js +72 -1123
- package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/commonjs/ui/components/OxyConsentScreen.js +50 -12
- package/lib/commonjs/ui/components/OxyConsentScreen.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +4 -4
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/OxySignInButton.js +74 -40
- package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js +527 -0
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js +90 -0
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/SignInRequestView.js +144 -0
- package/lib/commonjs/ui/components/authChooser/SignInRequestView.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/SignUpView.js +188 -0
- package/lib/commonjs/ui/components/authChooser/SignUpView.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/TroubleDisclosure.js +63 -0
- package/lib/commonjs/ui/components/authChooser/TroubleDisclosure.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/primitives.js +169 -0
- package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/requestSurfaces.js +149 -0
- package/lib/commonjs/ui/components/authChooser/requestSurfaces.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/signInProgress.js +54 -0
- package/lib/commonjs/ui/components/authChooser/signInProgress.js.map +1 -0
- package/lib/commonjs/ui/components/{oxyAuthChooserStyles.js → authChooser/styles.js} +19 -1
- package/lib/commonjs/ui/components/authChooser/styles.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/types.js +59 -0
- package/lib/commonjs/ui/components/authChooser/types.js.map +1 -0
- package/lib/commonjs/ui/components/authChooser/useUsernameAvailability.js +50 -0
- package/lib/commonjs/ui/components/authChooser/useUsernameAvailability.js.map +1 -0
- package/lib/commonjs/ui/context/OxyContext.js +205 -30
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/commitSessionFlow.js +46 -0
- package/lib/commonjs/ui/context/commitSessionFlow.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +15 -2
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/useOxyAccountGraph.js +13 -5
- package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +6 -1
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +1 -1
- package/lib/commonjs/ui/index.js +0 -13
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/oauth/browserAuthTransport.js +170 -0
- package/lib/commonjs/ui/oauth/browserAuthTransport.js.map +1 -0
- package/lib/commonjs/ui/oauth/completeOAuthCode.js +78 -0
- package/lib/commonjs/ui/oauth/completeOAuthCode.js.map +1 -0
- package/lib/commonjs/ui/oauth/legacyRedirectLanes.js +48 -0
- package/lib/commonjs/ui/oauth/legacyRedirectLanes.js.map +1 -0
- package/lib/commonjs/ui/oauth/oauthHandshake.js +53 -0
- package/lib/commonjs/ui/oauth/oauthHandshake.js.map +1 -0
- package/lib/commonjs/ui/oauth/oauthPopup.js +276 -0
- package/lib/commonjs/ui/oauth/oauthPopup.js.map +1 -0
- package/lib/commonjs/ui/oauth/oauthPopupMessages.js +141 -0
- package/lib/commonjs/ui/oauth/oauthPopupMessages.js.map +1 -0
- package/lib/commonjs/ui/oauth/types.js +2 -0
- package/lib/commonjs/ui/oauth/types.js.map +1 -0
- package/lib/commonjs/ui/server.js +2 -5
- package/lib/commonjs/ui/server.js.map +1 -1
- package/lib/commonjs/ui/session/authStore.js +6 -75
- package/lib/commonjs/ui/session/authStore.js.map +1 -1
- package/lib/commonjs/ui/session/createSessionClient.js +11 -3
- package/lib/commonjs/ui/session/createSessionClient.js.map +1 -1
- package/lib/commonjs/ui/session/identityBinding.js +95 -0
- package/lib/commonjs/ui/session/identityBinding.js.map +1 -0
- package/lib/commonjs/ui/session/index.js +13 -0
- package/lib/commonjs/ui/session/index.js.map +1 -1
- package/lib/commonjs/ui/session/nativeSecureStorage.js +90 -0
- package/lib/commonjs/ui/session/nativeSecureStorage.js.map +1 -0
- package/lib/commonjs/ui/session/tokenTransport.js +11 -1
- package/lib/commonjs/ui/session/tokenTransport.js.map +1 -1
- package/lib/commonjs/ui/utils/crossOriginRestore.js +3 -2
- package/lib/commonjs/ui/utils/crossOriginRestore.js.map +1 -1
- package/lib/commonjs/ui/utils/deliveryPlatform.js +58 -0
- package/lib/commonjs/ui/utils/deliveryPlatform.js.map +1 -0
- package/lib/commonjs/ui/utils/oauthReturn.js +33 -49
- package/lib/commonjs/ui/utils/oauthReturn.js.map +1 -1
- package/lib/module/index.js +9 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/boot/runProviderColdBoot.js +51 -9
- package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/module/ui/client.js +0 -1
- package/lib/module/ui/client.js.map +1 -1
- package/lib/module/ui/components/OxyAccountDialogScreen.js +27 -4
- package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/module/ui/components/OxyAuthChooser.js +76 -1128
- package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/module/ui/components/OxyConsentScreen.js +50 -12
- package/lib/module/ui/components/OxyConsentScreen.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +4 -4
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/OxySignInButton.js +76 -42
- package/lib/module/ui/components/OxySignInButton.js.map +1 -1
- package/lib/module/ui/components/authChooser/AccountsMenuView.js +523 -0
- package/lib/module/ui/components/authChooser/AccountsMenuView.js.map +1 -0
- package/lib/module/ui/components/authChooser/SignInEntryView.js +85 -0
- package/lib/module/ui/components/authChooser/SignInEntryView.js.map +1 -0
- package/lib/module/ui/components/authChooser/SignInRequestView.js +139 -0
- package/lib/module/ui/components/authChooser/SignInRequestView.js.map +1 -0
- package/lib/module/ui/components/authChooser/SignUpView.js +184 -0
- package/lib/module/ui/components/authChooser/SignUpView.js.map +1 -0
- package/lib/module/ui/components/authChooser/TroubleDisclosure.js +59 -0
- package/lib/module/ui/components/authChooser/TroubleDisclosure.js.map +1 -0
- package/lib/module/ui/components/authChooser/primitives.js +163 -0
- package/lib/module/ui/components/authChooser/primitives.js.map +1 -0
- package/lib/module/ui/components/authChooser/requestSurfaces.js +139 -0
- package/lib/module/ui/components/authChooser/requestSurfaces.js.map +1 -0
- package/lib/module/ui/components/authChooser/signInProgress.js +50 -0
- package/lib/module/ui/components/authChooser/signInProgress.js.map +1 -0
- package/lib/module/ui/components/{oxyAuthChooserStyles.js → authChooser/styles.js} +19 -1
- package/lib/module/ui/components/authChooser/styles.js.map +1 -0
- package/lib/module/ui/components/authChooser/types.js +55 -0
- package/lib/module/ui/components/authChooser/types.js.map +1 -0
- package/lib/module/ui/components/authChooser/useUsernameAvailability.js +46 -0
- package/lib/module/ui/components/authChooser/useUsernameAvailability.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +208 -33
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/commitSessionFlow.js +45 -0
- package/lib/module/ui/context/commitSessionFlow.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +15 -2
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/useOxyAccountGraph.js +13 -5
- package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/module/ui/hooks/useSwitchableAccounts.js +6 -1
- package/lib/module/ui/hooks/useSwitchableAccounts.js.map +1 -1
- package/lib/module/ui/index.js +0 -1
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/oauth/browserAuthTransport.js +167 -0
- package/lib/module/ui/oauth/browserAuthTransport.js.map +1 -0
- package/lib/module/ui/oauth/completeOAuthCode.js +75 -0
- package/lib/module/ui/oauth/completeOAuthCode.js.map +1 -0
- package/lib/module/ui/oauth/legacyRedirectLanes.js +44 -0
- package/lib/module/ui/oauth/legacyRedirectLanes.js.map +1 -0
- package/lib/module/ui/oauth/oauthHandshake.js +50 -0
- package/lib/module/ui/oauth/oauthHandshake.js.map +1 -0
- package/lib/module/ui/oauth/oauthPopup.js +268 -0
- package/lib/module/ui/oauth/oauthPopup.js.map +1 -0
- package/lib/module/ui/oauth/oauthPopupMessages.js +135 -0
- package/lib/module/ui/oauth/oauthPopupMessages.js.map +1 -0
- package/lib/module/ui/oauth/types.js +2 -0
- package/lib/module/ui/oauth/types.js.map +1 -0
- package/lib/module/ui/server.js +0 -2
- package/lib/module/ui/server.js.map +1 -1
- package/lib/module/ui/session/authStore.js +5 -75
- package/lib/module/ui/session/authStore.js.map +1 -1
- package/lib/module/ui/session/createSessionClient.js +11 -3
- package/lib/module/ui/session/createSessionClient.js.map +1 -1
- package/lib/module/ui/session/identityBinding.js +89 -0
- package/lib/module/ui/session/identityBinding.js.map +1 -0
- package/lib/module/ui/session/index.js +5 -2
- package/lib/module/ui/session/index.js.map +1 -1
- package/lib/module/ui/session/nativeSecureStorage.js +88 -0
- package/lib/module/ui/session/nativeSecureStorage.js.map +1 -0
- package/lib/module/ui/session/tokenTransport.js +11 -1
- package/lib/module/ui/session/tokenTransport.js.map +1 -1
- package/lib/module/ui/utils/crossOriginRestore.js +4 -3
- package/lib/module/ui/utils/crossOriginRestore.js.map +1 -1
- package/lib/module/ui/utils/deliveryPlatform.js +55 -0
- package/lib/module/ui/utils/deliveryPlatform.js.map +1 -0
- package/lib/module/ui/utils/oauthReturn.js +35 -50
- package/lib/module/ui/utils/oauthReturn.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +4 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts +34 -2
- package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/client.d.ts +0 -1
- package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts +21 -29
- package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyConsentScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts +17 -12
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts +38 -0
- package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts +32 -0
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/SignInRequestView.d.ts +34 -0
- package/lib/typescript/commonjs/ui/components/authChooser/SignInRequestView.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/SignUpView.d.ts +34 -0
- package/lib/typescript/commonjs/ui/components/authChooser/SignUpView.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/TroubleDisclosure.d.ts +43 -0
- package/lib/typescript/commonjs/ui/components/authChooser/TroubleDisclosure.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +55 -0
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/requestSurfaces.d.ts +54 -0
- package/lib/typescript/commonjs/ui/components/authChooser/requestSurfaces.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts +26 -0
- package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts.map +1 -0
- package/lib/typescript/{module/ui/components/oxyAuthChooserStyles.d.ts → commonjs/ui/components/authChooser/styles.d.ts} +19 -1
- package/lib/typescript/commonjs/ui/components/authChooser/styles.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts +85 -0
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/authChooser/useUsernameAvailability.d.ts +16 -0
- package/lib/typescript/commonjs/ui/components/authChooser/useUsernameAvailability.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/commitSessionFlow.d.ts +40 -0
- package/lib/typescript/commonjs/ui/context/commitSessionFlow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +11 -2
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +44 -1
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts +7 -1
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +0 -1
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/oauth/browserAuthTransport.d.ts +56 -0
- package/lib/typescript/commonjs/ui/oauth/browserAuthTransport.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/oauth/completeOAuthCode.d.ts +49 -0
- package/lib/typescript/commonjs/ui/oauth/completeOAuthCode.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/oauth/legacyRedirectLanes.d.ts +40 -0
- package/lib/typescript/commonjs/ui/oauth/legacyRedirectLanes.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/oauth/oauthHandshake.d.ts +50 -0
- package/lib/typescript/commonjs/ui/oauth/oauthHandshake.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/oauth/oauthPopup.d.ts +83 -0
- package/lib/typescript/commonjs/ui/oauth/oauthPopup.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/oauth/oauthPopupMessages.d.ts +67 -0
- package/lib/typescript/commonjs/ui/oauth/oauthPopupMessages.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/oauth/types.d.ts +176 -0
- package/lib/typescript/commonjs/ui/oauth/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/server.d.ts +0 -2
- package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/authStore.d.ts +3 -7
- package/lib/typescript/commonjs/ui/session/authStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +8 -1
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/identityBinding.d.ts +66 -0
- package/lib/typescript/commonjs/ui/session/identityBinding.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/index.d.ts +6 -2
- package/lib/typescript/commonjs/ui/session/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/nativeSecureStorage.d.ts +25 -0
- package/lib/typescript/commonjs/ui/session/nativeSecureStorage.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts +8 -1
- package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/navigation.d.ts +44 -0
- package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/crossOriginRestore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/deliveryPlatform.d.ts +33 -0
- package/lib/typescript/commonjs/ui/utils/deliveryPlatform.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/utils/oauthReturn.d.ts +11 -16
- package/lib/typescript/commonjs/ui/utils/oauthReturn.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +4 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts +34 -2
- package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/module/ui/client.d.ts +0 -1
- package/lib/typescript/module/ui/client.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts +21 -29
- package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyConsentScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts +17 -12
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts +38 -0
- package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts +32 -0
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/SignInRequestView.d.ts +34 -0
- package/lib/typescript/module/ui/components/authChooser/SignInRequestView.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/SignUpView.d.ts +34 -0
- package/lib/typescript/module/ui/components/authChooser/SignUpView.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/TroubleDisclosure.d.ts +43 -0
- package/lib/typescript/module/ui/components/authChooser/TroubleDisclosure.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +55 -0
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/requestSurfaces.d.ts +54 -0
- package/lib/typescript/module/ui/components/authChooser/requestSurfaces.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts +26 -0
- package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts.map +1 -0
- package/lib/typescript/{commonjs/ui/components/oxyAuthChooserStyles.d.ts → module/ui/components/authChooser/styles.d.ts} +19 -1
- package/lib/typescript/module/ui/components/authChooser/styles.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/types.d.ts +85 -0
- package/lib/typescript/module/ui/components/authChooser/types.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/authChooser/useUsernameAvailability.d.ts +16 -0
- package/lib/typescript/module/ui/components/authChooser/useUsernameAvailability.d.ts.map +1 -0
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/commitSessionFlow.d.ts +40 -0
- package/lib/typescript/module/ui/context/commitSessionFlow.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +11 -2
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +44 -1
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts +7 -1
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +0 -1
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/oauth/browserAuthTransport.d.ts +56 -0
- package/lib/typescript/module/ui/oauth/browserAuthTransport.d.ts.map +1 -0
- package/lib/typescript/module/ui/oauth/completeOAuthCode.d.ts +49 -0
- package/lib/typescript/module/ui/oauth/completeOAuthCode.d.ts.map +1 -0
- package/lib/typescript/module/ui/oauth/legacyRedirectLanes.d.ts +40 -0
- package/lib/typescript/module/ui/oauth/legacyRedirectLanes.d.ts.map +1 -0
- package/lib/typescript/module/ui/oauth/oauthHandshake.d.ts +50 -0
- package/lib/typescript/module/ui/oauth/oauthHandshake.d.ts.map +1 -0
- package/lib/typescript/module/ui/oauth/oauthPopup.d.ts +83 -0
- package/lib/typescript/module/ui/oauth/oauthPopup.d.ts.map +1 -0
- package/lib/typescript/module/ui/oauth/oauthPopupMessages.d.ts +67 -0
- package/lib/typescript/module/ui/oauth/oauthPopupMessages.d.ts.map +1 -0
- package/lib/typescript/module/ui/oauth/types.d.ts +176 -0
- package/lib/typescript/module/ui/oauth/types.d.ts.map +1 -0
- package/lib/typescript/module/ui/server.d.ts +0 -2
- package/lib/typescript/module/ui/server.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/authStore.d.ts +3 -7
- package/lib/typescript/module/ui/session/authStore.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/createSessionClient.d.ts +8 -1
- package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/identityBinding.d.ts +66 -0
- package/lib/typescript/module/ui/session/identityBinding.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/index.d.ts +6 -2
- package/lib/typescript/module/ui/session/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/nativeSecureStorage.d.ts +25 -0
- package/lib/typescript/module/ui/session/nativeSecureStorage.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/tokenTransport.d.ts +8 -1
- package/lib/typescript/module/ui/session/tokenTransport.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/navigation.d.ts +44 -0
- package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/crossOriginRestore.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/deliveryPlatform.d.ts +33 -0
- package/lib/typescript/module/ui/utils/deliveryPlatform.d.ts.map +1 -0
- package/lib/typescript/module/ui/utils/oauthReturn.d.ts +11 -16
- package/lib/typescript/module/ui/utils/oauthReturn.d.ts.map +1 -1
- package/package.json +6 -8
- package/src/index.ts +19 -5
- package/src/ui/boot/__tests__/coldBootWebAuthMode.test.ts +281 -0
- package/src/ui/boot/runProviderColdBoot.ts +83 -13
- package/src/ui/client.ts +0 -1
- package/src/ui/components/OxyAccountDialogScreen.tsx +33 -4
- package/src/ui/components/OxyAuthChooser.tsx +100 -1230
- package/src/ui/components/OxyConsentScreen.tsx +56 -13
- package/src/ui/components/OxyProvider.tsx +4 -4
- package/src/ui/components/OxySignInButton.tsx +119 -78
- package/src/ui/components/__tests__/OxyConsentScreen.test.tsx +27 -0
- package/src/ui/components/authChooser/AccountsMenuView.tsx +569 -0
- package/src/ui/components/authChooser/SignInEntryView.tsx +115 -0
- package/src/ui/components/authChooser/SignInRequestView.tsx +163 -0
- package/src/ui/components/authChooser/SignUpView.tsx +174 -0
- package/src/ui/components/authChooser/TroubleDisclosure.tsx +81 -0
- package/src/ui/components/authChooser/primitives.tsx +144 -0
- package/src/ui/components/authChooser/requestSurfaces.tsx +116 -0
- package/src/ui/components/authChooser/signInProgress.ts +54 -0
- package/src/ui/components/{oxyAuthChooserStyles.ts → authChooser/styles.ts} +18 -0
- package/src/ui/components/authChooser/types.ts +101 -0
- package/src/ui/components/authChooser/useUsernameAvailability.ts +60 -0
- package/src/ui/context/OxyContext.tsx +226 -24
- package/src/ui/context/__tests__/commitSessionFlow.test.ts +102 -0
- package/src/ui/context/commitSessionFlow.ts +64 -0
- package/src/ui/context/hooks/useAuthOperations.ts +26 -1
- package/src/ui/context/oxyContextTypes.ts +45 -1
- package/src/ui/context/useOxyAccountGraph.ts +19 -5
- package/src/ui/hooks/useSwitchableAccounts.ts +12 -1
- package/src/ui/index.ts +0 -1
- package/src/ui/oauth/__tests__/browserAuthTransport.test.ts +335 -0
- package/src/ui/oauth/__tests__/completeOAuthCode.test.ts +142 -0
- package/src/ui/oauth/__tests__/oauthPopup.test.ts +352 -0
- package/src/ui/oauth/__tests__/oauthPopupMessages.test.ts +189 -0
- package/src/ui/oauth/__tests__/sharedCompletionPath.test.ts +174 -0
- package/src/ui/oauth/browserAuthTransport.ts +193 -0
- package/src/ui/oauth/completeOAuthCode.ts +93 -0
- package/src/ui/oauth/legacyRedirectLanes.ts +43 -0
- package/src/ui/oauth/oauthHandshake.ts +74 -0
- package/src/ui/oauth/oauthPopup.ts +277 -0
- package/src/ui/oauth/oauthPopupMessages.ts +136 -0
- package/src/ui/oauth/types.ts +150 -0
- package/src/ui/server.ts +0 -2
- package/src/ui/session/__tests__/createSessionClient.test.ts +26 -0
- package/src/ui/session/__tests__/tokenTransport.test.ts +34 -0
- package/src/ui/session/authStore.ts +5 -89
- package/src/ui/session/createSessionClient.ts +15 -2
- package/src/ui/session/identityBinding.ts +116 -0
- package/src/ui/session/index.ts +6 -2
- package/src/ui/session/nativeSecureStorage.ts +98 -0
- package/src/ui/session/tokenTransport.ts +14 -1
- package/src/ui/types/navigation.ts +44 -1
- package/src/ui/utils/__tests__/crossOriginRestore.test.ts +17 -0
- package/src/ui/utils/crossOriginRestore.ts +7 -6
- package/src/ui/utils/deliveryPlatform.ts +65 -0
- package/src/ui/utils/oauthReturn.ts +38 -62
- package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
- package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
- package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
- package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
- package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
- package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
- package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
- package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
- package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
- package/lib/commonjs/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
- package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
- package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
- package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
- package/lib/commonjs/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
- package/lib/commonjs/ui/components/FontLoader.js +0 -35
- package/lib/commonjs/ui/components/FontLoader.js.map +0 -1
- package/lib/commonjs/ui/components/FontLoader.native.js +0 -88
- package/lib/commonjs/ui/components/FontLoader.native.js.map +0 -1
- package/lib/commonjs/ui/components/oxyAuthChooserStyles.js.map +0 -1
- package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
- package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
- package/lib/module/assets/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
- package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
- package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
- package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
- package/lib/module/assets/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
- package/lib/module/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
- package/lib/module/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
- package/lib/module/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
- package/lib/module/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
- package/lib/module/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
- package/lib/module/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
- package/lib/module/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
- package/lib/module/ui/components/FontLoader.js +0 -29
- package/lib/module/ui/components/FontLoader.js.map +0 -1
- package/lib/module/ui/components/FontLoader.native.js +0 -83
- package/lib/module/ui/components/FontLoader.native.js.map +0 -1
- package/lib/module/ui/components/oxyAuthChooserStyles.js.map +0 -1
- package/lib/typescript/commonjs/ui/components/FontLoader.d.ts +0 -24
- package/lib/typescript/commonjs/ui/components/FontLoader.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/FontLoader.native.d.ts +0 -13
- package/lib/typescript/commonjs/ui/components/FontLoader.native.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/oxyAuthChooserStyles.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/FontLoader.d.ts +0 -24
- package/lib/typescript/module/ui/components/FontLoader.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/FontLoader.native.d.ts +0 -13
- package/lib/typescript/module/ui/components/FontLoader.native.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/oxyAuthChooserStyles.d.ts.map +0 -1
- package/src/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
- package/src/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
- package/src/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
- package/src/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
- package/src/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
- package/src/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
- package/src/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
- package/src/ui/components/FontLoader.native.tsx +0 -88
- package/src/ui/components/FontLoader.tsx +0 -27
|
@@ -6,17 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
|
-
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
|
|
10
|
-
var _vectorIcons = require("@expo/vector-icons");
|
|
11
|
-
var _reactNativeQrcodeSvg = _interopRequireDefault(require("react-native-qrcode-svg"));
|
|
12
|
-
var _avatar = require("@oxyhq/bloom/avatar");
|
|
13
|
-
var _avatarGroup = require("@oxyhq/bloom/avatar-group");
|
|
14
|
-
var _button = require("@oxyhq/bloom/button");
|
|
15
|
-
var _pressableScale = require("@oxyhq/bloom/pressable-scale");
|
|
16
|
-
var _compositionBar = require("@oxyhq/bloom/composition-bar");
|
|
17
|
-
var _settingsList = require("@oxyhq/bloom/settings-list");
|
|
18
9
|
var _bloom = require("@oxyhq/bloom");
|
|
19
|
-
var _typography = require("@oxyhq/bloom/typography");
|
|
20
10
|
var _theme = require("@oxyhq/bloom/theme");
|
|
21
11
|
var _core = require("@oxyhq/core");
|
|
22
12
|
var _reactQuery = require("@tanstack/react-query");
|
|
@@ -26,11 +16,12 @@ var _accountDialogManager = require("../navigation/accountDialogManager.js");
|
|
|
26
16
|
var _isWebBrowser = require("../utils/isWebBrowser.js");
|
|
27
17
|
var _commonsStoreLinks = require("../utils/commonsStoreLinks.js");
|
|
28
18
|
var _useServicesQueries = require("../hooks/queries/useServicesQueries.js");
|
|
29
|
-
var
|
|
30
|
-
var
|
|
19
|
+
var _AccountsMenuView = _interopRequireDefault(require("./authChooser/AccountsMenuView.js"));
|
|
20
|
+
var _SignInEntryView = _interopRequireDefault(require("./authChooser/SignInEntryView.js"));
|
|
21
|
+
var _SignInRequestView = _interopRequireDefault(require("./authChooser/SignInRequestView.js"));
|
|
22
|
+
var _SignUpView = _interopRequireDefault(require("./authChooser/SignUpView.js"));
|
|
31
23
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
32
24
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
33
|
-
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
34
25
|
/**
|
|
35
26
|
* OxyAuthChooser — the account switcher + sign-in/sign-up surface, WITHOUT
|
|
36
27
|
* any dialog chrome.
|
|
@@ -43,35 +34,20 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
43
34
|
* cross-origin passkey popup (b2) — same chooser, two hosts, two completion
|
|
44
35
|
* strategies via the `onComplete` prop. Neither host duplicates view logic.
|
|
45
36
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* - `
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* - `
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* inline passkey creation (username + `registerWithPasskey`) offered
|
|
61
|
-
* UNDERNEATH as the de-emphasized "don't want to install anything"
|
|
62
|
-
* alternative — never co-equal, never a competing button. Anywhere else (a
|
|
63
|
-
* non-Oxy web origin, before the b2 hub-relay ships) shows an honest "not
|
|
64
|
-
* available here yet" message instead of a broken button.
|
|
65
|
-
* - `qr` — the cross-device Commons handoff, and the PRIMARY web sign-in
|
|
66
|
-
* surface. On a first-party Oxy origin this ALSO carries a "No Commons?"
|
|
67
|
-
* passkey link — identity is ONE thing (Commons key or browser passkey,
|
|
68
|
-
* same Oxy ID), so there is no separate "sign in with a passkey" button
|
|
69
|
-
* anywhere in this file, but passkey is explicitly the LIGHTWEIGHT
|
|
70
|
-
* ALTERNATIVE for someone who doesn't want to install Commons, never
|
|
71
|
-
* co-equal: same small-text-link subordination, same framing, wherever it
|
|
72
|
-
* appears. Native additionally branches on `commonsAvailability`: when
|
|
73
|
-
* Commons isn't installed, this leads with a "Get Commons" CTA instead of
|
|
74
|
-
* a same-device dead-end QR.
|
|
37
|
+
* This file owns WIRING only: the controller binding, the action handlers, and
|
|
38
|
+
* which view module renders. Every view lives in `./authChooser/`, one
|
|
39
|
+
* responsibility each:
|
|
40
|
+
*
|
|
41
|
+
* - `accounts` → `AccountsMenuView` — the signed-in Oxy account menu.
|
|
42
|
+
* - `add` / `signin` → `SignInEntryView` — ONE primary action, "Continue with
|
|
43
|
+
* Oxy" (issue #691, Phase 5). On WEB this view is transient: the flow
|
|
44
|
+
* auto-starts the instant the view is reached, because the request surface
|
|
45
|
+
* (a QR on an unknown desktop, "Check Commons on your phone" where Oxy could
|
|
46
|
+
* deliver) IS the primary route there, never something behind a second tap.
|
|
47
|
+
* - `qr` → `SignInRequestView` — the ACTIVE REQUEST: the route Oxy chose plus
|
|
48
|
+
* honest progress derived only from `snapshot.signIn`. Alternatives stay
|
|
49
|
+
* behind "Having trouble?" until the chosen route reports `routeFailed`.
|
|
50
|
+
* - `signup` → `SignUpView` — account creation, Commons-first.
|
|
75
51
|
*
|
|
76
52
|
* Per-account color re-theming uses Bloom's `APP_COLOR_PRESETS` + `BloomColorScope`
|
|
77
53
|
* (same visual language auth.oxy.so uses). Base theming is `useTheme()` + a
|
|
@@ -79,11 +55,6 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
79
55
|
* that do not use NativeWind (e.g. the accounts app).
|
|
80
56
|
*/
|
|
81
57
|
|
|
82
|
-
/** Diameter of a row avatar (the sign-in view's account rows). */const ROW_AVATAR_SIZE = 40;
|
|
83
|
-
/** High-contrast QR colors — intentionally fixed (NOT themed) for scan reliability. */
|
|
84
|
-
const QR_PLATE_BG = '#FFFFFF';
|
|
85
|
-
const QR_FOREGROUND = '#000000';
|
|
86
|
-
const QR_SIZE = 196;
|
|
87
58
|
/** Commons' own identity-creation deep link (mirrors the `approve`/`attest`/`card` intents). */
|
|
88
59
|
const COMMONS_CREATE_IDENTITY_URL = 'oxycommons://create-identity';
|
|
89
60
|
/**
|
|
@@ -93,29 +64,14 @@ const COMMONS_CREATE_IDENTITY_URL = 'oxycommons://create-identity';
|
|
|
93
64
|
* hands off to Commons; nothing here invents new API endpoints.
|
|
94
65
|
*/
|
|
95
66
|
const ACCOUNTS_APP_URL = 'https://accounts.oxy.so';
|
|
96
|
-
/**
|
|
97
|
-
* Resolve an account's stored color (a named Bloom preset, e.g. `'purple'`) to
|
|
98
|
-
* a concrete brand hex for the row accent. Falls back to the theme primary when
|
|
99
|
-
* the account has no color or the value is not a recognized preset, so the accent
|
|
100
|
-
* renders in EVERY consumer regardless of NativeWind availability.
|
|
101
|
-
*/
|
|
102
|
-
function resolveAccentHex(color, fallback) {
|
|
103
|
-
const preset = toPreset(color);
|
|
104
|
-
return preset ? _theme.APP_COLOR_PRESETS[preset].hex : fallback;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Narrow a stored color string to a known `AppColorName`, or `undefined`. */
|
|
108
|
-
function toPreset(color) {
|
|
109
|
-
if (!color) return undefined;
|
|
110
|
-
return _theme.APP_COLOR_NAMES.includes(color) ? color : undefined;
|
|
111
|
-
}
|
|
112
67
|
/**
|
|
113
68
|
* The account switcher + sign-in/sign-up chooser. Mounted by `OxyAccountDialogScreen`
|
|
114
69
|
* (wrapped in Bloom's `<Dialog>`) today; mountable bare by any future host that
|
|
115
70
|
* supplies its own `onComplete`.
|
|
116
71
|
*/
|
|
117
72
|
const OxyAuthChooser = ({
|
|
118
|
-
onComplete
|
|
73
|
+
onComplete,
|
|
74
|
+
autoStartSignIn: autoStartSignInEnabled = true
|
|
119
75
|
}) => {
|
|
120
76
|
const {
|
|
121
77
|
accountDialogController: controller,
|
|
@@ -146,7 +102,6 @@ const OxyAuthChooser = ({
|
|
|
146
102
|
if (!(0, _isWebBrowser.isWebBrowser)()) return 'none';
|
|
147
103
|
return (0, _core.isOxyRpOrigin)() ? 'direct' : 'hub';
|
|
148
104
|
}, []);
|
|
149
|
-
const passkeyAvailable = passkeyMode !== 'none';
|
|
150
105
|
const [signInPasskeyPending, setSignInPasskeyPending] = (0, _react.useState)(false);
|
|
151
106
|
const handleSignInWithPasskey = (0, _react.useCallback)(async () => {
|
|
152
107
|
if (signInPasskeyPending) return;
|
|
@@ -158,7 +113,7 @@ const OxyAuthChooser = ({
|
|
|
158
113
|
// A cancelled/failed ceremony keeps the view open so the user can retry
|
|
159
114
|
// or fall back to the QR — surface the reason as a toast (owner mandate:
|
|
160
115
|
// errors never render inline inside the dialog), never swallow.
|
|
161
|
-
_bloom.toast.error(error instanceof Error && error.message ? error.message : t('accountSwitcher.toasts.passkeySignInFailed')
|
|
116
|
+
_bloom.toast.error(error instanceof Error && error.message ? error.message : t('accountSwitcher.toasts.passkeySignInFailed'));
|
|
162
117
|
} finally {
|
|
163
118
|
setSignInPasskeyPending(false);
|
|
164
119
|
}
|
|
@@ -173,30 +128,31 @@ const OxyAuthChooser = ({
|
|
|
173
128
|
});
|
|
174
129
|
onComplete?.();
|
|
175
130
|
} catch (error) {
|
|
176
|
-
_bloom.toast.error(error instanceof Error && error.message ? error.message : t('signup.toasts.passkeyCreateFailed')
|
|
131
|
+
_bloom.toast.error(error instanceof Error && error.message ? error.message : t('signup.toasts.passkeyCreateFailed'));
|
|
177
132
|
} finally {
|
|
178
133
|
setCreatePasskeyPending(false);
|
|
179
134
|
}
|
|
180
135
|
}, [createPasskeyPending, registerWithPasskey, onComplete, t]);
|
|
181
136
|
|
|
182
137
|
// Web: auto-start "Sign in with Oxy" when the sign-in entry becomes the shown
|
|
183
|
-
// view — the
|
|
138
|
+
// view — the request surface is the PRIMARY web route, not something behind a
|
|
139
|
+
// second tap (the user's ONE action was the sign-in button that opened this).
|
|
184
140
|
// `signInWithOxy()` tries the shared keychain first (silently, native-only)
|
|
185
|
-
// then falls to the
|
|
186
|
-
// EVENTS that reach that view — the initial `subscribe` pass below (an
|
|
141
|
+
// then falls to the device flow, whose route the controller picks. Driven from
|
|
142
|
+
// the EVENTS that reach that view — the initial `subscribe` pass below (an
|
|
187
143
|
// open-to-sign-in) and the add / back-to-sign-in handlers — never a watcher
|
|
188
|
-
// effect. Guarded so it never restarts a live flow (phase must be idle) and is
|
|
189
|
-
// no-op on native (button-driven). Reads the live snapshot at call time (an
|
|
144
|
+
// effect. Guarded so it never restarts a live flow (phase must be idle) and is
|
|
145
|
+
// a no-op on native (button-driven). Reads the live snapshot at call time (an
|
|
190
146
|
// event callback, not render), so it is stable across renders.
|
|
191
147
|
const autoStartSignIn = (0, _react.useCallback)(() => {
|
|
192
|
-
if (!controller || !(0, _isWebBrowser.isWebBrowser)()) return;
|
|
148
|
+
if (!autoStartSignInEnabled || !controller || !(0, _isWebBrowser.isWebBrowser)()) return;
|
|
193
149
|
const {
|
|
194
150
|
view: currentView,
|
|
195
151
|
signIn
|
|
196
152
|
} = controller.getSnapshot();
|
|
197
153
|
if (currentView !== 'signin' && currentView !== 'add' || signIn.phase !== 'idle') return;
|
|
198
154
|
void controller.signInWithOxy();
|
|
199
|
-
}, [controller]);
|
|
155
|
+
}, [autoStartSignInEnabled, controller]);
|
|
200
156
|
|
|
201
157
|
// Bind the headless controller. `getSnapshot` returns a stable reference
|
|
202
158
|
// between changes, so it is `useSyncExternalStore`-safe. Guard the no-provider
|
|
@@ -207,8 +163,8 @@ const OxyAuthChooser = ({
|
|
|
207
163
|
// callbacks, not render/effect — so neither is a React effect hook:
|
|
208
164
|
// 1. Sign-in device-flow failures (poll / socket / popup-cancel land on
|
|
209
165
|
// `signIn` asynchronously) are toasted at the notification site, deduped
|
|
210
|
-
// per subscription — NEVER an inline banner in the
|
|
211
|
-
// same contract as account-switch).
|
|
166
|
+
// per subscription — NEVER an inline banner in the request view (owner
|
|
167
|
+
// mandate, same contract as account-switch).
|
|
212
168
|
// 2. On subscribe (mount / re-subscribe — a passive effect, the SAME timing
|
|
213
169
|
// the removed effects had) the web sign-in flow auto-starts if the opening
|
|
214
170
|
// view is the sign-in entry.
|
|
@@ -256,7 +212,7 @@ const OxyAuthChooser = ({
|
|
|
256
212
|
// re-fetches — the same side effects the context's own
|
|
257
213
|
// `switchToAccount` performs.
|
|
258
214
|
if (controller.getSnapshot().error) {
|
|
259
|
-
_bloom.toast.error(t('accountSwitcher.toasts.switchFailed')
|
|
215
|
+
_bloom.toast.error(t('accountSwitcher.toasts.switchFailed'));
|
|
260
216
|
return;
|
|
261
217
|
}
|
|
262
218
|
void refreshAccounts();
|
|
@@ -297,9 +253,31 @@ const OxyAuthChooser = ({
|
|
|
297
253
|
onEditAvatar: () => openAvatarPicker()
|
|
298
254
|
}), [handleSwitch, handleAdd, handleManage, openAvatarPicker]);
|
|
299
255
|
|
|
256
|
+
// Everything that is NOT the surface's one primary action. Wired once here;
|
|
257
|
+
// each view picks the subset that is a genuine alternative to ITS primary
|
|
258
|
+
// surface and hides them behind "Having trouble?" (issue #691).
|
|
259
|
+
const alternatives = (0, _react.useMemo)(() => ({
|
|
260
|
+
passkeyAvailable: passkeyMode !== 'none',
|
|
261
|
+
// The hub-popup flow reports progress through `snapshot.signIn` (already
|
|
262
|
+
// rendered by the request view) — only the DIRECT ceremony uses this
|
|
263
|
+
// component-local pending flag. A ceremony FAILURE is toasted by
|
|
264
|
+
// `handleSignInWithPasskey`, never rendered inline.
|
|
265
|
+
passkeyPending: passkeyMode === 'direct' ? signInPasskeyPending : false,
|
|
266
|
+
onSignInWithPasskey: () => {
|
|
267
|
+
if (passkeyMode === 'direct') {
|
|
268
|
+
void handleSignInWithPasskey();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
void controller?.startPasskeyHubSignIn();
|
|
272
|
+
},
|
|
273
|
+
onShowQr: () => void controller?.showQr(),
|
|
274
|
+
onGetCommons: () => void _reactNative.Linking.openURL((0, _commonsStoreLinks.getCommonsAcquisitionUrl)(_reactNative.Platform.OS)),
|
|
275
|
+
onCreateAccount: () => controller?.startSignup()
|
|
276
|
+
}), [passkeyMode, signInPasskeyPending, handleSignInWithPasskey, controller]);
|
|
277
|
+
|
|
300
278
|
// Real storage usage for the account menu's "Oxy storage" block. Disabled
|
|
301
279
|
// (no fetch) until a private-API session exists, so it is inert on the
|
|
302
|
-
// sign-in/
|
|
280
|
+
// sign-in/request/sign-up views; when present the block shows live used/total.
|
|
303
281
|
const storageQuery = (0, _useServicesQueries.useAccountStorageUsage)();
|
|
304
282
|
const storage = (0, _react.useMemo)(() => storageQuery.data ? {
|
|
305
283
|
usedBytes: storageQuery.data.totalUsedBytes,
|
|
@@ -347,7 +325,7 @@ const OxyAuthChooser = ({
|
|
|
347
325
|
return null;
|
|
348
326
|
}
|
|
349
327
|
if (view === 'accounts') {
|
|
350
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
328
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_AccountsMenuView.default, {
|
|
351
329
|
snapshot: snapshot,
|
|
352
330
|
theme: theme,
|
|
353
331
|
t: t,
|
|
@@ -357,1073 +335,39 @@ const OxyAuthChooser = ({
|
|
|
357
335
|
});
|
|
358
336
|
}
|
|
359
337
|
if (view === 'qr') {
|
|
360
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
338
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SignInRequestView.default, {
|
|
361
339
|
snapshot: snapshot,
|
|
362
340
|
theme: theme,
|
|
363
341
|
t: t,
|
|
364
342
|
onRetry: () => void controller.showQr(),
|
|
365
|
-
|
|
366
|
-
onSignInWithPasskey: passkeyMode === 'direct' ? () => void handleSignInWithPasskey() : () => void controller.startPasskeyHubSignIn()
|
|
367
|
-
// The hub-popup flow's pending state is `snapshot.signIn` (already
|
|
368
|
-
// rendered elsewhere in this view) — only the DIRECT ceremony uses this
|
|
369
|
-
// component-local pending flag. A ceremony FAILURE is surfaced as a
|
|
370
|
-
// toast by `handleSignInWithPasskey`, never inline.
|
|
371
|
-
,
|
|
372
|
-
passkeyPending: passkeyMode === 'direct' ? signInPasskeyPending : false,
|
|
373
|
-
onCreateAccount: () => controller.startSignup()
|
|
343
|
+
alternatives: alternatives
|
|
374
344
|
});
|
|
375
345
|
}
|
|
376
346
|
if (view === 'signup') {
|
|
377
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
347
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SignUpView.default, {
|
|
378
348
|
snapshot: snapshot,
|
|
379
349
|
theme: theme,
|
|
380
350
|
t: t,
|
|
381
351
|
oxyServices: oxyServices,
|
|
382
352
|
passkeyMode: passkeyMode,
|
|
383
|
-
onCreateWithPasskey: handleCreateWithPasskey,
|
|
353
|
+
onCreateWithPasskey: username => void handleCreateWithPasskey(username),
|
|
384
354
|
createPending: createPasskeyPending,
|
|
385
355
|
onOpenHub: () => void controller.startPasskeyHubSignIn(),
|
|
356
|
+
onCreateIdentityInCommons: () => void _reactNative.Linking.openURL(COMMONS_CREATE_IDENTITY_URL),
|
|
357
|
+
onGetCommons: alternatives.onGetCommons,
|
|
386
358
|
onBackToSignIn: () => {
|
|
387
359
|
controller.setView('signin');
|
|
388
360
|
autoStartSignIn();
|
|
389
361
|
}
|
|
390
362
|
});
|
|
391
363
|
}
|
|
392
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
364
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SignInEntryView.default, {
|
|
393
365
|
snapshot: snapshot,
|
|
394
366
|
theme: theme,
|
|
395
367
|
t: t,
|
|
396
368
|
handlers: handlers,
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
onCreateAccount: () => controller.startSignup()
|
|
400
|
-
});
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
// ---------------------------------------------------------------------------
|
|
404
|
-
// Accounts view — the signed-in Oxy account MENU (NativeWind)
|
|
405
|
-
// ---------------------------------------------------------------------------
|
|
406
|
-
|
|
407
|
-
/** Used/total storage bytes for the "Oxy storage" block, or `null` when unknown. */
|
|
408
|
-
|
|
409
|
-
/** The account-menu row actions the container wires (deep-links / sheets / sign-out). */
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* Leading glyph for the rows that live in a Bloom grouped section (the MENU
|
|
413
|
-
* block) and for the storage card's cloud, which lines its title up with them.
|
|
414
|
-
* It is Bloom's OWN icon-slot size: `SettingsListItem` reserves a fixed 20px
|
|
415
|
-
* leading column and Bloom is consumed exactly as it ships, so a menu glyph
|
|
416
|
-
* larger than this would overhang into the row's title.
|
|
417
|
-
*/
|
|
418
|
-
const ROW_ICON_SIZE = 20;
|
|
419
|
-
/**
|
|
420
|
-
* The switch card's two corner states. Collapsed it is one row and reads as a
|
|
421
|
-
* PILL; opened it is a card holding rows, on the same 16px corner the Bloom
|
|
422
|
-
* grouped section below it uses. Interpolated across the reveal, never snapped.
|
|
423
|
-
*/
|
|
424
|
-
const SWITCH_CARD_PILL_RADIUS = 999;
|
|
425
|
-
const SWITCH_CARD_RADIUS = 16;
|
|
426
|
-
/**
|
|
427
|
-
* The fraction of the reveal over which the corner resolves. The corner is a
|
|
428
|
-
* FASTER gesture than the reveal — it has to be finished before the rows read as
|
|
429
|
-
* rows, or the card still looks like a pill while a list falls out of it — so it
|
|
430
|
-
* is clamped to the reveal's opening fraction instead of tracking it end to end.
|
|
431
|
-
* Measured in a browser against the 240ms reveal: the corner reaches its card
|
|
432
|
-
* value ~120ms in, with the list only ~20% revealed, and (mirrored) the pill is
|
|
433
|
-
* back ~250ms into the close, with the list already down to ~0.
|
|
434
|
-
*/
|
|
435
|
-
const SWITCH_CARD_RADIUS_SETTLE = 0.2;
|
|
436
|
-
/** Diameter of an account row's avatar in the switch list (own markup). */
|
|
437
|
-
const SWITCH_AVATAR_SIZE = 36;
|
|
438
|
-
/** Glyph inside a bordered affordance badge, sized to the avatar it stands in for. */
|
|
439
|
-
const BADGE_GLYPH_SIZE = 19;
|
|
440
|
-
/** The hero block's large current-account avatar. */
|
|
441
|
-
const HERO_AVATAR_SIZE = 72;
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* The hero's address line, shown under the "Hi, <name>!" greeting: the account's
|
|
445
|
-
* canonical `@oxy.so` email when it has one, else its normalized `@handle`. Never
|
|
446
|
-
* synthesizes a `username@oxy.so` address (the identity contract forbids it) — a
|
|
447
|
-
* non-Oxy or missing email falls back to `getNormalizedUserHandle`.
|
|
448
|
-
*/
|
|
449
|
-
function heroAddressLine(account) {
|
|
450
|
-
if (account.email?.toLowerCase().endsWith('@oxy.so')) {
|
|
451
|
-
return account.email;
|
|
452
|
-
}
|
|
453
|
-
const handle = (0, _core.getNormalizedUserHandle)(account.user);
|
|
454
|
-
return handle ? `@${handle}` : null;
|
|
455
|
-
}
|
|
456
|
-
/** Avatars shown in the switch row's facepile before it collapses into `+N`. */
|
|
457
|
-
const FACEPILE_MAX = 2;
|
|
458
|
-
/** Facepile avatar diameter — one clear step down from a switch-list avatar. */
|
|
459
|
-
const FACEPILE_AVATAR_SIZE = 32;
|
|
460
|
-
/**
|
|
461
|
-
* Facepile overlap. Well under Bloom's `size / 3` default: the stack draws the
|
|
462
|
-
* FIRST item on top, so a deep overlap would bury the trailing `+N` chip's own
|
|
463
|
-
* label under the avatar before it.
|
|
464
|
-
*/
|
|
465
|
-
const FACEPILE_OVERLAP = 4;
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* `bytes` → `"11.6 GB"`. Whole plan sizes read as whole numbers (`"17 GB"`, not
|
|
469
|
-
* `"17.0 GB"`), and anything ≥ 100 GB drops the decimal entirely.
|
|
470
|
-
*/
|
|
471
|
-
function formatStorageGb(bytes) {
|
|
472
|
-
const gb = bytes / 1024 ** 3;
|
|
473
|
-
if (gb >= 100 || Number.isInteger(gb)) return `${Math.round(gb)} GB`;
|
|
474
|
-
return `${gb.toFixed(1)} GB`;
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* A `Pressable` that appends a hover-tint NativeWind token while pointer-hovered.
|
|
478
|
-
* The Metro web pipeline here does NOT emit NativeWind `hover:` variants, so hover
|
|
479
|
-
* is driven by RN's cross-platform `onHoverIn`/`onHoverOut` (they fire only on web
|
|
480
|
-
* via react-native-web; a no-op on native) toggling a plain background token —
|
|
481
|
-
* the tint stays a NativeWind class, only the trigger is JS.
|
|
482
|
-
*/
|
|
483
|
-
const HoverPressable = ({
|
|
484
|
-
baseClassName,
|
|
485
|
-
hoverClassName,
|
|
486
|
-
...rest
|
|
487
|
-
}) => {
|
|
488
|
-
const [hovered, setHovered] = (0, _react.useState)(false);
|
|
489
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
490
|
-
...rest,
|
|
491
|
-
className: hovered ? `${baseClassName} ${hoverClassName}` : baseClassName,
|
|
492
|
-
onHoverIn: () => setHovered(true),
|
|
493
|
-
onHoverOut: () => setHovered(false)
|
|
494
|
-
});
|
|
495
|
-
};
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
* The signed-in Oxy account MENU — a Google-account-menu-style full menu built
|
|
499
|
-
* entirely with NativeWind `className` (the dynamic per-account accent hex is
|
|
500
|
-
* the one inline style NativeWind can't express). Structure mirrors the
|
|
501
|
-
* approved demo:
|
|
502
|
-
* - ACCOUNT on its own distinct panel surface: a COMPACT current-account row
|
|
503
|
-
* (avatar + name + email + expand chevron) that toggles the switch list, a
|
|
504
|
-
* "Manage your Oxy account" pill, and — when expanded — the other switchable
|
|
505
|
-
* accounts + "Add another account" + "Manage accounts on this device".
|
|
506
|
-
* - OXY STORAGE: cloud + used/total + a progress bar + Upgrade / Manage chips.
|
|
507
|
-
* - MENU rows: Your data in Oxy · Oxy settings · Help & feedback · Sign out —
|
|
508
|
-
* Bloom's grouped section (`SettingsListGroup`/`SettingsListItem`), the same
|
|
509
|
-
* component every other SDK settings surface uses, not a local row copy.
|
|
510
|
-
* - FOOTER: Privacy Policy · Terms of Service.
|
|
511
|
-
*
|
|
512
|
-
* All three blocks share ONE rhythm taken from that grouped section: a 12px
|
|
513
|
-
* content inset, a 12px gap after the leading element, 16px between blocks, and
|
|
514
|
-
* a 16px trailing chevron column.
|
|
515
|
-
*
|
|
516
|
-
* Collapse state is a plain `useState` toggled in the current row's press
|
|
517
|
-
* handler — no effect hook, no derived-from-props sync. With only ONE account
|
|
518
|
-
* (nothing to switch to) the chevron is hidden and the list renders inline so
|
|
519
|
-
* "Add another account" stays reachable without a pointless toggle.
|
|
520
|
-
*/
|
|
521
|
-
const AccountsView = ({
|
|
522
|
-
snapshot,
|
|
523
|
-
theme,
|
|
524
|
-
t,
|
|
525
|
-
handlers,
|
|
526
|
-
storage,
|
|
527
|
-
menu
|
|
528
|
-
}) => {
|
|
529
|
-
const [expanded, setExpanded] = (0, _react.useState)(false);
|
|
530
|
-
// Measured natural height of the switch list, so the reveal animates to an
|
|
531
|
-
// exact height (and the content below reflows down smoothly) instead of a
|
|
532
|
-
// guessed max. The measuring wrapper is style-based, NOT className'd — on
|
|
533
|
-
// RN-Web `onLayout` never fires for className'd Views (see AGENTS.md).
|
|
534
|
-
const [listContentHeight, setListContentHeight] = (0, _react.useState)(0);
|
|
535
|
-
// 0 = collapsed, 1 = expanded. Set imperatively in the toggle handler (no
|
|
536
|
-
// effect hook). On RN-Web there is no worklets plugin, so every shared value a
|
|
537
|
-
// mapper reads MUST be in its deps array or it freezes on the first frame
|
|
538
|
-
// (AGENTS.md "Reanimated (web)").
|
|
539
|
-
const listProgress = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
540
|
-
const listStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
|
|
541
|
-
height: listProgress.value * listContentHeight,
|
|
542
|
-
opacity: listProgress.value
|
|
543
|
-
}), [listProgress, listContentHeight]);
|
|
544
|
-
const chevronStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
|
|
545
|
-
transform: [{
|
|
546
|
-
rotate: `${listProgress.value * 180}deg`
|
|
547
|
-
}]
|
|
548
|
-
}), [listProgress]);
|
|
549
|
-
// Collapsed, the switch card is a single row and reads as a PILL; opened, it
|
|
550
|
-
// becomes a card holding rows and takes the grouped-section corner. The corner
|
|
551
|
-
// is driven off the SAME `listProgress` as the reveal — but clamped to its
|
|
552
|
-
// opening fraction, so it resolves early instead of trailing the rows: the
|
|
553
|
-
// card already reads as a card by the time they are visible. Collapsing is the
|
|
554
|
-
// mirror image, the pill returning over the closing tail.
|
|
555
|
-
const switchCardStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
|
|
556
|
-
borderRadius: (0, _reactNativeReanimated.interpolate)(listProgress.value, [0, SWITCH_CARD_RADIUS_SETTLE], [SWITCH_CARD_PILL_RADIUS, SWITCH_CARD_RADIUS], _reactNativeReanimated.Extrapolation.CLAMP)
|
|
557
|
-
}), [listProgress]);
|
|
558
|
-
// `CompositionBar` ships as an interactive breakdown: a selected segment
|
|
559
|
-
// replaces its hint line with that segment's readout. Tapping the selected one
|
|
560
|
-
// again clears it.
|
|
561
|
-
const [storageSegment, setStorageSegment] = (0, _react.useState)(null);
|
|
562
|
-
const toggleStorageSegment = (0, _react.useCallback)(key => setStorageSegment(previous => previous === key ? null : key), []);
|
|
563
|
-
const toggleExpanded = (0, _react.useCallback)(() => {
|
|
564
|
-
const next = !expanded;
|
|
565
|
-
setExpanded(next);
|
|
566
|
-
listProgress.value = (0, _reactNativeReanimated.withTiming)(next ? 1 : 0, {
|
|
567
|
-
duration: 240
|
|
568
|
-
});
|
|
569
|
-
}, [expanded, listProgress]);
|
|
570
|
-
if (snapshot.loading && snapshot.accounts.length === 0) {
|
|
571
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
572
|
-
className: "items-center justify-center gap-space-12 py-space-24",
|
|
573
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
574
|
-
name: "loading",
|
|
575
|
-
size: 24,
|
|
576
|
-
color: theme.colors.textSecondary
|
|
577
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
578
|
-
className: "text-body text-text-secondary text-center",
|
|
579
|
-
children: t('accountSwitcher.loading')
|
|
580
|
-
})]
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
const switchingDisabled = snapshot.switchingAccountId !== null;
|
|
584
|
-
const current = snapshot.accounts.find(account => account.isCurrent) ?? snapshot.accounts[0];
|
|
585
|
-
const others = current ? snapshot.accounts.filter(account => account.accountId !== current.accountId) : snapshot.accounts;
|
|
586
|
-
const currentAccent = current ? resolveAccentHex(current.color, theme.colors.primary) : theme.colors.primary;
|
|
587
|
-
// The hero's address line under the greeting: the account's canonical @oxy.so
|
|
588
|
-
// email when it has one, else its normalized `@handle` (never a synthesized
|
|
589
|
-
// `username@oxy.so`, per the identity contract — `getNormalizedUserHandle`).
|
|
590
|
-
const currentAddress = current ? heroAddressLine(current) : null;
|
|
591
|
-
// The switch list repeats the CURRENT account (first, ringed) — unlike the old
|
|
592
|
-
// compact header it is not represented anywhere else once the hero moved out
|
|
593
|
-
// of the card, and the list is where you switch back to it.
|
|
594
|
-
const switchableAccounts = current ? [current, ...others] : others;
|
|
595
|
-
const facepile = switchableAccounts.map(account => ({
|
|
596
|
-
id: account.accountId,
|
|
597
|
-
uri: account.avatarUrl ?? undefined,
|
|
598
|
-
displayName: account.displayName
|
|
599
|
-
}));
|
|
600
|
-
|
|
601
|
-
// Used vs free is a two-part COMPOSITION (the parts always fill the bar), not
|
|
602
|
-
// a progress value — exactly what Bloom's `CompositionBar` models. Both colors
|
|
603
|
-
// are theme tokens, so the bar is correct in light and dark.
|
|
604
|
-
const storageCategories = storage ? [{
|
|
605
|
-
key: 'used',
|
|
606
|
-
name: t('accountMenu.storage.used'),
|
|
607
|
-
amount: storage.usedBytes,
|
|
608
|
-
color: theme.colors.primary
|
|
609
|
-
}, {
|
|
610
|
-
key: 'free',
|
|
611
|
-
name: t('accountMenu.storage.free'),
|
|
612
|
-
amount: Math.max(0, storage.limitBytes - storage.usedBytes),
|
|
613
|
-
color: theme.colors.contrast50
|
|
614
|
-
}] : [];
|
|
615
|
-
const usageLabel = storage ? t('accountMenu.storage.usage', {
|
|
616
|
-
used: formatStorageGb(storage.usedBytes),
|
|
617
|
-
total: formatStorageGb(storage.limitBytes)
|
|
618
|
-
}) : t('accountMenu.storage.unavailable');
|
|
619
|
-
|
|
620
|
-
// The switch list body, revealed under the "Switch account" row. Own markup,
|
|
621
|
-
// not a Bloom grouped section: this is not a list of settings rows and the
|
|
622
|
-
// component is not a card container. It mirrors the section's rhythm by hand —
|
|
623
|
-
// 12px content inset, 12px after the avatar, a hairline between rows — and
|
|
624
|
-
// draws those hairlines INSIDE the animated clip, so a collapsed list never
|
|
625
|
-
// strands one against the header row.
|
|
626
|
-
const listItems = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
627
|
-
children: [switchableAccounts.map((account, index) => {
|
|
628
|
-
const accent = resolveAccentHex(account.color, theme.colors.primary);
|
|
629
|
-
const isSwitching = snapshot.switchingAccountId === account.accountId;
|
|
630
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.Fragment, {
|
|
631
|
-
children: [index > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
632
|
-
className: "h-px bg-border opacity-30 ml-space-12"
|
|
633
|
-
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(HoverPressable, {
|
|
634
|
-
baseClassName: `flex-row items-center gap-space-12 px-space-12 py-[10px]${switchingDisabled ? ' opacity-60' : ''}`,
|
|
635
|
-
hoverClassName: "bg-fill-secondary",
|
|
636
|
-
onPress: () => handlers.onSwitch(account.accountId),
|
|
637
|
-
disabled: switchingDisabled,
|
|
638
|
-
accessibilityRole: "button",
|
|
639
|
-
accessibilityLabel: account.displayName,
|
|
640
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
641
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_avatar.Avatar, {
|
|
642
|
-
source: account.avatarUrl ?? undefined,
|
|
643
|
-
variant: "thumb",
|
|
644
|
-
name: account.displayName,
|
|
645
|
-
size: SWITCH_AVATAR_SIZE
|
|
646
|
-
}), account.isCurrent ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
647
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.currentAvatarRing, {
|
|
648
|
-
borderColor: accent
|
|
649
|
-
}],
|
|
650
|
-
pointerEvents: "none"
|
|
651
|
-
}) : null]
|
|
652
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
653
|
-
className: "flex-1 min-w-0",
|
|
654
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
655
|
-
className: "text-body font-semibold text-text",
|
|
656
|
-
numberOfLines: 1,
|
|
657
|
-
children: account.displayName
|
|
658
|
-
}), account.email ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
659
|
-
className: "text-caption text-text-secondary",
|
|
660
|
-
numberOfLines: 1,
|
|
661
|
-
children: account.email
|
|
662
|
-
}) : null]
|
|
663
|
-
}), isSwitching ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
664
|
-
name: "loading",
|
|
665
|
-
size: 20,
|
|
666
|
-
color: accent
|
|
667
|
-
}) : null]
|
|
668
|
-
})]
|
|
669
|
-
}, account.accountId);
|
|
670
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
671
|
-
className: "h-px bg-border opacity-30 ml-space-12"
|
|
672
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(AccountAffordanceRow, {
|
|
673
|
-
icon: "plus",
|
|
674
|
-
label: t('accountMenu.addAnother'),
|
|
675
|
-
onPress: handlers.onAdd,
|
|
676
|
-
disabled: switchingDisabled,
|
|
677
|
-
theme: theme
|
|
678
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
679
|
-
className: "h-px bg-border opacity-30 ml-space-12"
|
|
680
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(AccountAffordanceRow, {
|
|
681
|
-
icon: "account-multiple-outline",
|
|
682
|
-
label: t('accountSwitcher.manageOnDevice'),
|
|
683
|
-
onPress: handlers.onManage,
|
|
684
|
-
disabled: switchingDisabled,
|
|
685
|
-
theme: theme
|
|
686
|
-
})]
|
|
687
|
-
});
|
|
688
|
-
const manageLabel = t('accountMenu.manage');
|
|
689
|
-
const switchLabel = t('accountMenu.switchAccount');
|
|
690
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
691
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
692
|
-
style: _oxyAuthChooserStyles.authChooserStyles.hero,
|
|
693
|
-
children: [current ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
694
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_pressableScale.PressableScale, {
|
|
695
|
-
onPress: handlers.onEditAvatar,
|
|
696
|
-
accessibilityRole: "button",
|
|
697
|
-
accessibilityLabel: t('editProfile.changeAvatar'),
|
|
698
|
-
style: _oxyAuthChooserStyles.authChooserStyles.heroAvatarPressable,
|
|
699
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_avatar.Avatar, {
|
|
700
|
-
source: current.avatarUrl ?? undefined,
|
|
701
|
-
name: current.displayName,
|
|
702
|
-
size: HERO_AVATAR_SIZE
|
|
703
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
704
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.heroAvatarRing, {
|
|
705
|
-
borderColor: currentAccent
|
|
706
|
-
}],
|
|
707
|
-
pointerEvents: "none"
|
|
708
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AvatarCameraBadge.default, {})]
|
|
709
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
710
|
-
style: _oxyAuthChooserStyles.authChooserStyles.heroNameBlock,
|
|
711
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
712
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.heroGreeting, {
|
|
713
|
-
color: theme.colors.text
|
|
714
|
-
}],
|
|
715
|
-
numberOfLines: 2,
|
|
716
|
-
children: t('accountMenu.greeting', {
|
|
717
|
-
name: current.displayName
|
|
718
|
-
})
|
|
719
|
-
}), currentAddress ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
720
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.heroAddress, {
|
|
721
|
-
color: theme.colors.textSecondary
|
|
722
|
-
}],
|
|
723
|
-
numberOfLines: 1,
|
|
724
|
-
children: currentAddress
|
|
725
|
-
}) : null]
|
|
726
|
-
})]
|
|
727
|
-
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
728
|
-
variant: "secondary",
|
|
729
|
-
size: "small",
|
|
730
|
-
onPress: handlers.onManage,
|
|
731
|
-
accessibilityLabel: manageLabel,
|
|
732
|
-
children: manageLabel
|
|
733
|
-
})]
|
|
734
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
|
|
735
|
-
className: "bg-fill overflow-hidden mb-space-16",
|
|
736
|
-
style: switchCardStyle,
|
|
737
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(HoverPressable, {
|
|
738
|
-
baseClassName: `flex-row items-center gap-space-12 px-space-12 py-[10px] min-h-[44px]${switchingDisabled ? ' opacity-60' : ''}`,
|
|
739
|
-
hoverClassName: "bg-fill-secondary",
|
|
740
|
-
onPress: toggleExpanded,
|
|
741
|
-
disabled: switchingDisabled,
|
|
742
|
-
accessibilityRole: "button"
|
|
743
|
-
// The ARIA prop, not `accessibilityState`: react-native-web 0.21
|
|
744
|
-
// forwards only this one, and RN maps it to
|
|
745
|
-
// `accessibilityState.expanded` natively — so the disclosure state
|
|
746
|
-
// reaches assistive tech on BOTH platforms.
|
|
747
|
-
,
|
|
748
|
-
"aria-expanded": expanded,
|
|
749
|
-
accessibilityLabel: switchLabel,
|
|
750
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
751
|
-
className: "flex-1 text-body text-text",
|
|
752
|
-
numberOfLines: 1,
|
|
753
|
-
children: switchLabel
|
|
754
|
-
}), expanded ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_avatarGroup.AvatarGroup, {
|
|
755
|
-
items: facepile,
|
|
756
|
-
layout: "stack",
|
|
757
|
-
size: FACEPILE_AVATAR_SIZE,
|
|
758
|
-
max: FACEPILE_MAX,
|
|
759
|
-
overlap: FACEPILE_OVERLAP,
|
|
760
|
-
variant: "thumb",
|
|
761
|
-
showInitials: true,
|
|
762
|
-
ringColor: theme.colors.card
|
|
763
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
764
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.chevronCircle, {
|
|
765
|
-
backgroundColor: theme.colors.contrast50
|
|
766
|
-
}],
|
|
767
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
|
768
|
-
style: chevronStyle,
|
|
769
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
770
|
-
name: "chevron-down",
|
|
771
|
-
size: 20,
|
|
772
|
-
color: theme.colors.text
|
|
773
|
-
})
|
|
774
|
-
})
|
|
775
|
-
})]
|
|
776
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
|
777
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.collapse, listStyle],
|
|
778
|
-
pointerEvents: expanded ? 'auto' : 'none',
|
|
779
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
780
|
-
style: _oxyAuthChooserStyles.authChooserStyles.collapseMeasure,
|
|
781
|
-
onLayout: event => setListContentHeight(event.nativeEvent.layout.height),
|
|
782
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
783
|
-
children: listItems
|
|
784
|
-
})
|
|
785
|
-
})
|
|
786
|
-
})]
|
|
787
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
788
|
-
className: "bg-fill rounded-[16px] overflow-hidden mb-space-16 px-space-12 py-[10px] gap-space-12",
|
|
789
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
790
|
-
className: "flex-row items-center gap-space-12 min-h-[24px]",
|
|
791
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
792
|
-
className: "w-[20px] items-center",
|
|
793
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
794
|
-
name: "cloud-outline",
|
|
795
|
-
size: ROW_ICON_SIZE,
|
|
796
|
-
color: theme.colors.textSecondary
|
|
797
|
-
})
|
|
798
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
799
|
-
className: "flex-1 text-body font-semibold text-text",
|
|
800
|
-
numberOfLines: 1,
|
|
801
|
-
children: t('accountMenu.storage.title')
|
|
802
|
-
})]
|
|
803
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_compositionBar.CompositionBar, {
|
|
804
|
-
categories: storageCategories,
|
|
805
|
-
selectedKey: storageSegment,
|
|
806
|
-
onSelect: toggleStorageSegment,
|
|
807
|
-
hintLabel: usageLabel,
|
|
808
|
-
formatReadout: (bytes, percent) => `${formatStorageGb(bytes)} · ${percent}%`
|
|
809
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
810
|
-
className: "flex-row gap-space-8",
|
|
811
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(StorageChip, {
|
|
812
|
-
label: t('accountMenu.storage.upgrade'),
|
|
813
|
-
onPress: menu.onUpgradeStorage
|
|
814
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(StorageChip, {
|
|
815
|
-
label: t('accountMenu.storage.manage'),
|
|
816
|
-
onPress: menu.onManageStorage
|
|
817
|
-
})]
|
|
818
|
-
})]
|
|
819
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_settingsList.SettingsListGroup, {
|
|
820
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListItem, {
|
|
821
|
-
icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(MenuIcon, {
|
|
822
|
-
name: "tray-arrow-down",
|
|
823
|
-
theme: theme
|
|
824
|
-
}),
|
|
825
|
-
title: t('accountMenu.data'),
|
|
826
|
-
onPress: menu.onOpenData
|
|
827
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListItem, {
|
|
828
|
-
icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(MenuIcon, {
|
|
829
|
-
name: "cog-outline",
|
|
830
|
-
theme: theme
|
|
831
|
-
}),
|
|
832
|
-
title: t('accountMenu.settings'),
|
|
833
|
-
onPress: menu.onOpenSettings
|
|
834
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListItem, {
|
|
835
|
-
icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(MenuIcon, {
|
|
836
|
-
name: "help-circle-outline",
|
|
837
|
-
theme: theme
|
|
838
|
-
}),
|
|
839
|
-
title: t('accountMenu.help'),
|
|
840
|
-
onPress: menu.onHelp
|
|
841
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListItem, {
|
|
842
|
-
icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(MenuIcon, {
|
|
843
|
-
name: "logout",
|
|
844
|
-
theme: theme
|
|
845
|
-
}),
|
|
846
|
-
title: t('accountMenu.signOut'),
|
|
847
|
-
onPress: menu.onSignOut,
|
|
848
|
-
showChevron: false
|
|
849
|
-
})]
|
|
850
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
851
|
-
className: "flex-row items-center justify-center gap-space-12 px-space-12 pb-space-8",
|
|
852
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
853
|
-
onPress: menu.onPrivacy,
|
|
854
|
-
accessibilityRole: "link",
|
|
855
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
856
|
-
className: "text-bodySmall text-text-secondary",
|
|
857
|
-
children: t('accountMenu.privacy')
|
|
858
|
-
})
|
|
859
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
860
|
-
className: "text-bodySmall text-text-tertiary",
|
|
861
|
-
children: "\xB7"
|
|
862
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
863
|
-
onPress: menu.onTerms,
|
|
864
|
-
accessibilityRole: "link",
|
|
865
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
866
|
-
className: "text-bodySmall text-text-secondary",
|
|
867
|
-
children: t('accountMenu.terms')
|
|
868
|
-
})
|
|
869
|
-
})]
|
|
870
|
-
})]
|
|
871
|
-
});
|
|
872
|
-
};
|
|
873
|
-
|
|
874
|
-
// ---------------------------------------------------------------------------
|
|
875
|
-
// Account-menu row building blocks (NativeWind)
|
|
876
|
-
// ---------------------------------------------------------------------------
|
|
877
|
-
|
|
878
|
-
/**
|
|
879
|
-
* An account-list AFFORDANCE row ("Add another account", "Manage accounts on
|
|
880
|
-
* this device") — a bordered circle sized to the avatar it stands in for, so its
|
|
881
|
-
* label lands on the same line as every account name above it. Own markup, like
|
|
882
|
-
* the account rows it closes: this list is not a Bloom grouped section.
|
|
883
|
-
*/
|
|
884
|
-
const AccountAffordanceRow = ({
|
|
885
|
-
icon,
|
|
886
|
-
label,
|
|
887
|
-
onPress,
|
|
888
|
-
disabled,
|
|
889
|
-
theme
|
|
890
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(HoverPressable, {
|
|
891
|
-
baseClassName: `flex-row items-center gap-space-12 px-space-12 py-[10px]${disabled ? ' opacity-60' : ''}`,
|
|
892
|
-
hoverClassName: "bg-fill-secondary",
|
|
893
|
-
onPress: onPress,
|
|
894
|
-
disabled: disabled,
|
|
895
|
-
accessibilityRole: "button",
|
|
896
|
-
accessibilityLabel: label,
|
|
897
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
898
|
-
className: "w-[36px] h-[36px] items-center justify-center rounded-radius-max border border-border",
|
|
899
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
900
|
-
name: icon,
|
|
901
|
-
size: BADGE_GLYPH_SIZE,
|
|
902
|
-
color: theme.colors.textSecondary
|
|
903
|
-
})
|
|
904
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
905
|
-
className: "flex-1 text-body font-semibold text-text",
|
|
906
|
-
numberOfLines: 1,
|
|
907
|
-
children: label
|
|
908
|
-
})]
|
|
909
|
-
});
|
|
910
|
-
|
|
911
|
-
/**
|
|
912
|
-
* The leading glyph for a grouped-section menu row, sized to Bloom's 20px icon
|
|
913
|
-
* column so the icons, the storage block's cloud and every row title align.
|
|
914
|
-
*/
|
|
915
|
-
const MenuIcon = ({
|
|
916
|
-
name,
|
|
917
|
-
theme
|
|
918
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
919
|
-
name: name,
|
|
920
|
-
size: ROW_ICON_SIZE,
|
|
921
|
-
color: theme.colors.textSecondary
|
|
922
|
-
});
|
|
923
|
-
|
|
924
|
-
/** A storage action chip — a bordered pill on the sheet background. */
|
|
925
|
-
const StorageChip = ({
|
|
926
|
-
label,
|
|
927
|
-
onPress
|
|
928
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(HoverPressable, {
|
|
929
|
-
baseClassName: "rounded-radius-max border border-border bg-bg py-[9px] px-[14px]",
|
|
930
|
-
hoverClassName: "bg-fill-secondary",
|
|
931
|
-
onPress: onPress,
|
|
932
|
-
accessibilityRole: "button",
|
|
933
|
-
accessibilityLabel: label,
|
|
934
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
935
|
-
className: "text-bodySmall font-semibold text-text",
|
|
936
|
-
children: label
|
|
937
|
-
})
|
|
938
|
-
});
|
|
939
|
-
const AccountRow = ({
|
|
940
|
-
account,
|
|
941
|
-
theme,
|
|
942
|
-
switching,
|
|
943
|
-
disabled,
|
|
944
|
-
onPress
|
|
945
|
-
}) => {
|
|
946
|
-
const accent = resolveAccentHex(account.color, theme.colors.primary);
|
|
947
|
-
const rowStyle = [_oxyAuthChooserStyles.authChooserStyles.accountRow, {
|
|
948
|
-
borderColor: account.isCurrent ? accent : theme.colors.border,
|
|
949
|
-
backgroundColor: theme.colors.card
|
|
950
|
-
}, disabled && !switching ? _oxyAuthChooserStyles.authChooserStyles.rowDisabled : null];
|
|
951
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_theme.BloomColorScope, {
|
|
952
|
-
colorPreset: toPreset(account.color),
|
|
953
|
-
asChild: true,
|
|
954
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
|
|
955
|
-
style: rowStyle,
|
|
956
|
-
onPress: onPress,
|
|
957
|
-
disabled: disabled,
|
|
958
|
-
accessibilityRole: "button",
|
|
959
|
-
accessibilityState: {
|
|
960
|
-
selected: account.isCurrent,
|
|
961
|
-
disabled
|
|
962
|
-
},
|
|
963
|
-
accessibilityLabel: account.displayName,
|
|
964
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
965
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.avatarRing, {
|
|
966
|
-
borderColor: account.isCurrent ? accent : 'transparent'
|
|
967
|
-
}],
|
|
968
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_avatar.Avatar, {
|
|
969
|
-
source: account.avatarUrl ?? undefined,
|
|
970
|
-
variant: "thumb",
|
|
971
|
-
name: account.displayName,
|
|
972
|
-
size: ROW_AVATAR_SIZE
|
|
973
|
-
})
|
|
974
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
975
|
-
style: _oxyAuthChooserStyles.authChooserStyles.rowMeta,
|
|
976
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
977
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.rowName, {
|
|
978
|
-
color: theme.colors.text
|
|
979
|
-
}],
|
|
980
|
-
numberOfLines: 1,
|
|
981
|
-
children: account.displayName
|
|
982
|
-
}), account.email ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
983
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.rowHandle, {
|
|
984
|
-
color: theme.colors.textSecondary
|
|
985
|
-
}],
|
|
986
|
-
numberOfLines: 1,
|
|
987
|
-
children: account.email
|
|
988
|
-
}) : null]
|
|
989
|
-
}), switching ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
990
|
-
name: "loading",
|
|
991
|
-
size: 20,
|
|
992
|
-
color: accent
|
|
993
|
-
}) : account.isCurrent ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
994
|
-
name: "check-circle",
|
|
995
|
-
size: 20,
|
|
996
|
-
color: accent
|
|
997
|
-
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
998
|
-
name: "chevron-right",
|
|
999
|
-
size: 20,
|
|
1000
|
-
color: theme.colors.textSecondary
|
|
1001
|
-
})]
|
|
1002
|
-
})
|
|
1003
|
-
});
|
|
1004
|
-
};
|
|
1005
|
-
|
|
1006
|
-
// ---------------------------------------------------------------------------
|
|
1007
|
-
// Sign-in view (add / signin) — NATIVE-facing today: on web `autoStartSignIn`
|
|
1008
|
-
// (fired from the subscribe pass / the add / back-to-sign-in handlers) moves the
|
|
1009
|
-
// view to `qr` almost immediately, so this renders only for a brief instant there.
|
|
1010
|
-
// ---------------------------------------------------------------------------
|
|
1011
|
-
|
|
1012
|
-
const SignInView = ({
|
|
1013
|
-
snapshot,
|
|
1014
|
-
theme,
|
|
1015
|
-
t,
|
|
1016
|
-
handlers,
|
|
1017
|
-
onSignInWithOxy,
|
|
1018
|
-
onScanQr,
|
|
1019
|
-
onCreateAccount
|
|
1020
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1021
|
-
style: _oxyAuthChooserStyles.authChooserStyles.signInBlock,
|
|
1022
|
-
children: [snapshot.accounts.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1023
|
-
style: _oxyAuthChooserStyles.authChooserStyles.rows,
|
|
1024
|
-
children: [snapshot.accounts.map(account => /*#__PURE__*/(0, _jsxRuntime.jsx)(AccountRow, {
|
|
1025
|
-
account: account,
|
|
1026
|
-
theme: theme,
|
|
1027
|
-
switching: snapshot.switchingAccountId === account.accountId,
|
|
1028
|
-
disabled: snapshot.switchingAccountId !== null,
|
|
1029
|
-
onPress: () => handlers.onSwitch(account.accountId)
|
|
1030
|
-
}, account.accountId)), /*#__PURE__*/(0, _jsxRuntime.jsx)(Dividerish, {
|
|
1031
|
-
theme: theme,
|
|
1032
|
-
label: t('signin.or') || 'or'
|
|
1033
|
-
})]
|
|
1034
|
-
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1035
|
-
variant: "primary",
|
|
1036
|
-
onPress: onSignInWithOxy,
|
|
1037
|
-
style: _oxyAuthChooserStyles.authChooserStyles.primaryButton,
|
|
1038
|
-
children: t('accountSwitcher.signInWithOxy') || 'Sign in with Oxy'
|
|
1039
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1040
|
-
variant: "secondary",
|
|
1041
|
-
onPress: onScanQr,
|
|
1042
|
-
style: _oxyAuthChooserStyles.authChooserStyles.secondaryButton,
|
|
1043
|
-
children: t('accountSwitcher.scanQr') || 'Scan a QR from another device'
|
|
1044
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(SignUpFooterLink, {
|
|
1045
|
-
theme: theme,
|
|
1046
|
-
t: t,
|
|
1047
|
-
onPress: onCreateAccount
|
|
1048
|
-
})]
|
|
1049
|
-
});
|
|
1050
|
-
const Dividerish = ({
|
|
1051
|
-
theme,
|
|
1052
|
-
label
|
|
1053
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1054
|
-
style: _oxyAuthChooserStyles.authChooserStyles.dividerRow,
|
|
1055
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1056
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.dividerLine, {
|
|
1057
|
-
backgroundColor: theme.colors.border
|
|
1058
|
-
}]
|
|
1059
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1060
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.dividerText, {
|
|
1061
|
-
color: theme.colors.textSecondary
|
|
1062
|
-
}],
|
|
1063
|
-
children: label
|
|
1064
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1065
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.dividerLine, {
|
|
1066
|
-
backgroundColor: theme.colors.border
|
|
1067
|
-
}]
|
|
1068
|
-
})]
|
|
1069
|
-
});
|
|
1070
|
-
|
|
1071
|
-
/** "New to Oxy? Create one" — shared by `SignInView` and `QrView`. */
|
|
1072
|
-
const SignUpFooterLink = ({
|
|
1073
|
-
theme,
|
|
1074
|
-
t,
|
|
1075
|
-
onPress
|
|
1076
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
1077
|
-
onPress: onPress,
|
|
1078
|
-
accessibilityRole: "button",
|
|
1079
|
-
style: _oxyAuthChooserStyles.authChooserStyles.footerLink,
|
|
1080
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1081
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.linkText, {
|
|
1082
|
-
color: theme.colors.textSecondary
|
|
1083
|
-
}],
|
|
1084
|
-
children: t('signin.createAccountLink') || 'New to Oxy? Create one'
|
|
1085
|
-
})
|
|
1086
|
-
});
|
|
1087
|
-
|
|
1088
|
-
/** "Already have an account? Sign in" — used by `SignUpView`. */
|
|
1089
|
-
const SignInFooterLink = ({
|
|
1090
|
-
theme,
|
|
1091
|
-
t,
|
|
1092
|
-
onPress
|
|
1093
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
1094
|
-
onPress: onPress,
|
|
1095
|
-
accessibilityRole: "button",
|
|
1096
|
-
style: _oxyAuthChooserStyles.authChooserStyles.footerLink,
|
|
1097
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1098
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.linkText, {
|
|
1099
|
-
color: theme.colors.textSecondary
|
|
1100
|
-
}],
|
|
1101
|
-
children: t('signup.backToSignInLink') || 'Already have an account? Sign in'
|
|
1102
|
-
})
|
|
1103
|
-
});
|
|
1104
|
-
|
|
1105
|
-
// ---------------------------------------------------------------------------
|
|
1106
|
-
// QR view — the PRIMARY web sign-in surface, and the ONLY sign-in surface on
|
|
1107
|
-
// native. Commons is ALWAYS the priority path (owner mandate): the QR here
|
|
1108
|
-
// and the "Get Commons" CTA below are the leading content everywhere they
|
|
1109
|
-
// appear. The passkey link is explicitly the lightweight, de-emphasized
|
|
1110
|
-
// alternative for someone who doesn't want to install Commons — same visual
|
|
1111
|
-
// subordination (a small text link, never a button) and the same "No
|
|
1112
|
-
// Commons?" framing in its copy wherever it's offered.
|
|
1113
|
-
// ---------------------------------------------------------------------------
|
|
1114
|
-
|
|
1115
|
-
const QrView = ({
|
|
1116
|
-
snapshot,
|
|
1117
|
-
theme,
|
|
1118
|
-
t,
|
|
1119
|
-
onRetry,
|
|
1120
|
-
passkeyAvailable,
|
|
1121
|
-
onSignInWithPasskey,
|
|
1122
|
-
passkeyPending,
|
|
1123
|
-
onCreateAccount
|
|
1124
|
-
}) => {
|
|
1125
|
-
const {
|
|
1126
|
-
signIn,
|
|
1127
|
-
commonsAvailability
|
|
1128
|
-
} = snapshot;
|
|
1129
|
-
const [showQrAnyway, setShowQrAnyway] = (0, _react.useState)(false);
|
|
1130
|
-
|
|
1131
|
-
// A ceremony FAILURE is surfaced as a toast by `handleSignInWithPasskey` — the
|
|
1132
|
-
// link itself never renders an inline error (owner mandate).
|
|
1133
|
-
const passkeyLink = passkeyAvailable && signIn.phase !== 'authorized' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
1134
|
-
onPress: onSignInWithPasskey,
|
|
1135
|
-
disabled: passkeyPending,
|
|
1136
|
-
accessibilityRole: "button",
|
|
1137
|
-
style: _oxyAuthChooserStyles.authChooserStyles.footerLink,
|
|
1138
|
-
testID: "passkey-signin-link",
|
|
1139
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1140
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.linkText, {
|
|
1141
|
-
color: theme.colors.textSecondary
|
|
1142
|
-
}],
|
|
1143
|
-
children: passkeyPending ? t('accountSwitcher.passkeySigningIn') || 'Signing in…' : t('accountSwitcher.useIdentityOnDevice') || 'No Commons? Use a passkey on this device instead'
|
|
1144
|
-
})
|
|
1145
|
-
}) : null;
|
|
1146
|
-
|
|
1147
|
-
// Native, Commons confirmed NOT installed: a same-device QR is a dead
|
|
1148
|
-
// end (the user can't scan their own screen) — lead with "Get Commons"
|
|
1149
|
-
// instead, and demote the QR to an explicit "I have it elsewhere" reveal.
|
|
1150
|
-
if (commonsAvailability === 'unavailable' && !showQrAnyway) {
|
|
1151
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1152
|
-
style: _oxyAuthChooserStyles.authChooserStyles.centeredBlock,
|
|
1153
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1154
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1155
|
-
color: theme.colors.textSecondary
|
|
1156
|
-
}],
|
|
1157
|
-
children: t('accountSwitcher.commonsNotInstalled') || "Don't have Commons? Get the app to sign in with your Oxy ID."
|
|
1158
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1159
|
-
variant: "primary",
|
|
1160
|
-
onPress: () => void _reactNative.Linking.openURL((0, _commonsStoreLinks.getCommonsAcquisitionUrl)(_reactNative.Platform.OS)),
|
|
1161
|
-
style: _oxyAuthChooserStyles.authChooserStyles.primaryButton,
|
|
1162
|
-
children: t('accountSwitcher.getCommons') || 'Get Commons'
|
|
1163
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
1164
|
-
onPress: () => setShowQrAnyway(true),
|
|
1165
|
-
accessibilityRole: "button",
|
|
1166
|
-
style: _oxyAuthChooserStyles.authChooserStyles.footerLink,
|
|
1167
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1168
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.linkText, {
|
|
1169
|
-
color: theme.colors.textSecondary
|
|
1170
|
-
}],
|
|
1171
|
-
children: t('accountSwitcher.showQrAnyway') || 'I have Commons on another device'
|
|
1172
|
-
})
|
|
1173
|
-
}), passkeyLink, /*#__PURE__*/(0, _jsxRuntime.jsx)(SignUpFooterLink, {
|
|
1174
|
-
theme: theme,
|
|
1175
|
-
t: t,
|
|
1176
|
-
onPress: onCreateAccount
|
|
1177
|
-
})]
|
|
1178
|
-
});
|
|
1179
|
-
}
|
|
1180
|
-
if (signIn.phase === 'error') {
|
|
1181
|
-
// The failure reason is toasted by the controller subscription above — no
|
|
1182
|
-
// inline error copy here (owner mandate).
|
|
1183
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1184
|
-
style: _oxyAuthChooserStyles.authChooserStyles.centeredBlock,
|
|
1185
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1186
|
-
variant: "secondary",
|
|
1187
|
-
onPress: onRetry,
|
|
1188
|
-
style: _oxyAuthChooserStyles.authChooserStyles.secondaryButton,
|
|
1189
|
-
children: t('common.actions.tryAgain') || 'Try again'
|
|
1190
|
-
}), passkeyLink]
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
if (signIn.phase === 'starting' || signIn.phase === 'authorized' || !signIn.qrPayload) {
|
|
1194
|
-
const label = signIn.phase === 'authorized' ? t('signin.status.signingIn') || 'Signing in…' : t('accountSwitcher.loading') || 'Preparing sign-in…';
|
|
1195
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1196
|
-
style: _oxyAuthChooserStyles.authChooserStyles.centeredBlock,
|
|
1197
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, {
|
|
1198
|
-
name: "loading",
|
|
1199
|
-
size: 26,
|
|
1200
|
-
color: theme.colors.primary
|
|
1201
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1202
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1203
|
-
color: theme.colors.textSecondary
|
|
1204
|
-
}],
|
|
1205
|
-
children: label
|
|
1206
|
-
})]
|
|
1207
|
-
});
|
|
1208
|
-
}
|
|
1209
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1210
|
-
style: _oxyAuthChooserStyles.authChooserStyles.centeredBlock,
|
|
1211
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1212
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.qrHeadline, {
|
|
1213
|
-
color: theme.colors.text
|
|
1214
|
-
}],
|
|
1215
|
-
children: t('accountSwitcher.qrHeadline') || 'Sign in with your Oxy identity'
|
|
1216
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1217
|
-
style: _oxyAuthChooserStyles.authChooserStyles.qrPlate,
|
|
1218
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeQrcodeSvg.default, {
|
|
1219
|
-
value: signIn.qrPayload,
|
|
1220
|
-
size: QR_SIZE,
|
|
1221
|
-
backgroundColor: QR_PLATE_BG,
|
|
1222
|
-
color: QR_FOREGROUND
|
|
1223
|
-
})
|
|
1224
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1225
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1226
|
-
color: theme.colors.textSecondary
|
|
1227
|
-
}],
|
|
1228
|
-
children: t('accountSwitcher.scanWithOxy') || 'Scan with Commons on your phone to continue.'
|
|
1229
|
-
}), passkeyLink, /*#__PURE__*/(0, _jsxRuntime.jsx)(SignUpFooterLink, {
|
|
1230
|
-
theme: theme,
|
|
1231
|
-
t: t,
|
|
1232
|
-
onPress: onCreateAccount
|
|
1233
|
-
})]
|
|
1234
|
-
});
|
|
1235
|
-
};
|
|
1236
|
-
|
|
1237
|
-
// ---------------------------------------------------------------------------
|
|
1238
|
-
// Sign-up view
|
|
1239
|
-
// ---------------------------------------------------------------------------
|
|
1240
|
-
|
|
1241
|
-
/** Debounced username-availability check over the existing SDK method. */
|
|
1242
|
-
function useUsernameAvailability(oxyServices, t) {
|
|
1243
|
-
const [status, setStatus] = (0, _react.useState)('idle');
|
|
1244
|
-
const timerRef = (0, _react.useRef)(null);
|
|
1245
|
-
const requestSeqRef = (0, _react.useRef)(0);
|
|
1246
|
-
const check = (0, _react.useCallback)(value => {
|
|
1247
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
1248
|
-
const seq = ++requestSeqRef.current;
|
|
1249
|
-
if (!value || value.length < 3) {
|
|
1250
|
-
setStatus('idle');
|
|
1251
|
-
return;
|
|
1252
|
-
}
|
|
1253
|
-
setStatus('checking');
|
|
1254
|
-
timerRef.current = setTimeout(() => {
|
|
1255
|
-
void oxyServices.checkUsernameAvailability(value).then(result => {
|
|
1256
|
-
if (seq !== requestSeqRef.current) return; // superseded by a newer check
|
|
1257
|
-
setStatus(result.available ? 'available' : 'taken');
|
|
1258
|
-
}).catch(() => {
|
|
1259
|
-
if (seq !== requestSeqRef.current) return;
|
|
1260
|
-
// Reset the (now stale) verdict rather than block on it, and surface
|
|
1261
|
-
// the failure as a toast — never an inline error inside the dialog.
|
|
1262
|
-
setStatus('idle');
|
|
1263
|
-
_bloom.toast.error(t('accounts.create.username.checkFailed') || 'Could not check availability');
|
|
1264
|
-
});
|
|
1265
|
-
}, 400);
|
|
1266
|
-
}, [oxyServices, t]);
|
|
1267
|
-
return {
|
|
1268
|
-
status,
|
|
1269
|
-
check
|
|
1270
|
-
};
|
|
1271
|
-
}
|
|
1272
|
-
const UsernameStatusText = ({
|
|
1273
|
-
status,
|
|
1274
|
-
theme,
|
|
1275
|
-
t
|
|
1276
|
-
}) => {
|
|
1277
|
-
if (status === 'idle') return null;
|
|
1278
|
-
if (status === 'checking') {
|
|
1279
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1280
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1281
|
-
color: theme.colors.textSecondary
|
|
1282
|
-
}],
|
|
1283
|
-
children: t('signup.usernameChecking') || 'Checking…'
|
|
1284
|
-
});
|
|
1285
|
-
}
|
|
1286
|
-
if (status === 'available') {
|
|
1287
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1288
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1289
|
-
color: theme.colors.success
|
|
1290
|
-
}],
|
|
1291
|
-
children: t('signup.usernameAvailable') || 'Available'
|
|
1292
|
-
});
|
|
1293
|
-
}
|
|
1294
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1295
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1296
|
-
color: theme.colors.error
|
|
1297
|
-
}],
|
|
1298
|
-
children: t('signup.usernameTaken') || 'This username is taken'
|
|
1299
|
-
});
|
|
1300
|
-
};
|
|
1301
|
-
const SignUpView = ({
|
|
1302
|
-
snapshot,
|
|
1303
|
-
theme,
|
|
1304
|
-
t,
|
|
1305
|
-
oxyServices,
|
|
1306
|
-
passkeyMode,
|
|
1307
|
-
onCreateWithPasskey,
|
|
1308
|
-
createPending,
|
|
1309
|
-
onOpenHub,
|
|
1310
|
-
onBackToSignIn
|
|
1311
|
-
}) => {
|
|
1312
|
-
const [username, setUsername] = (0, _react.useState)('');
|
|
1313
|
-
const {
|
|
1314
|
-
status: usernameStatus,
|
|
1315
|
-
check: checkUsername
|
|
1316
|
-
} = useUsernameAvailability(oxyServices, t);
|
|
1317
|
-
const canSubmit = username.trim().length >= 3 && usernameStatus === 'available' && !createPending;
|
|
1318
|
-
|
|
1319
|
-
// Native — Commons owns identity creation. Mirrors the QR view's own
|
|
1320
|
-
// commonsAvailability branch: deep-link straight in when installed, else
|
|
1321
|
-
// lead with the same "Get Commons" fallback.
|
|
1322
|
-
if (!(0, _isWebBrowser.isWebBrowser)()) {
|
|
1323
|
-
const commonsInstalled = snapshot.commonsAvailability === 'available';
|
|
1324
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1325
|
-
style: _oxyAuthChooserStyles.authChooserStyles.centeredBlock,
|
|
1326
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1327
|
-
variant: "primary",
|
|
1328
|
-
onPress: () => void _reactNative.Linking.openURL(commonsInstalled ? COMMONS_CREATE_IDENTITY_URL : (0, _commonsStoreLinks.getCommonsAcquisitionUrl)(_reactNative.Platform.OS)),
|
|
1329
|
-
style: _oxyAuthChooserStyles.authChooserStyles.primaryButton,
|
|
1330
|
-
children: commonsInstalled ? t('signup.createInCommons') || 'Create your identity in Commons' : t('accountSwitcher.getCommons') || 'Get Commons'
|
|
1331
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(SignInFooterLink, {
|
|
1332
|
-
theme: theme,
|
|
1333
|
-
t: t,
|
|
1334
|
-
onPress: onBackToSignIn
|
|
1335
|
-
})]
|
|
1336
|
-
});
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
// Web, first-party Oxy origin. Commons leads (owner mandate: it's ALWAYS
|
|
1340
|
-
// the priority path, everywhere the two appear) with a "Get Commons" CTA;
|
|
1341
|
-
// passkey creation is the de-emphasized alternative underneath for someone
|
|
1342
|
-
// who doesn't want to install anything — secondary button, introduced by
|
|
1343
|
-
// its own "No Commons?" framing, same subordination as the QR view's link.
|
|
1344
|
-
if (passkeyMode === 'direct') {
|
|
1345
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1346
|
-
style: _oxyAuthChooserStyles.authChooserStyles.signInBlock,
|
|
1347
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1348
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.qrHeadline, {
|
|
1349
|
-
color: theme.colors.text
|
|
1350
|
-
}],
|
|
1351
|
-
children: t('signup.commonsHeadline') || 'Create your identity in Commons'
|
|
1352
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1353
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1354
|
-
color: theme.colors.textSecondary
|
|
1355
|
-
}],
|
|
1356
|
-
children: t('signup.commonsExplainer') || 'Commons is your full self-custody Oxy identity — one app, works everywhere.'
|
|
1357
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1358
|
-
variant: "primary",
|
|
1359
|
-
onPress: () => void _reactNative.Linking.openURL((0, _commonsStoreLinks.getCommonsAcquisitionUrl)(_reactNative.Platform.OS)),
|
|
1360
|
-
style: _oxyAuthChooserStyles.authChooserStyles.primaryButton,
|
|
1361
|
-
children: t('accountSwitcher.getCommons') || 'Get Commons'
|
|
1362
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(Dividerish, {
|
|
1363
|
-
theme: theme,
|
|
1364
|
-
label: t('signin.or') || 'or'
|
|
1365
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1366
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1367
|
-
color: theme.colors.textSecondary
|
|
1368
|
-
}],
|
|
1369
|
-
children: t('signup.passkeyAlternative') || "No Commons? Create a passkey on this device instead"
|
|
1370
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
|
|
1371
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.usernameInput, {
|
|
1372
|
-
borderColor: theme.colors.border,
|
|
1373
|
-
color: theme.colors.text
|
|
1374
|
-
}],
|
|
1375
|
-
placeholder: t('signup.usernamePlaceholder') || 'Choose a username',
|
|
1376
|
-
placeholderTextColor: theme.colors.textSecondary,
|
|
1377
|
-
value: username,
|
|
1378
|
-
autoCapitalize: "none",
|
|
1379
|
-
autoCorrect: false,
|
|
1380
|
-
autoComplete: "username",
|
|
1381
|
-
onChangeText: value => {
|
|
1382
|
-
setUsername(value);
|
|
1383
|
-
checkUsername(value.trim());
|
|
1384
|
-
},
|
|
1385
|
-
testID: "signup-username-input"
|
|
1386
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(UsernameStatusText, {
|
|
1387
|
-
status: usernameStatus,
|
|
1388
|
-
theme: theme,
|
|
1389
|
-
t: t
|
|
1390
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1391
|
-
variant: "secondary",
|
|
1392
|
-
onPress: () => void onCreateWithPasskey(username.trim()),
|
|
1393
|
-
disabled: !canSubmit,
|
|
1394
|
-
style: _oxyAuthChooserStyles.authChooserStyles.secondaryButton,
|
|
1395
|
-
testID: "signup-create-button",
|
|
1396
|
-
children: createPending ? t('signup.creating') || 'Creating…' : t('signup.createAccount') || 'Create account'
|
|
1397
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(SignInFooterLink, {
|
|
1398
|
-
theme: theme,
|
|
1399
|
-
t: t,
|
|
1400
|
-
onPress: onBackToSignIn
|
|
1401
|
-
})]
|
|
1402
|
-
});
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
// Web, non-Oxy origin (b2): passkey creation can't run locally here — the
|
|
1406
|
-
// same WebAuthn RP-ID boundary as sign-in — so this opens the SAME
|
|
1407
|
-
// auth.oxy.so passkey hub popup `QrView`'s "No Commons?" link uses.
|
|
1408
|
-
// Completing EITHER a sign-in OR a fresh sign-up there relays the resulting
|
|
1409
|
-
// session back via the SAME poll/socket engine `showQr` drives.
|
|
1410
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1411
|
-
style: _oxyAuthChooserStyles.authChooserStyles.centeredBlock,
|
|
1412
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
1413
|
-
style: [_oxyAuthChooserStyles.authChooserStyles.mutedText, {
|
|
1414
|
-
color: theme.colors.textSecondary
|
|
1415
|
-
}],
|
|
1416
|
-
children: t('signup.hubExplainer') || 'Create your Oxy ID in a secure window, then come right back.'
|
|
1417
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
1418
|
-
variant: "primary",
|
|
1419
|
-
onPress: onOpenHub,
|
|
1420
|
-
style: _oxyAuthChooserStyles.authChooserStyles.primaryButton,
|
|
1421
|
-
children: t('signup.continueInWindow') || 'Continue in a new window'
|
|
1422
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(SignInFooterLink, {
|
|
1423
|
-
theme: theme,
|
|
1424
|
-
t: t,
|
|
1425
|
-
onPress: onBackToSignIn
|
|
1426
|
-
})]
|
|
369
|
+
onContinueWithOxy: () => void controller.signInWithOxy(),
|
|
370
|
+
alternatives: alternatives
|
|
1427
371
|
});
|
|
1428
372
|
};
|
|
1429
373
|
|
|
@@ -1443,7 +387,12 @@ const EMPTY_SNAPSHOT = {
|
|
|
1443
387
|
authorizeCode: null,
|
|
1444
388
|
qrPayload: null,
|
|
1445
389
|
expiresAt: null,
|
|
1446
|
-
error: null
|
|
390
|
+
error: null,
|
|
391
|
+
route: null,
|
|
392
|
+
routeFailed: false,
|
|
393
|
+
pushSentAt: null,
|
|
394
|
+
openedAt: null,
|
|
395
|
+
progress: 'idle'
|
|
1447
396
|
},
|
|
1448
397
|
commonsAvailability: 'unknown'
|
|
1449
398
|
};
|