@oxyhq/services 23.2.0 → 24.0.1

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.
Files changed (172) hide show
  1. package/android/src/main/java/so/oxy/identity/OxyIdentityStore.kt +21 -127
  2. package/android/src/main/java/so/oxy/session/OxyBackgroundSession.kt +184 -0
  3. package/android/src/main/java/so/oxy/session/OxyBackgroundSessionApi.kt +162 -0
  4. package/android/src/main/java/so/oxy/session/OxyBackgroundSessionModule.kt +101 -0
  5. package/android/src/main/java/so/oxy/session/OxyBackgroundSessionStore.kt +179 -0
  6. package/android/src/main/java/so/oxy/session/OxyBackgroundToken.kt +61 -0
  7. package/android/src/main/java/so/oxy/storage/OxyEncryptedPrefs.kt +241 -0
  8. package/expo-module.config.json +4 -1
  9. package/lib/commonjs/ui/components/OxyProvider.js +3 -1
  10. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  11. package/lib/commonjs/ui/components/ProfileButton.js +1 -1
  12. package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
  13. package/lib/commonjs/ui/components/internal/PinInput.js +3 -1
  14. package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
  15. package/lib/commonjs/ui/components/logo/LogoText.js +4 -4
  16. package/lib/commonjs/ui/components/logo/LogoText.js.map +1 -1
  17. package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js +2 -2
  18. package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js.map +1 -1
  19. package/lib/commonjs/ui/context/OxyContext.js +13 -0
  20. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  21. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +2 -3
  22. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  23. package/lib/commonjs/ui/screens/ChangeAvatarScreen.js +2 -3
  24. package/lib/commonjs/ui/screens/ChangeAvatarScreen.js.map +1 -1
  25. package/lib/commonjs/ui/screens/EditProfileScreen.js +2 -3
  26. package/lib/commonjs/ui/screens/EditProfileScreen.js.map +1 -1
  27. package/lib/commonjs/ui/screens/FeedbackScreen.js +3 -1
  28. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  29. package/lib/commonjs/ui/screens/ManageAccountScreen.js +1 -1
  30. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  31. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +2 -2
  32. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  33. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +8 -9
  34. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  35. package/lib/commonjs/ui/screens/ProfileScreen.js +1 -1
  36. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/UserListScreen.js +2 -3
  38. package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
  39. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +1 -1
  40. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  41. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +2 -3
  42. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  43. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +1 -1
  44. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  45. package/lib/commonjs/ui/session/backgroundSession.js +264 -0
  46. package/lib/commonjs/ui/session/backgroundSession.js.map +1 -0
  47. package/lib/commonjs/ui/session/index.js +7 -0
  48. package/lib/commonjs/ui/session/index.js.map +1 -1
  49. package/lib/commonjs/ui/session/useBackgroundSessionSync.js +81 -0
  50. package/lib/commonjs/ui/session/useBackgroundSessionSync.js.map +1 -0
  51. package/lib/commonjs/ui/utils/userUtils.js +31 -22
  52. package/lib/commonjs/ui/utils/userUtils.js.map +1 -1
  53. package/lib/module/ui/components/OxyProvider.js +3 -1
  54. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  55. package/lib/module/ui/components/ProfileButton.js +2 -2
  56. package/lib/module/ui/components/ProfileButton.js.map +1 -1
  57. package/lib/module/ui/components/internal/PinInput.js +3 -1
  58. package/lib/module/ui/components/internal/PinInput.js.map +1 -1
  59. package/lib/module/ui/components/logo/LogoText.js +4 -4
  60. package/lib/module/ui/components/logo/LogoText.js.map +1 -1
  61. package/lib/module/ui/components/payment/PaymentSummaryStep.js +2 -2
  62. package/lib/module/ui/components/payment/PaymentSummaryStep.js.map +1 -1
  63. package/lib/module/ui/context/OxyContext.js +14 -1
  64. package/lib/module/ui/context/OxyContext.js.map +1 -1
  65. package/lib/module/ui/screens/AccountSettingsScreen.js +2 -3
  66. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  67. package/lib/module/ui/screens/ChangeAvatarScreen.js +3 -4
  68. package/lib/module/ui/screens/ChangeAvatarScreen.js.map +1 -1
  69. package/lib/module/ui/screens/EditProfileScreen.js +3 -4
  70. package/lib/module/ui/screens/EditProfileScreen.js.map +1 -1
  71. package/lib/module/ui/screens/FeedbackScreen.js +3 -1
  72. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  73. package/lib/module/ui/screens/ManageAccountScreen.js +2 -2
  74. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  75. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +2 -2
  76. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  77. package/lib/module/ui/screens/PrivacySettingsScreen.js +9 -10
  78. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  79. package/lib/module/ui/screens/ProfileScreen.js +1 -1
  80. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  81. package/lib/module/ui/screens/UserListScreen.js +2 -3
  82. package/lib/module/ui/screens/UserListScreen.js.map +1 -1
  83. package/lib/module/ui/screens/trust/TrustCenterScreen.js +1 -1
  84. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  85. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +2 -3
  86. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  87. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +1 -1
  88. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  89. package/lib/module/ui/session/backgroundSession.js +258 -0
  90. package/lib/module/ui/session/backgroundSession.js.map +1 -0
  91. package/lib/module/ui/session/index.js +1 -0
  92. package/lib/module/ui/session/index.js.map +1 -1
  93. package/lib/module/ui/session/useBackgroundSessionSync.js +76 -0
  94. package/lib/module/ui/session/useBackgroundSessionSync.js.map +1 -0
  95. package/lib/module/ui/utils/userUtils.js +31 -22
  96. package/lib/module/ui/utils/userUtils.js.map +1 -1
  97. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -1
  99. package/lib/typescript/commonjs/ui/components/internal/PinInput.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  101. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +22 -0
  102. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
  103. package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/ui/screens/EditProfileScreen.d.ts.map +1 -1
  105. package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  107. package/lib/typescript/commonjs/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  109. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts +1 -1
  110. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts.map +1 -1
  111. package/lib/typescript/commonjs/ui/session/backgroundSession.d.ts +42 -0
  112. package/lib/typescript/commonjs/ui/session/backgroundSession.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/ui/session/index.d.ts +1 -0
  114. package/lib/typescript/commonjs/ui/session/index.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/ui/session/useBackgroundSessionSync.d.ts +23 -0
  116. package/lib/typescript/commonjs/ui/session/useBackgroundSessionSync.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/ui/types/navigation.d.ts +7 -0
  118. package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/utils/userUtils.d.ts +7 -12
  120. package/lib/typescript/commonjs/ui/utils/userUtils.d.ts.map +1 -1
  121. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  122. package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -1
  123. package/lib/typescript/module/ui/components/internal/PinInput.d.ts.map +1 -1
  124. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  125. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +22 -0
  126. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
  127. package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts.map +1 -1
  128. package/lib/typescript/module/ui/screens/EditProfileScreen.d.ts.map +1 -1
  129. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  130. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  131. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  132. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  133. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts +1 -1
  134. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts.map +1 -1
  135. package/lib/typescript/module/ui/session/backgroundSession.d.ts +42 -0
  136. package/lib/typescript/module/ui/session/backgroundSession.d.ts.map +1 -0
  137. package/lib/typescript/module/ui/session/index.d.ts +1 -0
  138. package/lib/typescript/module/ui/session/index.d.ts.map +1 -1
  139. package/lib/typescript/module/ui/session/useBackgroundSessionSync.d.ts +23 -0
  140. package/lib/typescript/module/ui/session/useBackgroundSessionSync.d.ts.map +1 -0
  141. package/lib/typescript/module/ui/types/navigation.d.ts +7 -0
  142. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  143. package/lib/typescript/module/ui/utils/userUtils.d.ts +7 -12
  144. package/lib/typescript/module/ui/utils/userUtils.d.ts.map +1 -1
  145. package/package.json +5 -5
  146. package/src/ui/components/OxyProvider.tsx +2 -0
  147. package/src/ui/components/ProfileButton.tsx +5 -2
  148. package/src/ui/components/internal/PinInput.tsx +1 -0
  149. package/src/ui/components/logo/LogoText.tsx +4 -4
  150. package/src/ui/components/payment/PaymentSummaryStep.tsx +2 -2
  151. package/src/ui/context/OxyContext.tsx +14 -0
  152. package/src/ui/context/oxyContextTypes.ts +22 -0
  153. package/src/ui/screens/AccountSettingsScreen.tsx +4 -4
  154. package/src/ui/screens/ChangeAvatarScreen.tsx +6 -3
  155. package/src/ui/screens/EditProfileScreen.tsx +6 -3
  156. package/src/ui/screens/FeedbackScreen.tsx +1 -0
  157. package/src/ui/screens/ManageAccountScreen.tsx +8 -1
  158. package/src/ui/screens/PremiumSubscriptionScreen.tsx +2 -2
  159. package/src/ui/screens/PrivacySettingsScreen.tsx +13 -11
  160. package/src/ui/screens/ProfileScreen.tsx +3 -1
  161. package/src/ui/screens/UserListScreen.tsx +2 -2
  162. package/src/ui/screens/trust/TrustCenterScreen.tsx +2 -2
  163. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +3 -3
  164. package/src/ui/screens/trust/TrustRewardsScreen.tsx +1 -1
  165. package/src/ui/screens/trust/TrustRulesScreen.tsx +1 -1
  166. package/src/ui/screens/trust/trustTier.ts +1 -1
  167. package/src/ui/session/__tests__/backgroundSession.test.ts +387 -0
  168. package/src/ui/session/backgroundSession.ts +299 -0
  169. package/src/ui/session/index.ts +1 -0
  170. package/src/ui/session/useBackgroundSessionSync.ts +92 -0
  171. package/src/ui/types/navigation.ts +7 -0
  172. package/src/ui/utils/userUtils.ts +34 -20
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Keeps the native background credential in step with the session, so an app
3
+ * enables background authentication with one prop and writes no session code of
4
+ * its own.
5
+ *
6
+ * See `./backgroundSession` for what the credential is and why it is separate
7
+ * from the rotating device secret.
8
+ */
9
+ import { useEffect } from 'react';
10
+ import { AppState } from 'react-native';
11
+ import type { OxyServices } from '@oxyhq/core';
12
+ import {
13
+ clearBackgroundSession,
14
+ isBackgroundSessionSupported,
15
+ syncBackgroundSession,
16
+ } from './backgroundSession';
17
+
18
+ export interface UseBackgroundSessionSyncInput {
19
+ /** `OxyProviderProps.backgroundSession`. */
20
+ enabled: boolean;
21
+ oxyServices: OxyServices;
22
+ /** The signed-in account, or `null` when signed out. */
23
+ userId: string | null;
24
+ /** Whether a bearer is available yet — provisioning needs one. */
25
+ canUsePrivateApi: boolean;
26
+ }
27
+
28
+ /**
29
+ * An effect is the right shape here, unusually for this codebase: the work is a
30
+ * side effect on native storage, and it has to react both to an identity change
31
+ * (a value) and to the app being foregrounded (a subscription). There is no
32
+ * derived-state or React Query formulation of "write a credential to the
33
+ * keystore when the user changes or the app comes back".
34
+ *
35
+ * Re-runs on identity change, which is what makes sign-out and account switching
36
+ * work: `syncBackgroundSession` clears a credential belonging to anyone other
37
+ * than `userId` before it does any network work.
38
+ */
39
+ export function useBackgroundSessionSync({
40
+ enabled,
41
+ oxyServices,
42
+ userId,
43
+ canUsePrivateApi,
44
+ }: UseBackgroundSessionSyncInput): void {
45
+ useEffect(() => {
46
+ if (!isBackgroundSessionSupported()) {
47
+ return;
48
+ }
49
+
50
+ if (!enabled) {
51
+ // An app that leaves the feature off must not keep a credential THIS app
52
+ // provisioned earlier. The store is package-scoped (see
53
+ // OxyBackgroundSessionStore), so this cannot revoke a sibling Oxy app's
54
+ // credential under the shared UID.
55
+ void clearBackgroundSession();
56
+ return;
57
+ }
58
+
59
+ // A run that is superseded (unmount, or another identity change) must not
60
+ // write the credential it was about to write.
61
+ let current = true;
62
+ // Deliberately NOT caught. `syncBackgroundSession` already handles every
63
+ // runtime failure internally and throws for exactly one thing: an installed
64
+ // `@oxyhq/core` too old to provision. That is a dependency mistake which must
65
+ // surface, so it is allowed to reject — adding a `.catch()` here would put it
66
+ // back behind the silence it was moved out of.
67
+ const run = () => {
68
+ void syncBackgroundSession({
69
+ oxyServices,
70
+ userId,
71
+ canUsePrivateApi,
72
+ isCurrent: () => current,
73
+ });
74
+ };
75
+
76
+ run();
77
+ const subscription = AppState.addEventListener('change', (state) => {
78
+ if (state === 'active') {
79
+ run();
80
+ }
81
+ });
82
+
83
+ return () => {
84
+ current = false;
85
+ subscription.remove();
86
+ // Deliberately NOT clearing here. Unmount is the app closing, which is
87
+ // precisely when the credential has to survive — clearing on teardown
88
+ // would defeat the entire feature. Revocation happens on sign-out (via a
89
+ // `userId` of null), on the server, or when the credential expires.
90
+ };
91
+ }, [enabled, oxyServices, userId, canUsePrivateApi]);
92
+ }
@@ -136,4 +136,11 @@ export interface OxyProviderProps {
136
136
  * @default 'off'
137
137
  */
138
138
  requireAuth?: 'off' | 'soft' | 'hard';
139
+ /**
140
+ * When true, provisions a non-rotating background credential for native code
141
+ * (Android widgets) that runs without a JS runtime. Android-only today; inert
142
+ * on web and iOS.
143
+ * @default false
144
+ */
145
+ backgroundSession?: boolean;
139
146
  }
