@oxyhq/services 27.1.3 → 29.0.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/LICENSE +202 -661
- package/NOTICE +16 -0
- package/README.md +67 -2
- package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionModule.kt +178 -0
- package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionProvider.kt +99 -0
- package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionStore.kt +115 -0
- package/expo-module.config.json +1 -0
- package/lib/commonjs/index.js +78 -16
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/boot/runProviderColdBoot.js +7 -0
- package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/commonjs/ui/client.js +12 -7
- package/lib/commonjs/ui/client.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +10 -27
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAuthChooser.js +132 -44
- package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +4 -2
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/SurfaceScreen.js +31 -3
- package/lib/commonjs/ui/components/SurfaceScreen.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js +209 -84
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js +25 -7
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/primitives.js +35 -22
- package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/signInProgress.js +5 -0
- package/lib/commonjs/ui/components/authChooser/signInProgress.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/types.js +11 -0
- package/lib/commonjs/ui/components/authChooser/types.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +257 -306
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +27 -37
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/oxyContextHelpers.js +0 -29
- package/lib/commonjs/ui/context/oxyContextHelpers.js.map +1 -1
- package/lib/commonjs/ui/context/useOxyAccountGraph.js +6 -17
- package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/commonjs/ui/hooks/accountDialogSnapshot.js +42 -0
- package/lib/commonjs/ui/hooks/accountDialogSnapshot.js.map +1 -0
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +0 -19
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/useDeviceSwitcher.js +57 -0
- package/lib/commonjs/ui/hooks/useDeviceSwitcher.js.map +1 -0
- package/lib/commonjs/ui/hooks/useI18n.js +22 -3
- package/lib/commonjs/ui/hooks/useI18n.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +46 -153
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/index.js +12 -7
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/routes.js +85 -73
- package/lib/commonjs/ui/navigation/routes.js.map +1 -1
- package/lib/commonjs/ui/navigation/surfaces.js +8 -7
- package/lib/commonjs/ui/navigation/surfaces.js.map +1 -1
- package/lib/commonjs/ui/runtime/createOxyRuntime.js +433 -0
- package/lib/commonjs/ui/runtime/createOxyRuntime.js.map +1 -0
- package/lib/commonjs/ui/runtime/index.js +63 -0
- package/lib/commonjs/ui/runtime/index.js.map +1 -0
- package/lib/commonjs/ui/runtime/runtimeContext.js +83 -0
- package/lib/commonjs/ui/runtime/runtimeContext.js.map +1 -0
- package/lib/commonjs/ui/runtime/types.js +6 -0
- package/lib/commonjs/ui/runtime/types.js.map +1 -0
- package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js +57 -0
- package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js.map +1 -0
- package/lib/commonjs/ui/screens/AccountMembersScreen.js +3 -4
- package/lib/commonjs/ui/screens/AccountMembersScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/CreateAccountScreen.js +3 -12
- package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +6 -5
- package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +4 -4
- package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +1 -1
- package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +4 -2
- package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
- package/lib/commonjs/ui/server.js +1 -2
- package/lib/commonjs/ui/server.js.map +1 -1
- package/lib/commonjs/ui/session/authStore.js +45 -9
- package/lib/commonjs/ui/session/authStore.js.map +1 -1
- package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js +306 -0
- package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js.map +1 -0
- package/lib/commonjs/ui/stores/authStore.js +154 -55
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/stores/followTargetStore.js +27 -0
- package/lib/commonjs/ui/stores/followTargetStore.js.map +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js +2 -36
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/index.js +20 -9
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/boot/runProviderColdBoot.js +7 -0
- package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/module/ui/client.js +1 -2
- package/lib/module/ui/client.js.map +1 -1
- package/lib/module/ui/components/OxyAccountDialogScreen.js +10 -27
- package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/module/ui/components/OxyAuthChooser.js +134 -44
- package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +5 -3
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/SurfaceScreen.js +33 -5
- package/lib/module/ui/components/SurfaceScreen.js.map +1 -1
- package/lib/module/ui/components/authChooser/AccountsMenuView.js +210 -85
- package/lib/module/ui/components/authChooser/AccountsMenuView.js.map +1 -1
- package/lib/module/ui/components/authChooser/SignInEntryView.js +25 -7
- package/lib/module/ui/components/authChooser/SignInEntryView.js.map +1 -1
- package/lib/module/ui/components/authChooser/primitives.js +35 -22
- package/lib/module/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/module/ui/components/authChooser/signInProgress.js +5 -0
- package/lib/module/ui/components/authChooser/signInProgress.js.map +1 -1
- package/lib/module/ui/components/authChooser/types.js +11 -0
- package/lib/module/ui/components/authChooser/types.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +251 -303
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +27 -37
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/oxyContextHelpers.js +0 -28
- package/lib/module/ui/context/oxyContextHelpers.js.map +1 -1
- package/lib/module/ui/context/useOxyAccountGraph.js +6 -17
- package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/module/ui/hooks/accountDialogSnapshot.js +38 -0
- package/lib/module/ui/hooks/accountDialogSnapshot.js.map +1 -0
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +0 -19
- package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/module/ui/hooks/useDeviceSwitcher.js +53 -0
- package/lib/module/ui/hooks/useDeviceSwitcher.js.map +1 -0
- package/lib/module/ui/hooks/useI18n.js +24 -4
- package/lib/module/ui/hooks/useI18n.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +47 -155
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/index.js +1 -2
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/routes.js +84 -72
- package/lib/module/ui/navigation/routes.js.map +1 -1
- package/lib/module/ui/navigation/surfaces.js +6 -6
- package/lib/module/ui/navigation/surfaces.js.map +1 -1
- package/lib/module/ui/runtime/createOxyRuntime.js +430 -0
- package/lib/module/ui/runtime/createOxyRuntime.js.map +1 -0
- package/lib/module/ui/runtime/index.js +15 -0
- package/lib/module/ui/runtime/index.js.map +1 -0
- package/lib/module/ui/runtime/runtimeContext.js +75 -0
- package/lib/module/ui/runtime/runtimeContext.js.map +1 -0
- package/lib/module/ui/runtime/types.js +4 -0
- package/lib/module/ui/runtime/types.js.map +1 -0
- package/lib/module/ui/runtime/useRuntimeSnapshot.js +52 -0
- package/lib/module/ui/runtime/useRuntimeSnapshot.js.map +1 -0
- package/lib/module/ui/screens/AccountMembersScreen.js +4 -5
- package/lib/module/ui/screens/AccountMembersScreen.js.map +1 -1
- package/lib/module/ui/screens/CreateAccountScreen.js +4 -13
- package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustCenterScreen.js +6 -5
- package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +5 -5
- package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustRewardsScreen.js +1 -1
- package/lib/module/ui/screens/trust/TrustRulesScreen.js +4 -2
- package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
- package/lib/module/ui/server.js +0 -1
- package/lib/module/ui/server.js.map +1 -1
- package/lib/module/ui/session/authStore.js +46 -11
- package/lib/module/ui/session/authStore.js.map +1 -1
- package/lib/module/ui/session/sharedDeviceCredentialStore.js +302 -0
- package/lib/module/ui/session/sharedDeviceCredentialStore.js.map +1 -0
- package/lib/module/ui/stores/authStore.js +154 -55
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/stores/followTargetStore.js +25 -0
- package/lib/module/ui/stores/followTargetStore.js.map +1 -1
- package/lib/module/ui/utils/avatarUtils.js +2 -35
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +6 -4
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/client.d.ts +1 -2
- 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.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
- package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts +3 -1
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +18 -6
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts +33 -1
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +35 -4
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +8 -12
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts +0 -2
- package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +9 -1
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts +1 -3
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts +15 -0
- package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts +49 -0
- package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts +13 -0
- package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +23 -18
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +1 -2
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts +15 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts +144 -0
- package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/index.d.ts +16 -0
- package/lib/typescript/commonjs/ui/runtime/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts +43 -0
- package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/types.d.ts +89 -0
- package/lib/typescript/commonjs/ui/runtime/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
- package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/screens/AccountMembersScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/server.d.ts +0 -1
- package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/authStore.d.ts +60 -9
- package/lib/typescript/commonjs/ui/session/authStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
- package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/stores/authStore.d.ts +49 -5
- package/lib/typescript/commonjs/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts +8 -1
- package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/navigation.d.ts +26 -0
- package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts +2 -10
- package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +6 -4
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/module/ui/client.d.ts +1 -2
- 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.map +1 -1
- package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/SurfaceScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
- package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts +3 -1
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +18 -6
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/types.d.ts +33 -1
- package/lib/typescript/module/ui/components/authChooser/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +35 -4
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +8 -12
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts +0 -2
- package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +9 -1
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts +1 -3
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts +15 -0
- package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts +49 -0
- package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/useI18n.d.ts +13 -0
- package/lib/typescript/module/ui/hooks/useI18n.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +23 -18
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +1 -2
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts +15 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/surfaces.d.ts.map +1 -1
- package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts +144 -0
- package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/index.d.ts +16 -0
- package/lib/typescript/module/ui/runtime/index.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/runtimeContext.d.ts +43 -0
- package/lib/typescript/module/ui/runtime/runtimeContext.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/types.d.ts +89 -0
- package/lib/typescript/module/ui/runtime/types.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
- package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
- package/lib/typescript/module/ui/screens/AccountMembersScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/server.d.ts +0 -1
- package/lib/typescript/module/ui/server.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/authStore.d.ts +60 -9
- package/lib/typescript/module/ui/session/authStore.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
- package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
- package/lib/typescript/module/ui/stores/authStore.d.ts +49 -5
- package/lib/typescript/module/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/module/ui/stores/followTargetStore.d.ts +8 -1
- package/lib/typescript/module/ui/stores/followTargetStore.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/navigation.d.ts +26 -0
- package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/avatarUtils.d.ts +2 -10
- package/lib/typescript/module/ui/utils/avatarUtils.d.ts.map +1 -1
- package/package.json +8 -8
- package/plugins/withSharedDeviceSessionProvider.js +102 -0
- package/plugins/withSharedDeviceSessionReader.js +57 -0
- package/src/__tests__/esmSourcePurity.test.ts +61 -0
- package/src/index.ts +36 -9
- package/src/ui/boot/runProviderColdBoot.ts +7 -0
- package/src/ui/client.ts +1 -2
- package/src/ui/components/OxyAccountDialogScreen.tsx +10 -29
- package/src/ui/components/OxyAuthChooser.tsx +149 -50
- package/src/ui/components/OxyProvider.tsx +7 -5
- package/src/ui/components/SurfaceScreen.tsx +28 -4
- package/src/ui/components/__tests__/followTargetButton.test.ts +39 -0
- package/src/ui/components/authChooser/AccountsMenuView.tsx +246 -96
- package/src/ui/components/authChooser/SignInEntryView.tsx +31 -8
- package/src/ui/components/authChooser/primitives.tsx +37 -23
- package/src/ui/components/authChooser/signInProgress.ts +4 -0
- package/src/ui/components/authChooser/types.ts +34 -1
- package/src/ui/context/OxyContext.tsx +269 -324
- package/src/ui/context/hooks/useAuthOperations.ts +32 -35
- package/src/ui/context/oxyContextHelpers.ts +0 -30
- package/src/ui/context/oxyContextTypes.ts +9 -1
- package/src/ui/context/useOxyAccountGraph.ts +5 -19
- package/src/ui/hooks/accountDialogSnapshot.ts +37 -0
- package/src/ui/hooks/mutations/useAccountMutations.ts +0 -19
- package/src/ui/hooks/queries/__tests__/userCache.test.ts +12 -1
- package/src/ui/hooks/useDeviceSwitcher.ts +110 -0
- package/src/ui/hooks/useI18n.ts +23 -3
- package/src/ui/hooks/useSessionManagement.ts +62 -211
- package/src/ui/index.ts +1 -2
- package/src/ui/navigation/routes.ts +85 -75
- package/src/ui/navigation/surfaces.ts +6 -9
- package/src/ui/runtime/createOxyRuntime.ts +623 -0
- package/src/ui/runtime/index.ts +34 -0
- package/src/ui/runtime/runtimeContext.tsx +111 -0
- package/src/ui/runtime/types.ts +110 -0
- package/src/ui/runtime/useRuntimeSnapshot.ts +52 -0
- package/src/ui/screens/AccountMembersScreen.tsx +6 -5
- package/src/ui/screens/CreateAccountScreen.tsx +3 -16
- package/src/ui/screens/trust/TrustCenterScreen.tsx +7 -7
- package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +4 -5
- package/src/ui/screens/trust/TrustRewardsScreen.tsx +1 -1
- package/src/ui/screens/trust/TrustRulesScreen.tsx +3 -2
- package/src/ui/server.ts +0 -1
- package/src/ui/session/__tests__/authStore.test.ts +90 -0
- package/src/ui/session/__tests__/sharedDeviceCredentialStore.test.ts +289 -0
- package/src/ui/session/authStore.ts +78 -9
- package/src/ui/session/sharedDeviceCredentialStore.ts +318 -0
- package/src/ui/stores/authStore.ts +171 -43
- package/src/ui/stores/followTargetStore.ts +24 -1
- package/src/ui/types/navigation.ts +26 -0
- package/src/ui/utils/avatarUtils.ts +2 -37
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +0 -64
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +0 -1
- package/lib/commonjs/ui/screens/trust/trustTier.js +0 -23
- package/lib/commonjs/ui/screens/trust/trustTier.js.map +0 -1
- package/lib/commonjs/ui/stores/accountStore.js +0 -221
- package/lib/commonjs/ui/stores/accountStore.js.map +0 -1
- package/lib/module/ui/hooks/useSwitchableAccounts.js +0 -60
- package/lib/module/ui/hooks/useSwitchableAccounts.js.map +0 -1
- package/lib/module/ui/screens/trust/trustTier.js +0 -19
- package/lib/module/ui/screens/trust/trustTier.js.map +0 -1
- package/lib/module/ui/stores/accountStore.js +0 -213
- package/lib/module/ui/stores/accountStore.js.map +0 -1
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +0 -23
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts +0 -9
- package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/stores/accountStore.d.ts +0 -27
- package/lib/typescript/commonjs/ui/stores/accountStore.d.ts.map +0 -1
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +0 -23
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
- package/lib/typescript/module/ui/screens/trust/trustTier.d.ts +0 -9
- package/lib/typescript/module/ui/screens/trust/trustTier.d.ts.map +0 -1
- package/lib/typescript/module/ui/stores/accountStore.d.ts +0 -27
- package/lib/typescript/module/ui/stores/accountStore.d.ts.map +0 -1
- package/src/ui/hooks/useSwitchableAccounts.ts +0 -75
- package/src/ui/screens/trust/trustTier.ts +0 -20
- package/src/ui/stores/accountStore.ts +0 -264
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
* avatar (with a camera badge to change the photo), the greeting, the account
|
|
8
8
|
* address, and a "Manage your Oxy account" pill.
|
|
9
9
|
* - SWITCH ACCOUNT: a disclosure row whose corner animates from pill to card as
|
|
10
|
-
* the
|
|
11
|
-
*
|
|
10
|
+
* the device's people + "Add another account" + "Manage accounts on this
|
|
11
|
+
* device" reveal beneath it. The list is grouped BY PERSON (ADR 0002): an
|
|
12
|
+
* account sits under the human who can operate it, and the same organization
|
|
13
|
+
* reachable through two people is two rows under two names — the thing a list
|
|
14
|
+
* keyed by account id structurally cannot say.
|
|
12
15
|
* - OXY STORAGE: cloud + used/total + a composition meter + Upgrade / Manage chips.
|
|
13
16
|
* - MENU rows: Your data in Oxy · Oxy settings · Help & feedback · Sign out —
|
|
14
17
|
* Bloom's grouped section, the same component every other SDK settings surface
|
|
@@ -41,13 +44,18 @@ import { PressableScale } from '@oxyhq/bloom/pressable-scale';
|
|
|
41
44
|
import { CompositionBar, type CompositionCategory } from '@oxyhq/bloom/composition-bar';
|
|
42
45
|
import { SettingsListGroup, SettingsListItem } from '@oxyhq/bloom/settings-list';
|
|
43
46
|
import { Text } from '@oxyhq/bloom/typography';
|
|
44
|
-
import
|
|
45
|
-
|
|
47
|
+
import {
|
|
48
|
+
showsPrincipalHeaders,
|
|
49
|
+
type AccountDialogSnapshot,
|
|
50
|
+
type SwitcherContextRow,
|
|
51
|
+
type SwitcherPrincipalRow,
|
|
52
|
+
} from '@oxyhq/core';
|
|
46
53
|
import AvatarCameraBadge from '../AvatarCameraBadge';
|
|
47
54
|
import { HoverPressable } from './primitives';
|
|
48
55
|
import { authChooserStyles as styles } from './styles';
|
|
49
56
|
import {
|
|
50
57
|
resolveAccentHex,
|
|
58
|
+
type AccountHeroModel,
|
|
51
59
|
type AccountStorageModel,
|
|
52
60
|
type AccountsMenuActions,
|
|
53
61
|
type OxyAuthChooserHandlers,
|
|
@@ -84,6 +92,11 @@ const SWITCH_CARD_RADIUS_SETTLE = 0.2;
|
|
|
84
92
|
const SWITCH_REVEAL_MS = 240;
|
|
85
93
|
/** Diameter of an account row's avatar in the switch list (own markup). */
|
|
86
94
|
const SWITCH_AVATAR_SIZE = 36;
|
|
95
|
+
/**
|
|
96
|
+
* The person's avatar above their block of accounts. Smaller than the account
|
|
97
|
+
* rows beneath it: the header labels the group, the rows are the targets.
|
|
98
|
+
*/
|
|
99
|
+
const PRINCIPAL_AVATAR_SIZE = 24;
|
|
87
100
|
/** Glyph inside a bordered affordance badge, sized to the avatar it stands in for. */
|
|
88
101
|
const BADGE_GLYPH_SIZE = 19;
|
|
89
102
|
/** The hero block's large current-account avatar. */
|
|
@@ -99,20 +112,6 @@ const FACEPILE_AVATAR_SIZE = 32;
|
|
|
99
112
|
*/
|
|
100
113
|
const FACEPILE_OVERLAP = 4;
|
|
101
114
|
|
|
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
115
|
/**
|
|
117
116
|
* `bytes` → `"11.6 GB"`. Whole plan sizes read as whole numbers (`"17 GB"`, not
|
|
118
117
|
* `"17.0 GB"`), and anything ≥ 100 GB drops the decimal entirely.
|
|
@@ -125,6 +124,10 @@ function formatStorageGb(bytes: number): string {
|
|
|
125
124
|
|
|
126
125
|
interface AccountsMenuViewProps {
|
|
127
126
|
snapshot: AccountDialogSnapshot;
|
|
127
|
+
/** The device's people, each with the accounts they may act as. */
|
|
128
|
+
principals: SwitcherPrincipalRow[];
|
|
129
|
+
/** The current account, rendered large. `null` before the session resolves. */
|
|
130
|
+
hero: AccountHeroModel | null;
|
|
128
131
|
theme: Theme;
|
|
129
132
|
t: Translate;
|
|
130
133
|
handlers: OxyAuthChooserHandlers;
|
|
@@ -134,6 +137,8 @@ interface AccountsMenuViewProps {
|
|
|
134
137
|
|
|
135
138
|
const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
136
139
|
snapshot,
|
|
140
|
+
principals,
|
|
141
|
+
hero,
|
|
137
142
|
theme,
|
|
138
143
|
t,
|
|
139
144
|
handlers,
|
|
@@ -188,7 +193,7 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
188
193
|
listProgress.value = withTiming(next ? 1 : 0, { duration: SWITCH_REVEAL_MS });
|
|
189
194
|
}, [expanded, listProgress]);
|
|
190
195
|
|
|
191
|
-
if (snapshot.loading &&
|
|
196
|
+
if (snapshot.loading && principals.length === 0) {
|
|
192
197
|
return (
|
|
193
198
|
<View className="items-center justify-center gap-space-12 py-space-24">
|
|
194
199
|
<MaterialCommunityIcons name="loading" size={24} color={theme.colors.textSecondary} />
|
|
@@ -199,24 +204,26 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
199
204
|
);
|
|
200
205
|
}
|
|
201
206
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
207
|
+
// Activation and the two removals all mutate the same device, so any one of
|
|
208
|
+
// them in flight disables every row: a second press would race the first for
|
|
209
|
+
// which context the server ends up electing as active.
|
|
210
|
+
const busy =
|
|
211
|
+
snapshot.activatingContextId !== null ||
|
|
212
|
+
snapshot.removingContextId !== null ||
|
|
213
|
+
snapshot.removingPrincipalId !== null;
|
|
214
|
+
const currentAccent = hero?.accentHex ?? theme.colors.primary;
|
|
215
|
+
// Naming the person above each block earns its place only when the grouping
|
|
216
|
+
// carries information — a second person, or somebody with more than one
|
|
217
|
+
// account. On a one-person, one-account device it would just repeat the hero.
|
|
218
|
+
const showPrincipalHeaders = showsPrincipalHeaders(principals);
|
|
219
|
+
const contextRows = principals.flatMap((principal) => principal.contexts);
|
|
220
|
+
// Remounts the measured wrapper when the rows change, so the collapse animates
|
|
221
|
+
// to the new natural height instead of the previous one.
|
|
222
|
+
const switchListKey = contextRows.map((context) => context.contextId).join(':');
|
|
223
|
+
const facepile: AvatarGroupItem[] = contextRows.map((context) => ({
|
|
224
|
+
id: context.contextId,
|
|
225
|
+
uri: context.avatarUrl ?? undefined,
|
|
226
|
+
displayName: context.displayName,
|
|
220
227
|
}));
|
|
221
228
|
|
|
222
229
|
// Used vs free is a two-part COMPOSITION (the parts always fill the bar), not
|
|
@@ -253,62 +260,47 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
253
260
|
// strands one against the header row.
|
|
254
261
|
const listItems = (
|
|
255
262
|
<>
|
|
256
|
-
{
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
<Avatar
|
|
274
|
-
source={account.avatarUrl ?? undefined}
|
|
275
|
-
variant="thumb"
|
|
276
|
-
name={account.displayName}
|
|
277
|
-
size={SWITCH_AVATAR_SIZE}
|
|
278
|
-
/>
|
|
279
|
-
{/* The accent ring is an OVERLAY: it costs the row no width, so
|
|
280
|
-
every avatar in the list starts on the same content line. */}
|
|
281
|
-
{account.isCurrent ? (
|
|
282
|
-
<View
|
|
283
|
-
style={[styles.currentAvatarRing, { borderColor: accent }]}
|
|
284
|
-
pointerEvents="none"
|
|
285
|
-
/>
|
|
286
|
-
) : null}
|
|
287
|
-
</View>
|
|
288
|
-
<View className="flex-1 min-w-0">
|
|
289
|
-
<Text className="text-body font-semibold text-text" numberOfLines={1}>
|
|
290
|
-
{account.displayName}
|
|
291
|
-
</Text>
|
|
292
|
-
{account.email ? (
|
|
293
|
-
<Text className="text-caption text-text-secondary" numberOfLines={1}>
|
|
294
|
-
{account.email}
|
|
295
|
-
</Text>
|
|
296
|
-
) : null}
|
|
297
|
-
</View>
|
|
298
|
-
{isSwitching ? (
|
|
299
|
-
<MaterialCommunityIcons name="loading" size={20} color={accent} />
|
|
263
|
+
{principals.map((principal, principalIndex) => (
|
|
264
|
+
<Fragment key={principal.principalId}>
|
|
265
|
+
{principalIndex > 0 ? <View className="h-px bg-border opacity-30" /> : null}
|
|
266
|
+
{showPrincipalHeaders ? (
|
|
267
|
+
<PrincipalHeaderRow
|
|
268
|
+
principal={principal}
|
|
269
|
+
removing={snapshot.removingPrincipalId === principal.principalId}
|
|
270
|
+
disabled={busy}
|
|
271
|
+
onSignOut={() => handlers.onRemovePrincipal(principal.principalId)}
|
|
272
|
+
theme={theme}
|
|
273
|
+
t={t}
|
|
274
|
+
/>
|
|
275
|
+
) : null}
|
|
276
|
+
{principal.contexts.map((context, contextIndex) => (
|
|
277
|
+
<Fragment key={context.contextId}>
|
|
278
|
+
{contextIndex > 0 || showPrincipalHeaders ? (
|
|
279
|
+
<View className="h-px bg-border opacity-30 ml-space-12" />
|
|
300
280
|
) : null}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
281
|
+
<ContextRow
|
|
282
|
+
context={context}
|
|
283
|
+
principalName={principal.displayName}
|
|
284
|
+
accent={resolveAccentHex(context.color, theme.colors.primary)}
|
|
285
|
+
activating={snapshot.activatingContextId === context.contextId}
|
|
286
|
+
removing={snapshot.removingContextId === context.contextId}
|
|
287
|
+
disabled={busy}
|
|
288
|
+
onActivate={() => handlers.onActivate(context.contextId)}
|
|
289
|
+
onRemove={() => handlers.onRemoveContext(context.contextId)}
|
|
290
|
+
theme={theme}
|
|
291
|
+
t={t}
|
|
292
|
+
/>
|
|
293
|
+
</Fragment>
|
|
294
|
+
))}
|
|
295
|
+
</Fragment>
|
|
296
|
+
))}
|
|
305
297
|
|
|
306
298
|
<View className="h-px bg-border opacity-30 ml-space-12" />
|
|
307
299
|
<AccountAffordanceRow
|
|
308
300
|
icon="plus"
|
|
309
301
|
label={t('accountMenu.addAnother')}
|
|
310
302
|
onPress={handlers.onAdd}
|
|
311
|
-
disabled={
|
|
303
|
+
disabled={busy}
|
|
312
304
|
theme={theme}
|
|
313
305
|
/>
|
|
314
306
|
<View className="h-px bg-border opacity-30 ml-space-12" />
|
|
@@ -316,7 +308,7 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
316
308
|
icon="account-multiple-outline"
|
|
317
309
|
label={t('accountSwitcher.manageOnDevice')}
|
|
318
310
|
onPress={handlers.onManage}
|
|
319
|
-
disabled={
|
|
311
|
+
disabled={busy}
|
|
320
312
|
theme={theme}
|
|
321
313
|
/>
|
|
322
314
|
</>
|
|
@@ -332,7 +324,7 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
332
324
|
large pressable avatar (with a camera badge to change the photo), then
|
|
333
325
|
the greeting, then the account address under it, then the manage action. */}
|
|
334
326
|
<View style={styles.hero}>
|
|
335
|
-
{
|
|
327
|
+
{hero ? (
|
|
336
328
|
<>
|
|
337
329
|
<PressableScale
|
|
338
330
|
onPress={handlers.onEditAvatar}
|
|
@@ -341,8 +333,8 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
341
333
|
style={styles.heroAvatarPressable}
|
|
342
334
|
>
|
|
343
335
|
<Avatar
|
|
344
|
-
source={
|
|
345
|
-
name={
|
|
336
|
+
source={hero.avatarUrl ?? undefined}
|
|
337
|
+
name={hero.displayName}
|
|
346
338
|
size={HERO_AVATAR_SIZE}
|
|
347
339
|
/>
|
|
348
340
|
<View
|
|
@@ -353,14 +345,14 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
353
345
|
</PressableScale>
|
|
354
346
|
<View style={styles.heroNameBlock}>
|
|
355
347
|
<Text style={[styles.heroGreeting, { color: theme.colors.text }]} numberOfLines={2}>
|
|
356
|
-
{t('accountMenu.greeting', { name:
|
|
348
|
+
{t('accountMenu.greeting', { name: hero.displayName })}
|
|
357
349
|
</Text>
|
|
358
|
-
{
|
|
350
|
+
{hero.addressLine ? (
|
|
359
351
|
<Text
|
|
360
352
|
style={[styles.heroAddress, { color: theme.colors.textSecondary }]}
|
|
361
353
|
numberOfLines={1}
|
|
362
354
|
>
|
|
363
|
-
{
|
|
355
|
+
{hero.addressLine}
|
|
364
356
|
</Text>
|
|
365
357
|
) : null}
|
|
366
358
|
</View>
|
|
@@ -387,11 +379,11 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
387
379
|
<View className="bg-fill">
|
|
388
380
|
<HoverPressable
|
|
389
381
|
baseClassName={`flex-row items-center gap-space-12 px-space-12 py-[10px] min-h-[44px]${
|
|
390
|
-
|
|
382
|
+
busy ? ' opacity-60' : ''
|
|
391
383
|
}`}
|
|
392
384
|
hoverClassName="bg-fill-secondary"
|
|
393
385
|
onPress={toggleExpanded}
|
|
394
|
-
disabled={
|
|
386
|
+
disabled={busy}
|
|
395
387
|
accessibilityRole="button"
|
|
396
388
|
// The ARIA prop, not `accessibilityState`: react-native-web 0.21
|
|
397
389
|
// forwards only this one, and RN maps it to
|
|
@@ -432,7 +424,7 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
432
424
|
pointerEvents={expanded ? 'auto' : 'none'}
|
|
433
425
|
>
|
|
434
426
|
<View
|
|
435
|
-
key={
|
|
427
|
+
key={switchListKey}
|
|
436
428
|
style={styles.collapseMeasure}
|
|
437
429
|
onLayout={(event) => setListContentHeight(event.nativeEvent.layout.height)}
|
|
438
430
|
>
|
|
@@ -520,6 +512,164 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
520
512
|
);
|
|
521
513
|
};
|
|
522
514
|
|
|
515
|
+
/**
|
|
516
|
+
* The person a block of accounts hangs off, with the one action that removes
|
|
517
|
+
* THEM rather than one of their accounts.
|
|
518
|
+
*
|
|
519
|
+
* The distinction is the reason this row exists: dropping Alice's route to an
|
|
520
|
+
* organization is not the same as dropping Alice, and on a shared device the
|
|
521
|
+
* second must not touch Nate's route to the same organization. Two different
|
|
522
|
+
* server calls, two different rows, never one control doing both.
|
|
523
|
+
*/
|
|
524
|
+
const PrincipalHeaderRow: React.FC<{
|
|
525
|
+
principal: SwitcherPrincipalRow;
|
|
526
|
+
removing: boolean;
|
|
527
|
+
disabled: boolean;
|
|
528
|
+
onSignOut: () => void;
|
|
529
|
+
theme: Theme;
|
|
530
|
+
t: Translate;
|
|
531
|
+
}> = ({ principal, removing, disabled, onSignOut, theme, t }) => {
|
|
532
|
+
const signOutLabel = t('accountSwitcher.principal.signOut', { name: principal.displayName });
|
|
533
|
+
return (
|
|
534
|
+
<View className="flex-row items-center gap-space-12 px-space-12 pt-space-12 pb-space-8">
|
|
535
|
+
<Avatar
|
|
536
|
+
source={principal.avatarUrl ?? undefined}
|
|
537
|
+
variant="thumb"
|
|
538
|
+
name={principal.displayName}
|
|
539
|
+
size={PRINCIPAL_AVATAR_SIZE}
|
|
540
|
+
/>
|
|
541
|
+
<View className="flex-1 min-w-0">
|
|
542
|
+
<Text className="text-caption font-semibold text-text" numberOfLines={1}>
|
|
543
|
+
{principal.displayName}
|
|
544
|
+
</Text>
|
|
545
|
+
{principal.handle ? (
|
|
546
|
+
<Text className="text-caption text-text-tertiary" numberOfLines={1}>
|
|
547
|
+
{`@${principal.handle}`}
|
|
548
|
+
</Text>
|
|
549
|
+
) : null}
|
|
550
|
+
</View>
|
|
551
|
+
<HoverPressable
|
|
552
|
+
baseClassName={`rounded-radius-max px-space-8 py-[4px]${disabled ? ' opacity-60' : ''}`}
|
|
553
|
+
hoverClassName="bg-fill-secondary"
|
|
554
|
+
onPress={onSignOut}
|
|
555
|
+
disabled={disabled}
|
|
556
|
+
accessibilityRole="button"
|
|
557
|
+
accessibilityLabel={signOutLabel}
|
|
558
|
+
>
|
|
559
|
+
{removing ? (
|
|
560
|
+
<MaterialCommunityIcons name="loading" size={16} color={theme.colors.textSecondary} />
|
|
561
|
+
) : (
|
|
562
|
+
<Text className="text-caption text-text-secondary">{t('accountMenu.signOut')}</Text>
|
|
563
|
+
)}
|
|
564
|
+
</HoverPressable>
|
|
565
|
+
</View>
|
|
566
|
+
);
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* One `principal acting as account` row.
|
|
571
|
+
*
|
|
572
|
+
* Pressing it activates the PAIR — a `contextId`, not an account id, because on
|
|
573
|
+
* this device the account below may also be reachable through somebody else.
|
|
574
|
+
* A row the server marks unavailable is rendered rather than hidden, so a
|
|
575
|
+
* membership going away is something the person can see instead of a row that
|
|
576
|
+
* silently stopped existing; it is disabled, because activating it is a request
|
|
577
|
+
* the server answers with a 403 and then heals the row away.
|
|
578
|
+
*/
|
|
579
|
+
const ContextRow: React.FC<{
|
|
580
|
+
context: SwitcherContextRow;
|
|
581
|
+
principalName: string;
|
|
582
|
+
/**
|
|
583
|
+
* This ROW's own accent, resolved from `context.color` by the caller. Never
|
|
584
|
+
* the signed-in account's: two people on one device would then be drawn in
|
|
585
|
+
* whichever of them happens to be active.
|
|
586
|
+
*/
|
|
587
|
+
accent: string;
|
|
588
|
+
activating: boolean;
|
|
589
|
+
removing: boolean;
|
|
590
|
+
disabled: boolean;
|
|
591
|
+
onActivate: () => void;
|
|
592
|
+
onRemove: () => void;
|
|
593
|
+
theme: Theme;
|
|
594
|
+
t: Translate;
|
|
595
|
+
}> = ({
|
|
596
|
+
context,
|
|
597
|
+
principalName,
|
|
598
|
+
accent,
|
|
599
|
+
activating,
|
|
600
|
+
removing,
|
|
601
|
+
disabled,
|
|
602
|
+
onActivate,
|
|
603
|
+
onRemove,
|
|
604
|
+
theme,
|
|
605
|
+
t,
|
|
606
|
+
}) => {
|
|
607
|
+
const unavailable = !context.canActivate;
|
|
608
|
+
const rowDisabled = disabled || unavailable;
|
|
609
|
+
const removeLabel = t('accountSwitcher.context.remove', {
|
|
610
|
+
account: context.displayName,
|
|
611
|
+
person: principalName,
|
|
612
|
+
});
|
|
613
|
+
return (
|
|
614
|
+
<View className="flex-row items-center">
|
|
615
|
+
<HoverPressable
|
|
616
|
+
baseClassName={`flex-1 min-w-0 flex-row items-center gap-space-12 pl-space-12 py-[10px]${
|
|
617
|
+
rowDisabled ? ' opacity-60' : ''
|
|
618
|
+
}`}
|
|
619
|
+
hoverClassName="bg-fill-secondary"
|
|
620
|
+
onPress={onActivate}
|
|
621
|
+
disabled={rowDisabled}
|
|
622
|
+
accessibilityRole="button"
|
|
623
|
+
accessibilityState={{ selected: context.isActive, disabled: rowDisabled }}
|
|
624
|
+
accessibilityLabel={context.displayName}
|
|
625
|
+
>
|
|
626
|
+
<View>
|
|
627
|
+
<Avatar
|
|
628
|
+
source={context.avatarUrl ?? undefined}
|
|
629
|
+
variant="thumb"
|
|
630
|
+
name={context.displayName}
|
|
631
|
+
size={SWITCH_AVATAR_SIZE}
|
|
632
|
+
/>
|
|
633
|
+
{/* The accent ring is an OVERLAY: it costs the row no width, so every
|
|
634
|
+
avatar in the list starts on the same content line. */}
|
|
635
|
+
{context.isActive ? (
|
|
636
|
+
<View style={[styles.currentAvatarRing, { borderColor: accent }]} pointerEvents="none" />
|
|
637
|
+
) : null}
|
|
638
|
+
</View>
|
|
639
|
+
<View className="flex-1 min-w-0">
|
|
640
|
+
<Text className="text-body font-semibold text-text" numberOfLines={1}>
|
|
641
|
+
{context.displayName}
|
|
642
|
+
</Text>
|
|
643
|
+
<Text className="text-caption text-text-secondary" numberOfLines={1}>
|
|
644
|
+
{unavailable
|
|
645
|
+
? t('accountSwitcher.context.unavailable')
|
|
646
|
+
: context.handle
|
|
647
|
+
? `@${context.handle}`
|
|
648
|
+
: ''}
|
|
649
|
+
</Text>
|
|
650
|
+
</View>
|
|
651
|
+
{activating ? (
|
|
652
|
+
<MaterialCommunityIcons name="loading" size={20} color={accent} />
|
|
653
|
+
) : null}
|
|
654
|
+
</HoverPressable>
|
|
655
|
+
<HoverPressable
|
|
656
|
+
baseClassName={`px-space-12 py-[10px]${disabled ? ' opacity-60' : ''}`}
|
|
657
|
+
hoverClassName="bg-fill-secondary"
|
|
658
|
+
onPress={onRemove}
|
|
659
|
+
disabled={disabled}
|
|
660
|
+
accessibilityRole="button"
|
|
661
|
+
accessibilityLabel={removeLabel}
|
|
662
|
+
>
|
|
663
|
+
<MaterialCommunityIcons
|
|
664
|
+
name={removing ? 'loading' : 'close'}
|
|
665
|
+
size={18}
|
|
666
|
+
color={theme.colors.textTertiary}
|
|
667
|
+
/>
|
|
668
|
+
</HoverPressable>
|
|
669
|
+
</View>
|
|
670
|
+
);
|
|
671
|
+
};
|
|
672
|
+
|
|
523
673
|
/**
|
|
524
674
|
* An account-list AFFORDANCE row ("Add another account", "Manage accounts on
|
|
525
675
|
* this device") — a bordered circle sized to the avatar it stands in for, so its
|
|
@@ -19,7 +19,11 @@
|
|
|
19
19
|
import type React from 'react';
|
|
20
20
|
import { View } from 'react-native';
|
|
21
21
|
import { Button } from '@oxyhq/bloom/button';
|
|
22
|
-
import
|
|
22
|
+
import {
|
|
23
|
+
showsPrincipalHeaders,
|
|
24
|
+
type AccountDialogSnapshot,
|
|
25
|
+
type SwitcherPrincipalRow,
|
|
26
|
+
} from '@oxyhq/core';
|
|
23
27
|
import TroubleDisclosure from './TroubleDisclosure';
|
|
24
28
|
import { AccountRow, Dividerish, SubtleLink } from './primitives';
|
|
25
29
|
import { authChooserStyles as styles } from './styles';
|
|
@@ -33,6 +37,8 @@ import type {
|
|
|
33
37
|
|
|
34
38
|
interface SignInEntryViewProps {
|
|
35
39
|
snapshot: AccountDialogSnapshot;
|
|
40
|
+
/** The device's people, each with the accounts they may act as. */
|
|
41
|
+
principals: SwitcherPrincipalRow[];
|
|
36
42
|
theme: Theme;
|
|
37
43
|
t: Translate;
|
|
38
44
|
handlers: OxyAuthChooserHandlers;
|
|
@@ -43,6 +49,7 @@ interface SignInEntryViewProps {
|
|
|
43
49
|
|
|
44
50
|
const SignInEntryView: React.FC<SignInEntryViewProps> = ({
|
|
45
51
|
snapshot,
|
|
52
|
+
principals,
|
|
46
53
|
theme,
|
|
47
54
|
t,
|
|
48
55
|
handlers,
|
|
@@ -76,18 +83,34 @@ const SignInEntryView: React.FC<SignInEntryViewProps> = ({
|
|
|
76
83
|
},
|
|
77
84
|
];
|
|
78
85
|
|
|
86
|
+
// Whose route this is only needs naming when the list holds more than one
|
|
87
|
+
// person, or somebody with more than one account — the same rule the account
|
|
88
|
+
// menu's group headers follow, so the two surfaces agree on when the actor is
|
|
89
|
+
// worth stating.
|
|
90
|
+
const namesTheOperator = showsPrincipalHeaders(principals);
|
|
91
|
+
const rows = principals.flatMap((principal) =>
|
|
92
|
+
principal.contexts.map((context) => ({
|
|
93
|
+
context,
|
|
94
|
+
operatedBy:
|
|
95
|
+
namesTheOperator && context.isDelegated
|
|
96
|
+
? t('accountSwitcher.context.operatedBy', { name: principal.displayName })
|
|
97
|
+
: null,
|
|
98
|
+
})),
|
|
99
|
+
);
|
|
100
|
+
|
|
79
101
|
return (
|
|
80
102
|
<View style={styles.signInBlock}>
|
|
81
|
-
{
|
|
103
|
+
{rows.length > 0 ? (
|
|
82
104
|
<View style={styles.rows}>
|
|
83
|
-
{
|
|
105
|
+
{rows.map(({ context, operatedBy }) => (
|
|
84
106
|
<AccountRow
|
|
85
|
-
key={
|
|
86
|
-
|
|
107
|
+
key={context.contextId}
|
|
108
|
+
context={context}
|
|
109
|
+
operatedBy={operatedBy}
|
|
87
110
|
theme={theme}
|
|
88
|
-
|
|
89
|
-
disabled={snapshot.
|
|
90
|
-
onPress={() => handlers.
|
|
111
|
+
activating={snapshot.activatingContextId === context.contextId}
|
|
112
|
+
disabled={snapshot.activatingContextId !== null}
|
|
113
|
+
onPress={() => handlers.onActivate(context.contextId)}
|
|
91
114
|
/>
|
|
92
115
|
))}
|
|
93
116
|
<Dividerish theme={theme} label={t('signin.or')} />
|
|
@@ -9,9 +9,9 @@ import { useState } from 'react';
|
|
|
9
9
|
import { Pressable, View } from 'react-native-css/components';
|
|
10
10
|
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
|
|
11
11
|
import { Avatar } from '@oxyhq/bloom/avatar';
|
|
12
|
-
import { Text } from '@oxyhq/bloom/typography';
|
|
13
12
|
import { BloomColorScope } from '@oxyhq/bloom/theme';
|
|
14
|
-
import
|
|
13
|
+
import { Text } from '@oxyhq/bloom/typography';
|
|
14
|
+
import type { SwitcherContextRow } from '@oxyhq/core';
|
|
15
15
|
import { authChooserStyles as styles } from './styles';
|
|
16
16
|
import { resolveAccentHex, toPreset, type Theme } from './types';
|
|
17
17
|
|
|
@@ -83,57 +83,71 @@ export const Dividerish: React.FC<{ theme: Theme; label: string }> = ({ theme, l
|
|
|
83
83
|
);
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
*
|
|
87
|
-
* choice of authentication METHOD, which is why it stays
|
|
88
|
-
* instead of behind the trouble disclosure.
|
|
86
|
+
* A `principal acting as account` row on the sign-in entry — "continue as one of
|
|
87
|
+
* these" rather than a choice of authentication METHOD, which is why it stays
|
|
88
|
+
* above the primary CTA instead of behind the trouble disclosure.
|
|
89
|
+
*
|
|
90
|
+
* Pressing it activates the PAIR. The secondary line is the account's `@handle`:
|
|
91
|
+
* the device directory carries a handle and no email, deliberately — it is the
|
|
92
|
+
* minimum that renders a row for every person on the device, and this surface is
|
|
93
|
+
* reached while signed out, where fetching anyone's profile is not an option.
|
|
94
|
+
*
|
|
95
|
+
* The accent comes from the row's OWN account (`context.color`, straight off the
|
|
96
|
+
* directory), not from the theme and not from whoever is signed in. This surface
|
|
97
|
+
* is where a device holding two people is most visible, and it is reached while
|
|
98
|
+
* signed out — so there is no "current user" whose colour could stand in.
|
|
89
99
|
*/
|
|
90
100
|
export const AccountRow: React.FC<{
|
|
91
|
-
|
|
101
|
+
context: SwitcherContextRow;
|
|
102
|
+
/** The person this account is reached through, when that is not obvious. */
|
|
103
|
+
operatedBy: string | null;
|
|
92
104
|
theme: Theme;
|
|
93
|
-
|
|
105
|
+
activating: boolean;
|
|
94
106
|
disabled: boolean;
|
|
95
107
|
onPress: () => void;
|
|
96
|
-
}> = ({
|
|
97
|
-
const accent = resolveAccentHex(
|
|
108
|
+
}> = ({ context, operatedBy, theme, activating, disabled, onPress }) => {
|
|
109
|
+
const accent = resolveAccentHex(context.color, theme.colors.primary);
|
|
110
|
+
const rowDisabled = disabled || !context.canActivate;
|
|
111
|
+
const secondary = operatedBy ?? (context.handle ? `@${context.handle}` : null);
|
|
98
112
|
|
|
99
113
|
return (
|
|
100
|
-
<BloomColorScope colorPreset={toPreset(
|
|
114
|
+
<BloomColorScope colorPreset={toPreset(context.color)} asChild>
|
|
101
115
|
<Pressable
|
|
102
116
|
style={[
|
|
103
117
|
styles.accountRow,
|
|
104
118
|
{
|
|
105
|
-
borderColor:
|
|
119
|
+
borderColor: context.isActive ? accent : theme.colors.border,
|
|
106
120
|
backgroundColor: theme.colors.card,
|
|
107
121
|
},
|
|
108
|
-
|
|
122
|
+
rowDisabled && !activating ? styles.rowDisabled : null,
|
|
109
123
|
]}
|
|
110
124
|
onPress={onPress}
|
|
111
|
-
disabled={
|
|
125
|
+
disabled={rowDisabled}
|
|
112
126
|
accessibilityRole="button"
|
|
113
|
-
accessibilityState={{ selected:
|
|
114
|
-
accessibilityLabel={
|
|
127
|
+
accessibilityState={{ selected: context.isActive, disabled: rowDisabled }}
|
|
128
|
+
accessibilityLabel={context.displayName}
|
|
115
129
|
>
|
|
116
|
-
<View style={[styles.avatarRing, { borderColor:
|
|
130
|
+
<View style={[styles.avatarRing, { borderColor: context.isActive ? accent : 'transparent' }]}>
|
|
117
131
|
<Avatar
|
|
118
|
-
source={
|
|
132
|
+
source={context.avatarUrl ?? undefined}
|
|
119
133
|
variant="thumb"
|
|
120
|
-
name={
|
|
134
|
+
name={context.displayName}
|
|
121
135
|
size={ROW_AVATAR_SIZE}
|
|
122
136
|
/>
|
|
123
137
|
</View>
|
|
124
138
|
<View style={styles.rowMeta}>
|
|
125
139
|
<Text style={[styles.rowName, { color: theme.colors.text }]} numberOfLines={1}>
|
|
126
|
-
{
|
|
140
|
+
{context.displayName}
|
|
127
141
|
</Text>
|
|
128
|
-
{
|
|
142
|
+
{secondary ? (
|
|
129
143
|
<Text style={[styles.rowHandle, { color: theme.colors.textSecondary }]} numberOfLines={1}>
|
|
130
|
-
{
|
|
144
|
+
{secondary}
|
|
131
145
|
</Text>
|
|
132
146
|
) : null}
|
|
133
147
|
</View>
|
|
134
|
-
{
|
|
148
|
+
{activating ? (
|
|
135
149
|
<MaterialCommunityIcons name="loading" size={20} color={accent} />
|
|
136
|
-
) :
|
|
150
|
+
) : context.isActive ? (
|
|
137
151
|
<MaterialCommunityIcons name="check-circle" size={20} color={accent} />
|
|
138
152
|
) : (
|
|
139
153
|
<MaterialCommunityIcons name="chevron-right" size={20} color={theme.colors.textSecondary} />
|
|
@@ -50,5 +50,9 @@ export function signInProgressLabel(
|
|
|
50
50
|
return t('accountSwitcher.progress.confirming');
|
|
51
51
|
case 'identity-confirmed':
|
|
52
52
|
return t('accountSwitcher.progress.confirmed');
|
|
53
|
+
default: {
|
|
54
|
+
const _exhaustive: never = progress;
|
|
55
|
+
return _exhaustive;
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
58
|
}
|