@oxyhq/services 10.2.0 → 10.2.2

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 (246) hide show
  1. package/README.md +9 -13
  2. package/lib/commonjs/index.js +10 -0
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/ui/components/AccountMenu.js +297 -226
  5. package/lib/commonjs/ui/components/AccountMenu.js.map +1 -1
  6. package/lib/commonjs/ui/components/AccountMenuButton.js.map +1 -1
  7. package/lib/commonjs/ui/components/FollowButton.js +3 -1
  8. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  9. package/lib/commonjs/ui/components/OxySignInButton.js +1 -1
  10. package/lib/commonjs/ui/components/SignInModal.js +11 -12
  11. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  12. package/lib/commonjs/ui/components/accountMenuRows.js +18 -30
  13. package/lib/commonjs/ui/components/accountMenuRows.js.map +1 -1
  14. package/lib/commonjs/ui/context/OxyContext.js +57 -78
  15. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  16. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +7 -13
  17. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  18. package/lib/commonjs/ui/hooks/useAuth.js +10 -40
  19. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  20. package/lib/commonjs/ui/hooks/useDeviceAccounts.js +285 -0
  21. package/lib/commonjs/ui/hooks/useDeviceAccounts.js.map +1 -0
  22. package/lib/commonjs/ui/hooks/useFollow.js +21 -7
  23. package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
  24. package/lib/commonjs/ui/hooks/useSessionManagement.js +5 -6
  25. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  26. package/lib/commonjs/ui/hooks/useSessionSocket.js +4 -5
  27. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  28. package/lib/commonjs/ui/hooks/useWebSSO.js +1 -1
  29. package/lib/commonjs/ui/navigation/routes.js +7 -7
  30. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  31. package/lib/commonjs/ui/screens/OxyAuthScreen.js +6 -7
  32. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  33. package/lib/commonjs/ui/screens/ProfileScreen.js +18 -20
  34. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  35. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +4 -4
  36. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/{karma/KarmaAboutScreen.js → trust/TrustAboutScreen.js} +11 -11
  38. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js.map +1 -0
  39. package/lib/commonjs/ui/screens/{karma/KarmaCenterScreen.js → trust/TrustCenterScreen.js} +91 -41
  40. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -0
  41. package/lib/commonjs/ui/screens/{karma/KarmaFAQScreen.js → trust/TrustFAQScreen.js} +11 -11
  42. package/lib/commonjs/ui/screens/{karma/KarmaFAQScreen.js.map → trust/TrustFAQScreen.js.map} +1 -1
  43. package/lib/commonjs/ui/screens/{karma/KarmaLeaderboardScreen.js → trust/TrustLeaderboardScreen.js} +63 -42
  44. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -0
  45. package/lib/commonjs/ui/screens/{karma/KarmaRewardsScreen.js → trust/TrustRewardsScreen.js} +54 -54
  46. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -0
  47. package/lib/commonjs/ui/screens/{karma/KarmaRulesScreen.js → trust/TrustRulesScreen.js} +45 -16
  48. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -0
  49. package/lib/commonjs/ui/screens/trust/trustTier.js +23 -0
  50. package/lib/commonjs/ui/screens/trust/trustTier.js.map +1 -0
  51. package/lib/commonjs/utils/deviceFlowSignIn.js +12 -10
  52. package/lib/commonjs/utils/deviceFlowSignIn.js.map +1 -1
  53. package/lib/module/index.js +3 -0
  54. package/lib/module/index.js.map +1 -1
  55. package/lib/module/ui/components/AccountMenu.js +297 -226
  56. package/lib/module/ui/components/AccountMenu.js.map +1 -1
  57. package/lib/module/ui/components/AccountMenuButton.js.map +1 -1
  58. package/lib/module/ui/components/FollowButton.js +3 -1
  59. package/lib/module/ui/components/FollowButton.js.map +1 -1
  60. package/lib/module/ui/components/OxySignInButton.js +1 -1
  61. package/lib/module/ui/components/SignInModal.js +11 -12
  62. package/lib/module/ui/components/SignInModal.js.map +1 -1
  63. package/lib/module/ui/components/accountMenuRows.js +18 -30
  64. package/lib/module/ui/components/accountMenuRows.js.map +1 -1
  65. package/lib/module/ui/context/OxyContext.js +58 -79
  66. package/lib/module/ui/context/OxyContext.js.map +1 -1
  67. package/lib/module/ui/context/hooks/useAuthOperations.js +7 -13
  68. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  69. package/lib/module/ui/hooks/useAuth.js +10 -40
  70. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  71. package/lib/module/ui/hooks/useDeviceAccounts.js +281 -0
  72. package/lib/module/ui/hooks/useDeviceAccounts.js.map +1 -0
  73. package/lib/module/ui/hooks/useFollow.js +21 -7
  74. package/lib/module/ui/hooks/useFollow.js.map +1 -1
  75. package/lib/module/ui/hooks/useSessionManagement.js +5 -6
  76. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  77. package/lib/module/ui/hooks/useSessionSocket.js +4 -5
  78. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  79. package/lib/module/ui/hooks/useWebSSO.js +1 -1
  80. package/lib/module/ui/navigation/routes.js +7 -7
  81. package/lib/module/ui/navigation/routes.js.map +1 -1
  82. package/lib/module/ui/screens/OxyAuthScreen.js +6 -7
  83. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  84. package/lib/module/ui/screens/ProfileScreen.js +18 -20
  85. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  86. package/lib/module/ui/screens/WelcomeNewUserScreen.js +4 -4
  87. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  88. package/lib/module/ui/screens/{karma/KarmaAboutScreen.js → trust/TrustAboutScreen.js} +11 -11
  89. package/lib/module/ui/screens/trust/TrustAboutScreen.js.map +1 -0
  90. package/lib/module/ui/screens/{karma/KarmaCenterScreen.js → trust/TrustCenterScreen.js} +92 -42
  91. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -0
  92. package/lib/module/ui/screens/{karma/KarmaFAQScreen.js → trust/TrustFAQScreen.js} +11 -11
  93. package/lib/module/ui/screens/{karma/KarmaFAQScreen.js.map → trust/TrustFAQScreen.js.map} +1 -1
  94. package/lib/module/ui/screens/{karma/KarmaLeaderboardScreen.js → trust/TrustLeaderboardScreen.js} +63 -42
  95. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -0
  96. package/lib/module/ui/screens/{karma/KarmaRewardsScreen.js → trust/TrustRewardsScreen.js} +54 -54
  97. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -0
  98. package/lib/module/ui/screens/{karma/KarmaRulesScreen.js → trust/TrustRulesScreen.js} +45 -16
  99. package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -0
  100. package/lib/module/ui/screens/trust/trustTier.js +19 -0
  101. package/lib/module/ui/screens/trust/trustTier.js.map +1 -0
  102. package/lib/module/utils/deviceFlowSignIn.js +13 -10
  103. package/lib/module/utils/deviceFlowSignIn.js.map +1 -1
  104. package/lib/typescript/commonjs/index.d.ts +3 -1
  105. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +30 -10
  107. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts +1 -1
  109. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts +19 -12
  111. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts.map +1 -1
  112. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +3 -3
  113. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  114. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +1 -7
  116. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  117. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts +3 -7
  118. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts +133 -0
  120. package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/ui/hooks/useFollow.d.ts +1 -1
  122. package/lib/typescript/commonjs/ui/hooks/useFollow.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  124. package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts.map +1 -1
  125. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts +1 -1
  126. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
  127. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  128. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  129. package/lib/typescript/commonjs/ui/screens/trust/TrustAboutScreen.d.ts +5 -0
  130. package/lib/typescript/commonjs/ui/screens/{karma/KarmaAboutScreen.d.ts.map → trust/TrustAboutScreen.d.ts.map} +1 -1
  131. package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts +5 -0
  132. package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -0
  133. package/lib/typescript/{module/ui/screens/karma/KarmaFAQScreen.d.ts → commonjs/ui/screens/trust/TrustFAQScreen.d.ts} +1 -1
  134. package/lib/typescript/commonjs/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts +5 -0
  136. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/ui/screens/trust/TrustRewardsScreen.d.ts +5 -0
  138. package/lib/typescript/commonjs/ui/screens/{karma/KarmaRewardsScreen.d.ts.map → trust/TrustRewardsScreen.d.ts.map} +1 -1
  139. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts +5 -0
  140. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts +9 -0
  142. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts.map +1 -0
  143. package/lib/typescript/commonjs/ui/types/navigation.d.ts +1 -1
  144. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts +11 -9
  145. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts.map +1 -1
  146. package/lib/typescript/module/index.d.ts +3 -1
  147. package/lib/typescript/module/index.d.ts.map +1 -1
  148. package/lib/typescript/module/ui/components/AccountMenu.d.ts +30 -10
  149. package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -1
  150. package/lib/typescript/module/ui/components/SignInModal.d.ts +1 -1
  151. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  152. package/lib/typescript/module/ui/components/accountMenuRows.d.ts +19 -12
  153. package/lib/typescript/module/ui/components/accountMenuRows.d.ts.map +1 -1
  154. package/lib/typescript/module/ui/context/OxyContext.d.ts +3 -3
  155. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  156. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  157. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +1 -7
  158. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  159. package/lib/typescript/module/ui/hooks/useAuth.d.ts +3 -7
  160. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  161. package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts +133 -0
  162. package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts.map +1 -0
  163. package/lib/typescript/module/ui/hooks/useFollow.d.ts +1 -1
  164. package/lib/typescript/module/ui/hooks/useFollow.d.ts.map +1 -1
  165. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  166. package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts.map +1 -1
  167. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts +1 -1
  168. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  169. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  170. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  171. package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts +5 -0
  172. package/lib/typescript/module/ui/screens/{karma/KarmaAboutScreen.d.ts.map → trust/TrustAboutScreen.d.ts.map} +1 -1
  173. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts +5 -0
  174. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -0
  175. package/lib/typescript/{commonjs/ui/screens/karma/KarmaFAQScreen.d.ts → module/ui/screens/trust/TrustFAQScreen.d.ts} +1 -1
  176. package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -0
  177. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts +5 -0
  178. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -0
  179. package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts +5 -0
  180. package/lib/typescript/module/ui/screens/{karma/KarmaRewardsScreen.d.ts.map → trust/TrustRewardsScreen.d.ts.map} +1 -1
  181. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts +5 -0
  182. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -0
  183. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts +9 -0
  184. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts.map +1 -0
  185. package/lib/typescript/module/ui/types/navigation.d.ts +1 -1
  186. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts +11 -9
  187. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts.map +1 -1
  188. package/package.json +2 -2
  189. package/src/index.ts +10 -1
  190. package/src/ui/components/AccountMenu.tsx +311 -253
  191. package/src/ui/components/AccountMenuButton.tsx +2 -2
  192. package/src/ui/components/FollowButton.tsx +2 -2
  193. package/src/ui/components/OxySignInButton.tsx +1 -1
  194. package/src/ui/components/SignInModal.tsx +13 -14
  195. package/src/ui/components/accountMenuRows.ts +28 -40
  196. package/src/ui/context/OxyContext.tsx +71 -74
  197. package/src/ui/context/hooks/useAuthOperations.ts +7 -13
  198. package/src/ui/hooks/useAuth.ts +12 -49
  199. package/src/ui/hooks/useDeviceAccounts.ts +348 -0
  200. package/src/ui/hooks/useFollow.ts +16 -8
  201. package/src/ui/hooks/useSessionManagement.ts +5 -14
  202. package/src/ui/hooks/useSessionSocket.ts +4 -5
  203. package/src/ui/hooks/useWebSSO.ts +1 -1
  204. package/src/ui/navigation/routes.ts +13 -13
  205. package/src/ui/screens/OxyAuthScreen.tsx +6 -7
  206. package/src/ui/screens/ProfileScreen.tsx +15 -17
  207. package/src/ui/screens/WelcomeNewUserScreen.tsx +2 -2
  208. package/src/ui/screens/{karma/KarmaAboutScreen.tsx → trust/TrustAboutScreen.tsx} +15 -15
  209. package/src/ui/screens/{karma/KarmaCenterScreen.tsx → trust/TrustCenterScreen.tsx} +87 -41
  210. package/src/ui/screens/{karma/KarmaFAQScreen.tsx → trust/TrustFAQScreen.tsx} +10 -10
  211. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +101 -0
  212. package/src/ui/screens/{karma/KarmaRewardsScreen.tsx → trust/TrustRewardsScreen.tsx} +54 -54
  213. package/src/ui/screens/{karma/KarmaRulesScreen.tsx → trust/TrustRulesScreen.tsx} +27 -13
  214. package/src/ui/screens/trust/trustTier.ts +20 -0
  215. package/src/ui/types/navigation.ts +1 -2
  216. package/src/utils/__tests__/deviceFlowSignIn.test.ts +2 -3
  217. package/src/utils/deviceFlowSignIn.ts +18 -12
  218. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +0 -1
  219. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +0 -1
  220. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +0 -1
  221. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +0 -1
  222. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +0 -1
  223. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +0 -1
  224. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +0 -1
  225. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +0 -1
  226. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +0 -1
  227. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +0 -1
  228. package/lib/typescript/commonjs/ui/screens/karma/KarmaAboutScreen.d.ts +0 -5
  229. package/lib/typescript/commonjs/ui/screens/karma/KarmaCenterScreen.d.ts +0 -5
  230. package/lib/typescript/commonjs/ui/screens/karma/KarmaCenterScreen.d.ts.map +0 -1
  231. package/lib/typescript/commonjs/ui/screens/karma/KarmaFAQScreen.d.ts.map +0 -1
  232. package/lib/typescript/commonjs/ui/screens/karma/KarmaLeaderboardScreen.d.ts +0 -5
  233. package/lib/typescript/commonjs/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +0 -1
  234. package/lib/typescript/commonjs/ui/screens/karma/KarmaRewardsScreen.d.ts +0 -5
  235. package/lib/typescript/commonjs/ui/screens/karma/KarmaRulesScreen.d.ts +0 -5
  236. package/lib/typescript/commonjs/ui/screens/karma/KarmaRulesScreen.d.ts.map +0 -1
  237. package/lib/typescript/module/ui/screens/karma/KarmaAboutScreen.d.ts +0 -5
  238. package/lib/typescript/module/ui/screens/karma/KarmaCenterScreen.d.ts +0 -5
  239. package/lib/typescript/module/ui/screens/karma/KarmaCenterScreen.d.ts.map +0 -1
  240. package/lib/typescript/module/ui/screens/karma/KarmaFAQScreen.d.ts.map +0 -1
  241. package/lib/typescript/module/ui/screens/karma/KarmaLeaderboardScreen.d.ts +0 -5
  242. package/lib/typescript/module/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +0 -1
  243. package/lib/typescript/module/ui/screens/karma/KarmaRewardsScreen.d.ts +0 -5
  244. package/lib/typescript/module/ui/screens/karma/KarmaRulesScreen.d.ts +0 -5
  245. package/lib/typescript/module/ui/screens/karma/KarmaRulesScreen.d.ts.map +0 -1
  246. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +0 -88
