@oxyhq/services 5.17.17 → 5.17.18

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 (403) hide show
  1. package/README.md +32 -38
  2. package/lib/commonjs/core/CrossDomainAuth.js +277 -0
  3. package/lib/commonjs/core/CrossDomainAuth.js.map +1 -0
  4. package/lib/commonjs/core/HttpService.js +82 -15
  5. package/lib/commonjs/core/HttpService.js.map +1 -1
  6. package/lib/commonjs/core/OxyServices.base.js +11 -3
  7. package/lib/commonjs/core/OxyServices.base.js.map +1 -1
  8. package/lib/commonjs/core/OxyServices.js +4 -1
  9. package/lib/commonjs/core/OxyServices.js.map +1 -1
  10. package/lib/commonjs/core/index.js +30 -0
  11. package/lib/commonjs/core/index.js.map +1 -1
  12. package/lib/commonjs/core/mixins/OxyServices.assets.js +16 -3
  13. package/lib/commonjs/core/mixins/OxyServices.assets.js.map +1 -1
  14. package/lib/commonjs/core/mixins/OxyServices.auth.js +73 -32
  15. package/lib/commonjs/core/mixins/OxyServices.auth.js.map +1 -1
  16. package/lib/commonjs/core/mixins/OxyServices.fedcm.js +289 -0
  17. package/lib/commonjs/core/mixins/OxyServices.fedcm.js.map +1 -0
  18. package/lib/commonjs/core/mixins/OxyServices.popup.js +352 -0
  19. package/lib/commonjs/core/mixins/OxyServices.popup.js.map +1 -0
  20. package/lib/commonjs/core/mixins/OxyServices.redirect.js +378 -0
  21. package/lib/commonjs/core/mixins/OxyServices.redirect.js.map +1 -0
  22. package/lib/commonjs/core/mixins/OxyServices.user.js +35 -24
  23. package/lib/commonjs/core/mixins/OxyServices.user.js.map +1 -1
  24. package/lib/commonjs/core/mixins/index.js +27 -15
  25. package/lib/commonjs/core/mixins/index.js.map +1 -1
  26. package/lib/commonjs/crypto/index.js +30 -0
  27. package/lib/commonjs/crypto/index.js.map +1 -1
  28. package/lib/commonjs/crypto/keyManager.js +902 -0
  29. package/lib/commonjs/crypto/keyManager.js.map +1 -0
  30. package/lib/commonjs/crypto/polyfill.js +14 -5
  31. package/lib/commonjs/crypto/polyfill.js.map +1 -1
  32. package/lib/commonjs/crypto/recoveryPhrase.js +152 -0
  33. package/lib/commonjs/crypto/recoveryPhrase.js.map +1 -0
  34. package/lib/commonjs/crypto/signatureService.js +289 -0
  35. package/lib/commonjs/crypto/signatureService.js.map +1 -0
  36. package/lib/commonjs/i18n/locales/en-US.json +1 -1
  37. package/lib/commonjs/index.js +40 -26
  38. package/lib/commonjs/index.js.map +1 -1
  39. package/lib/commonjs/models/interfaces.js +0 -15
  40. package/lib/commonjs/models/interfaces.js.map +1 -1
  41. package/lib/commonjs/ui/components/BottomSheetRouter.js +9 -1
  42. package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
  43. package/lib/commonjs/ui/components/Icon.js.map +1 -1
  44. package/lib/commonjs/ui/components/IconButton/utils.js.map +1 -1
  45. package/lib/commonjs/ui/components/OxyProvider.js +41 -11
  46. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  47. package/lib/commonjs/ui/components/TextField/Adornment/utils.js.map +1 -1
  48. package/lib/commonjs/ui/components/TextField/helpers.js.map +1 -1
  49. package/lib/commonjs/ui/components/TouchableRipple/utils.js.map +1 -1
  50. package/lib/commonjs/ui/components/Typography/AnimatedText.js.map +1 -1
  51. package/lib/commonjs/ui/context/OxyContext.js +110 -199
  52. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  53. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +150 -19
  54. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  55. package/lib/commonjs/ui/context/hooks/useSessionManagement.js +279 -0
  56. package/lib/commonjs/ui/context/hooks/useSessionManagement.js.map +1 -0
  57. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +79 -72
  58. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  59. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +38 -51
  60. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  61. package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js +3 -3
  62. package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js.map +1 -1
  63. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +18 -12
  64. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
  65. package/lib/commonjs/ui/hooks/useProfileEditing.js +3 -5
  66. package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
  67. package/lib/commonjs/ui/hooks/useSessionManagement.js +4 -8
  68. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  69. package/lib/commonjs/ui/hooks/useSessionSocket.js +162 -315
  70. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  71. package/lib/commonjs/ui/hooks/useStorage.js +24 -58
  72. package/lib/commonjs/ui/hooks/useStorage.js.map +1 -1
  73. package/lib/commonjs/ui/index.js +50 -21
  74. package/lib/commonjs/ui/index.js.map +1 -1
  75. package/lib/commonjs/ui/navigation/routes.js +5 -1
  76. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  77. package/lib/commonjs/ui/screens/AccountCenterScreen.js +2 -2
  78. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  79. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  80. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +29 -24
  81. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  82. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +3 -3
  83. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  84. package/lib/commonjs/ui/screens/OxyAuthScreen.js +134 -66
  85. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  86. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +6 -13
  87. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  88. package/lib/commonjs/ui/stores/accountStore.js +2 -4
  89. package/lib/commonjs/ui/stores/accountStore.js.map +1 -1
  90. package/lib/commonjs/ui/stores/authStore.js +45 -32
  91. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  92. package/lib/commonjs/ui/styles/spacing.js +54 -2
  93. package/lib/commonjs/ui/styles/spacing.js.map +1 -1
  94. package/lib/commonjs/ui/utils/avatarUtils.js +37 -41
  95. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  96. package/lib/commonjs/ui/utils/storageHelpers.js.map +1 -1
  97. package/lib/commonjs/utils/errorUtils.js +13 -0
  98. package/lib/commonjs/utils/errorUtils.js.map +1 -1
  99. package/lib/commonjs/utils/validationUtils.js +15 -1
  100. package/lib/commonjs/utils/validationUtils.js.map +1 -1
  101. package/lib/module/core/CrossDomainAuth.js +271 -0
  102. package/lib/module/core/CrossDomainAuth.js.map +1 -0
  103. package/lib/module/core/HttpService.js +82 -15
  104. package/lib/module/core/HttpService.js.map +1 -1
  105. package/lib/module/core/OxyServices.base.js +11 -4
  106. package/lib/module/core/OxyServices.base.js.map +1 -1
  107. package/lib/module/core/OxyServices.js +4 -1
  108. package/lib/module/core/OxyServices.js.map +1 -1
  109. package/lib/module/core/index.js +6 -1
  110. package/lib/module/core/index.js.map +1 -1
  111. package/lib/module/core/mixins/OxyServices.assets.js +16 -3
  112. package/lib/module/core/mixins/OxyServices.assets.js.map +1 -1
  113. package/lib/module/core/mixins/OxyServices.auth.js +73 -32
  114. package/lib/module/core/mixins/OxyServices.auth.js.map +1 -1
  115. package/lib/module/core/mixins/OxyServices.fedcm.js +286 -0
  116. package/lib/module/core/mixins/OxyServices.fedcm.js.map +1 -0
  117. package/lib/module/core/mixins/OxyServices.popup.js +349 -0
  118. package/lib/module/core/mixins/OxyServices.popup.js.map +1 -0
  119. package/lib/module/core/mixins/OxyServices.redirect.js +375 -0
  120. package/lib/module/core/mixins/OxyServices.redirect.js.map +1 -0
  121. package/lib/module/core/mixins/OxyServices.user.js +35 -24
  122. package/lib/module/core/mixins/OxyServices.user.js.map +1 -1
  123. package/lib/module/core/mixins/index.js +15 -3
  124. package/lib/module/core/mixins/index.js.map +1 -1
  125. package/lib/module/crypto/index.js +8 -4
  126. package/lib/module/crypto/index.js.map +1 -1
  127. package/lib/module/crypto/keyManager.js +899 -0
  128. package/lib/module/crypto/keyManager.js.map +1 -0
  129. package/lib/module/crypto/polyfill.js +6 -5
  130. package/lib/module/crypto/polyfill.js.map +1 -1
  131. package/lib/module/crypto/recoveryPhrase.js +147 -0
  132. package/lib/module/crypto/recoveryPhrase.js.map +1 -0
  133. package/lib/module/crypto/signatureService.js +286 -0
  134. package/lib/module/crypto/signatureService.js.map +1 -0
  135. package/lib/module/i18n/locales/en-US.json +1 -1
  136. package/lib/module/index.js +6 -9
  137. package/lib/module/index.js.map +1 -1
  138. package/lib/module/models/interfaces.js +0 -15
  139. package/lib/module/models/interfaces.js.map +1 -1
  140. package/lib/module/ui/components/BottomSheetRouter.js +6 -2
  141. package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
  142. package/lib/module/ui/components/Icon.js.map +1 -1
  143. package/lib/module/ui/components/IconButton/utils.js.map +1 -1
  144. package/lib/module/ui/components/OxyProvider.js +41 -11
  145. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  146. package/lib/module/ui/components/TextField/Adornment/utils.js.map +1 -1
  147. package/lib/module/ui/components/TextField/helpers.js.map +1 -1
  148. package/lib/module/ui/components/TouchableRipple/utils.js.map +1 -1
  149. package/lib/module/ui/components/Typography/AnimatedText.js.map +1 -1
  150. package/lib/module/ui/context/OxyContext.js +112 -191
  151. package/lib/module/ui/context/OxyContext.js.map +1 -1
  152. package/lib/module/ui/context/hooks/useAuthOperations.js +150 -19
  153. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  154. package/lib/module/ui/context/hooks/useSessionManagement.js +274 -0
  155. package/lib/module/ui/context/hooks/useSessionManagement.js.map +1 -0
  156. package/lib/module/ui/hooks/mutations/useAccountMutations.js +80 -72
  157. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  158. package/lib/module/ui/hooks/queries/useAccountQueries.js +31 -44
  159. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  160. package/lib/module/ui/hooks/queries/useSecurityQueries.js +1 -1
  161. package/lib/module/ui/hooks/queries/useSecurityQueries.js.map +1 -1
  162. package/lib/module/ui/hooks/queries/useServicesQueries.js +13 -7
  163. package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
  164. package/lib/module/ui/hooks/useProfileEditing.js +3 -5
  165. package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
  166. package/lib/module/ui/hooks/useSessionManagement.js +4 -8
  167. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  168. package/lib/module/ui/hooks/useSessionSocket.js +162 -315
  169. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  170. package/lib/module/ui/hooks/useStorage.js +25 -59
  171. package/lib/module/ui/hooks/useStorage.js.map +1 -1
  172. package/lib/module/ui/index.js +15 -10
  173. package/lib/module/ui/index.js.map +1 -1
  174. package/lib/module/ui/navigation/routes.js +5 -1
  175. package/lib/module/ui/navigation/routes.js.map +1 -1
  176. package/lib/module/ui/screens/AccountCenterScreen.js +2 -2
  177. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  178. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  179. package/lib/module/ui/screens/AccountSettingsScreen.js +29 -24
  180. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  181. package/lib/module/ui/screens/AccountSwitcherScreen.js +3 -3
  182. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  183. package/lib/module/ui/screens/OxyAuthScreen.js +135 -68
  184. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  185. package/lib/module/ui/screens/PrivacySettingsScreen.js +6 -13
  186. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  187. package/lib/module/ui/stores/accountStore.js +2 -4
  188. package/lib/module/ui/stores/accountStore.js.map +1 -1
  189. package/lib/module/ui/stores/authStore.js +45 -32
  190. package/lib/module/ui/stores/authStore.js.map +1 -1
  191. package/lib/module/ui/styles/spacing.js +6 -2
  192. package/lib/module/ui/styles/spacing.js.map +1 -1
  193. package/lib/module/ui/utils/avatarUtils.js +37 -40
  194. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  195. package/lib/module/ui/utils/storageHelpers.js.map +1 -1
  196. package/lib/module/utils/errorUtils.js +7 -0
  197. package/lib/module/utils/errorUtils.js.map +1 -1
  198. package/lib/module/utils/validationUtils.js +13 -0
  199. package/lib/module/utils/validationUtils.js.map +1 -1
  200. package/lib/typescript/core/CrossDomainAuth.d.ts +161 -0
  201. package/lib/typescript/core/CrossDomainAuth.d.ts.map +1 -0
  202. package/lib/typescript/core/HttpService.d.ts +1 -1
  203. package/lib/typescript/core/HttpService.d.ts.map +1 -1
  204. package/lib/typescript/core/OxyServices.base.d.ts +0 -6
  205. package/lib/typescript/core/OxyServices.base.d.ts.map +1 -1
  206. package/lib/typescript/core/OxyServices.d.ts +5 -36
  207. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  208. package/lib/typescript/core/index.d.ts +4 -0
  209. package/lib/typescript/core/index.d.ts.map +1 -1
  210. package/lib/typescript/core/mixins/OxyServices.analytics.d.ts.map +1 -1
  211. package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
  212. package/lib/typescript/core/mixins/OxyServices.auth.d.ts +40 -20
  213. package/lib/typescript/core/mixins/OxyServices.auth.d.ts.map +1 -1
  214. package/lib/typescript/core/mixins/OxyServices.developer.d.ts.map +1 -1
  215. package/lib/typescript/core/mixins/OxyServices.devices.d.ts.map +1 -1
  216. package/lib/typescript/core/mixins/OxyServices.fedcm.d.ts +195 -0
  217. package/lib/typescript/core/mixins/OxyServices.fedcm.d.ts.map +1 -0
  218. package/lib/typescript/core/mixins/OxyServices.karma.d.ts.map +1 -1
  219. package/lib/typescript/core/mixins/OxyServices.language.d.ts.map +1 -1
  220. package/lib/typescript/core/mixins/OxyServices.location.d.ts.map +1 -1
  221. package/lib/typescript/core/mixins/OxyServices.payment.d.ts.map +1 -1
  222. package/lib/typescript/core/mixins/OxyServices.popup.d.ts +206 -0
  223. package/lib/typescript/core/mixins/OxyServices.popup.d.ts.map +1 -0
  224. package/lib/typescript/core/mixins/OxyServices.privacy.d.ts.map +1 -1
  225. package/lib/typescript/core/mixins/OxyServices.redirect.d.ts +246 -0
  226. package/lib/typescript/core/mixins/OxyServices.redirect.d.ts.map +1 -0
  227. package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
  228. package/lib/typescript/core/mixins/OxyServices.user.d.ts +6 -4
  229. package/lib/typescript/core/mixins/OxyServices.user.d.ts.map +1 -1
  230. package/lib/typescript/core/mixins/OxyServices.utility.d.ts.map +1 -1
  231. package/lib/typescript/core/mixins/index.d.ts +220 -8
  232. package/lib/typescript/core/mixins/index.d.ts.map +1 -1
  233. package/lib/typescript/crypto/index.d.ts +6 -3
  234. package/lib/typescript/crypto/index.d.ts.map +1 -1
  235. package/lib/typescript/crypto/keyManager.d.ts +190 -0
  236. package/lib/typescript/crypto/keyManager.d.ts.map +1 -0
  237. package/lib/typescript/crypto/polyfill.d.ts +4 -3
  238. package/lib/typescript/crypto/polyfill.d.ts.map +1 -1
  239. package/lib/typescript/crypto/recoveryPhrase.d.ts +59 -0
  240. package/lib/typescript/crypto/recoveryPhrase.d.ts.map +1 -0
  241. package/lib/typescript/crypto/signatureService.d.ts +87 -0
  242. package/lib/typescript/crypto/signatureService.d.ts.map +1 -0
  243. package/lib/typescript/index.d.ts +5 -6
  244. package/lib/typescript/index.d.ts.map +1 -1
  245. package/lib/typescript/models/interfaces.d.ts +2 -14
  246. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  247. package/lib/typescript/models/session.d.ts +0 -9
  248. package/lib/typescript/models/session.d.ts.map +1 -1
  249. package/lib/typescript/types/bip39.d.ts +32 -0
  250. package/lib/typescript/ui/components/BottomSheetRouter.d.ts +5 -0
  251. package/lib/typescript/ui/components/BottomSheetRouter.d.ts.map +1 -1
  252. package/lib/typescript/ui/components/IconButton/utils.d.ts +1 -1
  253. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  254. package/lib/typescript/ui/components/TextField/Addons/Outline.d.ts +2 -2
  255. package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts +1 -1
  256. package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts.map +1 -1
  257. package/lib/typescript/ui/components/TextField/helpers.d.ts +8 -8
  258. package/lib/typescript/ui/components/TextField/types.d.ts +1 -0
  259. package/lib/typescript/ui/components/TextField/types.d.ts.map +1 -1
  260. package/lib/typescript/ui/components/types.d.ts +4 -0
  261. package/lib/typescript/ui/components/types.d.ts.map +1 -1
  262. package/lib/typescript/ui/context/OxyContext.d.ts +57 -3
  263. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  264. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +10 -3
  265. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  266. package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts +41 -0
  267. package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts.map +1 -0
  268. package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  269. package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  270. package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  271. package/lib/typescript/ui/hooks/useProfileEditing.d.ts.map +1 -1
  272. package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +1 -1
  273. package/lib/typescript/ui/hooks/useSessionSocket.d.ts +1 -2
  274. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  275. package/lib/typescript/ui/hooks/useStorage.d.ts +3 -9
  276. package/lib/typescript/ui/hooks/useStorage.d.ts.map +1 -1
  277. package/lib/typescript/ui/index.d.ts +6 -2
  278. package/lib/typescript/ui/index.d.ts.map +1 -1
  279. package/lib/typescript/ui/navigation/routes.d.ts +1 -1
  280. package/lib/typescript/ui/navigation/routes.d.ts.map +1 -1
  281. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  282. package/lib/typescript/ui/screens/OxyAuthScreen.d.ts +1 -1
  283. package/lib/typescript/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  284. package/lib/typescript/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  285. package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -1
  286. package/lib/typescript/ui/stores/authStore.d.ts +8 -7
  287. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  288. package/lib/typescript/ui/styles/spacing.d.ts +5 -0
  289. package/lib/typescript/ui/styles/spacing.d.ts.map +1 -1
  290. package/lib/typescript/ui/types/navigation.d.ts +2 -1
  291. package/lib/typescript/ui/types/navigation.d.ts.map +1 -1
  292. package/lib/typescript/ui/utils/avatarUtils.d.ts +2 -13
  293. package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
  294. package/lib/typescript/ui/utils/storageHelpers.d.ts +0 -3
  295. package/lib/typescript/ui/utils/storageHelpers.d.ts.map +1 -1
  296. package/lib/typescript/utils/errorUtils.d.ts +6 -0
  297. package/lib/typescript/utils/errorUtils.d.ts.map +1 -1
  298. package/lib/typescript/utils/validationUtils.d.ts +8 -0
  299. package/lib/typescript/utils/validationUtils.d.ts.map +1 -1
  300. package/package.json +8 -7
  301. package/src/core/CrossDomainAuth.ts +307 -0
  302. package/src/core/HttpService.ts +99 -16
  303. package/src/core/OxyServices.base.ts +20 -3
  304. package/src/core/OxyServices.ts +7 -3
  305. package/src/core/index.ts +9 -1
  306. package/src/core/mixins/OxyServices.assets.ts +14 -3
  307. package/src/core/mixins/OxyServices.auth.ts +105 -36
  308. package/src/core/mixins/OxyServices.fedcm.ts +315 -0
  309. package/src/core/mixins/OxyServices.popup.ts +402 -0
  310. package/src/core/mixins/OxyServices.redirect.ts +397 -0
  311. package/src/core/mixins/OxyServices.user.ts +39 -24
  312. package/src/core/mixins/index.ts +19 -3
  313. package/src/crypto/index.ts +16 -5
  314. package/src/crypto/keyManager.ts +966 -0
  315. package/src/crypto/polyfill.ts +6 -5
  316. package/src/crypto/recoveryPhrase.ts +166 -0
  317. package/src/crypto/signatureService.ts +323 -0
  318. package/src/i18n/locales/en-US.json +1 -1
  319. package/src/index.ts +19 -15
  320. package/src/models/interfaces.ts +4 -16
  321. package/src/models/session.ts +2 -11
  322. package/src/types/bip39.d.ts +32 -0
  323. package/src/ui/components/BottomSheetRouter.tsx +6 -1
  324. package/src/ui/components/Icon.tsx +1 -1
  325. package/src/ui/components/IconButton/utils.ts +1 -1
  326. package/src/ui/components/OxyProvider.tsx +44 -12
  327. package/src/ui/components/TextField/Addons/Outline.tsx +2 -2
  328. package/src/ui/components/TextField/Adornment/utils.ts +2 -2
  329. package/src/ui/components/TextField/helpers.tsx +10 -10
  330. package/src/ui/components/TextField/types.tsx +1 -1
  331. package/src/ui/components/TouchableRipple/utils.ts +2 -2
  332. package/src/ui/components/Typography/AnimatedText.tsx +2 -2
  333. package/src/ui/components/types.tsx +6 -0
  334. package/src/ui/context/OxyContext.tsx +173 -195
  335. package/src/ui/context/hooks/useAuthOperations.ts +177 -36
  336. package/src/ui/context/hooks/useSessionManagement.ts +399 -0
  337. package/src/ui/hooks/mutations/useAccountMutations.ts +83 -76
  338. package/src/ui/hooks/queries/useAccountQueries.ts +29 -35
  339. package/src/ui/hooks/queries/useSecurityQueries.ts +1 -1
  340. package/src/ui/hooks/queries/useServicesQueries.ts +14 -6
  341. package/src/ui/hooks/useProfileEditing.ts +3 -3
  342. package/src/ui/hooks/useSessionManagement.ts +5 -10
  343. package/src/ui/hooks/useSessionSocket.ts +46 -175
  344. package/src/ui/hooks/useStorage.ts +24 -76
  345. package/src/ui/index.ts +22 -13
  346. package/src/ui/navigation/routes.ts +6 -2
  347. package/src/ui/screens/AccountCenterScreen.tsx +2 -2
  348. package/src/ui/screens/AccountOverviewScreen.tsx +1 -1
  349. package/src/ui/screens/AccountSettingsScreen.tsx +34 -37
  350. package/src/ui/screens/AccountSwitcherScreen.tsx +4 -4
  351. package/src/ui/screens/OxyAuthScreen.tsx +138 -64
  352. package/src/ui/screens/PrivacySettingsScreen.tsx +6 -12
  353. package/src/ui/stores/accountStore.ts +1 -11
  354. package/src/ui/stores/authStore.ts +43 -44
  355. package/src/ui/styles/spacing.ts +15 -2
  356. package/src/ui/types/navigation.ts +2 -2
  357. package/src/ui/utils/avatarUtils.ts +39 -46
  358. package/src/ui/utils/storageHelpers.ts +0 -4
  359. package/src/utils/__tests__/validationUtils.test.ts +16 -1
  360. package/src/utils/errorUtils.ts +8 -1
  361. package/src/utils/validationUtils.ts +12 -0
  362. package/lib/commonjs/core/services/SessionService.js +0 -163
  363. package/lib/commonjs/core/services/SessionService.js.map +0 -1
  364. package/lib/commonjs/core/services/TokenService.js +0 -220
  365. package/lib/commonjs/core/services/TokenService.js.map +0 -1
  366. package/lib/commonjs/crypto/types.js +0 -2
  367. package/lib/commonjs/crypto/types.js.map +0 -1
  368. package/lib/commonjs/ui/context/OxyContextBase.js +0 -21
  369. package/lib/commonjs/ui/context/OxyContextBase.js.map +0 -1
  370. package/lib/commonjs/ui/context/hooks/useStorage.js +0 -79
  371. package/lib/commonjs/ui/context/hooks/useStorage.js.map +0 -1
  372. package/lib/commonjs/ui/hooks/useAvatarPicker.js +0 -56
  373. package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +0 -1
  374. package/lib/module/core/services/SessionService.js +0 -159
  375. package/lib/module/core/services/SessionService.js.map +0 -1
  376. package/lib/module/core/services/TokenService.js +0 -217
  377. package/lib/module/core/services/TokenService.js.map +0 -1
  378. package/lib/module/crypto/types.js +0 -2
  379. package/lib/module/crypto/types.js.map +0 -1
  380. package/lib/module/ui/context/OxyContextBase.js +0 -16
  381. package/lib/module/ui/context/OxyContextBase.js.map +0 -1
  382. package/lib/module/ui/context/hooks/useStorage.js +0 -74
  383. package/lib/module/ui/context/hooks/useStorage.js.map +0 -1
  384. package/lib/module/ui/hooks/useAvatarPicker.js +0 -50
  385. package/lib/module/ui/hooks/useAvatarPicker.js.map +0 -1
  386. package/lib/typescript/core/services/SessionService.d.ts +0 -78
  387. package/lib/typescript/core/services/SessionService.d.ts.map +0 -1
  388. package/lib/typescript/core/services/TokenService.d.ts +0 -72
  389. package/lib/typescript/core/services/TokenService.d.ts.map +0 -1
  390. package/lib/typescript/crypto/types.d.ts +0 -22
  391. package/lib/typescript/crypto/types.d.ts.map +0 -1
  392. package/lib/typescript/ui/context/OxyContextBase.d.ts +0 -63
  393. package/lib/typescript/ui/context/OxyContextBase.d.ts.map +0 -1
  394. package/lib/typescript/ui/context/hooks/useStorage.d.ts +0 -22
  395. package/lib/typescript/ui/context/hooks/useStorage.d.ts.map +0 -1
  396. package/lib/typescript/ui/hooks/useAvatarPicker.d.ts +0 -19
  397. package/lib/typescript/ui/hooks/useAvatarPicker.d.ts.map +0 -1
  398. package/src/core/services/SessionService.ts +0 -173
  399. package/src/core/services/TokenService.ts +0 -237
  400. package/src/crypto/types.ts +0 -23
  401. package/src/ui/context/OxyContextBase.tsx +0 -78
  402. package/src/ui/context/hooks/useStorage.ts +0 -104
  403. package/src/ui/hooks/useAvatarPicker.ts +0 -61
