@oxyhq/services 6.10.7 → 7.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.
Files changed (454) hide show
  1. package/lib/commonjs/index.js +211 -49
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/client.js +25 -4
  4. package/lib/commonjs/ui/client.js.map +1 -1
  5. package/lib/commonjs/ui/components/AccountMenu.js +485 -0
  6. package/lib/commonjs/ui/components/AccountMenu.js.map +1 -0
  7. package/lib/commonjs/ui/components/AccountMenuButton.js +120 -0
  8. package/lib/commonjs/ui/components/AccountMenuButton.js.map +1 -0
  9. package/lib/commonjs/ui/components/ActingAsBanner.js +2 -2
  10. package/lib/commonjs/ui/components/ActingAsBanner.js.map +1 -1
  11. package/lib/commonjs/ui/components/ProfileCard.js +2 -2
  12. package/lib/commonjs/ui/components/ProfileCard.js.map +1 -1
  13. package/lib/commonjs/ui/components/StepBasedScreen.js +2 -2
  14. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  15. package/lib/commonjs/ui/components/accountMenuRows.js +45 -0
  16. package/lib/commonjs/ui/components/accountMenuRows.js.map +1 -0
  17. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js +5 -5
  18. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js.map +1 -1
  19. package/lib/commonjs/ui/components/payment/PaymentMethodStep.js +3 -2
  20. package/lib/commonjs/ui/components/payment/PaymentMethodStep.js.map +1 -1
  21. package/lib/commonjs/ui/components/theming.js +2 -2
  22. package/lib/commonjs/ui/components/theming.js.map +1 -1
  23. package/lib/commonjs/ui/context/OxyContext.js +211 -21
  24. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  25. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +36 -2
  26. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  27. package/lib/commonjs/ui/hooks/mutations/mutationKeys.js +6 -0
  28. package/lib/commonjs/ui/hooks/mutations/mutationKeys.js.map +1 -1
  29. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +138 -1
  30. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  31. package/lib/commonjs/ui/hooks/queries/queryKeys.js +67 -2
  32. package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
  33. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +27 -2
  34. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  35. package/lib/commonjs/ui/hooks/useAuth.js +13 -2
  36. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  37. package/lib/commonjs/ui/hooks/useSessionManagement.js +30 -0
  38. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  39. package/lib/commonjs/ui/index.js +132 -85
  40. package/lib/commonjs/ui/index.js.map +1 -1
  41. package/lib/commonjs/ui/navigation/routes.js +6 -7
  42. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  43. package/lib/commonjs/ui/screens/AccountVerificationScreen.js +3 -2
  44. package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
  45. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js +202 -0
  46. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js.map +1 -0
  47. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js +3 -2
  48. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +3 -2
  50. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/FAQScreen.js +7 -4
  52. package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/FeedbackScreen.js +21 -16
  54. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/HelpSupportScreen.js +3 -2
  56. package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/HistoryViewScreen.js +7 -4
  58. package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
  59. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +3 -2
  60. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  61. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +6 -4
  62. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
  63. package/lib/commonjs/ui/screens/ManageAccountScreen.js +780 -0
  64. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -0
  65. package/lib/commonjs/ui/screens/NotificationsScreen.js +175 -0
  66. package/lib/commonjs/ui/screens/NotificationsScreen.js.map +1 -0
  67. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +18 -12
  68. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  69. package/lib/commonjs/ui/screens/PreferencesScreen.js +220 -0
  70. package/lib/commonjs/ui/screens/PreferencesScreen.js.map +1 -0
  71. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +14 -10
  72. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  73. package/lib/commonjs/ui/screens/ProfileScreen.js +3 -3
  74. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  75. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +8 -5
  76. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
  77. package/lib/commonjs/ui/screens/SearchSettingsScreen.js +6 -4
  78. package/lib/commonjs/ui/screens/SearchSettingsScreen.js.map +1 -1
  79. package/lib/commonjs/ui/screens/UserLinksScreen.js +3 -2
  80. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -1
  81. package/lib/commonjs/ui/screens/UserListScreen.js +2 -2
  82. package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
  83. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +3 -2
  84. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  85. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +3 -2
  86. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  87. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +2 -2
  88. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  89. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +4 -3
  90. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  91. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +3 -2
  92. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  93. package/lib/commonjs/ui/utils/activeAuthuser.js +85 -0
  94. package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -0
  95. package/lib/module/index.js +58 -16
  96. package/lib/module/index.js.map +1 -1
  97. package/lib/module/ui/client.js +5 -3
  98. package/lib/module/ui/client.js.map +1 -1
  99. package/lib/module/ui/components/AccountMenu.js +480 -0
  100. package/lib/module/ui/components/AccountMenu.js.map +1 -0
  101. package/lib/module/ui/components/AccountMenuButton.js +115 -0
  102. package/lib/module/ui/components/AccountMenuButton.js.map +1 -0
  103. package/lib/module/ui/components/ActingAsBanner.js +2 -2
  104. package/lib/module/ui/components/ActingAsBanner.js.map +1 -1
  105. package/lib/module/ui/components/ProfileCard.js +1 -1
  106. package/lib/module/ui/components/ProfileCard.js.map +1 -1
  107. package/lib/module/ui/components/StepBasedScreen.js +1 -1
  108. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  109. package/lib/module/ui/components/accountMenuRows.js +41 -0
  110. package/lib/module/ui/components/accountMenuRows.js.map +1 -0
  111. package/lib/module/ui/components/payment/PaymentDetailsStep.js +1 -1
  112. package/lib/module/ui/components/payment/PaymentDetailsStep.js.map +1 -1
  113. package/lib/module/ui/components/payment/PaymentMethodStep.js +1 -1
  114. package/lib/module/ui/components/payment/PaymentMethodStep.js.map +1 -1
  115. package/lib/module/ui/components/theming.js +1 -1
  116. package/lib/module/ui/components/theming.js.map +1 -1
  117. package/lib/module/ui/context/OxyContext.js +211 -21
  118. package/lib/module/ui/context/OxyContext.js.map +1 -1
  119. package/lib/module/ui/context/hooks/useAuthOperations.js +36 -2
  120. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  121. package/lib/module/ui/hooks/mutations/mutationKeys.js +6 -0
  122. package/lib/module/ui/hooks/mutations/mutationKeys.js.map +1 -1
  123. package/lib/module/ui/hooks/mutations/useAccountMutations.js +135 -1
  124. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  125. package/lib/module/ui/hooks/queries/queryKeys.js +60 -1
  126. package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
  127. package/lib/module/ui/hooks/queries/useAccountQueries.js +24 -0
  128. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  129. package/lib/module/ui/hooks/useAuth.js +13 -2
  130. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  131. package/lib/module/ui/hooks/useSessionManagement.js +30 -0
  132. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  133. package/lib/module/ui/index.js +34 -78
  134. package/lib/module/ui/index.js.map +1 -1
  135. package/lib/module/ui/navigation/routes.js +6 -7
  136. package/lib/module/ui/navigation/routes.js.map +1 -1
  137. package/lib/module/ui/screens/AccountVerificationScreen.js +1 -1
  138. package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
  139. package/lib/module/ui/screens/ConnectedAppsScreen.js +198 -0
  140. package/lib/module/ui/screens/ConnectedAppsScreen.js.map +1 -0
  141. package/lib/module/ui/screens/CreateManagedAccountScreen.js +1 -1
  142. package/lib/module/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  143. package/lib/module/ui/screens/EditProfileFieldScreen.js +1 -1
  144. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  145. package/lib/module/ui/screens/FAQScreen.js +3 -1
  146. package/lib/module/ui/screens/FAQScreen.js.map +1 -1
  147. package/lib/module/ui/screens/FeedbackScreen.js +6 -2
  148. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  149. package/lib/module/ui/screens/HelpSupportScreen.js +1 -1
  150. package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
  151. package/lib/module/ui/screens/HistoryViewScreen.js +3 -1
  152. package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
  153. package/lib/module/ui/screens/LanguageSelectorScreen.js +1 -1
  154. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  155. package/lib/module/ui/screens/LegalDocumentsScreen.js +2 -1
  156. package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
  157. package/lib/module/ui/screens/ManageAccountScreen.js +775 -0
  158. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -0
  159. package/lib/module/ui/screens/NotificationsScreen.js +169 -0
  160. package/lib/module/ui/screens/NotificationsScreen.js.map +1 -0
  161. package/lib/module/ui/screens/PaymentGatewayScreen.js +9 -3
  162. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  163. package/lib/module/ui/screens/PreferencesScreen.js +214 -0
  164. package/lib/module/ui/screens/PreferencesScreen.js.map +1 -0
  165. package/lib/module/ui/screens/PrivacySettingsScreen.js +4 -1
  166. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  167. package/lib/module/ui/screens/ProfileScreen.js +2 -2
  168. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  169. package/lib/module/ui/screens/SavesCollectionsScreen.js +3 -1
  170. package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
  171. package/lib/module/ui/screens/SearchSettingsScreen.js +2 -1
  172. package/lib/module/ui/screens/SearchSettingsScreen.js.map +1 -1
  173. package/lib/module/ui/screens/UserLinksScreen.js +1 -1
  174. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -1
  175. package/lib/module/ui/screens/UserListScreen.js +1 -1
  176. package/lib/module/ui/screens/UserListScreen.js.map +1 -1
  177. package/lib/module/ui/screens/karma/KarmaAboutScreen.js +1 -1
  178. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  179. package/lib/module/ui/screens/karma/KarmaFAQScreen.js +1 -1
  180. package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  181. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +1 -1
  182. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  183. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +1 -1
  184. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  185. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +1 -1
  186. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  187. package/lib/module/ui/utils/activeAuthuser.js +79 -0
  188. package/lib/module/ui/utils/activeAuthuser.js.map +1 -0
  189. package/lib/typescript/commonjs/index.d.ts +23 -6
  190. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  191. package/lib/typescript/commonjs/ui/client.d.ts +7 -2
  192. package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
  193. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +23 -0
  194. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -0
  195. package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts +19 -0
  196. package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts.map +1 -0
  197. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts +27 -0
  198. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts.map +1 -0
  199. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  200. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  201. package/lib/typescript/commonjs/ui/hooks/mutations/mutationKeys.d.ts +5 -0
  202. package/lib/typescript/commonjs/ui/hooks/mutations/mutationKeys.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +26 -1
  204. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +32 -3
  206. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts +10 -1
  208. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/ui/hooks/queries/useSecurityQueries.d.ts +1 -1
  210. package/lib/typescript/commonjs/ui/hooks/queries/useSecurityQueries.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts +8 -2
  212. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  213. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  214. package/lib/typescript/commonjs/ui/index.d.ts +32 -18
  215. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  216. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
  217. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  218. package/lib/typescript/{module/ui/screens/AccountOverviewScreen.d.ts → commonjs/ui/screens/ConnectedAppsScreen.d.ts} +1 -1
  219. package/lib/typescript/commonjs/ui/screens/ConnectedAppsScreen.d.ts.map +1 -0
  220. package/lib/typescript/commonjs/ui/screens/FAQScreen.d.ts.map +1 -1
  221. package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
  222. package/lib/typescript/commonjs/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  224. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts +13 -0
  225. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -0
  226. package/lib/typescript/commonjs/ui/screens/{AccountOverviewScreen.d.ts → NotificationsScreen.d.ts} +1 -1
  227. package/lib/typescript/commonjs/ui/screens/NotificationsScreen.d.ts.map +1 -0
  228. package/lib/typescript/commonjs/ui/screens/PaymentGatewayScreen.d.ts +1 -1
  229. package/lib/typescript/commonjs/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  230. package/lib/typescript/commonjs/ui/screens/{AccountSettingsScreen.d.ts → PreferencesScreen.d.ts} +2 -5
  231. package/lib/typescript/commonjs/ui/screens/PreferencesScreen.d.ts.map +1 -0
  232. package/lib/typescript/commonjs/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts +42 -0
  236. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -0
  237. package/lib/typescript/module/index.d.ts +23 -6
  238. package/lib/typescript/module/index.d.ts.map +1 -1
  239. package/lib/typescript/module/ui/client.d.ts +7 -2
  240. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  241. package/lib/typescript/module/ui/components/AccountMenu.d.ts +23 -0
  242. package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -0
  243. package/lib/typescript/module/ui/components/AccountMenuButton.d.ts +19 -0
  244. package/lib/typescript/module/ui/components/AccountMenuButton.d.ts.map +1 -0
  245. package/lib/typescript/module/ui/components/accountMenuRows.d.ts +27 -0
  246. package/lib/typescript/module/ui/components/accountMenuRows.d.ts.map +1 -0
  247. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  248. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  249. package/lib/typescript/module/ui/hooks/mutations/mutationKeys.d.ts +5 -0
  250. package/lib/typescript/module/ui/hooks/mutations/mutationKeys.d.ts.map +1 -1
  251. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +26 -1
  252. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  253. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +32 -3
  254. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  255. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts +10 -1
  256. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  257. package/lib/typescript/module/ui/hooks/queries/useSecurityQueries.d.ts +1 -1
  258. package/lib/typescript/module/ui/hooks/queries/useSecurityQueries.d.ts.map +1 -1
  259. package/lib/typescript/module/ui/hooks/useAuth.d.ts +8 -2
  260. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  261. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  262. package/lib/typescript/module/ui/index.d.ts +32 -18
  263. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  264. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  265. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  266. package/lib/typescript/module/ui/screens/{AccountSettingsScreen.d.ts → ConnectedAppsScreen.d.ts} +2 -5
  267. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -0
  268. package/lib/typescript/module/ui/screens/FAQScreen.d.ts.map +1 -1
  269. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  270. package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  271. package/lib/typescript/module/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  272. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts +13 -0
  273. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -0
  274. package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts +5 -0
  275. package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts.map +1 -0
  276. package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts +1 -1
  277. package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  278. package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts +5 -0
  279. package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts.map +1 -0
  280. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  281. package/lib/typescript/module/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  282. package/lib/typescript/module/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  283. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts +42 -0
  284. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -0
  285. package/package.json +20 -9
  286. package/src/index.ts +141 -47
  287. package/src/ui/client.ts +7 -2
  288. package/src/ui/components/AccountMenu.tsx +534 -0
  289. package/src/ui/components/AccountMenuButton.tsx +113 -0
  290. package/src/ui/components/ActingAsBanner.tsx +2 -2
  291. package/src/ui/components/ProfileCard.tsx +1 -1
  292. package/src/ui/components/StepBasedScreen.tsx +1 -1
  293. package/src/ui/components/accountMenuRows.ts +60 -0
  294. package/src/ui/components/payment/PaymentDetailsStep.tsx +1 -1
  295. package/src/ui/components/payment/PaymentMethodStep.tsx +1 -1
  296. package/src/ui/components/theming.tsx +1 -1
  297. package/src/ui/context/OxyContext.tsx +204 -18
  298. package/src/ui/context/hooks/useAuthOperations.ts +36 -2
  299. package/src/ui/hooks/mutations/mutationKeys.ts +11 -0
  300. package/src/ui/hooks/mutations/useAccountMutations.ts +154 -2
  301. package/src/ui/hooks/queries/queryKeys.ts +54 -4
  302. package/src/ui/hooks/queries/useAccountQueries.ts +25 -1
  303. package/src/ui/hooks/useAuth.ts +23 -4
  304. package/src/ui/hooks/useSessionManagement.ts +29 -0
  305. package/src/ui/index.ts +37 -98
  306. package/src/ui/navigation/routes.ts +9 -11
  307. package/src/ui/screens/AccountVerificationScreen.tsx +1 -1
  308. package/src/ui/screens/ConnectedAppsScreen.tsx +225 -0
  309. package/src/ui/screens/CreateManagedAccountScreen.tsx +1 -1
  310. package/src/ui/screens/EditProfileFieldScreen.tsx +1 -1
  311. package/src/ui/screens/FAQScreen.tsx +3 -1
  312. package/src/ui/screens/FeedbackScreen.tsx +6 -10
  313. package/src/ui/screens/HelpSupportScreen.tsx +1 -1
  314. package/src/ui/screens/HistoryViewScreen.tsx +3 -1
  315. package/src/ui/screens/LanguageSelectorScreen.tsx +1 -1
  316. package/src/ui/screens/LegalDocumentsScreen.tsx +2 -1
  317. package/src/ui/screens/ManageAccountScreen.tsx +1102 -0
  318. package/src/ui/screens/NotificationsScreen.tsx +189 -0
  319. package/src/ui/screens/PaymentGatewayScreen.tsx +10 -12
  320. package/src/ui/screens/PreferencesScreen.tsx +263 -0
  321. package/src/ui/screens/PrivacySettingsScreen.tsx +4 -1
  322. package/src/ui/screens/ProfileScreen.tsx +2 -2
  323. package/src/ui/screens/SavesCollectionsScreen.tsx +3 -1
  324. package/src/ui/screens/SearchSettingsScreen.tsx +2 -1
  325. package/src/ui/screens/UserLinksScreen.tsx +1 -1
  326. package/src/ui/screens/UserListScreen.tsx +1 -1
  327. package/src/ui/screens/karma/KarmaAboutScreen.tsx +1 -1
  328. package/src/ui/screens/karma/KarmaFAQScreen.tsx +1 -1
  329. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +1 -1
  330. package/src/ui/screens/karma/KarmaRewardsScreen.tsx +1 -1
  331. package/src/ui/screens/karma/KarmaRulesScreen.tsx +1 -1
  332. package/src/ui/utils/activeAuthuser.ts +78 -0
  333. package/lib/commonjs/ui/components/feedback/index.js +0 -54
  334. package/lib/commonjs/ui/components/feedback/index.js.map +0 -1
  335. package/lib/commonjs/ui/components/icon/index.js +0 -21
  336. package/lib/commonjs/ui/components/icon/index.js.map +0 -1
  337. package/lib/commonjs/ui/components/index.js +0 -104
  338. package/lib/commonjs/ui/components/index.js.map +0 -1
  339. package/lib/commonjs/ui/components/modals/index.js +0 -14
  340. package/lib/commonjs/ui/components/modals/index.js.map +0 -1
  341. package/lib/commonjs/ui/components/payment/index.js +0 -80
  342. package/lib/commonjs/ui/components/payment/index.js.map +0 -1
  343. package/lib/commonjs/ui/hooks/index.js +0 -92
  344. package/lib/commonjs/ui/hooks/index.js.map +0 -1
  345. package/lib/commonjs/ui/hooks/mutations/index.js +0 -68
  346. package/lib/commonjs/ui/hooks/mutations/index.js.map +0 -1
  347. package/lib/commonjs/ui/hooks/queries/index.js +0 -155
  348. package/lib/commonjs/ui/hooks/queries/index.js.map +0 -1
  349. package/lib/commonjs/ui/screens/AccountCenterScreen.js +0 -344
  350. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +0 -1
  351. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +0 -724
  352. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +0 -1
  353. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +0 -643
  354. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +0 -1
  355. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +0 -1029
  356. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +0 -1
  357. package/lib/commonjs/ui/screens/SessionManagementScreen.js +0 -512
  358. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +0 -1
  359. package/lib/commonjs/ui/styles/index.js +0 -39
  360. package/lib/commonjs/ui/styles/index.js.map +0 -1
  361. package/lib/module/ui/components/feedback/index.js +0 -8
  362. package/lib/module/ui/components/feedback/index.js.map +0 -1
  363. package/lib/module/ui/components/icon/index.js +0 -5
  364. package/lib/module/ui/components/icon/index.js.map +0 -1
  365. package/lib/module/ui/components/index.js +0 -18
  366. package/lib/module/ui/components/index.js.map +0 -1
  367. package/lib/module/ui/components/modals/index.js +0 -4
  368. package/lib/module/ui/components/modals/index.js.map +0 -1
  369. package/lib/module/ui/components/payment/index.js +0 -10
  370. package/lib/module/ui/components/payment/index.js.map +0 -1
  371. package/lib/module/ui/hooks/index.js +0 -11
  372. package/lib/module/ui/hooks/index.js.map +0 -1
  373. package/lib/module/ui/hooks/mutations/index.js +0 -15
  374. package/lib/module/ui/hooks/mutations/index.js.map +0 -1
  375. package/lib/module/ui/hooks/queries/index.js +0 -26
  376. package/lib/module/ui/hooks/queries/index.js.map +0 -1
  377. package/lib/module/ui/screens/AccountCenterScreen.js +0 -339
  378. package/lib/module/ui/screens/AccountCenterScreen.js.map +0 -1
  379. package/lib/module/ui/screens/AccountOverviewScreen.js +0 -719
  380. package/lib/module/ui/screens/AccountOverviewScreen.js.map +0 -1
  381. package/lib/module/ui/screens/AccountSettingsScreen.js +0 -638
  382. package/lib/module/ui/screens/AccountSettingsScreen.js.map +0 -1
  383. package/lib/module/ui/screens/AccountSwitcherScreen.js +0 -1024
  384. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +0 -1
  385. package/lib/module/ui/screens/SessionManagementScreen.js +0 -508
  386. package/lib/module/ui/screens/SessionManagementScreen.js.map +0 -1
  387. package/lib/module/ui/styles/index.js +0 -6
  388. package/lib/module/ui/styles/index.js.map +0 -1
  389. package/lib/typescript/commonjs/ui/components/feedback/index.d.ts +0 -7
  390. package/lib/typescript/commonjs/ui/components/feedback/index.d.ts.map +0 -1
  391. package/lib/typescript/commonjs/ui/components/icon/index.d.ts +0 -4
  392. package/lib/typescript/commonjs/ui/components/icon/index.d.ts.map +0 -1
  393. package/lib/typescript/commonjs/ui/components/index.d.ts +0 -13
  394. package/lib/typescript/commonjs/ui/components/index.d.ts.map +0 -1
  395. package/lib/typescript/commonjs/ui/components/modals/index.d.ts +0 -2
  396. package/lib/typescript/commonjs/ui/components/modals/index.d.ts.map +0 -1
  397. package/lib/typescript/commonjs/ui/components/payment/index.d.ts +0 -9
  398. package/lib/typescript/commonjs/ui/components/payment/index.d.ts.map +0 -1
  399. package/lib/typescript/commonjs/ui/hooks/index.d.ts +0 -9
  400. package/lib/typescript/commonjs/ui/hooks/index.d.ts.map +0 -1
  401. package/lib/typescript/commonjs/ui/hooks/mutations/index.d.ts +0 -9
  402. package/lib/typescript/commonjs/ui/hooks/mutations/index.d.ts.map +0 -1
  403. package/lib/typescript/commonjs/ui/hooks/queries/index.d.ts +0 -13
  404. package/lib/typescript/commonjs/ui/hooks/queries/index.d.ts.map +0 -1
  405. package/lib/typescript/commonjs/ui/screens/AccountCenterScreen.d.ts +0 -5
  406. package/lib/typescript/commonjs/ui/screens/AccountCenterScreen.d.ts.map +0 -1
  407. package/lib/typescript/commonjs/ui/screens/AccountOverviewScreen.d.ts.map +0 -1
  408. package/lib/typescript/commonjs/ui/screens/AccountSettingsScreen.d.ts.map +0 -1
  409. package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts +0 -5
  410. package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts.map +0 -1
  411. package/lib/typescript/commonjs/ui/screens/SessionManagementScreen.d.ts +0 -5
  412. package/lib/typescript/commonjs/ui/screens/SessionManagementScreen.d.ts.map +0 -1
  413. package/lib/typescript/commonjs/ui/styles/index.d.ts +0 -4
  414. package/lib/typescript/commonjs/ui/styles/index.d.ts.map +0 -1
  415. package/lib/typescript/module/ui/components/feedback/index.d.ts +0 -7
  416. package/lib/typescript/module/ui/components/feedback/index.d.ts.map +0 -1
  417. package/lib/typescript/module/ui/components/icon/index.d.ts +0 -4
  418. package/lib/typescript/module/ui/components/icon/index.d.ts.map +0 -1
  419. package/lib/typescript/module/ui/components/index.d.ts +0 -13
  420. package/lib/typescript/module/ui/components/index.d.ts.map +0 -1
  421. package/lib/typescript/module/ui/components/modals/index.d.ts +0 -2
  422. package/lib/typescript/module/ui/components/modals/index.d.ts.map +0 -1
  423. package/lib/typescript/module/ui/components/payment/index.d.ts +0 -9
  424. package/lib/typescript/module/ui/components/payment/index.d.ts.map +0 -1
  425. package/lib/typescript/module/ui/hooks/index.d.ts +0 -9
  426. package/lib/typescript/module/ui/hooks/index.d.ts.map +0 -1
  427. package/lib/typescript/module/ui/hooks/mutations/index.d.ts +0 -9
  428. package/lib/typescript/module/ui/hooks/mutations/index.d.ts.map +0 -1
  429. package/lib/typescript/module/ui/hooks/queries/index.d.ts +0 -13
  430. package/lib/typescript/module/ui/hooks/queries/index.d.ts.map +0 -1
  431. package/lib/typescript/module/ui/screens/AccountCenterScreen.d.ts +0 -5
  432. package/lib/typescript/module/ui/screens/AccountCenterScreen.d.ts.map +0 -1
  433. package/lib/typescript/module/ui/screens/AccountOverviewScreen.d.ts.map +0 -1
  434. package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts.map +0 -1
  435. package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts +0 -5
  436. package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts.map +0 -1
  437. package/lib/typescript/module/ui/screens/SessionManagementScreen.d.ts +0 -5
  438. package/lib/typescript/module/ui/screens/SessionManagementScreen.d.ts.map +0 -1
  439. package/lib/typescript/module/ui/styles/index.d.ts +0 -4
  440. package/lib/typescript/module/ui/styles/index.d.ts.map +0 -1
  441. package/src/ui/components/feedback/index.ts +0 -6
  442. package/src/ui/components/icon/index.ts +0 -3
  443. package/src/ui/components/index.ts +0 -15
  444. package/src/ui/components/modals/index.ts +0 -1
  445. package/src/ui/components/payment/index.ts +0 -9
  446. package/src/ui/hooks/index.ts +0 -13
  447. package/src/ui/hooks/mutations/index.ts +0 -25
  448. package/src/ui/hooks/queries/index.ts +0 -61
  449. package/src/ui/screens/AccountCenterScreen.tsx +0 -182
  450. package/src/ui/screens/AccountOverviewScreen.tsx +0 -696
  451. package/src/ui/screens/AccountSettingsScreen.tsx +0 -620
  452. package/src/ui/screens/AccountSwitcherScreen.tsx +0 -1003
  453. package/src/ui/screens/SessionManagementScreen.tsx +0 -477
  454. package/src/ui/styles/index.ts +0 -3
