@oxyhq/services 11.0.0 → 11.1.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 (427) hide show
  1. package/lib/commonjs/index.js.map +1 -1
  2. package/lib/commonjs/ui/components/AccountMenu.js +9 -5
  3. package/lib/commonjs/ui/components/AccountMenu.js.map +1 -1
  4. package/lib/commonjs/ui/components/AnotherDeviceQR.js +51 -56
  5. package/lib/commonjs/ui/components/AnotherDeviceQR.js.map +1 -1
  6. package/lib/commonjs/ui/components/BottomSheetRouter.js +1 -0
  7. package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
  8. package/lib/commonjs/ui/components/FollowButton.js +18 -5
  9. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  10. package/lib/commonjs/ui/components/OxyProvider.js +23 -7
  11. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  12. package/lib/commonjs/ui/components/SignInModal.js +20 -1
  13. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  14. package/lib/commonjs/ui/components/fileManagement/FileViewer.js +19 -9
  15. package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
  16. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js +4 -2
  17. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
  18. package/lib/commonjs/ui/context/OxyContext.js +153 -19
  19. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  20. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +6 -17
  21. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  22. package/lib/commonjs/ui/hooks/mutations/mutationFactory.js +5 -5
  23. package/lib/commonjs/ui/hooks/mutations/mutationFactory.js.map +1 -1
  24. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +38 -38
  25. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  26. package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js +2 -2
  27. package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js.map +1 -1
  28. package/lib/commonjs/ui/hooks/queries/queryKeys.js +3 -3
  29. package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
  30. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +1 -1
  31. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  32. package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js +16 -12
  33. package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js.map +1 -1
  34. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +10 -6
  35. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
  36. package/lib/commonjs/ui/hooks/queryClient.js +6 -5
  37. package/lib/commonjs/ui/hooks/queryClient.js.map +1 -1
  38. package/lib/commonjs/ui/hooks/useOxyAuthSession.js +40 -2
  39. package/lib/commonjs/ui/hooks/useOxyAuthSession.js.map +1 -1
  40. package/lib/commonjs/ui/hooks/useProfileEditing.js +21 -0
  41. package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
  42. package/lib/commonjs/ui/hooks/useSessionManagement.js +3 -3
  43. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  44. package/lib/commonjs/ui/screens/AccountVerificationScreen.js +100 -108
  45. package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
  46. package/lib/commonjs/ui/screens/AppInfoScreen.js +227 -273
  47. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  48. package/lib/commonjs/ui/screens/AvatarCropScreen.js +10 -4
  49. package/lib/commonjs/ui/screens/AvatarCropScreen.js.map +1 -1
  50. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js +20 -37
  51. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js.map +1 -1
  52. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js +89 -201
  53. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  54. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +80 -208
  55. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  56. package/lib/commonjs/ui/screens/FAQScreen.js +56 -208
  57. package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -1
  58. package/lib/commonjs/ui/screens/FeedbackScreen.js +303 -352
  59. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  60. package/lib/commonjs/ui/screens/FileManagementScreen.js +20 -20
  61. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  62. package/lib/commonjs/ui/screens/HelpSupportScreen.js +77 -89
  63. package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
  64. package/lib/commonjs/ui/screens/HistoryViewScreen.js +43 -58
  65. package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
  66. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +67 -90
  67. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  68. package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js +77 -177
  69. package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
  70. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +113 -107
  71. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
  72. package/lib/commonjs/ui/screens/ManageAccountScreen.js +55 -114
  73. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  74. package/lib/commonjs/ui/screens/NotificationsScreen.js +67 -85
  75. package/lib/commonjs/ui/screens/NotificationsScreen.js.map +1 -1
  76. package/lib/commonjs/ui/screens/OxyAuthScreen.js +71 -135
  77. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  78. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +15 -9
  79. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  80. package/lib/commonjs/ui/screens/PreferencesScreen.js +65 -83
  81. package/lib/commonjs/ui/screens/PreferencesScreen.js.map +1 -1
  82. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +378 -1023
  83. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  84. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +294 -242
  85. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  86. package/lib/commonjs/ui/screens/ProfileScreen.js +192 -305
  87. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  88. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +57 -97
  89. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
  90. package/lib/commonjs/ui/screens/SearchSettingsScreen.js +41 -41
  91. package/lib/commonjs/ui/screens/SearchSettingsScreen.js.map +1 -1
  92. package/lib/commonjs/ui/screens/UserLinksScreen.js +17 -24
  93. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -1
  94. package/lib/commonjs/ui/screens/UserListScreen.js +83 -214
  95. package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
  96. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +115 -77
  97. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  98. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js +70 -57
  99. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js.map +1 -1
  100. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +136 -332
  101. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  102. package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js +47 -137
  103. package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js.map +1 -1
  104. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +182 -115
  105. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  106. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +138 -214
  107. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  108. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +54 -92
  109. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  110. package/lib/commonjs/ui/utils/activeAuthuser.js +15 -9
  111. package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -1
  112. package/lib/commonjs/ui/utils/avatarUtils.js +1 -1
  113. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  114. package/lib/module/index.js.map +1 -1
  115. package/lib/module/ui/components/AccountMenu.js +10 -6
  116. package/lib/module/ui/components/AccountMenu.js.map +1 -1
  117. package/lib/module/ui/components/AnotherDeviceQR.js +50 -56
  118. package/lib/module/ui/components/AnotherDeviceQR.js.map +1 -1
  119. package/lib/module/ui/components/BottomSheetRouter.js +2 -1
  120. package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
  121. package/lib/module/ui/components/FollowButton.js +18 -5
  122. package/lib/module/ui/components/FollowButton.js.map +1 -1
  123. package/lib/module/ui/components/OxyProvider.js +23 -7
  124. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  125. package/lib/module/ui/components/SignInModal.js +20 -1
  126. package/lib/module/ui/components/SignInModal.js.map +1 -1
  127. package/lib/module/ui/components/fileManagement/FileViewer.js +19 -9
  128. package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
  129. package/lib/module/ui/components/fileManagement/UploadPreview.js +4 -2
  130. package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
  131. package/lib/module/ui/context/OxyContext.js +154 -20
  132. package/lib/module/ui/context/OxyContext.js.map +1 -1
  133. package/lib/module/ui/context/hooks/useAuthOperations.js +6 -17
  134. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  135. package/lib/module/ui/hooks/mutations/mutationFactory.js +5 -5
  136. package/lib/module/ui/hooks/mutations/mutationFactory.js.map +1 -1
  137. package/lib/module/ui/hooks/mutations/useAccountMutations.js +38 -38
  138. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  139. package/lib/module/ui/hooks/mutations/useServicesMutations.js +2 -2
  140. package/lib/module/ui/hooks/mutations/useServicesMutations.js.map +1 -1
  141. package/lib/module/ui/hooks/queries/queryKeys.js +3 -3
  142. package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
  143. package/lib/module/ui/hooks/queries/useAccountQueries.js +1 -1
  144. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  145. package/lib/module/ui/hooks/queries/usePaymentQueries.js +16 -12
  146. package/lib/module/ui/hooks/queries/usePaymentQueries.js.map +1 -1
  147. package/lib/module/ui/hooks/queries/useServicesQueries.js +9 -6
  148. package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
  149. package/lib/module/ui/hooks/queryClient.js +6 -5
  150. package/lib/module/ui/hooks/queryClient.js.map +1 -1
  151. package/lib/module/ui/hooks/useOxyAuthSession.js +40 -2
  152. package/lib/module/ui/hooks/useOxyAuthSession.js.map +1 -1
  153. package/lib/module/ui/hooks/useProfileEditing.js +21 -0
  154. package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
  155. package/lib/module/ui/hooks/useSessionManagement.js +4 -3
  156. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  157. package/lib/module/ui/screens/AccountVerificationScreen.js +101 -109
  158. package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
  159. package/lib/module/ui/screens/AppInfoScreen.js +228 -275
  160. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  161. package/lib/module/ui/screens/AvatarCropScreen.js +10 -4
  162. package/lib/module/ui/screens/AvatarCropScreen.js.map +1 -1
  163. package/lib/module/ui/screens/ConnectedAppsScreen.js +19 -39
  164. package/lib/module/ui/screens/ConnectedAppsScreen.js.map +1 -1
  165. package/lib/module/ui/screens/CreateManagedAccountScreen.js +90 -202
  166. package/lib/module/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  167. package/lib/module/ui/screens/EditProfileFieldScreen.js +77 -205
  168. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  169. package/lib/module/ui/screens/FAQScreen.js +55 -207
  170. package/lib/module/ui/screens/FAQScreen.js.map +1 -1
  171. package/lib/module/ui/screens/FeedbackScreen.js +301 -350
  172. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  173. package/lib/module/ui/screens/FileManagementScreen.js +20 -20
  174. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  175. package/lib/module/ui/screens/HelpSupportScreen.js +78 -90
  176. package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
  177. package/lib/module/ui/screens/HistoryViewScreen.js +44 -59
  178. package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
  179. package/lib/module/ui/screens/LanguageSelectorScreen.js +68 -91
  180. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  181. package/lib/module/ui/screens/LearnMoreUsernamesScreen.js +75 -177
  182. package/lib/module/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
  183. package/lib/module/ui/screens/LegalDocumentsScreen.js +116 -108
  184. package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
  185. package/lib/module/ui/screens/ManageAccountScreen.js +52 -112
  186. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  187. package/lib/module/ui/screens/NotificationsScreen.js +68 -86
  188. package/lib/module/ui/screens/NotificationsScreen.js.map +1 -1
  189. package/lib/module/ui/screens/OxyAuthScreen.js +69 -134
  190. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  191. package/lib/module/ui/screens/PaymentGatewayScreen.js +16 -10
  192. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  193. package/lib/module/ui/screens/PreferencesScreen.js +66 -84
  194. package/lib/module/ui/screens/PreferencesScreen.js.map +1 -1
  195. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +366 -1012
  196. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  197. package/lib/module/ui/screens/PrivacySettingsScreen.js +295 -243
  198. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  199. package/lib/module/ui/screens/ProfileScreen.js +189 -302
  200. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  201. package/lib/module/ui/screens/SavesCollectionsScreen.js +58 -98
  202. package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
  203. package/lib/module/ui/screens/SearchSettingsScreen.js +42 -42
  204. package/lib/module/ui/screens/SearchSettingsScreen.js.map +1 -1
  205. package/lib/module/ui/screens/UserLinksScreen.js +18 -25
  206. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -1
  207. package/lib/module/ui/screens/UserListScreen.js +81 -212
  208. package/lib/module/ui/screens/UserListScreen.js.map +1 -1
  209. package/lib/module/ui/screens/WelcomeNewUserScreen.js +114 -76
  210. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  211. package/lib/module/ui/screens/trust/TrustAboutScreen.js +69 -57
  212. package/lib/module/ui/screens/trust/TrustAboutScreen.js.map +1 -1
  213. package/lib/module/ui/screens/trust/TrustCenterScreen.js +135 -332
  214. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  215. package/lib/module/ui/screens/trust/TrustFAQScreen.js +48 -138
  216. package/lib/module/ui/screens/trust/TrustFAQScreen.js.map +1 -1
  217. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +184 -117
  218. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  219. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +132 -208
  220. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  221. package/lib/module/ui/screens/trust/TrustRulesScreen.js +58 -94
  222. package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  223. package/lib/module/ui/utils/activeAuthuser.js +15 -9
  224. package/lib/module/ui/utils/activeAuthuser.js.map +1 -1
  225. package/lib/module/ui/utils/avatarUtils.js +1 -1
  226. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  227. package/lib/typescript/commonjs/index.d.ts +1 -0
  228. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  229. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +2 -0
  230. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -1
  231. package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts +12 -2
  232. package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/ui/components/BottomSheetRouter.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/ui/components/FollowButton.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts +3 -2
  236. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  237. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  238. package/lib/typescript/commonjs/ui/components/TouchableRipple/TouchableRipple.native.d.ts +1 -1
  239. package/lib/typescript/commonjs/ui/components/TouchableRipple/TouchableRipple.native.d.ts.map +1 -1
  240. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +34 -0
  241. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  242. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  243. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +3 -0
  244. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  245. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +3 -3
  246. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  247. package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  248. package/lib/typescript/commonjs/ui/hooks/queryClient.d.ts.map +1 -1
  249. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts +22 -0
  250. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
  251. package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts +3 -0
  252. package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts.map +1 -1
  253. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +2 -1
  254. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  255. package/lib/typescript/commonjs/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
  256. package/lib/typescript/commonjs/ui/screens/AppInfoScreen.d.ts.map +1 -1
  257. package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts.map +1 -1
  258. package/lib/typescript/commonjs/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  259. package/lib/typescript/commonjs/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
  260. package/lib/typescript/commonjs/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  261. package/lib/typescript/commonjs/ui/screens/FAQScreen.d.ts.map +1 -1
  262. package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
  263. package/lib/typescript/commonjs/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  264. package/lib/typescript/commonjs/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  265. package/lib/typescript/commonjs/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  266. package/lib/typescript/commonjs/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
  267. package/lib/typescript/commonjs/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  268. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  269. package/lib/typescript/commonjs/ui/screens/NotificationsScreen.d.ts.map +1 -1
  270. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  271. package/lib/typescript/commonjs/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  272. package/lib/typescript/commonjs/ui/screens/PreferencesScreen.d.ts.map +1 -1
  273. package/lib/typescript/commonjs/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  274. package/lib/typescript/commonjs/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  275. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  276. package/lib/typescript/commonjs/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  277. package/lib/typescript/commonjs/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  278. package/lib/typescript/commonjs/ui/screens/UserLinksScreen.d.ts.map +1 -1
  279. package/lib/typescript/commonjs/ui/screens/UserListScreen.d.ts.map +1 -1
  280. package/lib/typescript/commonjs/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  281. package/lib/typescript/commonjs/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
  282. package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
  283. package/lib/typescript/commonjs/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
  284. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  285. package/lib/typescript/commonjs/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
  286. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  287. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -1
  288. package/lib/typescript/module/index.d.ts +1 -0
  289. package/lib/typescript/module/index.d.ts.map +1 -1
  290. package/lib/typescript/module/ui/components/AccountMenu.d.ts +2 -0
  291. package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -1
  292. package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts +12 -2
  293. package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts.map +1 -1
  294. package/lib/typescript/module/ui/components/BottomSheetRouter.d.ts.map +1 -1
  295. package/lib/typescript/module/ui/components/FollowButton.d.ts.map +1 -1
  296. package/lib/typescript/module/ui/components/OxyProvider.d.ts +3 -2
  297. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  298. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  299. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts +1 -1
  300. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts.map +1 -1
  301. package/lib/typescript/module/ui/context/OxyContext.d.ts +34 -0
  302. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  303. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  304. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +3 -0
  305. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  306. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +3 -3
  307. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  308. package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  309. package/lib/typescript/module/ui/hooks/queryClient.d.ts.map +1 -1
  310. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts +22 -0
  311. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
  312. package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts +3 -0
  313. package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts.map +1 -1
  314. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +2 -1
  315. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  316. package/lib/typescript/module/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
  317. package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts.map +1 -1
  318. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts.map +1 -1
  319. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  320. package/lib/typescript/module/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
  321. package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  322. package/lib/typescript/module/ui/screens/FAQScreen.d.ts.map +1 -1
  323. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  324. package/lib/typescript/module/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  325. package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  326. package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  327. package/lib/typescript/module/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
  328. package/lib/typescript/module/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  329. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  330. package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts.map +1 -1
  331. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  332. package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  333. package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts.map +1 -1
  334. package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  335. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  336. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  337. package/lib/typescript/module/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  338. package/lib/typescript/module/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  339. package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts.map +1 -1
  340. package/lib/typescript/module/ui/screens/UserListScreen.d.ts.map +1 -1
  341. package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  342. package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
  343. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
  344. package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
  345. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  346. package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
  347. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  348. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -1
  349. package/lib/typescript/types/expo-haptics.d.ts +42 -0
  350. package/package.json +8 -3
  351. package/src/index.ts +1 -0
  352. package/src/types/expo-haptics.d.ts +42 -0
  353. package/src/ui/components/AccountMenu.tsx +11 -5
  354. package/src/ui/components/AnotherDeviceQR.tsx +53 -45
  355. package/src/ui/components/BottomSheetRouter.tsx +2 -1
  356. package/src/ui/components/FollowButton.tsx +24 -5
  357. package/src/ui/components/OxyProvider.tsx +22 -8
  358. package/src/ui/components/SignInModal.tsx +21 -2
  359. package/src/ui/components/TouchableRipple/TouchableRipple.native.tsx +1 -1
  360. package/src/ui/components/fileManagement/FileViewer.tsx +9 -9
  361. package/src/ui/components/fileManagement/UploadPreview.tsx +2 -2
  362. package/src/ui/context/OxyContext.tsx +178 -21
  363. package/src/ui/context/hooks/useAuthOperations.ts +6 -17
  364. package/src/ui/hooks/mutations/mutationFactory.ts +5 -5
  365. package/src/ui/hooks/mutations/useAccountMutations.ts +38 -38
  366. package/src/ui/hooks/mutations/useServicesMutations.ts +2 -2
  367. package/src/ui/hooks/queries/queryKeys.ts +6 -3
  368. package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
  369. package/src/ui/hooks/queries/usePaymentQueries.ts +12 -12
  370. package/src/ui/hooks/queries/useServicesQueries.ts +9 -6
  371. package/src/ui/hooks/queryClient.ts +5 -5
  372. package/src/ui/hooks/useOxyAuthSession.ts +76 -2
  373. package/src/ui/hooks/useProfileEditing.ts +24 -0
  374. package/src/ui/hooks/useSessionManagement.ts +9 -6
  375. package/src/ui/screens/AccountVerificationScreen.tsx +101 -113
  376. package/src/ui/screens/AppInfoScreen.tsx +200 -238
  377. package/src/ui/screens/AvatarCropScreen.tsx +17 -4
  378. package/src/ui/screens/ConnectedAppsScreen.tsx +16 -34
  379. package/src/ui/screens/CreateManagedAccountScreen.tsx +94 -170
  380. package/src/ui/screens/EditProfileFieldScreen.tsx +77 -190
  381. package/src/ui/screens/FAQScreen.tsx +77 -208
  382. package/src/ui/screens/FeedbackScreen.tsx +330 -239
  383. package/src/ui/screens/FileManagementScreen.tsx +20 -20
  384. package/src/ui/screens/HelpSupportScreen.tsx +67 -82
  385. package/src/ui/screens/HistoryViewScreen.tsx +32 -38
  386. package/src/ui/screens/LanguageSelectorScreen.tsx +79 -93
  387. package/src/ui/screens/LearnMoreUsernamesScreen.tsx +81 -164
  388. package/src/ui/screens/LegalDocumentsScreen.tsx +184 -123
  389. package/src/ui/screens/ManageAccountScreen.tsx +48 -114
  390. package/src/ui/screens/NotificationsScreen.tsx +107 -106
  391. package/src/ui/screens/OxyAuthScreen.tsx +76 -109
  392. package/src/ui/screens/PaymentGatewayScreen.tsx +16 -7
  393. package/src/ui/screens/PreferencesScreen.tsx +96 -116
  394. package/src/ui/screens/PremiumSubscriptionScreen.tsx +419 -872
  395. package/src/ui/screens/PrivacySettingsScreen.tsx +203 -185
  396. package/src/ui/screens/ProfileScreen.tsx +158 -200
  397. package/src/ui/screens/SavesCollectionsScreen.tsx +78 -125
  398. package/src/ui/screens/SearchSettingsScreen.tsx +52 -41
  399. package/src/ui/screens/UserLinksScreen.tsx +18 -25
  400. package/src/ui/screens/UserListScreen.tsx +95 -188
  401. package/src/ui/screens/WelcomeNewUserScreen.tsx +109 -36
  402. package/src/ui/screens/trust/TrustAboutScreen.tsx +52 -41
  403. package/src/ui/screens/trust/TrustCenterScreen.tsx +184 -222
  404. package/src/ui/screens/trust/TrustFAQScreen.tsx +64 -124
  405. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +190 -67
  406. package/src/ui/screens/trust/TrustRewardsScreen.tsx +147 -182
  407. package/src/ui/screens/trust/TrustRulesScreen.tsx +77 -50
  408. package/src/ui/utils/activeAuthuser.ts +15 -9
  409. package/src/ui/utils/avatarUtils.ts +1 -1
  410. package/lib/commonjs/ui/components/feedback/FormInput.js +0 -72
  411. package/lib/commonjs/ui/components/feedback/FormInput.js.map +0 -1
  412. package/lib/commonjs/ui/components/feedback/feedbackStyles.js +0 -261
  413. package/lib/commonjs/ui/components/feedback/feedbackStyles.js.map +0 -1
  414. package/lib/module/ui/components/feedback/FormInput.js +0 -67
  415. package/lib/module/ui/components/feedback/FormInput.js.map +0 -1
  416. package/lib/module/ui/components/feedback/feedbackStyles.js +0 -256
  417. package/lib/module/ui/components/feedback/feedbackStyles.js.map +0 -1
  418. package/lib/typescript/commonjs/ui/components/feedback/FormInput.d.ts +0 -20
  419. package/lib/typescript/commonjs/ui/components/feedback/FormInput.d.ts.map +0 -1
  420. package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts +0 -279
  421. package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts.map +0 -1
  422. package/lib/typescript/module/ui/components/feedback/FormInput.d.ts +0 -20
  423. package/lib/typescript/module/ui/components/feedback/FormInput.d.ts.map +0 -1
  424. package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts +0 -279
  425. package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts.map +0 -1
  426. package/src/ui/components/feedback/FormInput.tsx +0 -84
  427. package/src/ui/components/feedback/feedbackStyles.ts +0 -246