@@ -1,13 +1,15 @@
1
1
  /**
2
2
  * User display name and date formatting utilities.
3
3
  *
4
- * The display-name helpers are thin wrappers around the canonical
5
- * `getAccountDisplayName` in `@oxyhq/core`, which handles all the edge cases
6
- * (missing username, missing name, fallback to truncated `publicKey`, i18n).
4
+ * Display-name helpers follow the API contract: prefer `name.displayName` when
5
+ * present, otherwise fall back to the normalized handle. The legacy
6
+ * `getAccountDisplayName` chain is only used as a last resort for local
7
+ * account-switcher surfaces without a handle.
7
8
  */
8
9
 
9
10
  import {
10
11
  getAccountDisplayName as coreGetAccountDisplayName,
12
+ getNormalizedUserHandle,
11
13
  type DisplayNameUserShape,
12
14
  } from '@oxyhq/core';
13
15
 
@@ -31,44 +33,56 @@ export const formatDate = (dateString: string | undefined | null | Date): string
31
33
  }
32
34
  };
33
35
 
36
+ function readDisplayName(user: DisplayNameUserShape | null | undefined): string {
37
+ const name = user?.name;
38
+ if (!name || typeof name !== 'object') return '';
39
+ return typeof name.displayName === 'string' ? name.displayName.trim() : '';
40
+ }
41
+
34
42
  /**
35
43
  * Gets a display name from user data.
36
44
  *
37
- * Prefers full name composed first+last username `Account 0x12345678…`
38
- * (derived from publicKey) → translated "Unnamed".
39
- *
40
- * @param user - User-like object with optional name/username/publicKey
41
- * @param locale - Optional locale for the final fallback label
45
+ * Prefers API `name.displayName`, then the normalized handle, then the local
46
+ * account-switcher fallback chain.
42
47
  */