@@ -0,0 +1,60 @@
1
+ import type { User, ClientSession } from '@oxyhq/core';
2
+ import { getAccountDisplayName, getAccountFallbackHandle } from '@oxyhq/core';
3
+
4
+ export interface AccountRow {
5
+ sessionId: string;
6
+ isActive: boolean;
7
+ displayName: string;
8
+ secondary: string | null;
9
+ avatarUri?: string;
10
+ user: User | null;
11
+ }
12
+
13
+ export interface BuildAccountRowsInput {
14
+ sessions: ClientSession[] | null | undefined;
15
+ activeSessionId: string | null | undefined;
16
+ user: User | null | undefined;
17
+ locale: string;
18
+ getAvatarUrl: (avatarId: string) => string;
19
+ }
20
+
21
+ /**
22
+ * Pure builder for `AccountMenu` rows. Extracted so the multi-account display
23
+ * logic can be unit-tested without rendering React Native.
24
+ *
25
+ * Each `sessions[i]` becomes one row. Only the row matching `activeSessionId`
26
+ * carries the loaded `user` payload — the others are placeholders shown by
27
+ * fallback handle. This mirrors how `OxyContext` only hydrates one user at a
28
+ * time.
29
+ */
30
+ export function buildAccountRows({
31
+ sessions,
32
+ activeSessionId,
33
+ user,
34
+ locale,
35
+ getAvatarUrl,
36
+ }: BuildAccountRowsInput): AccountRow[] {
37
+ return (sessions ?? []).map((session: ClientSession) => {
38
+ const isActive = session.sessionId === activeSessionId;
39
+ const candidate: Partial<User> | null = isActive ? user ?? null : null;
40
+ const displayName = getAccountDisplayName(
41
+ candidate ?? { username: undefined },
42
+ locale,
43
+ );
44
+ const handle = getAccountFallbackHandle(candidate ?? { username: undefined });
45
+ const secondary = (candidate?.email)
46
+ ?? (handle && candidate?.username ? `@${handle}` : handle)
47
+ ?? null;
48
+ const avatarUri = candidate?.avatar
49
+ ? getAvatarUrl(candidate.avatar)
50
+ : undefined;
51
+ return {
52
+ sessionId: session.sessionId,
53
+ isActive,
54
+ displayName,
55
+ secondary,
56
+ avatarUri,
57
+ user: isActive ? user ?? null : null,
58
+ };
59
+ });
60
+ }
@@ -4,7 +4,7 @@ import { View, Text, Animated, TouchableOpacity, Clipboard, Linking } from 'reac
4
4
  import { Ionicons } from '@expo/vector-icons';