@@ -142,13 +142,12 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
142
142
  // `claimSessionByToken` — the device-flow equivalent of OAuth's
143
143
  // code-for-token exchange (RFC 8628 §3.4).
144
144
  //
145
- // Without that exchange the SDK has no bearer token, so the subsequent
146
- // `switchSession` -> `getTokenBySession` call (`GET /session/token/:id`) 401s
147
- // against the C1-hardened API the session is authorized server-side but the
148
- // app never becomes authenticated and the sheet sits "Waiting for
149
- // authorization..." forever. Once `claimSessionByToken` plants the tokens in
150
- // the HttpService, the rest of the session wiring flows through the normal
151
- // `switchSession` path. This mirrors `SignInModal`'s web flow exactly.
145
+ // Without that exchange the SDK has no bearer token the session is
146
+ // authorized server-side but the app never becomes authenticated and the
147
+ // sheet sits "Waiting for authorization..." forever. Once
148
+ // `claimSessionByToken` plants the tokens in the HttpService, the rest of the
149
+ // session wiring flows through the normal `switchSession` path. This mirrors
150
+ // `SignInModal`'s web flow exactly.
152
151
  const handleAuthSuccess = useCallback(async (sessionId: string, sessionToken: string) => {
153
152
  if (isProcessingRef.current) return;
154
153
  isProcessingRef.current = true;
@@ -32,7 +32,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
32
32
  // Use useOxy() hook for OxyContext values
33
33
  const { oxyServices, user: currentUser } = useOxy();
34
34
  const [profile, setProfile] = useState<User | null>(null);
35
- const [karmaTotal, setKarmaTotal] = useState<number | null>(null);
35
+ const [reputationTotal, setReputationTotal] = useState<number | null>(null);
36
36
  const [postsCount, setPostsCount] = useState<number | null>(null);
37
37
  const [commentsCount, setCommentsCount] = useState<number | null>(null);
38
38
  const [isLoading, setIsLoading] = useState(true);
@@ -77,7 +77,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
77
77
  setIsLoading(true);
78
78
  setError(null);
79
79
 
80
- // Load user profile, karma total, and stats
80
+ // Load user profile, reputation total, and stats
81
81
  Promise.all([
82
82
  oxyServices.getUserById(userId).catch((err: unknown) => {
83
83
  // If this is the current user and the API call fails, use current user data as fallback
@@ -88,18 +88,16 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
88
88
  }
89
89
  throw err;
90
90
  }),
91
- oxyServices.getUserKarmaTotal ?
92
- oxyServices.getUserKarmaTotal(userId).catch(() => {
93
- return { total: undefined };
94
- }) :
95
- Promise.resolve({ total: undefined }),
91
+ oxyServices.getReputationBalance(userId)
92
+ .then((balance): { total: number | undefined } => ({ total: balance.total }))
93
+ .catch((): { total: number | undefined } => ({ total: undefined })),
96
94
  oxyServices.getUserStats ?
97
95
  oxyServices.getUserStats(userId).catch(() => {
98
96
  return { postCount: 0, commentCount: 0 };
99
97
  }) :
100
98
  Promise.resolve({ postCount: 0, commentCount: 0 })
101
99
  ])
102
- .then(([profileRes, karmaRes, statsRes]) => {
100
+ .then(([profileRes, reputationRes, statsRes]) => {
103
101
  if (!profileRes) {
104
102
  setError('Profile data is not available');
105
103
  setIsLoading(false);
@@ -107,7 +105,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
107
105
  }
108
106
 
109
107
  setProfile(profileRes);
110
- setKarmaTotal(typeof karmaRes.total === 'number' ? karmaRes.total : null);
108
+ setReputationTotal(typeof reputationRes.total === 'number' ? reputationRes.total : null);
111
109
 
112
110
  // Extract links from profile data
113
111
  if (profileRes.linksMetadata && Array.isArray(profileRes.linksMetadata)) {
@@ -326,24 +324,24 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
326
324
  {/* All Stats in one row */}
327
325
  <View style={styles.statsRow}>
328
326
  <View style={styles.statItem}>
329
- <Text style={styles.karmaAmount} className="text-primary">{karmaTotal !== null && karmaTotal !== undefined ? karmaTotal : '--'}</Text>
330
- <Text style={styles.karmaLabel} className="text-muted-foreground">{t('profile.karma') || 'Karma'}</Text>
327
+ <Text style={styles.statAmount} className="text-primary">{reputationTotal !== null && reputationTotal !== undefined ? reputationTotal : '--'}</Text>
328
+ <Text style={styles.statLabel} className="text-muted-foreground">{t('profile.reputation') || 'Reputation'}</Text>
331
329
  </View>
332
330
  <View style={styles.statItem}>
333
331
  {isLoadingCounts ? (
334
332
  <ActivityIndicator size="small" color={bloomTheme.colors.text} />
335
333
  ) : (
336
- <Text style={styles.karmaAmount} className="text-foreground">{followerCount !== null ? followerCount : '--'}</Text>
334
+ <Text style={styles.statAmount} className="text-foreground">{followerCount !== null ? followerCount : '--'}</Text>
337
335
  )}
338
- <Text style={styles.karmaLabel} className="text-muted-foreground">{t('profile.followers') || 'Followers'}</Text>
336
+ <Text style={styles.statLabel} className="text-muted-foreground">{t('profile.followers') || 'Followers'}</Text>
339
337
  </View>
340
338
  <View style={styles.statItem}>
341
339
  {isLoadingCounts ? (
342
340
  <ActivityIndicator size="small" color={bloomTheme.colors.text} />
343
341
  ) : (
344
- <Text style={styles.karmaAmount} className="text-foreground">{followingCount !== null ? followingCount : '--'}</Text>
342
+ <Text style={styles.statAmount} className="text-foreground">{followingCount !== null ? followingCount : '--'}</Text>
345
343
  )}
346
- <Text style={styles.karmaLabel} className="text-muted-foreground">{t('profile.following') || 'Following'}</Text>
344
+ <Text style={styles.statLabel} className="text-muted-foreground">{t('profile.following') || 'Following'}</Text>
347
345
  </View>
348
346
  </View>
349
347
  </View>
@@ -401,8 +399,8 @@ const createStyles = () => StyleSheet.create({
401
399
  },
402
400
  statsRow: { width: '100%', flex: 1, flexDirection: 'row', alignItems: 'center', marginTop: 6, marginBottom: 2, justifyContent: 'space-between' },
403
401
  statItem: { flex: 1, alignItems: 'center', minWidth: 50, marginBottom: 12 },
404
- karmaLabel: { fontSize: 14, marginBottom: 2, textAlign: 'center' },
405
- karmaAmount: { fontSize: 24, fontWeight: 'bold', textAlign: 'center', letterSpacing: 0.2 },
402
+ statLabel: { fontSize: 14, marginBottom: 2, textAlign: 'center' },
403
+ statAmount: { fontSize: 24, fontWeight: 'bold', textAlign: 'center', letterSpacing: 0.2 },
406
404
  // Error handling styles
407
405
  errorHeader: {
408
406
  flexDirection: 'row',
@@ -115,9 +115,9 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
115
115
  t('welcomeNew.principles.bullets.3') || 'No selling your data',
116
116
  ]
117
117
  },
118
- { key: 'karma', title: t('welcomeNew.karma.title') || 'Karma = Trust & Growth', body: t('welcomeNew.karma.body') || 'Oxy Karma is a points system that reacts to what you do. Helpful, respectful, constructive actions earn it. Harmful or low‑effort stuff chips it away. More karma can unlock benefits; low karma can limit features. It keeps things fair and rewards real contribution.' },
118
+ { key: 'trust', title: t('welcomeNew.trust.title') || 'Oxy Trust = Trust & Growth', body: t('welcomeNew.trust.body') || 'Oxy Trust is a reputation system that reacts to what you do. Helpful, respectful, constructive actions earn reputation. Harmful or low‑effort stuff chips it away. More reputation raises your trust tier and can unlock benefits; low reputation can limit features. It keeps things fair and rewards real contribution.' },
119
119
  { key: 'avatar', title: t('welcomeNew.avatar.title') || 'Make It Yours', body: t('welcomeNew.avatar.body') || 'Add an avatar so people recognize you. It will show anywhere you show up here. Skip if you want — you can add it later.', showAvatar: true },
120
- { key: 'ready', title: t('welcomeNew.ready.title') || "You're Ready", body: t('welcomeNew.ready.body') || 'Explore. Contribute. Earn karma. Stay in control.' }
120
+ { key: 'ready', title: t('welcomeNew.ready.title') || "You're Ready", body: t('welcomeNew.ready.body') || 'Explore. Contribute. Earn reputation. Stay in control.' }
121
121
  ];
122
122
  const totalSteps = steps.length;
123
123
  const avatarStepIndex = steps.findIndex(s => s.showAvatar);
@@ -5,40 +5,40 @@ import Header from '../../components/Header';
5
5
  import { useI18n } from '../../hooks/useI18n';
6
6
  import { useTheme } from '@oxyhq/bloom/theme';
7
7
 
8
- const KarmaAboutScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
8
+ const TrustAboutScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
9
9
  const { t } = useI18n();
10
10
  const bloomTheme = useTheme();
11
- // Override primaryColor for Karma screens (purple instead of blue)
11
+ // Override primaryColor for Oxy Trust screens (purple instead of blue)
12
12
  const primaryColor = '#d169e5';
13
13
 
14
14
  return (
15
15
  <View style={[styles.container, { backgroundColor: bloomTheme.colors.background }]}>
16
16
  <Header
17
- title={t('karma.about.title') || 'About Karma'}
18
- subtitle={t('karma.about.subtitle') || 'Learn about the karma system'}
19
-
17
+ title={t('trust.about.title') || 'About Oxy Trust'}
18
+ subtitle={t('trust.about.subtitle') || 'Learn about the reputation system'}
19
+
20
20
  onBack={goBack}
21
21
  elevation="subtle"
22
22
  />
23
23
  <ScrollView contentContainerStyle={styles.contentContainer}>
24
24
  <Text style={[styles.paragraph, { color: bloomTheme.colors.text }]}>
25
- {t('karma.about.intro') || 'Karma is a recognition of your positive actions in the Oxy Ecosystem. It cannot be sent or received directly, only earned by contributing to the community.'}
25
+ {t('trust.about.intro') || 'Oxy Trust is a recognition of your positive actions in the Oxy Ecosystem. Reputation cannot be sent or received directly, only earned by contributing to the community.'}
26
26
  </Text>
27
27
  <Text style={[styles.section, { color: primaryColor }]}>
28
- {t('karma.about.how.title') || 'How to Earn Karma'}
28
+ {t('trust.about.how.title') || 'How to Earn Reputation'}
29
29
  </Text>
30
30
  <Text style={[styles.paragraph, { color: bloomTheme.colors.text }]}>
31
- • {t('karma.about.how.help') || 'Helping other users'}{'\n'}
32
- • {t('karma.about.how.report') || 'Reporting bugs'}{'\n'}
33
- • {t('karma.about.how.contribute') || 'Contributing content'}{'\n'}
34
- • {t('karma.about.how.participate') || 'Participating in events'}{'\n'}
35
- • {t('karma.about.how.other') || 'Other positive actions'}
31
+ • {t('trust.about.how.help') || 'Helping other users'}{'\n'}
32
+ • {t('trust.about.how.report') || 'Reporting bugs'}{'\n'}
33
+ • {t('trust.about.how.contribute') || 'Contributing content'}{'\n'}
34
+ • {t('trust.about.how.participate') || 'Participating in events'}{'\n'}
35
+ • {t('trust.about.how.other') || 'Other positive actions'}
36
36
  </Text>
37
37
  <Text style={[styles.section, { color: primaryColor }]}>
38
- {t('karma.about.why.title') || 'Why Karma?'}
38
+ {t('trust.about.why.title') || 'Why Oxy Trust?'}
39
39
  </Text>
40
40
  <Text style={[styles.paragraph, { color: bloomTheme.colors.text }]}>
41
- {t('karma.about.why.text') || 'Karma unlocks special features and recognition in the Oxy Ecosystem. The more you contribute, the more you earn!'}
41
+ {t('trust.about.why.text') || 'Your reputation and trust tier unlock special features and recognition in the Oxy Ecosystem. The more you contribute, the more you earn!'}
42
42
  </Text>
43
43
  </ScrollView>
44
44
  </View>
@@ -63,4 +63,4 @@ const styles = StyleSheet.create({
63
63
  paragraph: { fontSize: 16, marginBottom: 12 },
64
64
  });
65
65
 
66
- export default KarmaAboutScreen;
66
+ export default TrustAboutScreen;
@@ -1,5 +1,5 @@
1
1
  import type React from 'react';
2
- import { useEffect, useState } from 'react';
2
+ import { useEffect, useMemo, useState } from 'react';
3
3
  import {
4
4
  View,
5
5
  Text,
@@ -7,9 +7,9 @@ import {
7
7
  StyleSheet,
8
8
  ActivityIndicator,
9
9
  ScrollView,
10
- Alert,
11
10
  Platform,
12
11
  } from 'react-native';
12
+ import type { ReputationTransaction, TrustTier } from '@oxyhq/core';
13
13
  import type { BaseScreenProps } from '../../types/navigation';
14
14
  import { Ionicons } from '@expo/vector-icons';
15
15
  import { useI18n } from '../../hooks/useI18n';
@@ -19,8 +19,9 @@ import { Colors } from '../../constants/theme';
19
19
  import { normalizeColorScheme } from '../../utils/themeUtils';
20
20
  import { darkenColor } from '../../utils/colorUtils';
21
21
  import { useOxy } from '../../context/OxyContext';
22
+ import { getTrustTierLabel } from './trustTier';
22
23
 
23
- const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
24
+ const TrustCenterScreen: React.FC<BaseScreenProps> = ({
24
25
  theme,
25
26
  navigate,
26
27
  goBack,
@@ -28,8 +29,9 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
28
29
  // Use useOxy() hook for OxyContext values
29
30
  const { user, oxyServices, isAuthenticated } = useOxy();
30
31
  const { t } = useI18n();
31
- const [karmaTotal, setKarmaTotal] = useState<number | null>(null);
32
- const [karmaHistory, setKarmaHistory] = useState<any[]>([]);
32
+ const [reputationTotal, setReputationTotal] = useState<number | null>(null);
33
+ const [trustTier, setTrustTier] = useState<TrustTier | null>(null);
34
+ const [transactions, setTransactions] = useState<ReputationTransaction[]>([]);
33
35
  const [isLoading, setIsLoading] = useState(true);
34
36
  const [error, setError] = useState<string | null>(null);
35
37
 
@@ -37,7 +39,7 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
37
39
  const colorScheme = useColorScheme();
38
40
  const normalizedColorScheme = normalizeColorScheme(colorScheme);
39
41
  const themeColors = Colors[normalizedColorScheme];
40
- // Override primaryColor for Karma screens (purple instead of blue)
42
+ // Override primaryColor for Oxy Trust screens (purple instead of blue)
41
43
  const primaryColor = '#d169e5';
42
44
  const dangerColor = bloomTheme.colors.error;
43
45
  const mutedTextColor = bloomTheme.colors.textTertiary;
@@ -54,18 +56,27 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
54
56
  setIsLoading(true);
55
57
  setError(null);
56
58
  Promise.all([
57
- oxyServices.getUserKarmaTotal(user.id),
58
- oxyServices.getUserKarmaHistory(user.id, 20, 0),
59
+ oxyServices.getReputationBalance(user.id),
60
+ oxyServices.getReputationTransactions(user.id, 20, 0),
59
61
  ])
60
- .then(([totalRes, historyRes]) => {
61
- setKarmaTotal(totalRes.total);
62
- setKarmaHistory(Array.isArray(historyRes.history) ? historyRes.history : []);
62
+ .then(([balance, txns]) => {
63
+ setReputationTotal(balance.total);
64
+ setTrustTier(balance.trustTier);
65
+ setTransactions(Array.isArray(txns) ? txns : []);
63
66
  })
64
- .catch((err) => {
65
- setError(err.message || 'Failed to load karma data');
67
+ .catch((err: unknown) => {
68
+ setError(
69
+ (err instanceof Error ? err.message : null) ||
70
+ (t('trust.center.loadError') || 'Failed to load reputation data'),
71
+ );
66
72
  })
67
73
  .finally(() => setIsLoading(false));
68
- }, [user]);
74
+ }, [user, oxyServices, t]);
75
+
76
+ const trustTierLabel = useMemo(
77
+ () => (trustTier ? getTrustTierLabel(trustTier, t) : null),
78
+ [trustTier, t],
79
+ );
69
80
 
70
81
  if (!isAuthenticated) {
71
82
  return (
@@ -87,70 +98,81 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
87
98
  <View style={[styles.container, { backgroundColor: bloomTheme.colors.background }]}>
88
99
  <ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollContainer}>
89
100
  <View style={styles.walletHeader}>
90
- <Text style={[styles.karmaAmount, { color: primaryColor }]}>{karmaTotal ?? 0}</Text>
91
- <Text style={[styles.karmaLabel, { color: bloomTheme.colors.textTertiary }]}>
92
- {t('karma.center.balance') || 'Karma Balance'}
101
+ <Text style={[styles.reputationAmount, { color: primaryColor }]}>{reputationTotal ?? 0}</Text>
102
+ <Text style={[styles.reputationLabel, { color: bloomTheme.colors.textTertiary }]}>
103
+ {t('trust.center.balance') || 'Reputation Balance'}
93
104
  </Text>
105
+ {trustTierLabel && (
106
+ <View style={[styles.tierBadge, { borderColor: primaryColor }]}>
107
+ <Ionicons name="shield-checkmark-outline" size={14} color={primaryColor} />
108
+ <Text style={[styles.tierBadgeText, { color: primaryColor }]}>{trustTierLabel}</Text>
109
+ </View>
110
+ )}
94
111
  <View style={styles.actionContainer}>
95
112
  <View style={styles.actionRow}>
96
- <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('KarmaLeaderboard')}>
113
+ <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('TrustLeaderboard')}>
97
114
  <View style={[styles.actionIcon, { backgroundColor: iconLeaderboard }]}>
98
115
  <Ionicons name="trophy-outline" size={28} color={darkenColor(iconLeaderboard)} />
99
116
  </View>
100
- <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('karma.center.actions.leaderboard') || 'Leaderboard'}</Text>
117
+ <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('trust.center.actions.leaderboard') || 'Leaderboard'}</Text>
101
118
  </TouchableOpacity>
102
- <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('KarmaRules')}>
119
+ <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('TrustRules')}>
103
120
  <View style={[styles.actionIcon, { backgroundColor: iconRules }]}>
104
121
  <Ionicons name="document-text-outline" size={28} color={darkenColor(iconRules)} />
105
122
  </View>
106
- <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('karma.center.actions.rules') || 'Rules'}</Text>
123
+ <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('trust.center.actions.rules') || 'Rules'}</Text>
107
124
  </TouchableOpacity>
108
- <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('AboutKarma')}>
125
+ <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('AboutTrust')}>
109
126
  <View style={[styles.actionIcon, { backgroundColor: iconAbout }]}>