@@ -19,6 +19,7 @@ import {
19
19
  runColdBoot,
20
20
  resolveCentralAuthUrl,
21
21
  autoDetectAuthWebUrl,
22
+ registrableApex,
22
23
  SSO_CALLBACK_PATH,
23
24
  ssoStateKey,
24
25
  ssoGuardKey,
@@ -92,6 +93,24 @@ export interface OxyContextState {
92
93
  // Authentication
93
94
  signIn: (publicKey: string, deviceName?: string) => Promise<User>;
94
95
 
96
+ /**
97
+ * Sign in with a username/email + password.
98
+ *
99
+ * Commits a successful session into context state through the SAME path FedCM
100
+ * / SSO use (so `isAuthenticated` / `user` update and the session is persisted
101
+ * durably). Returns a discriminated result so the caller can branch on the
102
+ * two-factor-required case — which creates NO session; the caller completes
103
+ * the 2FA challenge with the returned `loginToken`.
104
+ *
105
+ * This is the keyless native sign-in path for the slimmed Accounts app, which
106
+ * no longer holds a local cryptographic identity key.
107
+ */
108
+ signInWithPassword: (
109
+ identifier: string,
110
+ password: string,
111
+ opts?: { deviceName?: string; deviceFingerprint?: string },
112
+ ) => Promise<PasswordSignInResult>;
113
+
95
114
  /**
96
115
  * Handle a session returned by web SSO.
97
116
  * Updates auth state, persists session metadata to storage.
@@ -145,6 +164,22 @@ export interface OxyContextState {
145
164
 
146
165
  const OxyContext = createContext<OxyContextState | null>(null);
147
166
 
167
+ /**
168
+ * Result of {@link OxyContextState.signInWithPassword}.
169
+ *
170
+ * `'ok'` — the password was accepted and the resulting session has been
171
+ * committed into context state (the SAME path FedCM / SSO sessions use), so
172
+ * `isAuthenticated` / `user` are updated and the session is durably persisted;
173
+ * the caller can proceed (e.g. navigate into the app).
174
+ *
175
+ * `'2fa_required'` — the account has two-factor auth enabled, so NO session was
176
+ * created. The caller must complete the challenge with the returned short-lived
177
+ * `loginToken` (`POST /security/2fa/verify-login`) before a session exists.
178
+ */
179
+ export type PasswordSignInResult =
180
+ | { status: 'ok' }
181
+ | { status: '2fa_required'; loginToken: string };
182
+
148
183
  // Active-authuser persistence helpers (web localStorage; native no-op) live in
149
184
  // `../utils/activeAuthuser` so the session-management and auth-operations hooks
150
185
  // can share them without re-importing this 1k-line context file.
@@ -236,6 +271,20 @@ const SILENT_IFRAME_TIMEOUT = 2500;
236
271
  */
237
272
  const COOKIE_RESTORE_TIMEOUT = 3000;
238
273
 
274
+ /**
275
+ * Per-step fail-fast budget (ms) for the native shared-key cold-boot step
276
+ * (`signInWithSharedIdentity`).
277
+ *
278
+ * That step does a challenge round-trip plus a verify against the shared
279
+ * cross-app identity key; if the device holds no shared identity it returns
280
+ * `null` quickly, but a slow/offline network must not let it block the cold
281
+ * boot. 8s mirrors the stored-session bearer-validation budget
282
+ * (`VALIDATION_TIMEOUT`) since both perform comparable bounded network work; on
283
+ * expiry the step resolves to `null` and cold boot falls through (native then
284
+ * reaches the unauthenticated backstop, web never runs this step at all).
285
+ */
286
+ const SHARED_KEY_SIGNIN_TIMEOUT = 8000;
287
+
239
288
  /**
240
289
  * HARD overall deadline (ms) for the entire cold-boot step loop —
241
290
  * defense-in-depth so a single non-settling step can NEVER hang auth resolution
@@ -265,13 +314,17 @@ const COOKIE_RESTORE_TIMEOUT = 3000;
265
314
  const COLD_BOOT_OVERALL_DEADLINE = 20000;
266
315
 
267
316
  /**
268
- * Per-session timeout (ms) for the parallel stored-session validation in
317
+ * Per-session soft timeout (ms) for the parallel stored-session validation in
269
318
  * `restoreStoredSession`. Each `validateSession` call races against this timer
270
319
  * so a single slow/offline session never blocks the whole startup validation
271
- * sweep sessions that don't answer in time resolve to `null` (treated as
272
- * unvalidated) and the remaining sessions still settle.
320
+ * sweep. Sessions that don't answer in time are treated as unvalidated and kept
321
+ * in the persisted ID list; only explicit invalid-session responses are pruned.
273
322
  */
274
323
  const VALIDATION_TIMEOUT = 8000;
324
+ const VALIDATION_TIMEOUT_RESULT = 'validation-timeout' as const;
325
+ type StoredSessionValidationResult =
326
+ | { session: ClientSession | null; timedOut: false }
327
+ | { sessionId: string; timedOut: true };
275
328
 
276
329
  /**
277
330
  * Fallback client-session validity window (ms) — 7 days — applied when a
@@ -357,12 +410,11 @@ function isSameSiteIdP(idpOrigin: string): boolean {
357
410
  const pageHostname = window.location.hostname;
358
411
  if (!idpHostname || !pageHostname) return false;
359
412
  if (idpHostname === pageHostname) return true;
360
- const apexOf = (hostname: string): string => hostname.split('.').slice(-2).join('.');
361
- const pageApex = apexOf(pageHostname);
362
- // Require a real registrable apex (≥2 labels) AND an exact apex match AND that
363
- // the IdP host is the page apex itself or a subdomain of it.
364
- if (pageHostname.split('.').length < 2) return false;
365
- if (apexOf(idpHostname) !== pageApex) return false;
413
+ const pageApex = registrableApex(pageHostname);
414
+ const idpApex = registrableApex(idpHostname);
415
+ // Require a real registrable apex (not a shared/public suffix) AND an exact
416
+ // apex match AND that the IdP host is the page apex itself or a subdomain of it.
417
+ if (!pageApex || idpApex !== pageApex) return false;
366
418
  return idpHostname === pageApex || idpHostname.endsWith(`.${pageApex}`);
367
419
  }
368
420
 
@@ -948,14 +1000,15 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
948
1000
  ]));
949
1001
 
950
1002
  let validSessions: ClientSession[] = [];
1003
+ let unvalidatedSessionIds: string[] = [];
951
1004
 
952
1005
  if (storedSessionIds.length > 0) {
953
1006
  // Validate all sessions in parallel (with a per-session timeout) to avoid
954
1007
  // sequential blocking that freezes the app on startup
955
1008
  const results = await Promise.allSettled(
956
1009
  storedSessionIds.map(async (sessionId) => {
957
- const timeoutPromise = new Promise<null>((resolve) =>
958
- setTimeout(() => resolve(null), VALIDATION_TIMEOUT),
1010
+ const timeoutPromise = new Promise<typeof VALIDATION_TIMEOUT_RESULT>((resolve) =>
1011
+ setTimeout(() => resolve(VALIDATION_TIMEOUT_RESULT), VALIDATION_TIMEOUT),
959
1012
  );
960
1013
  const validationPromise = oxyServices
961
1014
  .validateSession(sessionId, { useHeaderValidation: true })
@@ -969,6 +1022,9 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
969
1022
  });
970
1023
 
971
1024
  return Promise.race([validationPromise, timeoutPromise]).then((validation) => {
1025
+ if (validation === VALIDATION_TIMEOUT_RESULT) {
1026
+ return { sessionId, timedOut: true as const };
1027
+ }
972
1028
  if (validation?.valid && validation.user) {
973
1029
  const now = new Date();
974
1030
  const clientSession: ClientSession = {
@@ -982,21 +1038,31 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
982
1038
  if (isWebBrowser() && sessionId === storedActiveSessionId && storedActiveAuthuser !== null) {
983
1039
  clientSession.authuser = storedActiveAuthuser;
984
1040
  }
985
- return clientSession;
1041
+ return { session: clientSession, timedOut: false as const };
986
1042
  }
987
- return null;
1043
+ return { session: null, timedOut: false as const };
988
1044
  });
989
1045
  }),
990
1046
  );
991
1047
 
992
- validSessions = results
993
- .filter((r): r is PromiseFulfilledResult<ClientSession | null> => r.status === 'fulfilled')
994
- .map((r) => r.value)
995
- .filter((s): s is ClientSession => s !== null);
1048
+ for (const result of results) {
1049
+ if (result.status !== 'fulfilled') continue;
1050
+ const value: StoredSessionValidationResult = result.value;
1051
+ if (value.timedOut) {
1052
+ unvalidatedSessionIds.push(value.sessionId);
1053
+ } else if (value.session) {
1054
+ validSessions.push(value.session);
1055
+ }
1056
+ }
996
1057
 
997
- // Always persist validated sessions to storage (even empty list)
998
- // to clear stale/expired session IDs that would cause 401 loops on restart
999
- updateSessionsRef.current(validSessions, { merge: false });
1058
+ // Persist validated sessions while preserving soft-timed-out IDs. This
1059
+ // still clears sessions that were explicitly rejected as invalid, but
1060
+ // avoids logging out valid secondary accounts solely because the API was
1061
+ // slow during startup.
1062
+ updateSessionsRef.current(validSessions, {
1063
+ merge: false,
1064
+ preserveSessionIds: unvalidatedSessionIds,
1065
+ });
1000
1066
  }
1001
1067
 
1002
1068
  if (storedActiveSessionId) {
@@ -1014,7 +1080,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1014
1080
  await storage.removeItem(storageKeys.activeSessionId);
1015
1081
  updateSessionsRef.current(
1016
1082
  validSessions.filter((session) => session.sessionId !== storedActiveSessionId),
1017
- { merge: false },
1083
+ { merge: false, preserveSessionIds: unvalidatedSessionIds },
1018
1084
  );
1019
1085
  // Don't log expected session errors during restoration
1020
1086
  } else if (isTimeoutOrNetworkError(switchError)) {
@@ -1191,6 +1257,56 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1191
1257
  return { kind: 'skip' };
1192
1258
  },
1193
1259
  },
1260
+ {
1261
+ // 2.5) Shared-key SSO (NATIVE ONLY) — same-device, no interaction.
1262
+ //
1263
+ // When a sibling Oxy app (the Commons identity vault) has written
1264
+ // the cross-app shared identity into the `group.so.oxy.shared`
1265
+ // keychain, this mints THIS app's session from it silently:
1266
+ // `signInWithSharedIdentity()` proves control of the shared key
1267
+ // (challenge → sign → verify, which plants the tokens server-side)
1268
+ // and returns a `SessionLoginResponse`, which we commit through the
1269
+ // SAME path the web SSO steps use (`handleWebSSOSession`), so state,
1270
+ // durable persistence, profile fetch, and `markAuthResolved` all run
1271
+ // identically. Returns `null` when no shared identity is present, so
1272
+ // a device without Commons simply falls through.
1273
+ //
1274
+ // ORDERING: runs immediately AFTER `stored-session` (an already
1275
+ // restored local bearer always wins first — `storedSessionRestored`
1276
+ // gates this off) and BEFORE the web-only probes (which are gated
1277
+ // off on native anyway). Native-only: `enabled` requires
1278
+ // `!isWebBrowser()`, and the core method also returns `null` on web,
1279
+ // so `WebOxyProvider` / the web path are entirely unaffected.
1280
+ // Bounded by `SHARED_KEY_SIGNIN_TIMEOUT` so a slow/offline network
1281
+ // cannot stall cold boot.
1282
+ id: 'shared-key-signin',
1283
+ enabled: () => !isWebBrowser() && !storedSessionRestored,
1284
+ run: async () => {
1285
+ if (!commitWebSession) {
1286
+ return { kind: 'skip' };
1287
+ }
1288
+ let timeoutId: ReturnType<typeof setTimeout> | undefined;
1289
+ const session = await Promise.race<SessionLoginResponse | null>([
1290
+ oxyServices.signInWithSharedIdentity?.() ?? Promise.resolve(null),
1291
+ new Promise<null>((resolve) => {
1292
+ timeoutId = setTimeout(() => resolve(null), SHARED_KEY_SIGNIN_TIMEOUT);
1293
+ }),
1294
+ ]).finally(() => {
1295
+ if (timeoutId !== undefined) {
1296
+ clearTimeout(timeoutId);
1297
+ }
1298
+ });
1299
+ if (!session) {
1300
+ return { kind: 'skip' };
1301
+ }
1302
+ await commitWebSession(session);
1303
+ // Record the win so the (web-only) probes below explicitly skip —
1304
+ // belt-and-suspenders; `runColdBoot` already short-circuits on the
1305
+ // first `{kind:'session'}`, and those probes are off on native.
1306
+ storedSessionRestored = true;
1307
+ return { kind: 'session', session: true };
1308
+ },
1309
+ },
1194
1310
  {
1195
1311
  // 3) FedCM silent reauthn (Chrome) against the CENTRAL IdP
1196
1312
  // (auth.oxy.so). `silentSignInWithFedCM` plants the access token
@@ -1560,6 +1676,44 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1560
1676
  // before the cold-boot effect (gated on `storage`/`initialized`) can fire.
1561
1677
  handleWebSSOSessionRef.current = handleWebSSOSession;
1562
1678
 
1679
+ // Keyless native sign-in: username/email + password. The slimmed Accounts app
1680
+ // (which no longer holds a local identity key) uses this; it commits a
1681
+ // successful session through the SAME `handleWebSSOSession` path FedCM / SSO
1682
+ // use, so state, durable persistence, profile fetch, and `markAuthResolved`
1683
+ // all run identically. The API returns either a full session OR a two-factor
1684
+ // handoff (`{ twoFactorRequired, loginToken }`) — we surface the latter as a
1685
+ // discriminated result so the caller can run the 2FA challenge without any
1686
+ // session being committed.
1687
+ const signInWithPassword = useCallback(
1688
+ async (
1689
+ identifier: string,
1690
+ password: string,
1691
+ opts?: { deviceName?: string; deviceFingerprint?: string },
1692
+ ): Promise<PasswordSignInResult> => {
1693
+ const response = await oxyServices.signIn(
1694
+ identifier,
1695
+ password,
1696
+ opts?.deviceName,
1697
+ opts?.deviceFingerprint,
1698
+ );
1699
+ // Core types `signIn` as `SessionLoginResponse`, but the API may instead
1700
+ // return a 2FA challenge handoff. Widen with optional fields (no `any`) to
1701
+ // read them — the added members are optional, so the base type is
1702
+ // assignable to this intersection.
1703
+ const maybeTwoFactor: SessionLoginResponse & {
1704
+ twoFactorRequired?: boolean;
1705
+ loginToken?: string;
1706
+ } = response;
1707
+ if (maybeTwoFactor.twoFactorRequired && maybeTwoFactor.loginToken) {
1708
+ return { status: '2fa_required', loginToken: maybeTwoFactor.loginToken };
1709
+ }
1710
+ // Full session — commit it through the shared web-session path.
1711
+ await handleWebSSOSession(response);
1712
+ return { status: 'ok' };
1713
+ },
1714
+ [oxyServices, handleWebSSOSession],
1715
+ );
1716
+
1563
1717
  // Cross-domain silent SSO is now owned by the `fedcm-silent` / `silent-iframe`
1564
1718
  // cold-boot steps above (the ordered `runColdBoot` sequence). `useWebSSO`
1565
1719
  // remains mounted for its module-level run-once guard and its interactive
@@ -1831,6 +1985,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1831
1985
  hasIdentity,
1832
1986
  getPublicKey,
1833
1987
  signIn,
1988
+ signInWithPassword,
1834
1989
  handleWebSession: handleWebSSOSession,
1835
1990
  logout,
1836
1991
  logoutAll,
@@ -1857,6 +2012,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1857
2012
  }), [
1858
2013
  activeSessionId,
1859
2014
  signIn,
2015
+ signInWithPassword,
1860
2016
  handleWebSSOSession,
1861
2017
  currentLanguage,
1862
2018
  currentLanguageMetadata,
@@ -1947,6 +2103,7 @@ const LOADING_STATE: OxyContextState = {
1947
2103
  hasIdentity: () => Promise.resolve(false),
1948
2104
  getPublicKey: () => Promise.resolve(null),
1949
2105
  signIn: () => rejectMissingProvider<User>(),
2106
+ signInWithPassword: () => rejectMissingProvider<PasswordSignInResult>(),
1950
2107
  handleWebSession: () => rejectMissingProvider<void>(),
1951
2108
  logout: () => rejectMissingProvider<void>(),
1952
2109
  logoutAll: () => rejectMissingProvider<void>(),
@@ -275,26 +275,15 @@ export const useAuthOperations = ({
275
275
  }
276
276
 
277
277
  try {
278
- // Semantics intentionally diverge by platform to match user expectation:
279
- // - Web: "Sign out of all accounts" = sign out every device-local
280
- // account on THIS device. The cookie endpoint is the only path
281
- // that can `Set-Cookie` an immediate expiry on every
282
- // `oxy_rt_${n}` slots AND revoke every presented family server-side.
283
- // The bearer-protected
284
- // `logoutAllSessions(activeSessionId)` would only revoke the
285
- // active user's sessions across devices and leave sibling
286
- // accounts' cookies sitting on this device — wrong UX for the
287
- // chooser's "Sign out of all accounts".
288
- // - Native: there are no per-account cookies; "Sign out of all"
289
- // keeps its long-standing "revoke every session of THIS user"
290
- // meaning via the bearer endpoint.
291
- // After clearing on web, also drop the persisted active-authuser so
292
- // the next cold boot starts from a clean slate.
278
+ // Always invoke the bearer-protected global endpoint first: the public
279
+ // `logoutAll`/`signOutAll` contract means revoking this user's sessions
280
+ // across devices, not just clearing refresh cookies presented by the
281
+ // current browser. On web, follow up with the cookie endpoint so every
282
+ // device-local account slot is expired in the browser as well.
283
+ await oxyServices.logoutAllSessions(activeSessionId);
293
284
  if (isWebBrowser()) {
294
285
  await oxyServices.logoutAllSessionsViaCookie();
295
286
  clearActiveAuthuser();
296
- } else {
297
- await oxyServices.logoutAllSessions(activeSessionId);
298
287
  }
299
288
  // logoutAll is ALWAYS a full sign-out: clear the per-origin SSO bounce
300
289
  // state (web-guarded internally) so a fresh sign-in can re-probe.
@@ -81,20 +81,20 @@ export function createProfileMutation<TVariables>(
81
81
 
82
82
  onMutate: async (variables) => {
83
83
  // Cancel queries that might conflict
84
- await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
84
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current(activeSessionId) });
85
85
  for (const key of cancelQueryKeys) {
86
86
  await queryClient.cancelQueries({ queryKey: key });
87
87
  }
88
88
 
89
89
  // Snapshot previous user data
90
- const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
90
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
91
91
 
92
92
  // Apply optimistic update if provided
93
93
  if (previousUser && optimisticUpdate) {
94
94
  const updates = optimisticUpdate(previousUser, variables);
95
95
  const optimisticUser = { ...previousUser, ...updates };
96
96
 
97
- queryClient.setQueryData<User>(queryKeys.accounts.current(), optimisticUser);
97
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), optimisticUser);
98
98
 
99
99
  if (activeSessionId) {
100
100
  queryClient.setQueryData<User>(queryKeys.users.profile(activeSessionId), optimisticUser);
@@ -107,7 +107,7 @@ export function createProfileMutation<TVariables>(
107
107
  onError: (error, _variables, context) => {
108
108
  // Rollback optimistic update
109
109
  if (context?.previousUser) {
110
- queryClient.setQueryData(queryKeys.accounts.current(), context.previousUser);
110
+ queryClient.setQueryData(queryKeys.accounts.current(activeSessionId), context.previousUser);
111
111
  if (activeSessionId) {
112
112
  queryClient.setQueryData(queryKeys.users.profile(activeSessionId), context.previousUser);
113
113
  }
@@ -122,7 +122,7 @@ export function createProfileMutation<TVariables>(
122
122
 
123
123
  onSuccess: (data, variables) => {
124
124
  // Update cache with server response
125
- queryClient.setQueryData(queryKeys.accounts.current(), data);
125
+ queryClient.setQueryData(queryKeys.accounts.current(activeSessionId), data);
126
126
  if (activeSessionId) {
127
127
  queryClient.setQueryData(queryKeys.users.profile(activeSessionId), data);
128
128
  }
@@ -40,10 +40,10 @@ export const useUpdateProfile = () => {
40
40
  // Optimistic update
41
41
  onMutate: async (updates) => {
42
42
  // Cancel outgoing refetches
43
- await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
43
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current(activeSessionId) });
44
44
 
45
45
  // Snapshot previous value
46
- const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
46
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
47
47
 
48
48
  // Optimistically update
49
49
  if (previousUser) {
@@ -54,7 +54,7 @@ export const useUpdateProfile = () => {
54
54
  ? { ...previousUser.name, ...updates.name }
55
55
  : previousUser.name,
56
56
  };
57
- queryClient.setQueryData<User>(queryKeys.accounts.current(), optimisticUser);
57
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), optimisticUser);
58
58
 
59
59
  // Also update profile query if sessionId is available
60
60
  if (activeSessionId) {
@@ -74,9 +74,9 @@ export const useUpdateProfile = () => {
74
74
  return acc;
75
75
  }, {});
76
76
 
77
- const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
77
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
78
78
  if (current) {
79
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
79
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
80
80
  ...current,
81
81
  ...partialRollback,
82
82
  });
@@ -96,7 +96,7 @@ export const useUpdateProfile = () => {
96
96
  // On success, invalidate and refetch
97
97
  onSuccess: (data, updates) => {
98
98
  // Update cache with server response
99
- queryClient.setQueryData(queryKeys.accounts.current(), data);
99
+ queryClient.setQueryData(queryKeys.accounts.current(activeSessionId), data);
100
100
  if (activeSessionId) {
101
101
  queryClient.setQueryData(queryKeys.users.profile(activeSessionId), data);
102
102
  }
@@ -143,8 +143,8 @@ export const useUploadAvatar = () => {
143
143
  });
144
144
  },
145
145
  onMutate: async (file) => {
146
- await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
147
- const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
146
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current(activeSessionId) });
147
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
148
148
 
149
149
  // Optimistically set a temporary avatar (using file URI as placeholder)
150
150
  if (previousUser) {
@@ -152,7 +152,7 @@ export const useUploadAvatar = () => {
152
152
  ...previousUser,
153
153
  avatar: file.uri, // Temporary, will be replaced with fileId
154
154
  };
155
- queryClient.setQueryData<User>(queryKeys.accounts.current(), optimisticUser);
155
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), optimisticUser);
156
156
  if (activeSessionId) {
157
157
  queryClient.setQueryData<User>(queryKeys.users.profile(activeSessionId), optimisticUser);
158
158
  }
@@ -164,9 +164,9 @@ export const useUploadAvatar = () => {
164
164
  // Avatar upload only mutates the `avatar` field — restore only that key
165
165
  if (context?.previousUser) {
166
166
  const previousAvatar = context.previousUser.avatar;
167
- const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
167
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
168
168
  if (current) {
169
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
169
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
170
170
  ...current,
171
171
  avatar: previousAvatar,
172
172
  });
@@ -184,7 +184,7 @@ export const useUploadAvatar = () => {
184
184
  toast.error(error instanceof Error ? error.message : 'Failed to upload avatar');
185
185
  },
186
186
  onSuccess: (data) => {
187
- queryClient.setQueryData(queryKeys.accounts.current(), data);
187
+ queryClient.setQueryData(queryKeys.accounts.current(activeSessionId), data);
188
188
  if (activeSessionId) {
189
189
  queryClient.setQueryData(queryKeys.users.profile(activeSessionId), data);
190
190
  }
@@ -270,10 +270,10 @@ export const useUpdateAccountSettings = () => {
270
270
  },
271
271
  onMutate: async ({ updates }) => {
272
272
  await queryClient.cancelQueries({ queryKey: queryKeys.accounts.settings() });
273
- const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
273
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
274
274
 
275
275
  if (previousUser) {
276
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
276
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
277
277
  ...previousUser,
278
278
  privacySettings: {
279
279
  ...previousUser.privacySettings,
@@ -294,9 +294,9 @@ export const useUpdateAccountSettings = () => {
294
294
  return acc;
295
295
  }, {});
296
296
 
297
- const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
297
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
298
298
  if (current) {
299
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
299
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
300
300
  ...current,
301
301
  privacySettings: {
302
302
  ...(current.privacySettings ?? {}),
@@ -308,7 +308,7 @@ export const useUpdateAccountSettings = () => {
308
308
  toast.error(error instanceof Error ? error.message : 'Failed to update settings');
309
309
  },
310
310
  onSuccess: (data) => {
311
- queryClient.setQueryData(queryKeys.accounts.current(), data);
311
+ queryClient.setQueryData(queryKeys.accounts.current(activeSessionId), data);
312
312
 
313
313
  // Update authStore so frontend components see the changes immediately
314
314
  useAuthStore.getState().setUser(data);
@@ -328,7 +328,7 @@ export const useUpdateAccountSettings = () => {
328
328
  return {
329
329
  ...mutation,
330
330
  mutate: (updates: Partial<PrivacySettings>): void => {
331
- const currentUser = user ?? queryClient.getQueryData<User>(queryKeys.accounts.current());
331
+ const currentUser = user ?? queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
332
332
  if (!currentUser) {
333
333
  toast.error('Cannot update account settings: no current user');
334
334
  return;
@@ -336,7 +336,7 @@ export const useUpdateAccountSettings = () => {
336
336
  mutation.mutate({ updates, currentUser });
337
337
  },
338
338
  mutateAsync: async (updates: Partial<PrivacySettings>): Promise<User> => {
339
- const currentUser = user ?? queryClient.getQueryData<User>(queryKeys.accounts.current());
339
+ const currentUser = user ?? queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
340
340
  if (!currentUser) {
341
341
  throw new Error('Cannot update account settings: no current user');
342
342
  }
@@ -373,11 +373,11 @@ export const useUpdatePrivacySettings = () => {
373
373
 
374
374
  // Cancel outgoing refetches
375
375
  await queryClient.cancelQueries({ queryKey: queryKeys.privacy.settings(targetUserId) });
376
- await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
376
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current(activeSessionId) });
377
377
 
378
378
  // Snapshot previous values
379
379
  const previousPrivacySettings = queryClient.getQueryData(queryKeys.privacy.settings(targetUserId));
380
- const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
380
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
381
381
 
382
382
  // Optimistically update privacy settings
383
383
  if (previousPrivacySettings) {
@@ -389,7 +389,7 @@ export const useUpdatePrivacySettings = () => {
389
389
 
390
390
  // Also update user query if available
391
391
  if (previousUser) {
392
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
392
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
393
393
  ...previousUser,
394
394
  privacySettings: {
395
395
  ...previousUser.privacySettings,
@@ -431,9 +431,9 @@ export const useUpdatePrivacySettings = () => {
431
431
  (acc as Record<string, unknown>)[key as string] = previousPrivacy[key as string];
432
432
  return acc;
433
433
  }, {});
434
- const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
434
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
435
435
  if (current) {
436
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
436
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
437
437
  ...current,
438
438
  privacySettings: {
439
439
  ...(current.privacySettings ?? {}),
@@ -479,7 +479,7 @@ export const useUpdatePrivacySettings = () => {
479
479
  }),
480
480
  );
481
481
 
482
- const currentUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
482
+ const currentUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
483
483
  if (currentUser) {
484
484
  const updatedUser: User = {
485
485
  ...currentUser,
@@ -489,7 +489,7 @@ export const useUpdatePrivacySettings = () => {
489
489
  ...incoming,
490
490
  },
491
491
  };
492
- queryClient.setQueryData<User>(queryKeys.accounts.current(), updatedUser);
492
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), updatedUser);
493
493
  useAuthStore.getState().setUser(updatedUser);
494
494
  }
495
495
  // Deliberately NOT invalidating any queries here. invalidateAccountQueries
@@ -538,11 +538,11 @@ export const useUpdateNotificationPreferences = () => {
538
538
  );
539
539
  },
540
540
  onMutate: async (preferences) => {
541
- await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
542
- const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
541
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current(activeSessionId) });
542
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
543
543
 
544
544
  if (previousUser) {
545
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
545
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
546
546
  ...previousUser,
547
547
  notificationPreferences: {
548
548
  ...previousUser.notificationPreferences,
@@ -555,9 +555,9 @@ export const useUpdateNotificationPreferences = () => {
555
555
  },
556
556
  onError: (error, _preferences, context) => {
557
557
  if (context?.previousUser) {
558
- const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
558
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
559
559
  if (current) {
560
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
560
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
561
561
  ...current,
562
562
  notificationPreferences: context.previousUser.notificationPreferences,
563
563
  });
@@ -570,7 +570,7 @@ export const useUpdateNotificationPreferences = () => {
570
570
  );
571
571
  },
572
572
  onSuccess: (data) => {
573
- queryClient.setQueryData(queryKeys.accounts.current(), data);
573
+ queryClient.setQueryData(queryKeys.accounts.current(activeSessionId), data);
574
574
  useAuthStore.getState().setUser(data);
575
575
  invalidateAccountQueries(queryClient);
576
576
  },
@@ -596,11 +596,11 @@ export const useUpdateUserPreferences = () => {
596
596
  );
597
597
  },
598
598
  onMutate: async (preferences) => {
599
- await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current() });
600
- const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
599
+ await queryClient.cancelQueries({ queryKey: queryKeys.accounts.current(activeSessionId) });
600
+ const previousUser = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
601
601
 
602
602
  if (previousUser) {
603
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
603
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
604
604
  ...previousUser,
605
605
  userPreferences: {
606
606
  ...previousUser.userPreferences,
@@ -613,9 +613,9 @@ export const useUpdateUserPreferences = () => {
613
613
  },
614
614
  onError: (error, _preferences, context) => {
615
615
  if (context?.previousUser) {
616
- const current = queryClient.getQueryData<User>(queryKeys.accounts.current());
616
+ const current = queryClient.getQueryData<User>(queryKeys.accounts.current(activeSessionId));
617
617
  if (current) {
618
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
618
+ queryClient.setQueryData<User>(queryKeys.accounts.current(activeSessionId), {
619
619
  ...current,
620
620
  userPreferences: context.previousUser.userPreferences,
621
621
  });
@@ -624,7 +624,7 @@ export const useUpdateUserPreferences = () => {
624
624
  toast.error(error instanceof Error ? error.message : 'Failed to update preferences');
625
625
  },
626
626
  onSuccess: (data) => {
627
- queryClient.setQueryData(queryKeys.accounts.current(), data);
627
+ queryClient.setQueryData(queryKeys.accounts.current(activeSessionId), data);
628
628
  useAuthStore.getState().setUser(data);
629
629
  invalidateAccountQueries(queryClient);
630
630
  },
@@ -17,12 +17,12 @@ export const useSwitchSession = () => {
17
17
  mutationFn: async (sessionId: string) => {
18
18
  return await switchSession(sessionId);
19
19
  },
20
- onSuccess: (user) => {
20
+ onSuccess: (user, sessionId) => {
21
21
  // Invalidate all session queries
22
22
  invalidateSessionQueries(queryClient);
23
23
 
24
24
  // Update current user query
25
- queryClient.setQueryData(queryKeys.accounts.current(), user);
25
+ queryClient.setQueryData(queryKeys.accounts.current(sessionId), user);
26
26
 
27
27
  // Invalidate account queries
28
28
  queryClient.invalidateQueries({ queryKey: queryKeys.accounts.all });