@@ -22,6 +22,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
22
22
  import { toast } from '../../lib/sonner';
23
23
  import { fontFamilies } from '../styles/fonts';
24
24
  import { confirmAction } from '../utils/confirmAction';
25
+ import { useAuthStore } from '../stores/authStore';
25
26
  import { Header, GroupedSection, Section } from '../components';
26
27
  import { useI18n } from '../hooks/useI18n';
27
28
  import { useThemeStyles } from '../hooks/useThemeStyles';
@@ -76,9 +77,13 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
76
77
  const normalizedTheme = normalizeTheme(theme);
77
78
 
78
79
  // Use TanStack Query for user data
79
- const { data: finalUser, isLoading: userLoading } = useCurrentUser({ enabled: isAuthenticated });
80
+ const { data: user, isLoading: userLoading } = useCurrentUser({ enabled: isAuthenticated });
80
81
  const updateProfileMutation = useUpdateProfile();
81
82
  const uploadAvatarMutation = useUploadAvatar();
83
+
84
+ // Fallback to store for backward compatibility
85
+ const userFromStore = useAuthStore((state) => state.user);
86
+ const finalUser = user || userFromStore;
82
87
  const [isLoading, setIsLoading] = useState(false);
83
88
  const isSaving = updateProfileMutation.isPending;