110
127
  <Ionicons name="star-outline" size={28} color={darkenColor(iconAbout)} />
111
128
  </View>
112
- <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('karma.center.actions.about') || 'About'}</Text>
129
+ <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('trust.center.actions.about') || 'About'}</Text>
113
130
  </TouchableOpacity>
114
131
  </View>
115
132
  <View style={styles.actionRow}>
116
- <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('KarmaRewards')}>
133
+ <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('TrustRewards')}>
117
134
  <View style={[styles.actionIcon, { backgroundColor: iconRewards }]}>
118
135
  <Ionicons name="gift-outline" size={28} color={darkenColor(iconRewards)} />
119
136
  </View>
120
- <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('karma.center.actions.rewards') || 'Rewards'}</Text>
137
+ <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('trust.center.actions.rewards') || 'Rewards'}</Text>
121
138
  </TouchableOpacity>
122
- <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('KarmaFAQ')}>
139
+ <TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate?.('TrustFAQ')}>
123
140
  <View style={[styles.actionIcon, { backgroundColor: iconFAQ }]}>
124
141
  <Ionicons name="help-circle-outline" size={28} color={darkenColor(iconFAQ)} />
125
142
  </View>
126
- <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('karma.center.actions.faq') || 'FAQ'}</Text>
143
+ <Text style={[styles.actionLabel, { color: mutedTextColor }]}>{t('trust.center.actions.faq') || 'FAQ'}</Text>
127
144
  </TouchableOpacity>