5
5
  import { Button } from '@oxyhq/bloom/button';
6
6
  import TextField from '../TextField';
7
- import { FAIRWalletIcon } from '../icon';
7
+ import FAIRWalletIcon from '../icon/FAIRWalletIcon';
8
8
  import { createPaymentStyles } from './paymentStyles';
9
9
  import { toast } from '@oxyhq/bloom';
10
10
  import type { CardDetails, PaymentColors, PaymentStepAnimations } from './types';
@@ -4,7 +4,7 @@ import { View, Text, Animated } from 'react-native';
4
4
  import { Ionicons } from '@expo/vector-icons';
5
5
  import { SettingsListGroup, SettingsListItem } from '@oxyhq/bloom/settings-list';
6
6
  import { Button } from '@oxyhq/bloom/button';
7
- import { FAIRWalletIcon } from '../icon';
7
+ import FAIRWalletIcon from '../icon/FAIRWalletIcon';
8
8
  import { createPaymentStyles } from './paymentStyles';
9
9
  import type { PaymentMethod, PaymentColors, PaymentStepAnimations } from './types';
10
10
  import { useI18n } from '../../hooks/useI18n';
@@ -1,5 +1,5 @@
1
1
  import { useTheme } from '@oxyhq/bloom/theme';
2
- import { getTheme } from '../styles';
2
+ import { getTheme } from '../styles/theme';
3
3
  import type { InternalTheme } from './types';