84
89
  const isUpdatingAvatar = uploadAvatarMutation.isPending;
@@ -215,10 +220,9 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
215
220
  // Only reset all fields if it's a new user or first load
216
221
  // Skip reset if it's just an avatar update
217
222
  if (shouldInitialize && !isAvatarOnlyUpdate) {
218
- // Prioritize name.full over name.first for display name
219
223
  const userDisplayName = typeof finalUser.name === 'string'
220
224
  ? finalUser.name
221
- : finalUser.name?.full || finalUser.name?.first || '';
225
+ : finalUser.name?.first || finalUser.name?.full || '';
222
226
  const userLastName = typeof finalUser.name === 'object' ? finalUser.name?.last || '' : '';
223
227
  setDisplayName(userDisplayName);
224
228
  setLastName(userLastName);
@@ -363,15 +367,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
363
367
  try {
364
368
  switch (field) {
365
369
  case 'displayName':
366
- // Send both first/last AND full name for proper synchronization
367
- const fullName = [tempDisplayName, tempLastName].filter(Boolean).join(' ').trim() || tempDisplayName;
368
- await updateProfileMutation.mutateAsync({
369
- name: {
370
- first: tempDisplayName,
371
- last: tempLastName,
372
- full: fullName
373
- }
374
- });
370
+ await updateProfileMutation.mutateAsync({ name: { first: tempDisplayName, last: tempLastName } });
375
371
  setDisplayName(tempDisplayName);
376
372
  setLastName(tempLastName);
377
373
  break;
@@ -476,12 +472,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
476
472
 
477
473
  // Handle name field
478
474
  if (displayName || lastName) {
479
- const fullName = [displayName, lastName].filter(Boolean).join(' ').trim() || displayName;
480
- updates.name = {
481
- first: displayName,
482
- last: lastName,
483
- full: fullName
484
- };
475
+ updates.name = { first: displayName, last: lastName };
485
476
  }
486
477
 
487
478
  // Handle avatar
@@ -523,40 +514,46 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
523
514
  const handleOpenLinksModal = useCallback(() => setShowEditLinksModal(true), []);
524
515
 
525
516
  // Handler to refresh data after modal saves
526
- // Note: Query will automatically refetch after mutations invalidate it
517
+ // Note: Access user directly from store when invoked to get latest value,
518
+ // not from closure which may be stale after modal saves update the backend
527
519
  const handleModalSave = useCallback(() => {
520
+ // Get fresh user data from store to ensure we have the latest values
521
+ // after the modal's save operation updates the backend
522
+ // Read from store directly (not from closure) to avoid stale data
523
+ const currentUser = useAuthStore.getState().user;
524
+
528
525
  // Reload user data to reflect changes
529
- if (finalUser) {
530
- const userDisplayName = typeof finalUser.name === 'string'
531
- ? finalUser.name
532
- : finalUser.name?.first || finalUser.name?.full || '';
533
- const userLastName = typeof finalUser.name === 'object' ? finalUser.name?.last || '' : '';
526
+ if (currentUser) {
527
+ const userDisplayName = typeof currentUser.name === 'string'
528
+ ? currentUser.name
529
+ : currentUser.name?.first || currentUser.name?.full || '';
530
+ const userLastName = typeof currentUser.name === 'object' ? currentUser.name?.last || '' : '';
534
531
  setDisplayName(userDisplayName);
535
532
  setLastName(userLastName);
536
- setUsername(finalUser.username || '');
537
- setEmail(finalUser.email || '');
538
- setBio(finalUser.bio || '');
533
+ setUsername(currentUser.username || '');
534
+ setEmail(currentUser.email || '');
535
+ setBio(currentUser.bio || '');
539
536
 
540
537
  // Reload locations and links
541
- if (finalUser.locations && Array.isArray(finalUser.locations)) {
542
- setLocations(finalUser.locations.map((loc: any, index: number) => ({
538
+ if (currentUser.locations && Array.isArray(currentUser.locations)) {
539
+ setLocations(currentUser.locations.map((loc, index) => ({
543
540
  id: loc.id || `existing-${index}`,
544
541
  name: loc.name,
545
542
  label: loc.label,
546
543
  coordinates: loc.coordinates
547
544
  })));
548
- } else if (finalUser.location) {
545
+ } else if (currentUser.location) {
549
546
  setLocations([{
550
547
  id: 'existing-0',
551
- name: finalUser.location,
548
+ name: currentUser.location,
552
549
  label: 'Location'
553
550
  }]);
554
551
  } else {
555
552
  setLocations([]);
556
553
  }
557
554
 
558
- if (finalUser.linksMetadata && Array.isArray(finalUser.linksMetadata)) {
559
- setLinksMetadata(finalUser.linksMetadata.map((link: any, index: number) => ({
555
+ if (currentUser.linksMetadata && Array.isArray(currentUser.linksMetadata)) {
556
+ setLinksMetadata(currentUser.linksMetadata.map((link, index) => ({
560
557
  ...link,
561
558
  id: link.id || `existing-${index}`
562
559
  })));
@@ -564,7 +561,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
564
561
  setLinksMetadata([]);
565
562
  }
566
563
  }
567
- }, [finalUser]); // Query will automatically refetch after mutations
564
+ }, []); // Empty dependency array - callback reads fresh data from store at call time
568
565
 
569
566
  // Handle initialField prop - open appropriate modal
570
567
  useEffect(() => {
@@ -832,7 +829,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
832
829
  {/* Search results */}
833
830
  {locationSearchResults.length > 0 && (
834
831
  <View style={styles.searchResults}>
835
- {locationSearchResults.map((result: any) => (
832
+ {locationSearchResults.map((result) => (
836
833
  <TouchableOpacity
837
834
  key={result.place_id}
838
835
  style={styles.searchResultItem}
@@ -863,7 +860,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
863
860
  {tempLocations.length > 0 && (
864
861
  <View style={styles.locationsList}>
865
862
  <Text style={styles.locationsListTitle}>Your Locations ({tempLocations.length})</Text>
866
- {tempLocations.map((location: any, index: number) => (
863
+ {tempLocations.map((location, index) => (
867
864
  <View key={location.id} style={styles.locationItem}>
868
865
  <View style={styles.locationItemContent}>
869
866
  <View style={styles.locationItemDragHandle}>
@@ -991,7 +988,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
991
988
  onPress: () => setIsAddingLink(true),
992
989
  }]),
993
990
  // Existing links
994
- ...tempLinksWithMetadata.map((link: any, index: number) => ({
991
+ ...tempLinksWithMetadata.map((link, index) => ({
995
992
  id: link.id,
996
993
  customIcon: link.image ? (
997
994
  <Image source={{ uri: link.image }} style={{ width: 36, height: 36, borderRadius: 18 }} />
@@ -130,7 +130,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
130
130
 
131
131
  // Create a map for O(1) lookup
132
132
  const userProfileMap = new Map<string, User | null>();
133
- batchResults.forEach(({ sessionId, user }) => {
133
+ batchResults.forEach(({ sessionId, user }: { sessionId: string; user: any }) => {
134
134
  userProfileMap.set(sessionId, user);
135
135
  });
136
136
 
@@ -460,7 +460,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
460
460
  iconColor: '#007AFF',
461
461
  title: 'Add Another Account',
462
462
  subtitle: 'Sign in with a different account',
463
- onPress: () => navigate?.('OxyAuth'),
463
+ onPress: () => navigate?.('SignIn'),
464
464
  },
465
465
  {
466
466
  id: 'device-management',
@@ -561,7 +561,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
561
561
  iconColor: '#ccc',
562
562
  title: t('accountSwitcher.empty.title') || 'No saved accounts',
563
563
  subtitle: t('accountSwitcher.empty.subtitle') || 'Add another account to switch between them quickly',
564
- onPress: () => navigate?.('OxyAuth'),
564
+ onPress: () => navigate?.('SignIn'),
565
565
  customContent: (
566
566
  <View style={styles.emptyStateContainer}>
567
567
  <OxyIcon name="person-outline" size={48} color="#ccc" />
@@ -571,7 +571,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
571
571
  </Text>
572
572
  <TouchableOpacity
573
573
  style={styles.addAccountButton}
574
- onPress={() => navigate?.('OxyAuth')}
574
+ onPress={() => navigate?.('SignIn')}
575
575
  >
576
576
  <Text style={styles.addAccountButtonText}>{t('accountCenter.sections.addAccount') || 'Add Account'}</Text>
577
577
  </TouchableOpacity>
@@ -4,7 +4,7 @@
4
4
  * This screen is used by OTHER apps in the Oxy ecosystem to authenticate users.
5
5
  * It presents two options:
6
6
  * 1. Scan QR code with Oxy Accounts app
7
- * 2. Open Oxy Accounts app directly (via deep link)
7
+ * 2. Open the Oxy Auth web flow
8
8
  *
9
9
  * Uses WebSocket for real-time authorization updates (with polling fallback).
10
10
  * The Oxy Accounts app is where users manage their cryptographic identity.
@@ -29,9 +29,8 @@ import { useOxy } from '../context/OxyContext';
29
29
  import QRCode from 'react-native-qrcode-svg';
30
30
  import OxyLogo from '../components/OxyLogo';
31
31
 
32
- // Deep link scheme for Oxy Accounts app
33
- const OXY_ACCOUNTS_SCHEME = 'oxyaccounts://';
34
32
  const OXY_ACCOUNTS_WEB_URL = 'https://accounts.oxy.so';
33
+ const OXY_AUTH_WEB_URL = 'https://auth.oxy.so';
35
34
 
36
35
  // Auth session expiration (5 minutes)
37
36
  const AUTH_SESSION_EXPIRY_MS = 5 * 60 * 1000;
@@ -52,6 +51,63 @@ interface AuthUpdatePayload {
52
51
  username?: string;
53
52
  }
54
53
 
54
+ const resolveAuthWebBaseUrl = (baseURL: string, authWebUrl?: string): string => {
55
+ if (authWebUrl) {
56
+ return authWebUrl;
57
+ }
58
+
59
+ try {
60
+ const url = new URL(baseURL);
61
+ if (url.port === '3001') {
62
+ url.port = '3000';
63
+ return url.origin;
64
+ }
65
+ if (url.hostname.startsWith('api.')) {
66
+ url.hostname = `auth.${url.hostname.slice(4)}`;
67
+ return url.origin;
68
+ }
69
+ } catch {
70
+ // Ignore parsing errors, fall back to default.
71
+ }
72
+ return OXY_AUTH_WEB_URL;
73
+ };
74
+
75
+ const resolveAuthRedirectUri = async (authRedirectUri?: string): Promise<string | null> => {
76
+ if (authRedirectUri) {
77
+ return authRedirectUri;
78
+ }
79
+
80
+ try {
81
+ const initialUrl = await Linking.getInitialURL();
82
+ if (!initialUrl) {
83
+ return null;
84
+ }
85
+
86
+ const parsed = new URL(initialUrl);
87
+ parsed.search = '';
88
+ parsed.hash = '';
89
+ return parsed.toString();
90
+ } catch {
91
+ return null;
92
+ }
93
+ };
94
+
95
+ const getRedirectParams = (url: string): { sessionId?: string; error?: string } | null => {
96
+ try {
97
+ const parsed = new URL(url);
98
+ const sessionId = parsed.searchParams.get('session_id') ?? undefined;
99
+ const error = parsed.searchParams.get('error') ?? undefined;
100
+
101
+ if (!sessionId && !error) {
102
+ return null;
103
+ }
104
+
105
+ return { sessionId, error };
106
+ } catch {
107
+ return null;
108
+ }
109
+ };
110
+
55
111
  const OxyAuthScreen: React.FC<BaseScreenProps> = ({
56
112
  navigate,
57
113
  goBack,
@@ -60,7 +116,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
60
116
  }) => {
61
117
  const themeValue = (theme === 'light' || theme === 'dark') ? theme : 'light';
62
118
  const colors = useThemeColors(themeValue);
63
- const { oxyServices, switchSession } = useOxy();
119
+ const { oxyServices, signIn, switchSession } = useOxy();
64
120
 
65
121
  const [authSession, setAuthSession] = useState<AuthSession | null>(null);
66
122
  const [isLoading, setIsLoading] = useState(true);
@@ -71,22 +127,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
71
127
  const socketRef = useRef<Socket | null>(null);
72
128
  const pollingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
73
129
  const isProcessingRef = useRef(false);
74
-
75
- const resolveDeviceIdForSession = useCallback(
76
- async (sessionId: string): Promise<string | undefined> => {
77
- try {
78
- const deviceSessions = await oxyServices.getDeviceSessions(sessionId);
79
- const matchingSession = deviceSessions?.find((session) => session.sessionId === sessionId);
80
- return matchingSession?.deviceId || undefined;
81
- } catch (err) {
82
- if (__DEV__) {
83
- console.log('Failed to resolve deviceId for session', err);
84
- }
85
- return undefined;
86
- }
87
- },
88
- [oxyServices],
89
- );
130
+ const linkingHandledRef = useRef(false);
90
131
 
91
132
  // Handle successful authorization
92
133
  const handleAuthSuccess = useCallback(async (sessionId: string) => {
@@ -102,8 +143,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
102
143
  }
103
144
  } else {
104
145
  // Fallback if switchSession not available (shouldn't happen, but for safety)
105
- const deviceId = await resolveDeviceIdForSession(sessionId);
106
- await oxyServices.getTokenBySession(sessionId, deviceId);
146
+ await oxyServices.getTokenBySession(sessionId);
107
147
  const user = await oxyServices.getUserBySession(sessionId);
108
148
  if (onAuthenticated) {
109
149
  onAuthenticated(user);
@@ -116,7 +156,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
116
156
  setError('Authorization successful but failed to complete sign in. Please try again.');
117
157
  isProcessingRef.current = false;
118
158
  }
119
- }, [oxyServices, resolveDeviceIdForSession, switchSession, onAuthenticated]);
159
+ }, [oxyServices, switchSession, onAuthenticated]);
120
160
 
121
161
  // Connect to socket for real-time updates
122
162
  const connectSocket = useCallback((sessionToken: string) => {
@@ -188,12 +228,12 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
188
228
  if (isProcessingRef.current) return;
189
229
 
190
230
  try {
191
- const response = await oxyServices.makeRequest<{
231
+ const response: {
192
232
  authorized: boolean;
193
233
  sessionId?: string;
194
234
  publicKey?: string;
195
235
  status?: string;
196
- }>('GET', `/api/auth/session/status/${sessionToken}`, undefined, { cache: false });
236
+ } = await oxyServices.makeRequest('GET', `/api/auth/session/status/${sessionToken}`, undefined, { cache: false });
197
237
 
198
238
  if (response.authorized && response.sessionId) {
199
239
  cleanup();
@@ -298,31 +338,27 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
298
338
  return `oxyauth://${authSession.sessionToken}`;
299
339
  };
300
340
 
301
- // Open Oxy Accounts app
302
- const handleOpenAccounts = useCallback(async () => {
341
+ // Open Oxy Auth web flow
342
+ const handleOpenAuth = useCallback(async () => {
303
343
  if (!authSession) return;
304
344
 
305
- const deepLinkUrl = `${OXY_ACCOUNTS_SCHEME}authorize?token=${authSession.sessionToken}`;
306
- const webUrl = `${OXY_ACCOUNTS_WEB_URL}/authorize?token=${authSession.sessionToken}`;
345
+ const authBaseUrl = resolveAuthWebBaseUrl(
346
+ oxyServices.getBaseURL(),
347
+ oxyServices.config?.authWebUrl
348
+ );
349
+ const webUrl = new URL('/authorize', authBaseUrl);
350
+ webUrl.searchParams.set('token', authSession.sessionToken);
351
+ const redirectUri = await resolveAuthRedirectUri(oxyServices.config?.authRedirectUri);
352
+ if (redirectUri) {
353
+ webUrl.searchParams.set('redirect_uri', redirectUri);
354
+ }
307
355
 
308
356
  try {
309
- const canOpen = await Linking.canOpenURL(deepLinkUrl);
310
-
311
- if (canOpen) {
312
- await Linking.openURL(deepLinkUrl);
313
- } else {
314
- // Fallback to web URL
315
- await Linking.openURL(webUrl);
316
- }
357
+ await Linking.openURL(webUrl.toString());
317
358
  } catch (err) {
318
- // Fallback to web URL
319
- try {
320
- await Linking.openURL(webUrl);
321
- } catch {
322
- setError('Unable to open Oxy Accounts. Please install the app or use QR code.');
323
- }
359
+ setError('Unable to open Oxy Auth. Please try again or use the QR code.');
324
360
  }
325
- }, [authSession]);
361
+ }, [authSession, oxyServices]);
326
362
 
327
363
  // Refresh session
328
364
  const handleRefresh = useCallback(() => {
@@ -330,6 +366,49 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
330
366
  generateAuthSession();
331
367
  }, [generateAuthSession, cleanup]);
332
368
 
369
+ const handleAuthRedirect = useCallback((url: string) => {
370
+ const params = getRedirectParams(url);
371
+ if (!params) {
372
+ return;
373
+ }
374
+
375
+ if (params.error) {
376
+ cleanup();
377
+ setError('Authorization was denied.');
378
+ return;
379
+ }
380
+
381
+ if (params.sessionId) {
382
+ cleanup();
383
+ handleAuthSuccess(params.sessionId);
384
+ }
385
+ }, [cleanup, handleAuthSuccess]);
386
+
387
+ useEffect(() => {
388
+ if (Platform.OS === 'web') {
389
+ return;
390
+ }
391
+
392
+ const subscription = Linking.addEventListener('url', ({ url }) => {
393
+ linkingHandledRef.current = true;
394
+ handleAuthRedirect(url);
395
+ });
396
+
397
+ Linking.getInitialURL()
398
+ .then((url) => {
399
+ if (url && !linkingHandledRef.current) {
400
+ handleAuthRedirect(url);
401
+ }
402
+ })
403
+ .catch(() => {
404
+ // Ignore linking errors; auth will still resolve via socket/polling.
405
+ });
406
+
407
+ return () => {
408
+ subscription.remove();
409
+ };
410
+ }, [handleAuthRedirect]);
411
+
333
412
  if (isLoading) {
334
413
  return (
335
414
  <View style={[styles.container, { backgroundColor: colors.background }]}>
@@ -381,26 +460,21 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
381
460
  </Text>
382
461
  </View>
383
462
 
384
- {/* Divider and Open Accounts Button - Only show on native platforms */}
385
- {Platform.OS !== 'web' && (
386
- <>
387
- {/* Divider */}
388
- <View style={styles.dividerContainer}>
389
- <View style={[styles.divider, { backgroundColor: colors.border }]} />
390
- <Text style={[styles.dividerText, { color: colors.secondaryText }]}>or</Text>
391
- <View style={[styles.divider, { backgroundColor: colors.border }]} />
392
- </View>
393
-
394
- {/* Open Accounts Button */}
395
- <TouchableOpacity
396
- style={[styles.button, { backgroundColor: colors.primary }]}
397
- onPress={handleOpenAccounts}
398
- >
399
- <OxyLogo width={20} height={20} fillColor="white" style={styles.buttonIcon} />
400
- <Text style={styles.buttonText}>Open Oxy Accounts</Text>
401
- </TouchableOpacity>
402
- </>
403
- )}
463
+ {/* Divider */}
464
+ <View style={styles.dividerContainer}>
465
+ <View style={[styles.divider, { backgroundColor: colors.border }]} />
466
+ <Text style={[styles.dividerText, { color: colors.secondaryText }]}>or</Text>
467
+ <View style={[styles.divider, { backgroundColor: colors.border }]} />
468
+ </View>
469
+
470
+ {/* Open Oxy Auth Button */}
471
+ <TouchableOpacity
472
+ style={[styles.button, { backgroundColor: colors.primary }]}
473
+ onPress={handleOpenAuth}
474
+ >
475
+ <OxyLogo width={20} height={20} fillColor="white" style={styles.buttonIcon} />
476
+ <Text style={styles.buttonText}>Open Oxy Auth</Text>
477
+ </TouchableOpacity>
404
478
 
405
479
  {/* Status */}
406
480
  {isWaiting && (
@@ -78,11 +78,8 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
78
78
  const loadSettings = async () => {
79
79
  try {
80
80
  setIsLoading(true);
81
- // Use getCurrentUserId() which returns MongoDB ObjectId from JWT token
82
- // Never use user?.id as it may be set to publicKey
83
- const userId = oxyServices?.getCurrentUserId();
84
- if (userId && oxyServices) {
85
- const privacySettings = await oxyServices.getPrivacySettings(userId);
81
+ if (user?.id && oxyServices) {
82
+ const privacySettings = await oxyServices.getPrivacySettings(user.id);
86
83
  if (privacySettings) {
87
84
  setSettings(privacySettings);
88
85
  }
@@ -96,7 +93,7 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
96
93
  };
97
94
 
98
95
  loadSettings();
99
- }, [oxyServices, t]);
96
+ }, [user?.id, oxyServices, t]);
100
97
 
101
98
  // Load blocked and restricted users
102
99
  useEffect(() => {
@@ -126,11 +123,8 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
126
123
  const newSettings = { ...settings, [key]: value };
127
124
  setSettings(newSettings);
128
125
 
129
- // Use getCurrentUserId() which returns MongoDB ObjectId from JWT token
130
- // Never use user?.id as it may be set to publicKey
131
- const userId = oxyServices?.getCurrentUserId();
132
- if (userId && oxyServices) {
133
- await oxyServices.updatePrivacySettings({ [key]: value }, userId);
126
+ if (user?.id && oxyServices) {
127
+ await oxyServices.updatePrivacySettings({ [key]: value }, user.id);
134
128
  toast.success(t('privacySettings.updated') || 'Privacy settings updated');
135
129
  }
136
130
  } catch (error) {
@@ -141,7 +135,7 @@ const PrivacySettingsScreen: React.FC<BaseScreenProps> = ({
141
135
  } finally {
142
136
  setIsSaving(false);
143
137
  }
144
- }, [settings, oxyServices, t]);
138
+ }, [settings, user?.id, oxyServices, t]);
145
139
 
146
140
  const handleUnblock = useCallback(async (userId: string) => {
147
141
  if (!oxyServices) return;
@@ -112,8 +112,6 @@ export const useAccountStore = create<AccountState>((set, get) => ({
112
112
  return existing &&
113
113
  existing.sessionId === newAccount.sessionId &&
114
114
  existing.userId === newAccount.userId &&
115
- existing.username === newAccount.username &&
116
- existing.displayName === newAccount.displayName &&
117
115
  existing.avatar === newAccount.avatar &&
118
116
  existing.avatarUrl === newAccount.avatarUrl;
119
117
  });
@@ -152,15 +150,7 @@ export const useAccountStore = create<AccountState>((set, get) => ({
152
150
  if (!existing) return {} as any;
153
151
 
154
152
  const updated = { ...existing, ...updates };
155
- // Check if any meaningful field has changed
156
- const hasChanges =
157
- existing.username !== updated.username ||
158
- existing.displayName !== updated.displayName ||
159
- existing.avatar !== updated.avatar ||
160
- existing.avatarUrl !== updated.avatarUrl ||
161
- existing.userId !== updated.userId;
162
-
163
- if (!hasChanges) {
153
+ if (existing.avatar === updated.avatar && existing.avatarUrl === updated.avatarUrl) {
164
154
  return {} as any; // No change
165
155
  }
166
156
 
@@ -1,65 +1,64 @@
1
- /** Auth store for Services SDK (sessions/tokens only). */
2
-
3
1
  import { create } from 'zustand';
2
+ import type { User } from '../../models/interfaces';
4
3
 
5
4
  export interface AuthState {
5
+ user: User | null;
6
6
  isAuthenticated: boolean;
7
- isOnline: boolean;
8
7
  isLoading: boolean;
9
8
  error: string | null;
10
- identitySynced: boolean;
9
+ lastUserFetch: number | null; // Timestamp of last user fetch for caching
11
10
 
12
- setOnline: (online: boolean) => void;
13
- loginSuccess: () => void;
11
+ loginSuccess: (user: User) => void;
14
12
  loginFailure: (error: string) => void;
15
13
  logout: () => void;
16
- setIdentitySynced: (synced: boolean) => void;
17
-
18
- canAuthenticate: () => boolean;
14
+ fetchUser: (oxyServices: { getCurrentUser: () => Promise<User> }, forceRefresh?: boolean) => Promise<void>;
15
+ setUser: (user: User) => void; // Direct user setter for caching
19
16
  }
20
17
 
21
- export const useAuthStore = create<AuthState>((set, get) => ({
18
+ export const useAuthStore = create<AuthState>((set: (state: Partial<AuthState>) => void, get: () => AuthState) => ({
19
+ user: null,
22
20
  isAuthenticated: false,
23
- isOnline: true, // Assume online initially
24
21
  isLoading: false,
25
22
  error: null,
26
- identitySynced: false,
27
-
28
- setOnline: (online: boolean) => {
29
- set({ isOnline: online });
30
- // If we go offline, we can't be authenticated
31
- if (!online) {
32
- set({ isAuthenticated: false });
33
- }
34
- },
35
-
36
- loginSuccess: () => set({
37
- isLoading: false,
38
- isAuthenticated: get().isOnline, // Only authenticated if online
39
- error: null,
40
- }),
23
+ lastUserFetch: null,
41
24
 
42
- loginFailure: (error: string) => set({
25
+ loginSuccess: (user: User) => set({
43
26
  isLoading: false,
44
- isAuthenticated: false,
45
- error
27
+ isAuthenticated: true,
28
+ user,
29
+ lastUserFetch: Date.now(),
46
30
  }),
47
-
31
+ loginFailure: (error: string) => set({ isLoading: false, error }),
48
32
  logout: () => set({
49
- isAuthenticated: false,
50
- error: null,
51
- identitySynced: false,
33
+ user: null,
34
+ isAuthenticated: false,
35
+ lastUserFetch: null,
52
36
  }),
53
-
54
- // Track whether identity registration is confirmed with backend
55
- setIdentitySynced: (synced: boolean) => set({ identitySynced: synced }),
56
-
57
- /**
58
- * Check if user can authenticate
59
- * Requires both valid tokens (checked by caller) and network
60
- */
61
- canAuthenticate: () => {
37
+ setUser: (user: User) => set({ user, lastUserFetch: Date.now() }),
38
+ fetchUser: async (oxyServices, forceRefresh = false) => {
62
39
  const state = get();
63
- return state.isOnline;
40
+ const now = Date.now();
41
+ const cacheAge = state.lastUserFetch ? now - state.lastUserFetch : Number.POSITIVE_INFINITY;
42
+ const cacheValid = cacheAge < 5 * 60 * 1000; // 5 minutes cache
43
+
44
+ // Use cached data if available and not forcing refresh
45
+ if (!forceRefresh && state.user && cacheValid) {
46
+ if (__DEV__) {
47
+ console.log('AuthStore: Using cached user data (age:', cacheAge, 'ms)');
48
+ }
49
+ return;
50
+ }
51
+
52
+ set({ isLoading: true, error: null });
53
+ try {
54
+ const user = await oxyServices.getCurrentUser();
55
+ set({ user, isLoading: false, isAuthenticated: true, lastUserFetch: now });
56
+ } catch (error) {
57
+ const errorMessage = error instanceof Error ? error.message : 'Failed to fetch user';
58
+ if (__DEV__) {
59
+ console.error('AuthStore: Error fetching user:', error);
60
+ }
61
+ set({ error: errorMessage, isLoading: false });
62
+ }
64
63
  },
65
- }));
64
+ }));