128
145
  </View>
129
146
  </View>
130
147
  <Text style={[styles.infoText, { color: mutedTextColor }]}>
131
- {t('karma.center.info') || 'Karma can only be earned by positive actions in the Oxy Ecosystem. It cannot be sent or received directly.'}
148
+ {t('trust.center.info') || 'Reputation can only be earned by positive actions in the Oxy Ecosystem. It cannot be sent or received directly.'}
132
149
  </Text>
133
150
  </View>
134
151
  <Text style={[styles.sectionTitle, { color: bloomTheme.colors.text }]}>
135
- {t('karma.center.history') || 'Karma History'}
152
+ {t('trust.center.history') || 'Reputation History'}
136
153
  </Text>
137
154
  <View style={styles.historyContainer}>
138
- {karmaHistory.length === 0 ? (
155
+ {transactions.length === 0 ? (
139
156
  <Text style={{ color: bloomTheme.colors.text, textAlign: 'center', marginTop: 16 }}>
140
- {t('karma.center.noHistory') || 'No karma history yet.'}
157
+ {t('trust.center.noHistory') || 'No reputation history yet.'}
141
158
  </Text>
142
159
  ) : (
143
- karmaHistory.map((entry: any) => (
160
+ transactions.map((entry) => (
144
161
  <View key={entry.id} style={[styles.historyItem, { borderColor: bloomTheme.colors.border }]}>
145
162
  <Text style={[styles.historyPoints, { color: entry.points > 0 ? primaryColor : dangerColor }]}>
146
163
  {entry.points > 0 ? '+' : ''}{entry.points}
147
164
  </Text>
148
165
  <Text style={[styles.historyDesc, { color: bloomTheme.colors.text }]}>
149
- {entry.reason || (t('karma.center.noDescription') || 'No description')}
150
- </Text>
151
- <Text style={[styles.historyDate, { color: bloomTheme.colors.textTertiary }]}>
152
- {entry.createdAt ? new Date(entry.createdAt).toLocaleString() : ''}
166
+ {entry.reason || entry.actionType || (t('trust.center.noDescription') || 'No description')}
153
167
  </Text>
168
+ <View style={styles.historyMetaRow}>
169
+ <Text style={[styles.historyCategory, { color: primaryColor }]}>
170
+ {entry.category}
171
+ </Text>
172
+ <Text style={[styles.historyDate, { color: bloomTheme.colors.textTertiary }]}>
173
+ {entry.createdAt ? new Date(entry.createdAt).toLocaleString() : ''}
174
+ </Text>
175
+ </View>
154
176
  </View>
155
177
  ))
156
178
  )}
@@ -179,15 +201,29 @@ const styles = StyleSheet.create({
179
201
  width: '100%',
180
202
  backgroundColor: 'transparent',
181
203
  },
182
- karmaLabel: {
204
+ reputationLabel: {
183
205
  fontSize: 16,
184
- marginBottom: 18,
206
+ marginBottom: 12,
185
207
  },
186
- karmaAmount: {
208
+ reputationAmount: {
187
209
  fontSize: 48,
188
210
  fontWeight: 'bold',
189
211
  marginBottom: 4,
190
212
  },
213
+ tierBadge: {
214
+ flexDirection: 'row',
215
+ alignItems: 'center',
216
+ gap: 6,
217
+ borderWidth: 1,
218
+ borderRadius: 999,
219
+ paddingHorizontal: 12,
220
+ paddingVertical: 5,
221
+ marginBottom: 18,
222
+ },
223
+ tierBadgeText: {
224
+ fontSize: 13,
225
+ fontWeight: '600',
226
+ },
191
227
  actionContainer: {
192
228
  marginBottom: 18,
193
229
  gap: 8,
@@ -248,9 +284,19 @@ const styles = StyleSheet.create({
248
284
  fontSize: 15,
249
285
  marginTop: 2,
250
286
  },
287
+ historyMetaRow: {
288
+ flexDirection: 'row',
289
+ alignItems: 'center',
290
+ justifyContent: 'space-between',
291
+ marginTop: 2,
292
+ },
293
+ historyCategory: {
294
+ fontSize: 12,
295
+ fontWeight: '600',
296
+ textTransform: 'capitalize',
297
+ },
251
298
  historyDate: {
252
299
  fontSize: 13,
253
- marginTop: 2,
254
300
  },
255
301
 
256
302
  message: {
@@ -260,4 +306,4 @@ const styles = StyleSheet.create({
260
306
  },
261
307
  });
262
308
 
263
- export default KarmaCenterScreen;
309
+ export default TrustCenterScreen;
@@ -13,15 +13,15 @@ import { Colors } from '../../constants/theme';
13
13
  const FAQ_KEYS = ['what', 'earn', 'lose', 'use', 'transfer', 'support'] as const;
14
14
 
15
15
  /**
16
- * KarmaFAQScreen - Optimized for performance
17
- *
16
+ * TrustFAQScreen - Optimized for performance
17
+ *
18
18
  * Performance optimizations implemented:
19
19
  * - useMemo for theme calculations (only recalculates when theme changes)
20
20
  * - useMemo for filtered FAQs (only recalculates when search changes)
21
21
  * - useCallback for event handlers to prevent unnecessary re-renders
22
22
  * - React.memo wrapper to prevent re-renders when props haven't changed
23
23
  */
24
- const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
24
+ const TrustFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
25
25
  const { t } = useI18n();
26
26
  const [expanded, setExpanded] = useState<string | null>(null);
27
27
  const [search, setSearch] = useState('');
@@ -35,8 +35,8 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
35
35
  // Memoize filtered FAQs to prevent filtering on every render
36
36
  const faqs = useMemo(() => FAQ_KEYS.map(key => ({
37
37
  id: key,
38
- q: t(`karma.faq.items.${key}.q`) || '',
39
- a: t(`karma.faq.items.${key}.a`) || '',
38
+ q: t(`trust.faq.items.${key}.q`) || '',
39
+ a: t(`trust.faq.items.${key}.a`) || '',
40
40
  })), [t]);
41
41
 
42
42
  const filteredFaqs = useMemo(() => {
@@ -57,8 +57,8 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
57
57
  return (
58
58
  <View style={[styles.container, { backgroundColor: bloomTheme.colors.background }]}>
59
59
  <Header
60
- title={t('karma.faq.title') || 'Karma FAQ'}
61
- subtitle={t('karma.faq.subtitle') || 'Frequently asked questions about karma'}
60
+ title={t('trust.faq.title') || 'Trust FAQ'}
61
+ subtitle={t('trust.faq.subtitle') || 'Frequently asked questions about Oxy Trust'}
62
62
  subtitleVariant="muted"
63
63
 
64
64
  onBack={goBack}
@@ -72,7 +72,7 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
72
72
  <Ionicons name="search" size={22} color={colors.icon} />
73
73
  <TextInput
74
74
  style={[styles.searchInput, { color: bloomTheme.colors.text }]}
75
- placeholder={t('karma.faq.search') || 'Search FAQ...'}
75
+ placeholder={t('trust.faq.search') || 'Search FAQ...'}
76
76
  placeholderTextColor={bloomTheme.colors.textTertiary}
77
77
  value={search}
78
78
  onChangeText={setSearch}
@@ -81,7 +81,7 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
81
81
  </View>
82
82
  {filteredFaqs.length === 0 ? (
83
83
  <Text style={[styles.noResults, { color: colors.secondaryText }]}>
84
- {t('karma.faq.noResults', { query: search }) || `No FAQ items found matching "${search}"`}
84
+ {t('trust.faq.noResults', { query: search }) || `No FAQ items found matching "${search}"`}
85
85
  </Text>
86
86
  ) : (
87
87
  <View style={styles.groupedSectionContainer}>
@@ -167,4 +167,4 @@ const styles = StyleSheet.create({
167
167
  },
168
168
  });
169
169
 
170
- export default React.memo(KarmaFAQScreen);
170
+ export default React.memo(TrustFAQScreen);
@@ -0,0 +1,101 @@
1
+ import type React from 'react';
2
+ import { useEffect, useState } from 'react';
3
+ import { View, Text, StyleSheet, ScrollView, ActivityIndicator, TouchableOpacity } from 'react-native';
4
+ import type { ReputationLeaderboardEntry } from '@oxyhq/core';
5
+ import type { BaseScreenProps } from '../../types/navigation';
6
+ import Avatar from '../../components/Avatar';
7
+ import Header from '../../components/Header';
8
+ import { useI18n } from '../../hooks/useI18n';
9
+ import { useTheme } from '@oxyhq/bloom/theme';
10
+ import { useOxy } from '../../context/OxyContext';
11
+ import { getTrustTierLabel } from './trustTier';
12
+
13
+ const TrustLeaderboardScreen: React.FC<BaseScreenProps> = ({ goBack, theme, navigate }) => {
14
+ // Use useOxy() hook for OxyContext values
15
+ const { oxyServices } = useOxy();
16
+ const { t } = useI18n();
17
+ const [leaderboard, setLeaderboard] = useState<ReputationLeaderboardEntry[]>([]);
18
+ const [isLoading, setIsLoading] = useState(true);
19
+ const [error, setError] = useState<string | null>(null);
20
+
21
+ const bloomTheme = useTheme();
22
+ // Override primaryColor for Oxy Trust screens (purple instead of blue)
23
+ const primaryColor = '#d169e5';
24
+
25
+ useEffect(() => {
26
+ setIsLoading(true);
27
+ setError(null);
28
+ oxyServices.getReputationLeaderboard()
29
+ .then((data) => setLeaderboard(Array.isArray(data) ? data : []))
30
+ .catch((err: unknown) => setError((err instanceof Error ? err.message : null) || 'Failed to load leaderboard'))
31
+ .finally(() => setIsLoading(false));
32
+ }, [oxyServices]);
33
+
34
+ return (
35
+ <View style={[styles.container, { backgroundColor: bloomTheme.colors.background }]}>
36
+ <Header
37
+ title={t('trust.leaderboard.title') || 'Trust Leaderboard'}
38
+ subtitle={t('trust.leaderboard.subtitle') || 'Top contributors in the community'}
39
+
40
+ onBack={goBack}
41
+ elevation="subtle"
42
+ />
43
+ {isLoading ? (
44
+ <ActivityIndicator size="large" color={primaryColor} style={{ marginTop: 40 }} />
45
+ ) : error ? (
46
+ <Text style={[styles.error, { color: bloomTheme.colors.error }]}>{error}</Text>
47
+ ) : (
48
+ <ScrollView contentContainerStyle={styles.listContainer}>
49
+ {leaderboard.length === 0 ? (
50
+ <Text style={[styles.placeholder, { color: bloomTheme.colors.text }]}>{t('trust.leaderboard.empty') || 'No leaderboard data.'}</Text>
51
+ ) : (
52
+ leaderboard.map((entry) => {
53
+ const username = entry.user.username;
54
+ const displayName = username || entry.user.id;
55
+ return (
56
+ <TouchableOpacity
57
+ key={entry.user.id}
58
+ style={[styles.row, { borderColor: bloomTheme.colors.border }, entry.rank <= 3 && { backgroundColor: bloomTheme.colors.primarySubtle }]}
59
+ onPress={() => navigate?.('Profile', { userId: entry.user.id, username })}
60
+ activeOpacity={0.7}
61
+ >
62
+ <Text style={[styles.rank, { color: primaryColor }]}>{entry.rank}</Text>
63
+ <Avatar name={username || 'User'} size={40} style={styles.avatar} />
64
+ <View style={styles.userColumn}>
65
+ <Text style={[styles.username, { color: bloomTheme.colors.text }]} numberOfLines={1}>{displayName}</Text>
66
+ <Text style={[styles.tier, { color: bloomTheme.colors.textTertiary }]} numberOfLines={1}>
67
+ {getTrustTierLabel(entry.trustTier, t)}
68
+ </Text>
69
+ </View>
70
+ <Text style={[styles.reputation, { color: primaryColor }]}>{entry.total}</Text>
71
+ </TouchableOpacity>
72
+ );
73
+ })
74
+ )}
75
+ </ScrollView>
76
+ )}
77
+ </View>
78
+ );
79
+ };
80
+
81
+ const styles = StyleSheet.create({
82
+ container: { flex: 1 },
83
+ listContainer: { paddingBottom: 40, paddingTop: 20 },
84
+ row: {
85
+ flexDirection: 'row',
86
+ alignItems: 'center',
87
+ paddingVertical: 12,
88
+ paddingHorizontal: 20,
89
+ borderBottomWidth: 1,
90
+ },
91
+ rank: { fontSize: 20, width: 32, textAlign: 'center', fontWeight: 'bold' },
92
+ avatar: { marginHorizontal: 8 },
93
+ userColumn: { flex: 1, marginLeft: 8 },
94
+ username: { fontSize: 16 },
95
+ tier: { fontSize: 12, marginTop: 1 },
96
+ reputation: { fontSize: 18, fontWeight: 'bold', marginLeft: 12 },
97
+ placeholder: { fontSize: 16, textAlign: 'center', marginTop: 40 },
98
+ error: { fontSize: 16, textAlign: 'center', marginTop: 40 },
99
+ });
100
+
101
+ export default TrustLeaderboardScreen;