4
4
 
5
5
  /**
@@ -25,6 +25,7 @@ import { useAuthOperations } from './hooks/useAuthOperations';
25
25
  import { useDeviceManagement } from '../hooks/useDeviceManagement';
26
26
  import { getStorageKeys, createPlatformStorage, type StorageInterface } from '../utils/storageHelpers';
27
27
  import { isInvalidSessionError, isTimeoutOrNetworkError } from '../utils/errorHandlers';
28
+ import { readActiveAuthuser, writeActiveAuthuser } from '../utils/activeAuthuser';
28
29
  import type { RouteName } from '../navigation/routes';
29
30
  import { showBottomSheet as globalShowBottomSheet } from '../navigation/bottomSheetManager';
30
31
  import { useQueryClient } from '@tanstack/react-query';
@@ -97,6 +98,10 @@ export interface OxyContextState {
97
98
 
98
99
  const OxyContext = createContext<OxyContextState | null>(null);
99
100
 
101
+ // Active-authuser persistence helpers (web localStorage; native no-op) live in
102
+ // `../utils/activeAuthuser` so the session-management and auth-operations hooks
103
+ // can share them without re-importing this 1k-line context file.
104
+
100
105
  export interface OxyContextProviderProps {
101
106
  children: ReactNode;
102
107
  oxyServices?: OxyServices;
@@ -235,16 +240,58 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
235
240
 
236
241
  const storageKeys = useMemo(() => getStorageKeys(storageKeyPrefix), [storageKeyPrefix]);
237
242
 
238
- // Simple storage initialization - no complex hook needed
243
+ // Storage initialization.
244
+ //
245
+ // `storage` (state) drives render-time gating (`isStorageReady`) and the
246
+ // hooks below. But it is `null` for a brief window after mount while
247
+ // `createPlatformStorage()` resolves (a microtask on web; a dynamic
248
+ // `import()` on native). Any persistence path that fires during that window
249
+ // — e.g. an interactive FedCM sign-in the instant the screen mounts — would
250
+ // read `storage === null` and SILENTLY skip writing the session, leaving the
251
+ // user signed-in in-memory but with nothing to restore on reload.
252
+ //
253
+ // To make persistence robust regardless of timing we ALSO expose the storage
254
+ // as an awaitable promise (`getReadyStorage`). Persistence code awaits the
255
+ // ready instance instead of branching on the possibly-null state, so a write
256
+ // is never silently dropped just because it raced storage init.
239
257
  const storageRef = useRef<StorageInterface | null>(null);
240
258
  const [storage, setStorage] = useState<StorageInterface | null>(null);
241
259
 
260
+ // A single, stable deferred that resolves with the initialized storage. Built
261
+ // lazily via a ref initializer so the resolver is captured exactly once and
262
+ // the promise identity is stable across renders.
263
+ const buildStorageDeferred = () => {
264
+ let resolve: (storage: StorageInterface) => void = () => undefined;
265
+ const promise = new Promise<StorageInterface>((res) => {
266
+ resolve = res;
267
+ });
268
+ return { promise, resolve };
269
+ };
270
+ const storageReadyRef = useRef<ReturnType<typeof buildStorageDeferred> | null>(null);
271
+ if (storageReadyRef.current === null) {
272
+ storageReadyRef.current = buildStorageDeferred();
273
+ }
274
+ const storageReady = storageReadyRef.current;
275
+
276
+ // Resolve the storage instance that is guaranteed to be ready. Returns the
277
+ // already-initialized instance synchronously when available, otherwise awaits
278
+ // the init promise. Never resolves to `null`.
279
+ const getReadyStorage = useCallback((): Promise<StorageInterface> => {
280
+ if (storageRef.current) {
281
+ return Promise.resolve(storageRef.current);
282
+ }
283
+ return storageReady.promise;
284
+ }, [storageReady]);
285
+
242
286
  useEffect(() => {
243
287
  let mounted = true;
244
288
  createPlatformStorage()
245
289
  .then((storageInstance) => {
290
+ // Resolve the ready-promise even if the component unmounted: in-flight
291
+ // persistence awaiting it must still complete against a real store.
292
+ storageRef.current = storageInstance;
293
+ storageReady.resolve(storageInstance);
246
294
  if (mounted) {
247
- storageRef.current = storageInstance;
248
295
  setStorage(storageInstance);
249
296
  }
250
297
  })
@@ -262,7 +309,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
262
309
  return () => {
263
310
  mounted = false;
264
311
  };
265
- }, [logger, onError]);
312
+ }, [logger, onError, storageReady]);
266
313
 
267
314
 
268
315
  // Offline queuing is now handled by TanStack Query mutations
@@ -375,6 +422,130 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
375
422
  const clearSessionStateRef = useRef(clearSessionState);
376
423
  clearSessionStateRef.current = clearSessionState;
377
424
 
425
+ // Durable, navigation-safe session persistence.
426
+ //
427
+ // Writes the active-session id and appends the session id to the durable
428
+ // `session_ids` list, awaiting the READY storage instance (never the possibly
429
+ // -null `storage` state) so a write is never dropped because it raced storage
430
+ // init. Callers MUST invoke this BEFORE any work that can trigger a route
431
+ // navigation (`onAuthStateChange`) — navigation can interrupt a still-pending
432
+ // async write, which is exactly what once left `session_ids` empty after a
433
+ // successful sign-in. Shared by the FedCM/popup path and the cold-boot
434
+ // refresh-cookie restore so both land the same durable record.
435
+ const persistSessionDurably = useCallback(async (sessionId: string): Promise<void> => {
436
+ const readyStorage = await getReadyStorage();
437
+ await readyStorage.setItem(storageKeys.activeSessionId, sessionId);
438
+ const existingIds = await readyStorage.getItem(storageKeys.sessionIds);
439
+ let sessionIds: string[] = [];
440
+ try { sessionIds = existingIds ? JSON.parse(existingIds) : []; } catch { /* corrupted storage */ }
441
+ if (!sessionIds.includes(sessionId)) {
442
+ sessionIds.push(sessionId);
443
+ await readyStorage.setItem(storageKeys.sessionIds, JSON.stringify(sessionIds));
444
+ }
445
+ }, [getReadyStorage, storageKeys.activeSessionId, storageKeys.sessionIds]);
446
+
447
+ // Refs so the cold-boot restore can plant session state without widening its
448
+ // dependency array (mirrors the existing ref pattern above).
449
+ const setActiveSessionIdRef = useRef(setActiveSessionId);
450
+ setActiveSessionIdRef.current = setActiveSessionId;
451
+ const loginSuccessRef = useRef(loginSuccess);
452
+ loginSuccessRef.current = loginSuccess;
453
+ const onAuthStateChangeRef = useRef(onAuthStateChange);
454
+ onAuthStateChangeRef.current = onAuthStateChange;
455
+
456
+ // Cold-boot session restore via the secure refresh cookies (web only).
457
+ //
458
+ // Calls `oxyServices.refreshAllSessions()` → `POST /auth/refresh-all` with
459
+ // `credentials: 'include'`. The server rotates every device-local
460
+ // `oxy_rt_${authuser}` cookie in parallel and returns one entry per valid
461
+ // account (Google-style multi-account). On an older server that lacks the
462
+ // multi-account endpoint, the SDK transparently falls back to the legacy
463
+ // `/auth/refresh` single-account path and wraps the result in the same
464
+ // shape, so this caller doesn't branch.
465
+ //
466
+ // Active-account selection: the persisted `oxy_active_authuser` slot index
467
+ // wins when it matches a returned account; otherwise the lowest `authuser`
468
+ // is picked. JS never sees the refresh cookies (httpOnly).
469
+ //
470
+ // Returns `true` when at least one session was restored (caller short-
471
+ // circuits the bearer path); `false` on no signed-in accounts / any failure
472
+ // (caller proceeds unauthenticated through the existing flow — nothing is
473
+ // cleared).
474
+ const restoreViaRefreshCookie = useCallback(async (): Promise<boolean> => {
475
+ if (!isWebBrowser()) {
476
+ return false;
477
+ }
478
+
479
+ let snapshot;
480
+ try {
481
+ snapshot = await oxyServices.refreshAllSessions();
482
+ } catch (fetchError) {
483
+ // Offline / network error — fall through to the cached/stored-session flow.
484
+ if (__DEV__) {
485
+ loggerUtil.debug('Refresh-all cookie restore network error (expected when offline)', { component: 'OxyContext', method: 'restoreViaRefreshCookie' }, fetchError as unknown);
486
+ }
487
+ return false;
488
+ }
489
+
490
+ if (snapshot.accounts.length === 0) {
491
+ return false;
492
+ }
493
+
494
+ // Pick the active account: persisted authuser if it still matches a returned
495
+ // account, otherwise the lowest authuser (deterministic). The server has
496
+ // already sorted ascending so [0] is the lowest.
497
+ const persistedAuthuser = readActiveAuthuser();
498
+ const matched = persistedAuthuser !== null
499
+ ? snapshot.accounts.find((a) => a.authuser === persistedAuthuser)
500
+ : undefined;
501
+ const activeAccount = matched ?? snapshot.accounts[0];
502
+
503
+ // Plant the active access token. Sibling accounts' access tokens stay in
504
+ // the snapshot (the chooser can drive a per-account refresh via
505
+ // `refreshTokenViaCookie({authuser})` on switch).
506
+ oxyServices.httpService.setTokens(activeAccount.accessToken);
507
+
508
+ // Fetch the full user with the freshly planted token. The refresh-all
509
+ // payload includes a minimal user shape (id, username, name, avatar,
510
+ // email, color) — sufficient for the chooser but the auth store wants the
511
+ // canonical User document for downstream rendering.
512
+ let fullUser: User;
513
+ try {
514
+ fullUser = await oxyServices.getCurrentUser();
515
+ } catch (userError) {
516
+ // Token planted but profile fetch failed (e.g. transient network). Do
517
+ // not claim a restored session; fall through so the stored-session flow
518
+ // can retry. Leave the planted token in place — it is valid and harmless.
519
+ if (__DEV__) {
520
+ loggerUtil.debug('Refresh-all cookie restore: getCurrentUser failed', { component: 'OxyContext', method: 'restoreViaRefreshCookie' }, userError as unknown);
521
+ }
522
+ return false;
523
+ }
524
+
525
+ // Build a ClientSession per returned account so the multi-session store
526
+ // reflects every device-local slot, not just the active one. The active
527
+ // account is flagged `isCurrent: true`.
528
+ const now = new Date();
529
+ const clientSessions: ClientSession[] = snapshot.accounts.map((account) => ({
530
+ sessionId: account.sessionId,
531
+ deviceId: '',
532
+ expiresAt: account.expiresAt || new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
533
+ lastActive: now.toISOString(),
534
+ userId: account.user?.id,
535
+ isCurrent: account.sessionId === activeAccount.sessionId,
536
+ authuser: account.authuser,
537
+ }));
538
+
539
+ updateSessionsRef.current(clientSessions, { merge: true });
540
+ setActiveSessionIdRef.current(activeAccount.sessionId);
541
+ writeActiveAuthuser(activeAccount.authuser);
542
+ await persistSessionDurably(activeAccount.sessionId);
543
+
544
+ loginSuccessRef.current(fullUser);
545
+ onAuthStateChangeRef.current?.(fullUser);
546
+ return true;
547
+ }, [oxyServices, persistSessionDurably]);
548
+
378
549
  const restoreSessionsFromStorage = useCallback(async (): Promise<void> => {
379
550
  if (!storage) {
380
551
  return;
@@ -383,6 +554,15 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
383
554
  setTokenReady(false);
384
555
 
385
556
  try {
557
+ // Web cold-boot fast path: restore the active session from the secure
558
+ // httpOnly refresh cookie before the bearer-protected stored-session
559
+ // validation (which 401s on a hard reload). On success we are signed in
560
+ // from the cookie alone — no FedCM needed. On failure we fall through to
561
+ // the existing stored-session flow below; nothing is cleared.
562
+ if (await restoreViaRefreshCookie()) {
563
+ return;
564
+ }
565
+
386
566
  const storedSessionIdsJson = await storage.getItem(storageKeys.sessionIds);
387
567
  const storedSessionIds: string[] = storedSessionIdsJson ? JSON.parse(storedSessionIdsJson) : [];
388
568
  const storedActiveSessionId = await storage.getItem(storageKeys.activeSessionId);
@@ -473,6 +653,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
473
653
  storage,
474
654
  storageKeys.activeSessionId,
475
655
  storageKeys.sessionIds,
656
+ restoreViaRefreshCookie,
476
657
  ]);
477
658
 
478
659
  useEffect(() => {
@@ -517,8 +698,25 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
517
698
  updateSessions([clientSession], { merge: true });
518
699
  setActiveSessionId(session.sessionId);
519
700
 
520
- // Fetch the full user profile now that we have a valid access token.
521
- // The session only carries MinimalUserData; the store and callbacks expect a full User.
701
+ // Persist to storage BEFORE fetching the profile and BEFORE notifying the
702
+ // auth-state-change callback. The token is planted and the in-memory store
703
+ // is updated above; durably committing the session id here — ahead of
704
+ // `getCurrentUser()` / `loginSuccess` / `onAuthStateChange` — is critical
705
+ // because `onAuthStateChange` triggers a route navigation that can
706
+ // interrupt/supersede a still-pending async write. Persisting first
707
+ // guarantees the durable record lands; that is exactly what was missing
708
+ // when `oxy_session_session_ids` came back empty after a successful FedCM
709
+ // sign-in (the user appeared logged in until reload, then had no session to
710
+ // restore). `persistSessionDurably` awaits the READY storage instance rather
711
+ // than reading the possibly-null `storage` state, so a sign-in fired the
712
+ // instant the screen mounts (before storage-init populates state) is not
713
+ // silently dropped.
714
+ await persistSessionDurably(session.sessionId);
715
+
716
+ // Fetch the full user profile now that we have a valid access token and the
717
+ // session is durably persisted. The session only carries MinimalUserData;
718
+ // the store and callbacks expect a full User. The navigation kicked off by
719
+ // `onAuthStateChange` now happens only after the durable write is committed.
522
720
  let fullUser: User;
523
721
  try {
524
722
  fullUser = await oxyServices.getCurrentUser();
@@ -529,19 +727,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
529
727
  }
530
728
  loginSuccess(fullUser);
531
729
  onAuthStateChange?.(fullUser);
532
-
533
- // Persist to storage
534
- if (storage) {
535
- await storage.setItem(storageKeys.activeSessionId, session.sessionId);
536
- const existingIds = await storage.getItem(storageKeys.sessionIds);
537
- let sessionIds: string[] = [];
538
- try { sessionIds = existingIds ? JSON.parse(existingIds) : []; } catch { /* corrupted storage */ }
539
- if (!sessionIds.includes(session.sessionId)) {
540
- sessionIds.push(session.sessionId);
541
- await storage.setItem(storageKeys.sessionIds, JSON.stringify(sessionIds));
542
- }
543
- }
544
- }, [oxyServices, updateSessions, setActiveSessionId, loginSuccess, onAuthStateChange, storage, storageKeys]);
730
+ }, [oxyServices, updateSessions, setActiveSessionId, loginSuccess, onAuthStateChange, persistSessionDurably]);
545
731
 
