@oxyhq/services 22.12.4 → 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 +5 -4
- 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 +72 -46
- 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 +6 -5
- 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 +73 -47
- 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 +30 -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 +30 -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 +9 -13
- package/src/ui/utils/deliveryPlatform.ts +65 -0
- package/src/ui/utils/oauthReturn.ts +79 -65
- 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
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed-in Oxy account MENU (`accounts` view) — a Google-account-menu-style
|
|
3
|
+
* full menu built entirely with NativeWind `className` (the dynamic per-account
|
|
4
|
+
* accent hex is the one inline style NativeWind cannot express). Structure:
|
|
5
|
+
*
|
|
6
|
+
* - HERO on its own chrome-free block: the current account's large pressable
|
|
7
|
+
* avatar (with a camera badge to change the photo), the greeting, the account
|
|
8
|
+
* address, and a "Manage your Oxy account" pill.
|
|
9
|
+
* - SWITCH ACCOUNT: a disclosure row whose corner animates from pill to card as
|
|
10
|
+
* the other switchable accounts + "Add another account" + "Manage accounts on
|
|
11
|
+
* this device" reveal beneath it.
|
|
12
|
+
* - OXY STORAGE: cloud + used/total + a composition meter + Upgrade / Manage chips.
|
|
13
|
+
* - MENU rows: Your data in Oxy · Oxy settings · Help & feedback · Sign out —
|
|
14
|
+
* Bloom's grouped section, the same component every other SDK settings surface
|
|
15
|
+
* uses, not a local row copy.
|
|
16
|
+
* - FOOTER: Privacy Policy · Terms of Service.
|
|
17
|
+
*
|
|
18
|
+
* All three blocks share ONE rhythm taken from that grouped section: a 12px
|
|
19
|
+
* content inset, a 12px gap after the leading element, 16px between blocks, and
|
|
20
|
+
* a 16px trailing chevron column.
|
|
21
|
+
*
|
|
22
|
+
* Collapse state is a plain `useState` toggled in the row's press handler — no
|
|
23
|
+
* effect hook, no derived-from-props sync.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type React from 'react';
|
|
27
|
+
import { Fragment, useCallback, useState } from 'react';
|
|
28
|
+
import { Pressable, View } from 'react-native';
|
|
29
|
+
import Animated, {
|
|
30
|
+
Extrapolation,
|
|
31
|
+
interpolate,
|
|
32
|
+
useAnimatedStyle,
|
|
33
|
+
useSharedValue,
|
|
34
|
+
withTiming,
|
|
35
|
+
} from 'react-native-reanimated';
|
|
36
|
+
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|
37
|
+
import { Avatar } from '@oxyhq/bloom/avatar';
|
|
38
|
+
import { AvatarGroup, type AvatarGroupItem } from '@oxyhq/bloom/avatar-group';
|
|
39
|
+
import { Button } from '@oxyhq/bloom/button';
|
|
40
|
+
import { PressableScale } from '@oxyhq/bloom/pressable-scale';
|
|
41
|
+
import { CompositionBar, type CompositionCategory } from '@oxyhq/bloom/composition-bar';
|
|
42
|
+
import { SettingsListGroup, SettingsListItem } from '@oxyhq/bloom/settings-list';
|
|
43
|
+
import { Text } from '@oxyhq/bloom/typography';
|
|
44
|
+
import type { AccountDialogSnapshot, SwitchableAccount } from '@oxyhq/core';
|
|
45
|
+
import { getNormalizedUserHandle } from '@oxyhq/core';
|
|
46
|
+
import AvatarCameraBadge from '../AvatarCameraBadge';
|
|
47
|
+
import { HoverPressable } from './primitives';
|
|
48
|
+
import { authChooserStyles as styles } from './styles';
|
|
49
|
+
import {
|
|
50
|
+
resolveAccentHex,
|
|
51
|
+
type AccountStorageModel,
|
|
52
|
+
type AccountsMenuActions,
|
|
53
|
+
type OxyAuthChooserHandlers,
|
|
54
|
+
type Theme,
|
|
55
|
+
type Translate,
|
|
56
|
+
} from './types';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Leading glyph for the rows that live in a Bloom grouped section (the MENU
|
|
60
|
+
* block) and for the storage card's cloud, which lines its title up with them.
|
|
61
|
+
* It is Bloom's OWN icon-slot size: `SettingsListItem` reserves a fixed 20px
|
|
62
|
+
* leading column and Bloom is consumed exactly as it ships, so a menu glyph
|
|
63
|
+
* larger than this would overhang into the row's title.
|
|
64
|
+
*/
|
|
65
|
+
const ROW_ICON_SIZE = 20;
|
|
66
|
+
/**
|
|
67
|
+
* The switch card's two corner states. Collapsed it is one row and reads as a
|
|
68
|
+
* PILL; opened it is a card holding rows, on the same 16px corner the Bloom
|
|
69
|
+
* grouped section below it uses. Interpolated across the reveal, never snapped.
|
|
70
|
+
*/
|
|
71
|
+
const SWITCH_CARD_PILL_RADIUS = 999;
|
|
72
|
+
const SWITCH_CARD_RADIUS = 16;
|
|
73
|
+
/**
|
|
74
|
+
* The fraction of the reveal over which the corner resolves. The corner is a
|
|
75
|
+
* FASTER gesture than the reveal — it has to be finished before the rows read as
|
|
76
|
+
* rows, or the card still looks like a pill while a list falls out of it — so it
|
|
77
|
+
* is clamped to the reveal's opening fraction instead of tracking it end to end.
|
|
78
|
+
* Measured in a browser against the 240ms reveal: the corner reaches its card
|
|
79
|
+
* value ~120ms in, with the list only ~20% revealed, and (mirrored) the pill is
|
|
80
|
+
* back ~250ms into the close, with the list already down to ~0.
|
|
81
|
+
*/
|
|
82
|
+
const SWITCH_CARD_RADIUS_SETTLE = 0.2;
|
|
83
|
+
/** Duration of the switch-list reveal. */
|
|
84
|
+
const SWITCH_REVEAL_MS = 240;
|
|
85
|
+
/** Diameter of an account row's avatar in the switch list (own markup). */
|
|
86
|
+
const SWITCH_AVATAR_SIZE = 36;
|
|
87
|
+
/** Glyph inside a bordered affordance badge, sized to the avatar it stands in for. */
|
|
88
|
+
const BADGE_GLYPH_SIZE = 19;
|
|
89
|
+
/** The hero block's large current-account avatar. */
|
|
90
|
+
const HERO_AVATAR_SIZE = 72;
|
|
91
|
+
/** Avatars shown in the switch row's facepile before it collapses into `+N`. */
|
|
92
|
+
const FACEPILE_MAX = 2;
|
|
93
|
+
/** Facepile avatar diameter — one clear step down from a switch-list avatar. */
|
|
94
|
+
const FACEPILE_AVATAR_SIZE = 32;
|
|
95
|
+
/**
|
|
96
|
+
* Facepile overlap. Well under Bloom's `size / 3` default: the stack draws the
|
|
97
|
+
* FIRST item on top, so a deep overlap would bury the trailing `+N` chip's own
|
|
98
|
+
* label under the avatar before it.
|
|
99
|
+
*/
|
|
100
|
+
const FACEPILE_OVERLAP = 4;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The hero's address line, shown under the "Hi, <name>!" greeting: the account's
|
|
104
|
+
* canonical `@oxy.so` email when it has one, else its normalized `@handle`. Never
|
|
105
|
+
* synthesizes a `username@oxy.so` address (the identity contract forbids it) — a
|
|
106
|
+
* non-Oxy or missing email falls back to `getNormalizedUserHandle`.
|
|
107
|
+
*/
|
|
108
|
+
function heroAddressLine(account: SwitchableAccount): string | null {
|
|
109
|
+
if (account.email?.toLowerCase().endsWith('@oxy.so')) {
|
|
110
|
+
return account.email;
|
|
111
|
+
}
|
|
112
|
+
const handle = getNormalizedUserHandle(account.user);
|
|
113
|
+
return handle ? `@${handle}` : null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* `bytes` → `"11.6 GB"`. Whole plan sizes read as whole numbers (`"17 GB"`, not
|
|
118
|
+
* `"17.0 GB"`), and anything ≥ 100 GB drops the decimal entirely.
|
|
119
|
+
*/
|
|
120
|
+
function formatStorageGb(bytes: number): string {
|
|
121
|
+
const gb = bytes / 1024 ** 3;
|
|
122
|
+
if (gb >= 100 || Number.isInteger(gb)) return `${Math.round(gb)} GB`;
|
|
123
|
+
return `${gb.toFixed(1)} GB`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface AccountsMenuViewProps {
|
|
127
|
+
snapshot: AccountDialogSnapshot;
|
|
128
|
+
theme: Theme;
|
|
129
|
+
t: Translate;
|
|
130
|
+
handlers: OxyAuthChooserHandlers;
|
|
131
|
+
storage: AccountStorageModel | null;
|
|
132
|
+
menu: AccountsMenuActions;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
136
|
+
snapshot,
|
|
137
|
+
theme,
|
|
138
|
+
t,
|
|
139
|
+
handlers,
|
|
140
|
+
storage,
|
|
141
|
+
menu,
|
|
142
|
+
}) => {
|
|
143
|
+
const [expanded, setExpanded] = useState(false);
|
|
144
|
+
// Measured natural height of the switch list, so the reveal animates to an
|
|
145
|
+
// exact height (and the content below reflows down smoothly) instead of a
|
|
146
|
+
// guessed max. The measuring wrapper is style-based, NOT className'd — on
|
|
147
|
+
// RN-Web `onLayout` never fires for className'd Views (see AGENTS.md).
|
|
148
|
+
const [listContentHeight, setListContentHeight] = useState(0);
|
|
149
|
+
// 0 = collapsed, 1 = expanded. Set imperatively in the toggle handler (no
|
|
150
|
+
// effect hook). On RN-Web there is no worklets plugin, so every shared value a
|
|
151
|
+
// mapper reads MUST be in its deps array or it freezes on the first frame
|
|
152
|
+
// (AGENTS.md "Reanimated (web)").
|
|
153
|
+
const listProgress = useSharedValue(0);
|
|
154
|
+
const listStyle = useAnimatedStyle(
|
|
155
|
+
() => ({ height: listProgress.value * listContentHeight, opacity: listProgress.value }),
|
|
156
|
+
[listProgress, listContentHeight],
|
|
157
|
+
);
|
|
158
|
+
const chevronStyle = useAnimatedStyle(
|
|
159
|
+
() => ({ transform: [{ rotate: `${listProgress.value * 180}deg` }] }),
|
|
160
|
+
[listProgress],
|
|
161
|
+
);
|
|
162
|
+
// Collapsed, the switch card is a single row and reads as a PILL; opened, it
|
|
163
|
+
// becomes a card holding rows and takes the grouped-section corner. The corner
|
|
164
|
+
// is driven off the SAME `listProgress` as the reveal — but clamped to its
|
|
165
|
+
// opening fraction, so it resolves early instead of trailing the rows.
|
|
166
|
+
const switchCardStyle = useAnimatedStyle(
|
|
167
|
+
() => ({
|
|
168
|
+
borderRadius: interpolate(
|
|
169
|
+
listProgress.value,
|
|
170
|
+
[0, SWITCH_CARD_RADIUS_SETTLE],
|
|
171
|
+
[SWITCH_CARD_PILL_RADIUS, SWITCH_CARD_RADIUS],
|
|
172
|
+
Extrapolation.CLAMP,
|
|
173
|
+
),
|
|
174
|
+
}),
|
|
175
|
+
[listProgress],
|
|
176
|
+
);
|
|
177
|
+
// `CompositionBar` ships as an interactive breakdown: a selected segment
|
|
178
|
+
// replaces its hint line with that segment's readout. Tapping the selected one
|
|
179
|
+
// again clears it.
|
|
180
|
+
const [storageSegment, setStorageSegment] = useState<string | null>(null);
|
|
181
|
+
const toggleStorageSegment = useCallback(
|
|
182
|
+
(key: string) => setStorageSegment((previous) => (previous === key ? null : key)),
|
|
183
|
+
[],
|
|
184
|
+
);
|
|
185
|
+
const toggleExpanded = useCallback(() => {
|
|
186
|
+
const next = !expanded;
|
|
187
|
+
setExpanded(next);
|
|
188
|
+
listProgress.value = withTiming(next ? 1 : 0, { duration: SWITCH_REVEAL_MS });
|
|
189
|
+
}, [expanded, listProgress]);
|
|
190
|
+
|
|
191
|
+
if (snapshot.loading && snapshot.accounts.length === 0) {
|
|
192
|
+
return (
|
|
193
|
+
<View className="items-center justify-center gap-space-12 py-space-24">
|
|
194
|
+
<MaterialCommunityIcons name="loading" size={24} color={theme.colors.textSecondary} />
|
|
195
|
+
<Text className="text-body text-text-secondary text-center">
|
|
196
|
+
{t('accountSwitcher.loading')}
|
|
197
|
+
</Text>
|
|
198
|
+
</View>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const switchingDisabled = snapshot.switchingAccountId !== null;
|
|
203
|
+
const current = snapshot.accounts.find((account) => account.isCurrent) ?? snapshot.accounts[0];
|
|
204
|
+
const others = current
|
|
205
|
+
? snapshot.accounts.filter((account) => account.accountId !== current.accountId)
|
|
206
|
+
: snapshot.accounts;
|
|
207
|
+
const currentAccent = current
|
|
208
|
+
? resolveAccentHex(current.color, theme.colors.primary)
|
|
209
|
+
: theme.colors.primary;
|
|
210
|
+
const currentAddress = current ? heroAddressLine(current) : null;
|
|
211
|
+
// The switch list repeats the CURRENT account (first, ringed) — unlike the old
|
|
212
|
+
// compact header it is not represented anywhere else once the hero moved out
|
|
213
|
+
// of the card, and the list is where you switch back to it.
|
|
214
|
+
const switchableAccounts = current ? [current, ...others] : others;
|
|
215
|
+
const facepile: AvatarGroupItem[] = switchableAccounts.map((account) => ({
|
|
216
|
+
id: account.accountId,
|
|
217
|
+
uri: account.avatarUrl ?? undefined,
|
|
218
|
+
displayName: account.displayName,
|
|
219
|
+
}));
|
|
220
|
+
|
|
221
|
+
// Used vs free is a two-part COMPOSITION (the parts always fill the bar), not
|
|
222
|
+
// a progress value — exactly what Bloom's `CompositionBar` models. Both colors
|
|
223
|
+
// are theme tokens, so the bar is correct in light and dark.
|
|
224
|
+
const storageCategories: CompositionCategory[] = storage
|
|
225
|
+
? [
|
|
226
|
+
{
|
|
227
|
+
key: 'used',
|
|
228
|
+
name: t('accountMenu.storage.used'),
|
|
229
|
+
amount: storage.usedBytes,
|
|
230
|
+
color: theme.colors.primary,
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
key: 'free',
|
|
234
|
+
name: t('accountMenu.storage.free'),
|
|
235
|
+
amount: Math.max(0, storage.limitBytes - storage.usedBytes),
|
|
236
|
+
color: theme.colors.contrast50,
|
|
237
|
+
},
|
|
238
|
+
]
|
|
239
|
+
: [];
|
|
240
|
+
const usageLabel = storage
|
|
241
|
+
? t('accountMenu.storage.usage', {
|
|
242
|
+
used: formatStorageGb(storage.usedBytes),
|
|
243
|
+
total: formatStorageGb(storage.limitBytes),
|
|
244
|
+
})
|
|
245
|
+
: t('accountMenu.storage.unavailable');
|
|
246
|
+
|
|
247
|
+
// The switch list body, revealed under the "Switch account" row. Own markup,
|
|
248
|
+
// not a Bloom grouped section: this is not a list of settings rows and the
|
|
249
|
+
// component is not a card container. It mirrors the section's rhythm by hand —
|
|
250
|
+
// 12px content inset, 12px after the avatar, a hairline between rows — and
|
|
251
|
+
// draws those hairlines INSIDE the animated clip, so a collapsed list never
|
|
252
|
+
// strands one against the header row.
|
|
253
|
+
const listItems = (
|
|
254
|
+
<>
|
|
255
|
+
{switchableAccounts.map((account, index) => {
|
|
256
|
+
const accent = resolveAccentHex(account.color, theme.colors.primary);
|
|
257
|
+
const isSwitching = snapshot.switchingAccountId === account.accountId;
|
|
258
|
+
return (
|
|
259
|
+
<Fragment key={account.accountId}>
|
|
260
|
+
{index > 0 ? <View className="h-px bg-border opacity-30 ml-space-12" /> : null}
|
|
261
|
+
<HoverPressable
|
|
262
|
+
baseClassName={`flex-row items-center gap-space-12 px-space-12 py-[10px]${
|
|
263
|
+
switchingDisabled ? ' opacity-60' : ''
|
|
264
|
+
}`}
|
|
265
|
+
hoverClassName="bg-fill-secondary"
|
|
266
|
+
onPress={() => handlers.onSwitch(account.accountId)}
|
|
267
|
+
disabled={switchingDisabled}
|
|
268
|
+
accessibilityRole="button"
|
|
269
|
+
accessibilityLabel={account.displayName}
|
|
270
|
+
>
|
|
271
|
+
<View>
|
|
272
|
+
<Avatar
|
|
273
|
+
source={account.avatarUrl ?? undefined}
|
|
274
|
+
variant="thumb"
|
|
275
|
+
name={account.displayName}
|
|
276
|
+
size={SWITCH_AVATAR_SIZE}
|
|
277
|
+
/>
|
|
278
|
+
{/* The accent ring is an OVERLAY: it costs the row no width, so
|
|
279
|
+
every avatar in the list starts on the same content line. */}
|
|
280
|
+
{account.isCurrent ? (
|
|
281
|
+
<View
|
|
282
|
+
style={[styles.currentAvatarRing, { borderColor: accent }]}
|
|
283
|
+
pointerEvents="none"
|
|
284
|
+
/>
|
|
285
|
+
) : null}
|
|
286
|
+
</View>
|
|
287
|
+
<View className="flex-1 min-w-0">
|
|
288
|
+
<Text className="text-body font-semibold text-text" numberOfLines={1}>
|
|
289
|
+
{account.displayName}
|
|
290
|
+
</Text>
|
|
291
|
+
{account.email ? (
|
|
292
|
+
<Text className="text-caption text-text-secondary" numberOfLines={1}>
|
|
293
|
+
{account.email}
|
|
294
|
+
</Text>
|
|
295
|
+
) : null}
|
|
296
|
+
</View>
|
|
297
|
+
{isSwitching ? (
|
|
298
|
+
<MaterialCommunityIcons name="loading" size={20} color={accent} />
|
|
299
|
+
) : null}
|
|
300
|
+
</HoverPressable>
|
|
301
|
+
</Fragment>
|
|
302
|
+
);
|
|
303
|
+
})}
|
|
304
|
+
|
|
305
|
+
<View className="h-px bg-border opacity-30 ml-space-12" />
|
|
306
|
+
<AccountAffordanceRow
|
|
307
|
+
icon="plus"
|
|
308
|
+
label={t('accountMenu.addAnother')}
|
|
309
|
+
onPress={handlers.onAdd}
|
|
310
|
+
disabled={switchingDisabled}
|
|
311
|
+
theme={theme}
|
|
312
|
+
/>
|
|
313
|
+
<View className="h-px bg-border opacity-30 ml-space-12" />
|
|
314
|
+
<AccountAffordanceRow
|
|
315
|
+
icon="account-multiple-outline"
|
|
316
|
+
label={t('accountSwitcher.manageOnDevice')}
|
|
317
|
+
onPress={handlers.onManage}
|
|
318
|
+
disabled={switchingDisabled}
|
|
319
|
+
theme={theme}
|
|
320
|
+
/>
|
|
321
|
+
</>
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
const manageLabel = t('accountMenu.manage');
|
|
325
|
+
const switchLabel = t('accountMenu.switchAccount');
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<View>
|
|
329
|
+
{/* HERO — chrome-free and centred, in the reference's reading order:
|
|
330
|
+
NOTHING above the avatar (the nav bar's Oxy wordmark stands alone), the
|
|
331
|
+
large pressable avatar (with a camera badge to change the photo), then
|
|
332
|
+
the greeting, then the account address under it, then the manage action. */}
|
|
333
|
+
<View style={styles.hero}>
|
|
334
|
+
{current ? (
|
|
335
|
+
<>
|
|
336
|
+
<PressableScale
|
|
337
|
+
onPress={handlers.onEditAvatar}
|
|
338
|
+
accessibilityRole="button"
|
|
339
|
+
accessibilityLabel={t('editProfile.changeAvatar')}
|
|
340
|
+
style={styles.heroAvatarPressable}
|
|
341
|
+
>
|
|
342
|
+
<Avatar
|
|
343
|
+
source={current.avatarUrl ?? undefined}
|
|
344
|
+
name={current.displayName}
|
|
345
|
+
size={HERO_AVATAR_SIZE}
|
|
346
|
+
/>
|
|
347
|
+
<View
|
|
348
|
+
style={[styles.heroAvatarRing, { borderColor: currentAccent }]}
|
|
349
|
+
pointerEvents="none"
|
|
350
|
+
/>
|
|
351
|
+
<AvatarCameraBadge />
|
|
352
|
+
</PressableScale>
|
|
353
|
+
<View style={styles.heroNameBlock}>
|
|
354
|
+
<Text style={[styles.heroGreeting, { color: theme.colors.text }]} numberOfLines={2}>
|
|
355
|
+
{t('accountMenu.greeting', { name: current.displayName })}
|
|
356
|
+
</Text>
|
|
357
|
+
{currentAddress ? (
|
|
358
|
+
<Text
|
|
359
|
+
style={[styles.heroAddress, { color: theme.colors.textSecondary }]}
|
|
360
|
+
numberOfLines={1}
|
|
361
|
+
>
|
|
362
|
+
{currentAddress}
|
|
363
|
+
</Text>
|
|
364
|
+
) : null}
|
|
365
|
+
</View>
|
|
366
|
+
</>
|
|
367
|
+
) : null}
|
|
368
|
+
{/* Bloom's own compact outlined pill — `secondary` is the outlined
|
|
369
|
+
variant, `small` the compact height; it hugs its label instead of
|
|
370
|
+
spanning the surface. */}
|
|
371
|
+
<Button
|
|
372
|
+
variant="secondary"
|
|
373
|
+
size="small"
|
|
374
|
+
onPress={handlers.onManage}
|
|
375
|
+
accessibilityLabel={manageLabel}
|
|
376
|
+
>
|
|
377
|
+
{manageLabel}
|
|
378
|
+
</Button>
|
|
379
|
+
</View>
|
|
380
|
+
|
|
381
|
+
{/* SWITCH ACCOUNT — own NativeWind card, NOT a Bloom grouped section: it
|
|
382
|
+
is a disclosure header over an animated list, not a list of settings
|
|
383
|
+
rows, and the grouped section is not a bare card container. */}
|
|
384
|
+
<Animated.View className="bg-fill overflow-hidden mb-space-16" style={switchCardStyle}>
|
|
385
|
+
<HoverPressable
|
|
386
|
+
baseClassName={`flex-row items-center gap-space-12 px-space-12 py-[10px] min-h-[44px]${
|
|
387
|
+
switchingDisabled ? ' opacity-60' : ''
|
|
388
|
+
}`}
|
|
389
|
+
hoverClassName="bg-fill-secondary"
|
|
390
|
+
onPress={toggleExpanded}
|
|
391
|
+
disabled={switchingDisabled}
|
|
392
|
+
accessibilityRole="button"
|
|
393
|
+
// The ARIA prop, not `accessibilityState`: react-native-web 0.21
|
|
394
|
+
// forwards only this one, and RN maps it to
|
|
395
|
+
// `accessibilityState.expanded` natively — so the disclosure state
|
|
396
|
+
// reaches assistive tech on BOTH platforms.
|
|
397
|
+
aria-expanded={expanded}
|
|
398
|
+
accessibilityLabel={switchLabel}
|
|
399
|
+
>
|
|
400
|
+
<Text className="flex-1 text-body text-text" numberOfLines={1}>
|
|
401
|
+
{switchLabel}
|
|
402
|
+
</Text>
|
|
403
|
+
{/* The facepile previews who you can switch to; once the list is open
|
|
404
|
+
it would just restate the rows below it. */}
|
|
405
|
+
{expanded ? null : (
|
|
406
|
+
<AvatarGroup
|
|
407
|
+
items={facepile}
|
|
408
|
+
layout="stack"
|
|
409
|
+
size={FACEPILE_AVATAR_SIZE}
|
|
410
|
+
max={FACEPILE_MAX}
|
|
411
|
+
overlap={FACEPILE_OVERLAP}
|
|
412
|
+
variant="thumb"
|
|
413
|
+
showInitials
|
|
414
|
+
ringColor={theme.colors.card}
|
|
415
|
+
/>
|
|
416
|
+
)}
|
|
417
|
+
<View style={[styles.chevronCircle, { backgroundColor: theme.colors.contrast50 }]}>
|
|
418
|
+
<Animated.View style={chevronStyle}>
|
|
419
|
+
<MaterialCommunityIcons name="chevron-down" size={20} color={theme.colors.text} />
|
|
420
|
+
</Animated.View>
|
|
421
|
+
</View>
|
|
422
|
+
</HoverPressable>
|
|
423
|
+
|
|
424
|
+
{/* Animated reveal: an overflow-clipped container whose height + opacity
|
|
425
|
+
are driven by `listProgress`; the inner style-based wrapper measures
|
|
426
|
+
the natural content height via `onLayout`. */}
|
|
427
|
+
<Animated.View
|
|
428
|
+
style={[styles.collapse, listStyle]}
|
|
429
|
+
pointerEvents={expanded ? 'auto' : 'none'}
|
|
430
|
+
>
|
|
431
|
+
<View
|
|
432
|
+
style={styles.collapseMeasure}
|
|
433
|
+
onLayout={(event) => setListContentHeight(event.nativeEvent.layout.height)}
|
|
434
|
+
>
|
|
435
|
+
<View>{listItems}</View>
|
|
436
|
+
</View>
|
|
437
|
+
</Animated.View>
|
|
438
|
+
</Animated.View>
|
|
439
|
+
|
|
440
|
+
{/* OXY STORAGE — own NativeWind card for the same reason: a title, a meter
|
|
441
|
+
and two chips are not settings rows. Its cloud sits in the same 20px
|
|
442
|
+
column Bloom's own rows use, so the title below lines up with the menu
|
|
443
|
+
titles. */}
|
|
444
|
+
<View className="bg-fill rounded-[16px] overflow-hidden mb-space-16 px-space-12 py-[10px] gap-space-12">
|
|
445
|
+
<View className="flex-row items-center gap-space-12 min-h-[24px]">
|
|
446
|
+
<View className="w-[20px] items-center">
|
|
447
|
+
<MaterialCommunityIcons
|
|
448
|
+
name="cloud-outline"
|
|
449
|
+
size={ROW_ICON_SIZE}
|
|
450
|
+
color={theme.colors.textSecondary}
|
|
451
|
+
/>
|
|
452
|
+
</View>
|
|
453
|
+
<Text className="flex-1 text-body font-semibold text-text" numberOfLines={1}>
|
|
454
|
+
{t('accountMenu.storage.title')}
|
|
455
|
+
</Text>
|
|
456
|
+
</View>
|
|
457
|
+
<CompositionBar
|
|
458
|
+
categories={storageCategories}
|
|
459
|
+
selectedKey={storageSegment}
|
|
460
|
+
onSelect={toggleStorageSegment}
|
|
461
|
+
hintLabel={usageLabel}
|
|
462
|
+
formatReadout={(bytes, percent) => `${formatStorageGb(bytes)} · ${percent}%`}
|
|
463
|
+
/>
|
|
464
|
+
<View className="flex-row gap-space-8">
|
|
465
|
+
<StorageChip label={t('accountMenu.storage.upgrade')} onPress={menu.onUpgradeStorage} />
|
|
466
|
+
<StorageChip label={t('accountMenu.storage.manage')} onPress={menu.onManageStorage} />
|
|
467
|
+
</View>
|
|
468
|
+
</View>
|
|
469
|
+
|
|
470
|
+
{/* MENU — the same stock grouped section. */}
|
|
471
|
+
<SettingsListGroup>
|
|
472
|
+
<SettingsListItem
|
|
473
|
+
icon={<MenuIcon name="tray-arrow-down" theme={theme} />}
|
|
474
|
+
title={t('accountMenu.data')}
|
|
475
|
+
onPress={menu.onOpenData}
|
|
476
|
+
/>
|
|
477
|
+
<SettingsListItem
|
|
478
|
+
icon={<MenuIcon name="cog-outline" theme={theme} />}
|
|
479
|
+
title={t('accountMenu.settings')}
|
|
480
|
+
onPress={menu.onOpenSettings}
|
|
481
|
+
/>
|
|
482
|
+
<SettingsListItem
|
|
483
|
+
icon={<MenuIcon name="help-circle-outline" theme={theme} />}
|
|
484
|
+
title={t('accountMenu.help')}
|
|
485
|
+
onPress={menu.onHelp}
|
|
486
|
+
/>
|
|
487
|
+
<SettingsListItem
|
|
488
|
+
icon={<MenuIcon name="logout" theme={theme} />}
|
|
489
|
+
title={t('accountMenu.signOut')}
|
|
490
|
+
onPress={menu.onSignOut}
|
|
491
|
+
showChevron={false}
|
|
492
|
+
/>
|
|
493
|
+
</SettingsListGroup>
|
|
494
|
+
|
|
495
|
+
{/* FOOTER. */}
|
|
496
|
+
<View className="flex-row items-center justify-center gap-space-12 px-space-12 pb-space-8">
|
|
497
|
+
<Pressable onPress={menu.onPrivacy} accessibilityRole="link">
|
|
498
|
+
<Text className="text-bodySmall text-text-secondary">{t('accountMenu.privacy')}</Text>
|
|
499
|
+
</Pressable>
|
|
500
|
+
<Text className="text-bodySmall text-text-tertiary">·</Text>
|
|
501
|
+
<Pressable onPress={menu.onTerms} accessibilityRole="link">
|
|
502
|
+
<Text className="text-bodySmall text-text-secondary">{t('accountMenu.terms')}</Text>
|
|
503
|
+
</Pressable>
|
|
504
|
+
</View>
|
|
505
|
+
</View>
|
|
506
|
+
);
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* An account-list AFFORDANCE row ("Add another account", "Manage accounts on
|
|
511
|
+
* this device") — a bordered circle sized to the avatar it stands in for, so its
|
|
512
|
+
* label lands on the same line as every account name above it. Own markup, like
|
|
513
|
+
* the account rows it closes: this list is not a Bloom grouped section.
|
|
514
|
+
*/
|
|
515
|
+
const AccountAffordanceRow: React.FC<{
|
|
516
|
+
icon: keyof typeof MaterialCommunityIcons.glyphMap;
|
|
517
|
+
label: string;
|
|
518
|
+
onPress: () => void;
|
|
519
|
+
disabled?: boolean;
|
|
520
|
+
theme: Theme;
|
|
521
|
+
}> = ({ icon, label, onPress, disabled, theme }) => (
|
|
522
|
+
<HoverPressable
|
|
523
|
+
baseClassName={`flex-row items-center gap-space-12 px-space-12 py-[10px]${
|
|
524
|
+
disabled ? ' opacity-60' : ''
|
|
525
|
+
}`}
|
|
526
|
+
hoverClassName="bg-fill-secondary"
|
|
527
|
+
onPress={onPress}
|
|
528
|
+
disabled={disabled}
|
|
529
|
+
accessibilityRole="button"
|
|
530
|
+
accessibilityLabel={label}
|
|
531
|
+
>
|
|
532
|
+
<View className="w-[36px] h-[36px] items-center justify-center rounded-radius-max border border-border">
|
|
533
|
+
<MaterialCommunityIcons
|
|
534
|
+
name={icon}
|
|
535
|
+
size={BADGE_GLYPH_SIZE}
|
|
536
|
+
color={theme.colors.textSecondary}
|
|
537
|
+
/>
|
|
538
|
+
</View>
|
|
539
|
+
<Text className="flex-1 text-body font-semibold text-text" numberOfLines={1}>
|
|
540
|
+
{label}
|
|
541
|
+
</Text>
|
|
542
|
+
</HoverPressable>
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* The leading glyph for a grouped-section menu row, sized to Bloom's 20px icon
|
|
547
|
+
* column so the icons, the storage block's cloud and every row title align.
|
|
548
|
+
*/
|
|
549
|
+
const MenuIcon: React.FC<{
|
|
550
|
+
name: keyof typeof MaterialCommunityIcons.glyphMap;
|
|
551
|
+
theme: Theme;
|
|
552
|
+
}> = ({ name, theme }) => (
|
|
553
|
+
<MaterialCommunityIcons name={name} size={ROW_ICON_SIZE} color={theme.colors.textSecondary} />
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
/** A storage action chip — a bordered pill on the sheet background. */
|
|
557
|
+
const StorageChip: React.FC<{ label: string; onPress: () => void }> = ({ label, onPress }) => (
|
|
558
|
+
<HoverPressable
|
|
559
|
+
baseClassName="rounded-radius-max border border-border bg-bg py-[9px] px-[14px]"
|
|
560
|
+
hoverClassName="bg-fill-secondary"
|
|
561
|
+
onPress={onPress}
|
|
562
|
+
accessibilityRole="button"
|
|
563
|
+
accessibilityLabel={label}
|
|
564
|
+
>
|
|
565
|
+
<Text className="text-bodySmall font-semibold text-text">{label}</Text>
|
|
566
|
+
</HoverPressable>
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
export default AccountsMenuView;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sign-in ENTRY (`signin` / `add` views) — ONE primary action.
|
|
3
|
+
*
|
|
4
|
+
* Issue #691, Phase 5: the normal experience presents no menu of authentication
|
|
5
|
+
* methods. The user sees "Continue with Oxy"; Oxy — not the user — then picks
|
|
6
|
+
* how the request reaches their Commons identity, and the request surface shows
|
|
7
|
+
* honest progress. Everything else (a QR from another device, a passkey on this
|
|
8
|
+
* device, getting Commons, creating an account) lives behind "Having trouble?".
|
|
9
|
+
*
|
|
10
|
+
* Existing accounts still render ABOVE the CTA: "continue as one of these" is a
|
|
11
|
+
* choice of WHO, not of HOW, so it is not one of the competing method buttons
|
|
12
|
+
* the issue removes.
|
|
13
|
+
*
|
|
14
|
+
* On web this view is transient — the container auto-starts the flow the instant
|
|
15
|
+
* the view is reached, because the request surface (QR, or "Check Commons on
|
|
16
|
+
* your phone") IS the primary route there, never something behind a tap.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type React from 'react';
|
|
20
|
+
import { View } from 'react-native';
|
|
21
|
+
import { Button } from '@oxyhq/bloom/button';
|
|
22
|
+
import type { AccountDialogSnapshot } from '@oxyhq/core';
|
|
23
|
+
import TroubleDisclosure, { type TroubleAction } from './TroubleDisclosure';
|
|
24
|
+
import { AccountRow, Dividerish, SubtleLink } from './primitives';
|
|
25
|
+
import { authChooserStyles as styles } from './styles';
|
|
26
|
+
import type { OxyAuthChooserHandlers, SignInAlternatives, Theme, Translate } from './types';
|
|
27
|
+
|
|
28
|
+
interface SignInEntryViewProps {
|
|
29
|
+
snapshot: AccountDialogSnapshot;
|
|
30
|
+
theme: Theme;
|
|
31
|
+
t: Translate;
|
|
32
|
+
handlers: OxyAuthChooserHandlers;
|
|
33
|
+
/** The ONE primary action. Starts the flow; Oxy chooses the route from there. */
|
|
34
|
+
onContinueWithOxy: () => void;
|
|
35
|
+
alternatives: SignInAlternatives;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const SignInEntryView: React.FC<SignInEntryViewProps> = ({
|
|
39
|
+
snapshot,
|
|
40
|
+
theme,
|
|
41
|
+
t,
|
|
42
|
+
handlers,
|
|
43
|
+
onContinueWithOxy,
|
|
44
|
+
alternatives,
|
|
45
|
+
}) => {
|
|
46
|
+
// The entry has no chosen route yet, so nothing here can have failed: the
|
|
47
|
+
// alternatives stay behind the disclosure unconditionally.
|
|
48
|
+
const troubleActions: TroubleAction[] = [
|
|
49
|
+
{
|
|
50
|
+
key: 'scan-qr-link',
|
|
51
|
+
label: t('accountSwitcher.scanQr'),
|
|
52
|
+
onPress: alternatives.onShowQr,
|
|
53
|
+
},
|
|
54
|
+
...(alternatives.passkeyAvailable
|
|
55
|
+
? [
|
|
56
|
+
{
|
|
57
|
+
key: 'passkey-signin-link',
|
|
58
|
+
label: alternatives.passkeyPending
|
|
59
|
+
? t('accountSwitcher.passkeySigningIn')
|
|
60
|
+
: t('accountSwitcher.useIdentityOnDevice'),
|
|
61
|
+
onPress: alternatives.onSignInWithPasskey,
|
|
62
|
+
disabled: alternatives.passkeyPending,
|
|
63
|
+
},
|
|
64
|
+
]
|
|
65
|
+
: []),
|
|
66
|
+
{
|
|
67
|
+
key: 'get-commons-link',
|
|
68
|
+
label: t('accountSwitcher.getCommons'),
|
|
69
|
+
onPress: alternatives.onGetCommons,
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<View style={styles.signInBlock}>
|
|
75
|
+
{snapshot.accounts.length > 0 ? (
|
|
76
|
+
<View style={styles.rows}>
|
|
77
|
+
{snapshot.accounts.map((account) => (
|
|
78
|
+
<AccountRow
|
|
79
|
+
key={account.accountId}
|
|
80
|
+
account={account}
|
|
81
|
+
theme={theme}
|
|
82
|
+
switching={snapshot.switchingAccountId === account.accountId}
|
|
83
|
+
disabled={snapshot.switchingAccountId !== null}
|
|
84
|
+
onPress={() => handlers.onSwitch(account.accountId)}
|
|
85
|
+
/>
|
|
86
|
+
))}
|
|
87
|
+
<Dividerish theme={theme} label={t('signin.or')} />
|
|
88
|
+
</View>
|
|
89
|
+
) : null}
|
|
90
|
+
|
|
91
|
+
<Button
|
|
92
|
+
variant="primary"
|
|
93
|
+
onPress={onContinueWithOxy}
|
|
94
|
+
style={styles.primaryButton}
|
|
95
|
+
testID="continue-with-oxy"
|
|
96
|
+
>
|
|
97
|
+
{t('accountSwitcher.continueWithOxy')}
|
|
98
|
+
</Button>
|
|
99
|
+
|
|
100
|
+
{/* Account CREATION is not an authentication method — it is the way in for
|
|
101
|
+
someone who has no Oxy ID yet — so it keeps its own subordinate link
|
|
102
|
+
rather than hiding behind a troubleshooting affordance. */}
|
|
103
|
+
<SubtleLink
|
|
104
|
+
label={t('signin.createAccountLink')}
|
|
105
|
+
theme={theme}
|
|
106
|
+
onPress={alternatives.onCreateAccount}
|
|
107
|
+
testID="create-account-link"
|
|
108
|
+
/>
|
|
109
|
+
|
|
110
|
+
<TroubleDisclosure actions={troubleActions} revealed={false} theme={theme} t={t} />
|
|
111
|
+
</View>
|
|
112
|
+
);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export default SignInEntryView;
|