@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import type { ApiError, AuthStateStore, IdentityBinding, SessionClient, User } from '@oxyhq/core';
|
|
3
|
-
import type { AuthState } from '../../stores/authStore';
|
|
4
3
|
import type { ClientSession, SessionLoginResponse } from '@oxyhq/core';
|
|
4
|
+
import type { OxyRuntime } from '../../runtime';
|
|
5
5
|
import { DeviceManager } from '@oxyhq/core';
|
|
6
6
|
import { fetchSessionsWithFallback } from '../../utils/sessionHelpers';
|
|
7
7
|
import { handleAuthError, isInvalidSessionError } from '../../utils/errorHandlers';
|
|
@@ -20,9 +20,12 @@ export interface UseAuthOperationsOptions {
|
|
|
20
20
|
* warm-restores without a redirect.
|
|
21
21
|
*/
|
|
22
22
|
store: AuthStateStore;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The one owner of the session facts. Reads (`activeSessionId`) and writes
|
|
25
|
+
* (the account, the session mirror, the loading/error gates) both go through
|
|
26
|
+
* it, so this hook holds no copy of anything to fall out of step.
|
|
27
|
+
*/
|
|
28
|
+
runtime: OxyRuntime;
|
|
26
29
|
saveActiveSessionId: (sessionId: string) => Promise<void>;
|
|
27
30
|
clearSessionState: () => Promise<void>;
|
|
28
31
|
/** Used only by `performSignIn`'s same-user duplicate-session dedup (legacy session-validate path; unrelated to the SessionClient device-account set). */
|
|
@@ -38,10 +41,6 @@ export interface UseAuthOperationsOptions {
|
|
|
38
41
|
syncFromClient: () => Promise<void>;
|
|
39
42
|
onAuthStateChange?: (user: User | null) => void;
|
|
40
43
|
onError?: (error: ApiError) => void;
|
|
41
|
-
loginSuccess: (user: User) => void;
|
|
42
|
-
loginFailure: (message: string) => void;
|
|
43
|
-
logoutStore: () => void;
|
|
44
|
-
setAuthState: (state: Partial<AuthState>) => void;
|
|
45
44
|
logger?: (message: string, error?: unknown) => void;
|
|
46
45
|
/**
|
|
47
46
|
* Identity-bound session (`sessionMode: 'identity'`). When set, a successful
|
|
@@ -91,9 +90,7 @@ export function clearPersistedAuthSafe(
|
|
|
91
90
|
export const useAuthOperations = ({
|
|
92
91
|
oxyServices,
|
|
93
92
|
store,
|
|
94
|
-
|
|
95
|
-
setActiveSessionId,
|
|
96
|
-
updateSessions,
|
|
93
|
+
runtime,
|
|
97
94
|
saveActiveSessionId,
|
|
98
95
|
clearSessionState,
|
|
99
96
|
switchSession,
|
|
@@ -101,10 +98,6 @@ export const useAuthOperations = ({
|
|
|
101
98
|
syncFromClient,
|
|
102
99
|
onAuthStateChange,
|
|
103
100
|
onError,
|
|
104
|
-
loginSuccess,
|
|
105
|
-
loginFailure,
|
|
106
|
-
logoutStore,
|
|
107
|
-
setAuthState,
|
|
108
101
|
logger,
|
|
109
102
|
identityBinding,
|
|
110
103
|
refreshPinnedAccountId,
|
|
@@ -231,7 +224,7 @@ export const useAuthOperations = ({
|
|
|
231
224
|
}
|
|
232
225
|
}
|
|
233
226
|
await switchSession(existingSession.sessionId);
|
|
234
|
-
|
|
227
|
+
runtime.mergeSessions(
|
|
235
228
|
allDeviceSessions.filter((session) => session.sessionId !== sessionResponse.sessionId),
|
|
236
229
|
{ merge: false },
|
|
237
230
|
);
|
|
@@ -239,27 +232,28 @@ export const useAuthOperations = ({
|
|
|
239
232
|
return fullUser;
|
|
240
233
|
}
|
|
241
234
|
|
|
242
|
-
|
|
235
|
+
// One transition: the active id, the session mirror and the account all
|
|
236
|
+
// land together, so nothing is woken holding two of the three.
|
|
237
|
+
runtime.batch(() => {
|
|
238
|
+
runtime.setActiveSessionId(sessionResponse.sessionId);
|
|
239
|
+
runtime.mergeSessions(allDeviceSessions, { merge: true });
|
|
240
|
+
runtime.setAccount(fullUser);
|
|
241
|
+
});
|
|
243
242
|
await saveActiveSessionId(sessionResponse.sessionId);
|
|
244
|
-
updateSessions(allDeviceSessions, { merge: true });
|
|
245
|
-
|
|
246
|
-
loginSuccess(fullUser);
|
|
247
243
|
onAuthStateChange?.(fullUser);
|
|
248
244
|
|
|
249
245
|
return fullUser;
|
|
250
246
|
},
|
|
251
247
|
[
|
|
252
248
|
logger,
|
|
253
|
-
loginSuccess,
|
|
254
249
|
onAuthStateChange,
|
|
255
250
|
oxyServices,
|
|
251
|
+
runtime,
|
|
256
252
|
saveActiveSessionId,
|
|
257
253
|
sessionClient,
|
|
258
|
-
setActiveSessionId,
|
|
259
254
|
store,
|
|
260
255
|
switchSession,
|
|
261
256
|
syncFromClient,
|
|
262
|
-
updateSessions,
|
|
263
257
|
identityBinding,
|
|
264
258
|
refreshPinnedAccountId,
|
|
265
259
|
],
|
|
@@ -270,7 +264,10 @@ export const useAuthOperations = ({
|
|
|
270
264
|
*/
|
|
271
265
|
const signIn = useCallback(
|
|
272
266
|
async (publicKey: string, deviceName?: string): Promise<User> => {
|
|
273
|
-
|
|
267
|
+
runtime.batch(() => {
|
|
268
|
+
runtime.setLoading(true);
|
|
269
|
+
runtime.setError(null);
|
|
270
|
+
});
|
|
274
271
|
|
|
275
272
|
try {
|
|
276
273
|
return await performSignIn(publicKey);
|
|
@@ -279,16 +276,16 @@ export const useAuthOperations = ({
|
|
|
279
276
|
defaultMessage: 'Sign in failed',
|
|
280
277
|
code: LOGIN_ERROR_CODE,
|
|
281
278
|
onError,
|
|
282
|
-
setAuthError: (msg: string) =>
|
|
279
|
+
setAuthError: (msg: string) => runtime.setError(msg),
|
|
283
280
|
logger,
|
|
284
281
|
});
|
|
285
|
-
|
|
282
|
+
runtime.setError(message);
|
|
286
283
|
throw error;
|
|
287
284
|
} finally {
|
|
288
|
-
|
|
285
|
+
runtime.setLoading(false);
|
|
289
286
|
}
|
|
290
287
|
},
|
|
291
|
-
[
|
|
288
|
+
[runtime, performSignIn, onError, logger],
|
|
292
289
|
);
|
|
293
290
|
|
|
294
291
|
/**
|
|
@@ -296,6 +293,7 @@ export const useAuthOperations = ({
|
|
|
296
293
|
*/
|
|
297
294
|
const logout = useCallback(
|
|
298
295
|
async (targetSessionId?: string): Promise<void> => {
|
|
296
|
+
const activeSessionId = runtime.getSnapshot().activeSessionId;
|
|
299
297
|
if (!activeSessionId) return;
|
|
300
298
|
|
|
301
299
|
try {
|
|
@@ -342,20 +340,19 @@ export const useAuthOperations = ({
|
|
|
342
340
|
defaultMessage: 'Logout failed',
|
|
343
341
|
code: LOGOUT_ERROR_CODE,
|
|
344
342
|
onError,
|
|
345
|
-
setAuthError: (msg: string) =>
|
|
343
|
+
setAuthError: (msg: string) => runtime.setError(msg),
|
|
346
344
|
logger,
|
|
347
345
|
status: isInvalid ? 401 : undefined,
|
|
348
346
|
});
|
|
349
347
|
}
|
|
350
348
|
},
|
|
351
349
|
[
|
|
352
|
-
activeSessionId,
|
|
353
350
|
clearSessionState,
|
|
354
351
|
store,
|
|
355
352
|
logger,
|
|
356
353
|
onError,
|
|
354
|
+
runtime,
|
|
357
355
|
sessionClient,
|
|
358
|
-
setAuthState,
|
|
359
356
|
syncFromClient,
|
|
360
357
|
],
|
|
361
358
|
);
|
|
@@ -364,9 +361,9 @@ export const useAuthOperations = ({
|
|
|
364
361
|
* Logout from all sessions
|
|
365
362
|
*/
|
|
366
363
|
const logoutAll = useCallback(async (): Promise<void> => {
|
|
367
|
-
if (!activeSessionId) {
|
|
364
|
+
if (!runtime.getSnapshot().activeSessionId) {
|
|
368
365
|
const error = new Error('No active session found');
|
|
369
|
-
|
|
366
|
+
runtime.setError(error.message);
|
|
370
367
|
onError?.({ message: error.message, code: LOGOUT_ALL_ERROR_CODE, status: 404 });
|
|
371
368
|
throw error;
|
|
372
369
|
}
|
|
@@ -387,12 +384,12 @@ export const useAuthOperations = ({
|
|
|
387
384
|
defaultMessage: 'Logout all failed',
|
|
388
385
|
code: LOGOUT_ALL_ERROR_CODE,
|
|
389
386
|
onError,
|
|
390
|
-
setAuthError: (msg: string) =>
|
|
387
|
+
setAuthError: (msg: string) => runtime.setError(msg),
|
|
391
388
|
logger,
|
|
392
389
|
});
|
|
393
390
|
throw error instanceof Error ? error : new Error('Logout all failed');
|
|
394
391
|
}
|
|
395
|
-
}, [
|
|
392
|
+
}, [clearSessionState, store, logger, onError, runtime, sessionClient]);
|
|
396
393
|
|
|
397
394
|
return {
|
|
398
395
|
signIn,
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import type { UseFollowHook } from '../hooks/useFollow.types';
|
|
2
|
-
import { logger as loggerUtil } from '@oxyhq/core';
|
|
3
|
-
|
|
4
1
|
/** Local display hint when a session lacks explicit `expiresAt` (7 days). */
|
|
5
2
|
export const DEFAULT_SESSION_VALIDITY_MS = 7 * 24 * 60 * 60 * 1000;
|
|
6
3
|
|
|
@@ -29,30 +26,3 @@ export function getHttpStatus(error: unknown): number | undefined {
|
|
|
29
26
|
export function isUnauthorizedStatus(error: unknown): boolean {
|
|
30
27
|
return getHttpStatus(error) === 401;
|
|
31
28
|
}
|
|
32
|
-
|
|
33
|
-
let cachedUseFollowHook: UseFollowHook | null = null;
|
|
34
|
-
|
|
35
|
-
export const loadUseFollowHook = (): UseFollowHook => {
|
|
36
|
-
if (cachedUseFollowHook) {
|
|
37
|
-
return cachedUseFollowHook;
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
41
|
-
const { useFollow } = require('../hooks/useFollow');
|
|
42
|
-
cachedUseFollowHook = useFollow as UseFollowHook;
|
|
43
|
-
return cachedUseFollowHook;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
if (__DEV__) {
|
|
46
|
-
loggerUtil.warn(
|
|
47
|
-
'useFollow hook is not available. Please import useFollow from @oxyhq/services directly.',
|
|
48
|
-
{ component: 'OxyContext', method: 'loadUseFollowHook' },
|
|
49
|
-
error,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
const fallback: UseFollowHook = () => {
|
|
53
|
-
throw new Error('useFollow hook is only available in the UI bundle. Import it from @oxyhq/services.');
|
|
54
|
-
};
|
|
55
|
-
cachedUseFollowHook = fallback;
|
|
56
|
-
return cachedUseFollowHook;
|
|
57
|
-
}
|
|
58
|
-
};
|
|
@@ -151,7 +151,7 @@ export interface OxyContextState {
|
|
|
151
151
|
createAccount: (data: CreateAccountInput) => Promise<AccountNode>;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
export interface
|
|
154
|
+
export interface OxyRuntimeProviderProps {
|
|
155
155
|
children: ReactNode;
|
|
156
156
|
oxyServices?: OxyServices;
|
|
157
157
|
baseURL?: string;
|
|
@@ -198,6 +198,14 @@ export interface OxyContextProviderProps {
|
|
|
198
198
|
* @default false
|
|
199
199
|
*/
|
|
200
200
|
backgroundSession?: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* Whether this origin/app persists the durable device credential at all. See
|
|
203
|
+
* `OxyProviderProps.deviceCredentialStorage` for the full rule and the one
|
|
204
|
+
* caller of `'ephemeral'`.
|
|
205
|
+
*
|
|
206
|
+
* @default 'persistent'
|
|
207
|
+
*/
|
|
208
|
+
deviceCredentialStorage?: 'persistent' | 'ephemeral';
|
|
201
209
|
onAuthStateChange?: (user: User | null) => void;
|
|
202
210
|
onError?: (error: ApiError) => void;
|
|
203
211
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState, type RefObject } from 'react';
|
|
2
|
-
import type { QueryClient } from '@tanstack/react-query';
|
|
3
2
|
import type { OxyServices, AccountNode, CreateAccountInput, AccountDialogController, SessionClient } from '@oxyhq/core';
|
|
4
3
|
import { logger as loggerUtil } from '@oxyhq/core';
|
|
5
|
-
import { useAuthStore } from '../stores/authStore';
|
|
6
4
|
import { isUnauthorizedStatus } from './oxyContextHelpers';
|
|
7
|
-
import { resetSessionScopedStores } from '../stores/resetSessionScopedStores';
|
|
8
|
-
import { ASSET_DOWNLOAD_URLS_QUERY_KEY } from '../hooks/useResolvedFileUrls';
|
|
9
5
|
import { IdentityBoundSessionError } from '../session';
|
|
10
6
|
import type { CommitInput } from './oxyContextTypes';
|
|
11
7
|
|
|
@@ -23,7 +19,6 @@ interface UseOxyAccountGraphParams {
|
|
|
23
19
|
sessionClient: SessionClient;
|
|
24
20
|
syncFromClient: () => Promise<void>;
|
|
25
21
|
commitSession: (input: CommitInput, options: { activate: boolean }) => Promise<void>;
|
|
26
|
-
queryClient: QueryClient;
|
|
27
22
|
accountDialogControllerRef: RefObject<AccountDialogController | null>;
|
|
28
23
|
clearSessionStateRef: RefObject<() => Promise<void>>;
|
|
29
24
|
}
|
|
@@ -37,7 +32,6 @@ export function useOxyAccountGraph({
|
|
|
37
32
|
sessionClient,
|
|
38
33
|
syncFromClient,
|
|
39
34
|
commitSession,
|
|
40
|
-
queryClient,
|
|
41
35
|
accountDialogControllerRef,
|
|
42
36
|
clearSessionStateRef,
|
|
43
37
|
}: UseOxyAccountGraphParams) {
|
|
@@ -70,16 +64,6 @@ export function useOxyAccountGraph({
|
|
|
70
64
|
}
|
|
71
65
|
}, [identityBound, isAuthenticated, initialized, tokenReady, refreshAccounts, accountDialogControllerRef]);
|
|
72
66
|
|
|
73
|
-
const runPostAccountSwitchSideEffects = useCallback(async (): Promise<void> => {
|
|
74
|
-
resetSessionScopedStores();
|
|
75
|
-
// Scoped media tokens are per-viewer — drop any cached URLs immediately so
|
|
76
|
-
// `keepPreviousData`-style placeholders cannot flash the prior account's
|
|
77
|
-
// private thumbnails while the new bearer mint lands.
|
|
78
|
-
queryClient.removeQueries({ queryKey: [ASSET_DOWNLOAD_URLS_QUERY_KEY] });
|
|
79
|
-
await refreshAccounts();
|
|
80
|
-
queryClient.invalidateQueries();
|
|
81
|
-
}, [refreshAccounts, queryClient]);
|
|
82
|
-
|
|
83
67
|
const switchToAccount = useCallback(
|
|
84
68
|
async (accountId: string): Promise<void> => {
|
|
85
69
|
if (identityBound) {
|
|
@@ -92,7 +76,6 @@ export function useOxyAccountGraph({
|
|
|
92
76
|
if (deviceState?.accounts.some((account) => account.accountId === accountId)) {
|
|
93
77
|
await sessionClient.switchAccount(accountId);
|
|
94
78
|
await syncFromClient();
|
|
95
|
-
await runPostAccountSwitchSideEffects();
|
|
96
79
|
return;
|
|
97
80
|
}
|
|
98
81
|
|
|
@@ -114,9 +97,12 @@ export function useOxyAccountGraph({
|
|
|
114
97
|
// `session_state` socket.
|
|
115
98
|
{ activate: true },
|
|
116
99
|
);
|
|
117
|
-
await runPostAccountSwitchSideEffects();
|
|
118
100
|
},
|
|
119
|
-
|
|
101
|
+
// The account-scoped cache reset that used to trail both branches here now
|
|
102
|
+
// runs inside the runtime's subject transition, BEFORE any subscriber is
|
|
103
|
+
// woken — so a socket-pushed switch (which never reached this function at
|
|
104
|
+
// all) gets it too.
|
|
105
|
+
[identityBound, oxyServices, sessionClient, syncFromClient, commitSession],
|
|
120
106
|
);
|
|
121
107
|
|
|
122
108
|
const createAccount = useCallback(
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AccountDialogSnapshot } from '@oxyhq/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The snapshot `useSyncExternalStore` reads before a controller exists.
|
|
5
|
+
*
|
|
6
|
+
* `useSyncExternalStore` calls `getSnapshot` several times per commit and
|
|
7
|
+
* compares by identity, so the no-controller answer has to be one constant
|
|
8
|
+
* reference — a fresh object literal loops.
|
|
9
|
+
*
|
|
10
|
+
* It is ONE constant because there were three, byte-identical, in the hook and
|
|
11
|
+
* both dialog surfaces. Adding a field to `AccountDialogSnapshot` broke all
|
|
12
|
+
* three at once and would have gone on doing so; a shared constant makes the
|
|
13
|
+
* compiler point at one place.
|
|
14
|
+
*/
|
|
15
|
+
export const EMPTY_ACCOUNT_DIALOG_SNAPSHOT: AccountDialogSnapshot = {
|
|
16
|
+
view: 'accounts',
|
|
17
|
+
directory: null,
|
|
18
|
+
activeContext: null,
|
|
19
|
+
activatingContextId: null,
|
|
20
|
+
removingContextId: null,
|
|
21
|
+
removingPrincipalId: null,
|
|
22
|
+
loading: false,
|
|
23
|
+
error: null,
|
|
24
|
+
signIn: {
|
|
25
|
+
phase: 'idle',
|
|
26
|
+
authorizeCode: null,
|
|
27
|
+
qrPayload: null,
|
|
28
|
+
expiresAt: null,
|
|
29
|
+
error: null,
|
|
30
|
+
route: null,
|
|
31
|
+
routeFailed: false,
|
|
32
|
+
pushSentAt: null,
|
|
33
|
+
openedAt: null,
|
|
34
|
+
progress: 'idle',
|
|
35
|
+
},
|
|
36
|
+
commonsAvailability: 'unknown',
|
|
37
|
+
};
|
|
@@ -18,9 +18,7 @@ import {
|
|
|
18
18
|
import { mutationKeys } from './mutationKeys';
|
|
19
19
|
import { useOxy } from '../../context/OxyContext';
|
|
20
20
|
import { toast } from '@oxyhq/bloom/toast';
|
|
21
|
-
import { refreshAvatarInStore } from '../../utils/avatarUtils';
|
|
22
21
|
import { useAuthStore } from '../../stores/authStore';
|
|
23
|
-
import { useAccountStore } from '../../stores/accountStore';
|
|
24
22
|
import {
|
|
25
23
|
clearedFieldsFromProfileUpdate,
|
|
26
24
|
upsertCachedUser,
|
|
@@ -114,18 +112,6 @@ export const useUpdateProfile = () => {
|
|
|
114
112
|
cleared: cleared.length > 0 ? cleared : undefined,
|
|
115
113
|
});
|
|
116
114
|
|
|
117
|
-
// Avatar add/remove: keep the account switcher in sync with profile writes
|
|
118
|
-
if (typeof updates.avatar === 'string' && activeSessionId) {
|
|
119
|
-
if (updates.avatar && oxyServices) {
|
|
120
|
-
refreshAvatarInStore(activeSessionId, updates.avatar, oxyServices);
|
|
121
|
-
} else {
|
|
122
|
-
useAccountStore.getState().updateAccount(activeSessionId, {
|
|
123
|
-
avatar: undefined,
|
|
124
|
-
avatarUrl: undefined,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
115
|
// Invalidate all related queries so every consumer (the account dialog,
|
|
130
116
|
// session lists, managed accounts, etc.) refetches the fresh profile.
|
|
131
117
|
// This is critical right after `username` is set the first time, when
|
|
@@ -209,11 +195,6 @@ export const useUploadAvatar = () => {
|
|
|
209
195
|
// Update authStore so frontend components see the changes immediately
|
|
210
196
|
useAuthStore.getState().setUser(data);
|
|
211
197
|
|
|
212
|
-
// Refresh accountStore with cache-busted URL if avatar was updated
|
|
213
|
-
if (data?.avatar && activeSessionId && oxyServices) {
|
|
214
|
-
refreshAvatarInStore(activeSessionId, data.avatar, oxyServices);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
198
|
// Invalidate all related queries to refresh everywhere, including the
|
|
218
199
|
// sessions cache so other-account avatars update too.
|
|
219
200
|
invalidateUserQueries(queryClient);
|
|
@@ -17,7 +17,8 @@ import { upsertCachedUser, upsertCachedUsers } from '../userCache';
|
|
|
17
17
|
import { patchCachedUserRelationship } from '../userCacheRelationship';
|
|
18
18
|
import type { CacheableUser } from '../userCache';
|
|
19
19
|
import { queryKeys } from '../queryKeys';
|
|
20
|
-
import { useAuthStore } from '../../../stores/authStore';
|
|
20
|
+
import { bindAuthStoreToRuntime, useAuthStore } from '../../../stores/authStore';
|
|
21
|
+
import { createTestRuntime } from '../../../../../__tests__/helpers/runtimeHarness';
|
|
21
22
|
|
|
22
23
|
function makeClient(): QueryClient {
|
|
23
24
|
return new QueryClient({
|
|
@@ -35,11 +36,21 @@ function readByUsername(qc: QueryClient, username: string, viewerId: string): Ca
|
|
|
35
36
|
return qc.getQueryData<CacheableUser>(queryKeys.users.byUsername(username, viewerId));
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
// `useAuthStore` projects the runtime now, so the viewer these cases read has
|
|
40
|
+
// to live somewhere: bind a runtime per test and let the writes go through it.
|
|
41
|
+
let unbindAuthStore: (() => void) | null = null;
|
|
42
|
+
|
|
38
43
|
beforeEach(() => {
|
|
44
|
+
unbindAuthStore = bindAuthStoreToRuntime(createTestRuntime());
|
|
39
45
|
// Default to anonymous viewer unless a test sets one.
|
|
40
46
|
useAuthStore.setState({ user: null });
|
|
41
47
|
});
|
|
42
48
|
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
unbindAuthStore?.();
|
|
51
|
+
unbindAuthStore = null;
|
|
52
|
+
});
|
|
53
|
+
|
|
43
54
|
describe('upsertCachedUser — cold slot', () => {
|
|
44
55
|
it('seeds the full object and marks it STALE (updatedAt: 0) under both keys', () => {
|
|
45
56
|
const qc = makeClient();
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { useCallback, useMemo, useSyncExternalStore } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
buildSwitcherRows,
|
|
4
|
+
projectDevicePrincipals,
|
|
5
|
+
type DeviceContext,
|
|
6
|
+
type SwitcherPrincipalRow,
|
|
7
|
+
} from '@oxyhq/core';
|
|
8
|
+
import { useOxy } from '../context/OxyContext';
|
|
9
|
+
import { useI18n } from './useI18n';
|
|
10
|
+
import { EMPTY_ACCOUNT_DIALOG_SNAPSHOT } from './accountDialogSnapshot';
|
|
11
|
+
|
|
12
|
+
export interface UseDeviceSwitcherResult {
|
|
13
|
+
/**
|
|
14
|
+
* Everyone signed in on this device, each with the accounts they may act as,
|
|
15
|
+
* with names, handles and avatar URLs already resolved.
|
|
16
|
+
*
|
|
17
|
+
* Grouped by PERSON, which is the whole point: the same organization
|
|
18
|
+
* reachable through two people is two rows under two humans. The flat list
|
|
19
|
+
* this replaced was keyed by account id and could show only one of them.
|
|
20
|
+
*/
|
|
21
|
+
principals: SwitcherPrincipalRow[];
|
|
22
|
+
/** The active `principal acting as account` pair, or `null`. */
|
|
23
|
+
activeContext: DeviceContext | null;
|
|
24
|
+
/** True until the first directory read settles with nothing to show. */
|
|
25
|
+
isLoading: boolean;
|
|
26
|
+
/** The `contextId` of an activation in flight, or `null`. */
|
|
27
|
+
activatingContextId: string | null;
|
|
28
|
+
/** The `contextId` of a context removal in flight, or `null`. */
|
|
29
|
+
removingContextId: string | null;
|
|
30
|
+
/** The `principalId` of a principal removal in flight, or `null`. */
|
|
31
|
+
removingPrincipalId: string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Make one pair active. Resolves `false` when it was refused — the reason is
|
|
34
|
+
* on the dialog controller's `error`, and the row is simply not offered
|
|
35
|
+
* again after the refresh that follows.
|
|
36
|
+
*/
|
|
37
|
+
activateContext: (contextId: string) => Promise<boolean>;
|
|
38
|
+
/** Drop ONE `principal → account` pair, leaving anyone else's route intact. */
|
|
39
|
+
signOutContext: (contextId: string) => Promise<boolean>;
|
|
40
|
+
/** Drop ONE PERSON and every context they reach, and nobody else's. */
|
|
41
|
+
signOutPrincipal: (principalId: string) => Promise<boolean>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The device switcher, straight from `GET /session/device/directory` (ADR 0002).
|
|
46
|
+
*
|
|
47
|
+
* A thin binding over the shared `AccountDialogController` in `@oxyhq/core` —
|
|
48
|
+
* the SAME headless source `OxyAccountDialogScreen` renders — so the SDK's own
|
|
49
|
+
* dialog and the `auth.oxy.so` chooser show one list, built once, on the server.
|
|
50
|
+
*
|
|
51
|
+
* It used to hand back a flat `SwitchableAccount[]` assembled here from
|
|
52
|
+
* `listAccounts()` + `getUsersByIds()` unioned with the device's session set.
|
|
53
|
+
* That union was not merely redundant: the client holds ONE caller's account
|
|
54
|
+
* graph, so on a device holding two people it presented one person's answer as
|
|
55
|
+
* the device's, and switchability — an authorization question — was decided
|
|
56
|
+
* client-side. Both are the server's answers now, and selecting a row activates
|
|
57
|
+
* a `contextId`, never an `accountId`.
|
|
58
|
+
*/
|
|
59
|
+
export function useDeviceSwitcher(): UseDeviceSwitcherResult {
|
|
60
|
+
const { accountDialogController: controller, oxyServices } = useOxy();
|
|
61
|
+
const { locale } = useI18n();
|
|
62
|
+
|
|
63
|
+
const subscribe = useCallback(
|
|
64
|
+
(listener: () => void) => (controller ? controller.subscribe(listener) : () => undefined),
|
|
65
|
+
[controller],
|
|
66
|
+
);
|
|
67
|
+
const getSnapshot = useCallback(
|
|
68
|
+
() => (controller ? controller.getSnapshot() : EMPTY_ACCOUNT_DIALOG_SNAPSHOT),
|
|
69
|
+
[controller],
|
|
70
|
+
);
|
|
71
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
72
|
+
|
|
73
|
+
// `directory` is a stable reference between reads (`SessionClient` holds the
|
|
74
|
+
// one it applied), so this recomputes only when the device actually moved.
|
|
75
|
+
const principals = useMemo(
|
|
76
|
+
() =>
|
|
77
|
+
buildSwitcherRows(
|
|
78
|
+
projectDevicePrincipals(snapshot.directory),
|
|
79
|
+
snapshot.activeContext?.contextId ?? null,
|
|
80
|
+
(avatar) => (avatar ? oxyServices.getFileDownloadUrl(avatar, 'thumb') : undefined),
|
|
81
|
+
locale,
|
|
82
|
+
),
|
|
83
|
+
[snapshot.directory, snapshot.activeContext, oxyServices, locale],
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const activateContext = useCallback(
|
|
87
|
+
async (contextId: string) => (controller ? controller.activateContext(contextId) : false),
|
|
88
|
+
[controller],
|
|
89
|
+
);
|
|
90
|
+
const signOutContext = useCallback(
|
|
91
|
+
async (contextId: string) => (controller ? controller.signOutContext(contextId) : false),
|
|
92
|
+
[controller],
|
|
93
|
+
);
|
|
94
|
+
const signOutPrincipal = useCallback(
|
|
95
|
+
async (principalId: string) => (controller ? controller.signOutPrincipal(principalId) : false),
|
|
96
|
+
[controller],
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
principals,
|
|
101
|
+
activeContext: snapshot.activeContext,
|
|
102
|
+
isLoading: snapshot.loading,
|
|
103
|
+
activatingContextId: snapshot.activatingContextId,
|
|
104
|
+
removingContextId: snapshot.removingContextId,
|
|
105
|
+
removingPrincipalId: snapshot.removingPrincipalId,
|
|
106
|
+
activateContext,
|
|
107
|
+
signOutContext,
|
|
108
|
+
signOutPrincipal,
|
|
109
|
+
};
|
|
110
|
+
}
|
package/src/ui/hooks/useI18n.ts
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { useOptionalOxy } from '../context/OxyContext';
|
|
3
3
|
import { translate } from '@oxyhq/core';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The locale `@oxyhq/core`'s translator falls back to. Mirrors its own
|
|
7
|
+
* `FALLBACK`, so a surface rendered without a provider reads the same strings
|
|
8
|
+
* an unrecognised locale would.
|
|
9
|
+
*/
|
|
10
|
+
const FALLBACK_LOCALE = 'en-US';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Display copy for SDK surfaces.
|
|
14
|
+
*
|
|
15
|
+
* This is the ONE hook that reads the runtime optionally. The locale is display
|
|
16
|
+
* metadata, not session state — ADR 0004 lists it among the things that come off
|
|
17
|
+
* the central value entirely — and purely presentational surfaces
|
|
18
|
+
* (`OxyConsentScreen`, `OxySignInRequestSurface`) are rendered outside a
|
|
19
|
+
* provider on purpose: `packages/auth`'s production-bundle probe builds the real
|
|
20
|
+
* Vite bundle and renders the surface standalone to prove every element beneath
|
|
21
|
+
* it links. Throwing there would report a linkage failure that is not one.
|
|
22
|
+
*
|
|
23
|
+
* Anything that reads or mutates session state uses `useOxy()`, which throws.
|
|
24
|
+
*/
|
|
5
25
|
export function useI18n() {
|
|
6
|
-
const
|
|
26
|
+
const oxy = useOptionalOxy();
|
|
27
|
+
const currentLanguage = oxy?.currentLanguage ?? FALLBACK_LOCALE;
|
|
7
28
|
const t = useMemo(() => {
|
|
8
29
|
return (key: string, vars?: Record<string, string | number>) => translate(currentLanguage, key, vars);
|
|
9
30
|
}, [currentLanguage]);
|
|
10
31
|
return { t, locale: currentLanguage };
|
|
11
32
|
}
|
|
12
|
-
|