546
732
  // Enable web SSO only after local storage check completes and no user found
547
733
  const shouldTryWebSSO = isWebBrowser() && tokenReady && !user && initialized;
@@ -8,6 +8,8 @@ import { handleAuthError, isInvalidSessionError } from '../../utils/errorHandler
8
8
  import type { StorageInterface } from '../../utils/storageHelpers';
9
9
  import type { OxyServices } from '@oxyhq/core';
10
10
  import { SignatureService } from '@oxyhq/core';
11
+ import { isWebBrowser } from '../../hooks/useWebSSO';
12
+ import { clearActiveAuthuser } from '../../utils/activeAuthuser';
11
13
 
12
14
  /** Type guard for error objects with optional code and status properties */
13
15
  function isErrorWithCodeOrStatus(error: unknown): error is { code?: string; status?: number; message?: string } {
@@ -300,7 +302,19 @@ export const useAuthOperations = ({
300
302
 
301
303
  try {
302
304
  const sessionToLogout = targetSessionId || activeSessionId;
303
- await oxyServices.logoutSession(activeSessionId, sessionToLogout);
305
+ // Web multi-account: when the target session carries an `authuser`
306
+ // slot index it is backed by an httpOnly `oxy_rt_${n}` cookie. Use
307
+ // the cookie-cleared logout endpoint so the server can `Set-Cookie`
308
+ // an immediate expiry alongside revoking the family. Native and
309
+ // legacy sessions (no `authuser` plumbed yet) fall through to the
310
+ // bearer-protected endpoint.
311
+ const targetSession = sessionsRef.current.find((s) => s.sessionId === sessionToLogout);
312
+ const targetAuthuser = targetSession?.authuser;
313
+ if (isWebBrowser() && typeof targetAuthuser === 'number') {
314
+ await oxyServices.logoutSessionByAuthuser(targetAuthuser);
315
+ } else {
316
+ await oxyServices.logoutSession(activeSessionId, sessionToLogout);
317
+ }
304
318
 
305
319
  const filteredSessions = sessionsRef.current.filter((session) => session.sessionId !== sessionToLogout);
306
320
  updateSessions(filteredSessions, { merge: false });
@@ -355,7 +369,27 @@ export const useAuthOperations = ({
355
369
  }
356
370
 
357
371
  try {
358
- await oxyServices.logoutAllSessions(activeSessionId);
372
+ // Semantics intentionally diverge by platform to match user expectation:
373
+ // - Web: "Sign out of all accounts" = sign out every device-local
374
+ // account on THIS device. The cookie endpoint is the only path
375
+ // that can `Set-Cookie` an immediate expiry on every
376
+ // `oxy_rt_${n}` slot (plus legacy `oxy_rt`) AND revoke every
377
+ // presented family server-side. The bearer-protected
378
+ // `logoutAllSessions(activeSessionId)` would only revoke the
379
+ // active user's sessions across devices and leave sibling
380
+ // accounts' cookies sitting on this device — wrong UX for the
381
+ // chooser's "Sign out of all accounts".
382
+ // - Native: there are no per-account cookies; "Sign out of all"
383
+ // keeps its long-standing "revoke every session of THIS user"
384
+ // meaning via the bearer endpoint.
385
+ // After clearing on web, also drop the persisted active-authuser so
386
+ // the next cold boot starts from a clean slate.
387
+ if (isWebBrowser()) {
388
+ await oxyServices.logoutAllSessionsViaCookie();
389
+ clearActiveAuthuser();
390
+ } else {
391
+ await oxyServices.logoutAllSessions(activeSessionId);
392
+ }
359
393
  await clearSessionState();
360
394
  } catch (error) {
361
395
  handleAuthError(error, {
@@ -14,6 +14,12 @@ export const mutationKeys = {
14
14
  uploadAvatar: ['mutation', 'account', 'uploadAvatar'] as const,
15
15
  updateSettings: ['mutation', 'account', 'updateSettings'] as const,
16
16
  updatePrivacySettings: ['mutation', 'account', 'updatePrivacySettings'] as const,
17
+ updateNotificationPreferences: [
18
+ 'mutation',
19
+ 'account',
20
+ 'updateNotificationPreferences',
21
+ ] as const,
22
+ updateUserPreferences: ['mutation', 'account', 'updateUserPreferences'] as const,
17
23
  uploadFile: ['mutation', 'account', 'uploadFile'] as const,
18
24
  },
19
25
 
@@ -25,4 +31,9 @@ export const mutationKeys = {
25
31
  updateDeviceName: ['mutation', 'session', 'updateDeviceName'] as const,
26
32
  removeDevice: ['mutation', 'session', 'removeDevice'] as const,
27
33
  },
34
+
35
+ // Connected apps (FedCM grants)
36
+ connectedApps: {
37
+ revoke: ['mutation', 'connectedApps', 'revoke'] as const,
38
+ },
28
39
  } as const;
@@ -1,7 +1,19 @@
1
1
  import { useMutation, useQueryClient } from '@tanstack/react-query';
2
2
  import { authenticatedApiCall } from '@oxyhq/core';
3
- import type { AssetUploadInput, PrivacySettings, User } from '@oxyhq/core';
4
- import { queryKeys, invalidateAccountQueries, invalidateUserQueries, invalidateSessionQueries } from '../queries/queryKeys';
3
+ import type {
4
+ AssetUploadInput,
5
+ NotificationPreferences,
6
+ PrivacySettings,
7
+ User,
8
+ UserPreferences,
9
+ } from '@oxyhq/core';
10
+ import {
11
+ queryKeys,
12
+ invalidateAccountQueries,
13
+ invalidateConnectedAppsQueries,
14
+ invalidateUserQueries,
15
+ invalidateSessionQueries,
16
+ } from '../queries/queryKeys';
5
17
  import { mutationKeys } from './mutationKeys';
6
18
  import { useOxy } from '../../context/OxyContext';
7
19
  import { toast } from '@oxyhq/bloom';
@@ -505,6 +517,146 @@ interface UploadResult {
505
517
  id?: string;
506
518
  }
507
519
 
520
+ /**
521
+ * Update the authenticated user's notification preferences with optimistic
522
+ * updates. Persisted on the User document via `PUT /users/me` — same cache-
523
+ * invalidation behaviour as `useUpdateProfile`.
524
+ */
525
+ export const useUpdateNotificationPreferences = () => {
526
+ const { oxyServices, activeSessionId } = useOxy();
527
+ const queryClient = useQueryClient();
528
+
529
+ return useMutation({
530
+ mutationKey: [...mutationKeys.account.updateNotificationPreferences],
531
+ mutationFn: async (preferences: Partial<NotificationPreferences>) => {
532
+ return authenticatedApiCall<User>(
533
+ oxyServices,
534
+ activeSessionId,
535
+ () => oxyServices.updateNotificationPreferences(preferences)
536
+ );
537
+ },
538
+ onMutate: async (preferences) => {
539
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
540
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
541
+
542
+ if (previousUser) {
543
+ queryClient.setQueryData<User>(queryKeys.accounts.current(), {
544
+ ...previousUser,
545
+ notificationPreferences: {
546
+ ...previousUser.notificationPreferences,
547
+ ...preferences,
548
+ },
549
+ });
550
+ }
551
+
552
+ return { previousUser };
553
+ },
554
+ onError: (error, _preferences, context) => {
555
+ if (context?.previousUser) {
556
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
557
+ if (current) {
558
+ queryClient.setQueryData<User>(queryKeys.accounts.current(), {
559
+ ...current,
560
+ notificationPreferences: context.previousUser.notificationPreferences,
561
+ });
562
+ }
563
+ }
564
+ toast.error(
565
+ error instanceof Error
566
+ ? error.message
567
+ : 'Failed to update notification preferences'
568
+ );
569
+ },
570
+ onSuccess: (data) => {
571
+ queryClient.setQueryData(queryKeys.accounts.current(), data);
572
+ useAuthStore.getState().setUser(data);
573
+ invalidateAccountQueries(queryClient);
574
+ },
575
+ });
576
+ };
577
+
578
+ /**
579
+ * Update the authenticated user's general preferences (language, theme,
580
+ * reduce-motion, timezone). Persisted on the User document via
581
+ * `PUT /users/me`.
582
+ */
583
+ export const useUpdateUserPreferences = () => {
584
+ const { oxyServices, activeSessionId } = useOxy();
585
+ const queryClient = useQueryClient();
586
+
587
+ return useMutation({
588
+ mutationKey: [...mutationKeys.account.updateUserPreferences],
589
+ mutationFn: async (preferences: Partial<UserPreferences>) => {
590
+ return authenticatedApiCall<User>(
591
+ oxyServices,
592
+ activeSessionId,
593
+ () => oxyServices.updateUserPreferences(preferences)
594
+ );
595
+ },
596
+ onMutate: async (preferences) => {
597
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
598
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
599
+
600
+ if (previousUser) {
601
+ queryClient.setQueryData<User>(queryKeys.accounts.current(), {
602
+ ...previousUser,
603
+ userPreferences: {
604
+ ...previousUser.userPreferences,
605
+ ...preferences,
606
+ },
607
+ });
608
+ }
609
+
610
+ return { previousUser };
611
+ },
612
+ onError: (error, _preferences, context) => {
613
+ if (context?.previousUser) {
614
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
615
+ if (current) {
616
+ queryClient.setQueryData<User>(queryKeys.accounts.current(), {
617
+ ...current,
618
+ userPreferences: context.previousUser.userPreferences,
619
+ });
620
+ }
621
+ }
622
+ toast.error(error instanceof Error ? error.message : 'Failed to update preferences');
623
+ },
624
+ onSuccess: (data) => {
625
+ queryClient.setQueryData(queryKeys.accounts.current(), data);
626
+ useAuthStore.getState().setUser(data);
627
+ invalidateAccountQueries(queryClient);
628
+ },
629
+ });
630
+ };
631
+
632
+ /**
633
+ * Revoke the authenticated user's authorization for a specific RP origin.
634
+ * Removes the FedCM grant so the origin no longer appears in the user's
635
+ * "Connected apps" list — next sign-in from that origin will require explicit
636
+ * re-consent.
637
+ */
638
+ export const useRevokeAuthorizedApp = () => {
639
+ const { oxyServices, activeSessionId } = useOxy();
640
+ const queryClient = useQueryClient();
641
+
642
+ return useMutation({
643
+ mutationKey: [...mutationKeys.connectedApps.revoke],
644
+ mutationFn: async (origin: string) => {
645
+ return authenticatedApiCall<void>(oxyServices, activeSessionId, () =>
646
+ oxyServices.revokeAuthorizedApp(origin)
647
+ );
648
+ },
649
+ onSuccess: () => {
650
+ invalidateConnectedAppsQueries(queryClient);
651
+ },
652
+ onError: (error) => {
653
+ toast.error(
654
+ error instanceof Error ? error.message : 'Failed to revoke authorized app'
655
+ );
656
+ },
657
+ });
658
+ };
659
+
508
660
  /**
509
661
  * Upload file with authentication handling and progress tracking
510
662
  */