43
48
  export const getDisplayName = (
44
49
  user: DisplayNameUserShape | null | undefined,
45
50
  locale?: string,
46
- ): string => coreGetAccountDisplayName(user, locale);
51
+ ): string => {
52
+ const displayName = readDisplayName(user);
53
+ if (displayName) return displayName;
54
+
55
+ const handle = getNormalizedUserHandle(user);
56
+ if (handle) return handle;
57
+
58
+ return coreGetAccountDisplayName(user, locale);
59
+ };
47
60
 
48
61
  /**
49
- * Gets a short display name (first name or username).
50
- *
51
- * Used for compact UI (e.g. greetings). Falls back to the full display name
52
- * helper, which also handles publicKey-only accounts.
62
+ * Gets a short display name (first token) for compact UI.
53
63
  */
54
64
  export const getShortDisplayName = (
55
65
  user: DisplayNameUserShape | null | undefined,
56
66
  locale?: string,
57
67
  ): string => {
58
- if (!user) return coreGetAccountDisplayName(user, locale);
68
+ const displayName = readDisplayName(user);
69
+ if (displayName) {
70
+ const firstToken = displayName.split(/\s+/).find(Boolean);
71
+ if (firstToken) return firstToken;
72
+ }
59
73
 
60
- const name = user.name;
74
+ const name = user?.name;
61
75
  if (name && typeof name === 'object') {
62
76
  const first = typeof name.first === 'string' ? name.first.trim() : '';
63
- if (first) return first;
77
+ if (first) return first.split(/\s+/)[0] ?? first;
64
78
  const full = typeof name.full === 'string' ? name.full.trim() : '';
65
- if (full) return full.split(' ')[0];
79
+ if (full) return full.split(/\s+/)[0] ?? full;
66
80
  } else if (typeof name === 'string' && name.trim()) {
67
- return name.trim().split(' ')[0];
81
+ return name.trim().split(/\s+/)[0] ?? name.trim();
68
82
  }
69
83
 
70
- if (typeof user.username === 'string' && user.username.trim()) return user.username.trim();
84
+ const handle = getNormalizedUserHandle(user);
85
+ if (handle) return handle;
71
86
 
72
- // Defer to the canonical helper for publicKey/unnamed fallbacks.
73
87
  return coreGetAccountDisplayName(user, locale);
74
88
  };