@oxyhq/services 5.13.0 → 5.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/README.md +71 -0
  2. package/lib/commonjs/core/HttpClient.js +238 -0
  3. package/lib/commonjs/core/HttpClient.js.map +1 -0
  4. package/lib/commonjs/core/OxyServices.js +530 -332
  5. package/lib/commonjs/core/OxyServices.js.map +1 -1
  6. package/lib/commonjs/core/RequestManager.js +199 -0
  7. package/lib/commonjs/core/RequestManager.js.map +1 -0
  8. package/lib/commonjs/core/index.js +38 -1
  9. package/lib/commonjs/core/index.js.map +1 -1
  10. package/lib/commonjs/i18n/index.js +37 -1
  11. package/lib/commonjs/i18n/index.js.map +1 -1
  12. package/lib/commonjs/i18n/locales/ar-SA.json +128 -0
  13. package/lib/commonjs/i18n/locales/ca-ES.json +128 -0
  14. package/lib/commonjs/i18n/locales/de-DE.json +128 -0
  15. package/lib/commonjs/i18n/locales/en-US.json +85 -12
  16. package/lib/commonjs/i18n/locales/es-ES.json +58 -6
  17. package/lib/commonjs/i18n/locales/fr-FR.json +128 -0
  18. package/lib/commonjs/i18n/locales/it-IT.json +128 -0
  19. package/lib/commonjs/i18n/locales/ja-JP.json +127 -0
  20. package/lib/commonjs/i18n/locales/ko-KR.json +128 -0
  21. package/lib/commonjs/i18n/locales/pt-PT.json +128 -0
  22. package/lib/commonjs/i18n/locales/zh-CN.json +128 -0
  23. package/lib/commonjs/index.js +36 -0
  24. package/lib/commonjs/index.js.map +1 -1
  25. package/lib/commonjs/ui/components/Avatar.js +94 -27
  26. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  27. package/lib/commonjs/ui/components/FollowButton.js +1 -0
  28. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  29. package/lib/commonjs/ui/components/FontLoader.js +22 -42
  30. package/lib/commonjs/ui/components/FontLoader.js.map +1 -1
  31. package/lib/commonjs/ui/components/OxyProvider.js +5 -8
  32. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  33. package/lib/commonjs/ui/components/StepBasedScreen.js +64 -44
  34. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  35. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +14 -35
  36. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  37. package/lib/commonjs/ui/components/internal/PinInput.js +2 -2
  38. package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
  39. package/lib/commonjs/ui/components/internal/TextField.js +13 -8
  40. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
  41. package/lib/commonjs/ui/context/OxyContext.js +443 -371
  42. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  43. package/lib/commonjs/ui/hooks/useSessionSocket.js +80 -22
  44. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  45. package/lib/commonjs/ui/index.js +4 -1
  46. package/lib/commonjs/ui/index.js.map +1 -1
  47. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +32 -2
  48. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +101 -59
  50. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -2
  52. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +75 -117
  54. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SignInScreen.js +43 -50
  56. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/SignUpScreen.js +14 -16
  58. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  59. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +188 -142
  60. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  61. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +10 -10
  62. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  63. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +2 -4
  64. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  65. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +45 -25
  66. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  67. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +88 -53
  68. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
  69. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +79 -58
  70. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  71. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +61 -52
  72. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  73. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +218 -39
  74. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  75. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +77 -50
  76. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -1
  77. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +424 -71
  78. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  79. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +55 -30
  80. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  81. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +64 -46
  82. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  83. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +84 -146
  84. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  85. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +113 -34
  86. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  87. package/lib/commonjs/ui/stores/accountStore.js +237 -0
  88. package/lib/commonjs/ui/stores/accountStore.js.map +1 -0
  89. package/lib/commonjs/ui/stores/authStore.js +17 -20
  90. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  91. package/lib/commonjs/ui/styles/authStyles.js +16 -8
  92. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  93. package/lib/commonjs/ui/styles/index.js +11 -0
  94. package/lib/commonjs/ui/styles/index.js.map +1 -1
  95. package/lib/commonjs/ui/styles/spacing.js +51 -0
  96. package/lib/commonjs/ui/styles/spacing.js.map +1 -0
  97. package/lib/commonjs/utils/asyncUtils.js +9 -22
  98. package/lib/commonjs/utils/asyncUtils.js.map +1 -1
  99. package/lib/commonjs/utils/cache.js +259 -0
  100. package/lib/commonjs/utils/cache.js.map +1 -0
  101. package/lib/commonjs/utils/index.js +99 -0
  102. package/lib/commonjs/utils/index.js.map +1 -1
  103. package/lib/commonjs/utils/languageUtils.js +159 -0
  104. package/lib/commonjs/utils/languageUtils.js.map +1 -0
  105. package/lib/commonjs/utils/requestUtils.js +217 -0
  106. package/lib/commonjs/utils/requestUtils.js.map +1 -0
  107. package/lib/commonjs/utils/sessionUtils.js +191 -0
  108. package/lib/commonjs/utils/sessionUtils.js.map +1 -0
  109. package/lib/commonjs/utils/validationUtils.js +1 -1
  110. package/lib/module/core/HttpClient.js +232 -0
  111. package/lib/module/core/HttpClient.js.map +1 -0
  112. package/lib/module/core/OxyServices.js +528 -326
  113. package/lib/module/core/OxyServices.js.map +1 -1
  114. package/lib/module/core/RequestManager.js +194 -0
  115. package/lib/module/core/RequestManager.js.map +1 -0
  116. package/lib/module/core/index.js +2 -0
  117. package/lib/module/core/index.js.map +1 -1
  118. package/lib/module/i18n/index.js +37 -1
  119. package/lib/module/i18n/index.js.map +1 -1
  120. package/lib/module/i18n/locales/ar-SA.json +128 -0
  121. package/lib/module/i18n/locales/ca-ES.json +128 -0
  122. package/lib/module/i18n/locales/de-DE.json +128 -0
  123. package/lib/module/i18n/locales/en-US.json +85 -12
  124. package/lib/module/i18n/locales/es-ES.json +58 -6
  125. package/lib/module/i18n/locales/fr-FR.json +128 -0
  126. package/lib/module/i18n/locales/it-IT.json +128 -0
  127. package/lib/module/i18n/locales/ja-JP.json +127 -0
  128. package/lib/module/i18n/locales/ko-KR.json +128 -0
  129. package/lib/module/i18n/locales/pt-PT.json +128 -0
  130. package/lib/module/i18n/locales/zh-CN.json +128 -0
  131. package/lib/module/index.js +2 -0
  132. package/lib/module/index.js.map +1 -1
  133. package/lib/module/ui/components/Avatar.js +94 -27
  134. package/lib/module/ui/components/Avatar.js.map +1 -1
  135. package/lib/module/ui/components/FollowButton.js +1 -0
  136. package/lib/module/ui/components/FollowButton.js.map +1 -1
  137. package/lib/module/ui/components/FontLoader.js +23 -43
  138. package/lib/module/ui/components/FontLoader.js.map +1 -1
  139. package/lib/module/ui/components/OxyProvider.js +6 -8
  140. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  141. package/lib/module/ui/components/StepBasedScreen.js +65 -45
  142. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  143. package/lib/module/ui/components/internal/GroupedPillButtons.js +14 -35
  144. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  145. package/lib/module/ui/components/internal/PinInput.js +2 -2
  146. package/lib/module/ui/components/internal/PinInput.js.map +1 -1
  147. package/lib/module/ui/components/internal/TextField.js +13 -8
  148. package/lib/module/ui/components/internal/TextField.js.map +1 -1
  149. package/lib/module/ui/context/OxyContext.js +442 -370
  150. package/lib/module/ui/context/OxyContext.js.map +1 -1
  151. package/lib/module/ui/hooks/useSessionSocket.js +80 -22
  152. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  153. package/lib/module/ui/index.js +4 -2
  154. package/lib/module/ui/index.js.map +1 -1
  155. package/lib/module/ui/screens/AccountSettingsScreen.js +33 -2
  156. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  157. package/lib/module/ui/screens/AccountSwitcherScreen.js +102 -60
  158. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  159. package/lib/module/ui/screens/FileManagementScreen.js +3 -2
  160. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  161. package/lib/module/ui/screens/LanguageSelectorScreen.js +73 -117
  162. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  163. package/lib/module/ui/screens/SignInScreen.js +44 -51
  164. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  165. package/lib/module/ui/screens/SignUpScreen.js +14 -16
  166. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  167. package/lib/module/ui/screens/WelcomeNewUserScreen.js +187 -143
  168. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  169. package/lib/module/ui/screens/internal/SignInPasswordStep.js +10 -10
  170. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  171. package/lib/module/ui/screens/internal/SignInUsernameStep.js +2 -4
  172. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  173. package/lib/module/ui/screens/steps/RecoverRequestStep.js +45 -25
  174. package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  175. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +89 -54
  176. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
  177. package/lib/module/ui/screens/steps/RecoverSuccessStep.js +80 -59
  178. package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  179. package/lib/module/ui/screens/steps/RecoverVerifyStep.js +62 -53
  180. package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  181. package/lib/module/ui/screens/steps/SignInPasswordStep.js +219 -40
  182. package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  183. package/lib/module/ui/screens/steps/SignInTotpStep.js +78 -51
  184. package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -1
  185. package/lib/module/ui/screens/steps/SignInUsernameStep.js +426 -73
  186. package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  187. package/lib/module/ui/screens/steps/SignUpIdentityStep.js +55 -30
  188. package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  189. package/lib/module/ui/screens/steps/SignUpSecurityStep.js +65 -47
  190. package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  191. package/lib/module/ui/screens/steps/SignUpSummaryStep.js +84 -146
  192. package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  193. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +114 -35
  194. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  195. package/lib/module/ui/stores/accountStore.js +229 -0
  196. package/lib/module/ui/stores/accountStore.js.map +1 -0
  197. package/lib/module/ui/stores/authStore.js +17 -20
  198. package/lib/module/ui/stores/authStore.js.map +1 -1
  199. package/lib/module/ui/styles/authStyles.js +16 -8
  200. package/lib/module/ui/styles/authStyles.js.map +1 -1
  201. package/lib/module/ui/styles/index.js +1 -0
  202. package/lib/module/ui/styles/index.js.map +1 -1
  203. package/lib/module/ui/styles/spacing.js +48 -0
  204. package/lib/module/ui/styles/spacing.js.map +1 -0
  205. package/lib/module/utils/asyncUtils.js +10 -22
  206. package/lib/module/utils/asyncUtils.js.map +1 -1
  207. package/lib/module/utils/cache.js +250 -0
  208. package/lib/module/utils/cache.js.map +1 -0
  209. package/lib/module/utils/index.js +7 -0
  210. package/lib/module/utils/index.js.map +1 -1
  211. package/lib/module/utils/languageUtils.js +151 -0
  212. package/lib/module/utils/languageUtils.js.map +1 -0
  213. package/lib/module/utils/requestUtils.js +210 -0
  214. package/lib/module/utils/requestUtils.js.map +1 -0
  215. package/lib/module/utils/sessionUtils.js +180 -0
  216. package/lib/module/utils/sessionUtils.js.map +1 -0
  217. package/lib/module/utils/validationUtils.js +1 -1
  218. package/lib/typescript/core/HttpClient.d.ts +64 -0
  219. package/lib/typescript/core/HttpClient.d.ts.map +1 -0
  220. package/lib/typescript/core/OxyServices.d.ts +86 -73
  221. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  222. package/lib/typescript/core/RequestManager.d.ts +67 -0
  223. package/lib/typescript/core/RequestManager.d.ts.map +1 -0
  224. package/lib/typescript/core/index.d.ts +2 -0
  225. package/lib/typescript/core/index.d.ts.map +1 -1
  226. package/lib/typescript/i18n/index.d.ts.map +1 -1
  227. package/lib/typescript/index.d.ts +2 -0
  228. package/lib/typescript/index.d.ts.map +1 -1
  229. package/lib/typescript/models/interfaces.d.ts +15 -0
  230. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  231. package/lib/typescript/models/session.d.ts +1 -0
  232. package/lib/typescript/models/session.d.ts.map +1 -1
  233. package/lib/typescript/ui/components/Avatar.d.ts +6 -7
  234. package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
  235. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  236. package/lib/typescript/ui/components/FontLoader.d.ts +3 -3
  237. package/lib/typescript/ui/components/FontLoader.d.ts.map +1 -1
  238. package/lib/typescript/ui/components/OxyProvider.d.ts +2 -2
  239. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  240. package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
  241. package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
  242. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
  243. package/lib/typescript/ui/context/OxyContext.d.ts +5 -0
  244. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  245. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  246. package/lib/typescript/ui/index.d.ts +2 -2
  247. package/lib/typescript/ui/index.d.ts.map +1 -1
  248. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  249. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  250. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts +3 -3
  251. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  252. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  253. package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
  254. package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  255. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  256. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
  257. package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -1
  258. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
  259. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
  260. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +2 -0
  261. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
  262. package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -1
  263. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
  264. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
  265. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
  266. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
  267. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
  268. package/lib/typescript/ui/stores/accountStore.d.ts +34 -0
  269. package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -0
  270. package/lib/typescript/ui/stores/authStore.d.ts +7 -3
  271. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  272. package/lib/typescript/ui/styles/authStyles.d.ts +19 -2
  273. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
  274. package/lib/typescript/ui/styles/index.d.ts +1 -0
  275. package/lib/typescript/ui/styles/index.d.ts.map +1 -1
  276. package/lib/typescript/ui/styles/spacing.d.ts +43 -0
  277. package/lib/typescript/ui/styles/spacing.d.ts.map +1 -0
  278. package/lib/typescript/utils/asyncUtils.d.ts +2 -0
  279. package/lib/typescript/utils/asyncUtils.d.ts.map +1 -1
  280. package/lib/typescript/utils/cache.d.ts +128 -0
  281. package/lib/typescript/utils/cache.d.ts.map +1 -0
  282. package/lib/typescript/utils/index.d.ts +4 -0
  283. package/lib/typescript/utils/index.d.ts.map +1 -1
  284. package/lib/typescript/utils/languageUtils.d.ts +38 -0
  285. package/lib/typescript/utils/languageUtils.d.ts.map +1 -0
  286. package/lib/typescript/utils/requestUtils.d.ts +122 -0
  287. package/lib/typescript/utils/requestUtils.d.ts.map +1 -0
  288. package/lib/typescript/utils/sessionUtils.d.ts +55 -0
  289. package/lib/typescript/utils/sessionUtils.d.ts.map +1 -0
  290. package/lib/typescript/utils/validationUtils.d.ts +1 -1
  291. package/package.json +1 -1
  292. package/src/core/HttpClient.ts +277 -0
  293. package/src/core/OxyServices.ts +461 -352
  294. package/src/core/RequestManager.ts +240 -0
  295. package/src/core/index.ts +10 -0
  296. package/src/i18n/index.ts +36 -0
  297. package/src/i18n/locales/ar-SA.json +128 -0
  298. package/src/i18n/locales/ca-ES.json +128 -0
  299. package/src/i18n/locales/de-DE.json +128 -0
  300. package/src/i18n/locales/en-US.json +85 -12
  301. package/src/i18n/locales/es-ES.json +58 -6
  302. package/src/i18n/locales/fr-FR.json +128 -0
  303. package/src/i18n/locales/it-IT.json +128 -0
  304. package/src/i18n/locales/ja-JP.json +127 -0
  305. package/src/i18n/locales/ko-KR.json +128 -0
  306. package/src/i18n/locales/pt-PT.json +128 -0
  307. package/src/i18n/locales/zh-CN.json +128 -0
  308. package/src/index.ts +10 -0
  309. package/src/models/interfaces.ts +19 -0
  310. package/src/models/session.ts +1 -1
  311. package/src/ui/components/Avatar.tsx +151 -35
  312. package/src/ui/components/FollowButton.tsx +1 -0
  313. package/src/ui/components/FontLoader.tsx +17 -37
  314. package/src/ui/components/OxyProvider.tsx +14 -13
  315. package/src/ui/components/StepBasedScreen.tsx +66 -43
  316. package/src/ui/components/internal/GroupedPillButtons.tsx +15 -31
  317. package/src/ui/components/internal/PinInput.tsx +2 -2
  318. package/src/ui/components/internal/TextField.tsx +7 -6
  319. package/src/ui/context/OxyContext.tsx +441 -326
  320. package/src/ui/hooks/useSessionSocket.ts +72 -18
  321. package/src/ui/index.ts +4 -1
  322. package/src/ui/screens/AccountSettingsScreen.tsx +34 -2
  323. package/src/ui/screens/AccountSwitcherScreen.tsx +102 -68
  324. package/src/ui/screens/FileManagementScreen.tsx +16 -16
  325. package/src/ui/screens/LanguageSelectorScreen.tsx +86 -143
  326. package/src/ui/screens/SignInScreen.tsx +59 -43
  327. package/src/ui/screens/SignUpScreen.tsx +14 -15
  328. package/src/ui/screens/WelcomeNewUserScreen.tsx +153 -105
  329. package/src/ui/screens/internal/SignInPasswordStep.tsx +4 -6
  330. package/src/ui/screens/internal/SignInUsernameStep.tsx +1 -1
  331. package/src/ui/screens/steps/RecoverRequestStep.tsx +34 -24
  332. package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +65 -36
  333. package/src/ui/screens/steps/RecoverSuccessStep.tsx +71 -47
  334. package/src/ui/screens/steps/RecoverVerifyStep.tsx +60 -50
  335. package/src/ui/screens/steps/SignInPasswordStep.tsx +190 -32
  336. package/src/ui/screens/steps/SignInTotpStep.tsx +68 -34
  337. package/src/ui/screens/steps/SignInUsernameStep.tsx +446 -63
  338. package/src/ui/screens/steps/SignUpIdentityStep.tsx +49 -35
  339. package/src/ui/screens/steps/SignUpSecurityStep.tsx +56 -39
  340. package/src/ui/screens/steps/SignUpSummaryStep.tsx +99 -89
  341. package/src/ui/screens/steps/SignUpWelcomeStep.tsx +88 -20
  342. package/src/ui/stores/accountStore.ts +285 -0
  343. package/src/ui/stores/authStore.ts +16 -19
  344. package/src/ui/styles/authStyles.ts +16 -8
  345. package/src/ui/styles/index.ts +1 -0
  346. package/src/ui/styles/spacing.ts +46 -0
  347. package/src/utils/asyncUtils.ts +10 -24
  348. package/src/utils/cache.ts +264 -0
  349. package/src/utils/index.ts +19 -0
  350. package/src/utils/languageUtils.ts +174 -0
  351. package/src/utils/requestUtils.ts +234 -0
  352. package/src/utils/sessionUtils.ts +206 -0
  353. package/src/utils/validationUtils.ts +1 -1
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { useState } from 'react';
1
+ import React, { useState, useMemo, useCallback } from 'react';
3
2
  import {
4
3
  View,
5
4
  Text,
@@ -15,101 +14,18 @@ import { Ionicons } from '@expo/vector-icons';
15
14
  import { toast } from '../../lib/sonner';
16
15
  import { Header, Section, GroupedSection } from '../components';
17
16
  import { useI18n } from '../hooks/useI18n';
18
-
19
- // Supported languages with their metadata
20
- const SUPPORTED_LANGUAGES = [
21
- {
22
- id: 'en-US',
23
- name: 'English',
24
- nativeName: 'English',
25
- flag: '🇺🇸',
26
- icon: 'language-outline',
27
- color: '#007AFF',
28
- },
29
- {
30
- id: 'es-ES',
31
- name: 'Spanish',
32
- nativeName: 'Español',
33
- flag: '🇪🇸',
34
- icon: 'language-outline',
35
- color: '#FF3B30',
36
- },
37
- {
38
- id: 'ca-ES',
39
- name: 'Catalan',
40
- nativeName: 'Català',
41
- flag: '🇪🇸',
42
- icon: 'language-outline',
43
- color: '#0CA678',
44
- },
45
- {
46
- id: 'fr-FR',
47
- name: 'French',
48
- nativeName: 'Français',
49
- flag: '🇫🇷',
50
- icon: 'language-outline',
51
- color: '#5856D6',
52
- },
53
- {
54
- id: 'de-DE',
55
- name: 'German',
56
- nativeName: 'Deutsch',
57
- flag: '🇩🇪',
58
- icon: 'language-outline',
59
- color: '#FF9500',
60
- },
61
- {
62
- id: 'it-IT',
63
- name: 'Italian',
64
- nativeName: 'Italiano',
65
- flag: '🇮🇹',
66
- icon: 'language-outline',
67
- color: '#34C759',
68
- },
69
- {
70
- id: 'pt-PT',
71
- name: 'Portuguese',
72
- nativeName: 'Português',
73
- flag: '🇵🇹',
74
- icon: 'language-outline',
75
- color: '#AF52DE',
76
- },
77
- {
78
- id: 'ja-JP',
79
- name: 'Japanese',
80
- nativeName: '日本語',
81
- flag: '🇯🇵',
82
- icon: 'language-outline',
83
- color: '#FF2D92',
84
- },
85
- {
86
- id: 'ko-KR',
87
- name: 'Korean',
88
- nativeName: '한국어',
89
- flag: '🇰🇷',
90
- icon: 'language-outline',
91
- color: '#32D74B',
92
- },
93
- {
94
- id: 'zh-CN',
95
- name: 'Chinese',
96
- nativeName: '中文',
97
- flag: '🇨🇳',
98
- icon: 'language-outline',
99
- color: '#FF9F0A',
100
- },
101
- {
102
- id: 'ar-SA',
103
- name: 'Arabic',
104
- nativeName: 'العربية',
105
- flag: '🇸🇦',
106
- icon: 'language-outline',
107
- color: '#30B0C7',
108
- },
109
- ];
17
+ import { SUPPORTED_LANGUAGES } from '../../utils/languageUtils';
110
18
 
111
19
  interface LanguageSelectorScreenProps extends BaseScreenProps { }
112
20
 
21
+ /**
22
+ * LanguageSelectorScreen - Optimized for performance
23
+ *
24
+ * Performance optimizations:
25
+ * - useMemo for language items to prevent recreation on every render
26
+ * - useCallback for handlers to prevent unnecessary re-renders
27
+ * - Memoized current language section
28
+ */
113
29
  const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
114
30
  goBack,
115
31
  onClose,
@@ -121,20 +37,27 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
121
37
  const colors = useThemeColors(theme);
122
38
  const [isLoading, setIsLoading] = useState(false);
123
39
 
124
- const handleLanguageSelect = async (languageId: string) => {
125
- if (languageId === currentLanguage) {
126
- return; // Already selected
40
+ // Memoize the language select handler to prevent recreation on every render
41
+ const handleLanguageSelect = useCallback(async (languageId: string) => {
42
+ if (languageId === currentLanguage || isLoading) {
43
+ return; // Already selected or loading
127
44
  }
128
45
 
129
46
  setIsLoading(true);
130
47
 
131
48
  try {
49
+ let serverSyncFailed = false;
50
+
132
51
  // If signed in, persist preference to backend user settings
133
52
  if (isAuthenticated && user?.id) {
134
53
  try {
135
54
  await oxyServices.updateProfile({ language: languageId });
136
55
  } catch (e: any) {
137
- console.warn('Failed to update language on server, falling back to local storage', e);
56
+ // Server sync failed, but we'll save locally anyway
57
+ serverSyncFailed = true;
58
+ if (__DEV__) {
59
+ console.warn('Failed to sync language to server (will save locally only):', e?.message || e);
60
+ }
138
61
  }
139
62
  }
140
63
 
@@ -142,34 +65,71 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
142
65
  await setLanguage(languageId);
143
66
 
144
67
  const selectedLang = SUPPORTED_LANGUAGES.find(lang => lang.id === languageId);
68
+
69
+ // Show success message (language is saved locally regardless of server sync)
145
70
  toast.success(t('language.changed', { lang: selectedLang?.name || languageId }));
71
+
72
+ // Log server sync failure only in dev mode (user experience is still good - saved locally)
73
+ if (serverSyncFailed && __DEV__) {
74
+ console.warn('Language saved locally but server sync failed');
75
+ }
146
76
 
147
77
  setIsLoading(false);
148
78
  // Close the bottom sheet if possible; otherwise, go back
149
79
  if (onClose) onClose(); else goBack();
150
80
 
151
81
  } catch (error) {
82
+ // Only show error if local storage also failed
152
83
  console.error('Error saving language preference:', error);
153
84
  toast.error('Failed to save language preference');
154
85
  setIsLoading(false);
155
86
  }
156
- };
87
+ }, [currentLanguage, isLoading, isAuthenticated, user?.id, oxyServices, setLanguage, t, onClose, goBack]);
88
+
89
+ // Memoize language items to prevent recreation on every render
90
+ const languageItems = useMemo(() =>
91
+ SUPPORTED_LANGUAGES.map(language => ({
92
+ id: language.id,
93
+ title: language.name,
94
+ subtitle: language.nativeName,
95
+ customIcon: (
96
+ <View style={[styles.languageFlag, { backgroundColor: `${language.color}20` }]}>
97
+ <Text style={styles.flagEmoji}>{language.flag}</Text>
98
+ </View>
99
+ ),
100
+ iconColor: language.color,
101
+ selected: currentLanguage === language.id,
102
+ onPress: () => handleLanguageSelect(language.id),
103
+ dense: true,
104
+ })),
105
+ [currentLanguage, handleLanguageSelect]
106
+ );
157
107
 
158
- // Create grouped items for the language list
159
- const languageItems = SUPPORTED_LANGUAGES.map(language => ({
160
- id: language.id,
161
- title: language.name,
162
- subtitle: language.nativeName,
163
- customIcon: (
164
- <View style={[styles.languageFlag, { backgroundColor: `${language.color}20` }]}>
165
- <Text style={styles.flagEmoji}>{language.flag}</Text>
166
- </View>
167
- ),
168
- iconColor: language.color,
169
- selected: currentLanguage === language.id,
170
- onPress: () => handleLanguageSelect(language.id),
171
- dense: true,
172
- }));
108
+ // Memoize current language data to prevent recalculation
109
+ const currentLanguageData = useMemo(() => {
110
+ if (!currentLanguage) return null;
111
+ return SUPPORTED_LANGUAGES.find(lang => lang.id === currentLanguage);
112
+ }, [currentLanguage]);
113
+
114
+ // Memoize current language section items
115
+ const currentLanguageItems = useMemo(() => {
116
+ if (!currentLanguageData) return [];
117
+ return [{
118
+ id: `current-${currentLanguageData.id}`,
119
+ title: currentLanguageData.name,
120
+ subtitle: currentLanguageData.nativeName,
121
+ customIcon: (
122
+ <View style={[styles.languageFlag, { backgroundColor: `${currentLanguageData.color}20` }]}>
123
+ <Text style={styles.flagEmoji}>{currentLanguageData.flag}</Text>
124
+ </View>
125
+ ),
126
+ iconColor: currentLanguageData.color,
127
+ selected: false,
128
+ showChevron: false,
129
+ dense: true,
130
+ disabled: true,
131
+ }];
132
+ }, [currentLanguageData]);
173
133
 
174
134
  return (
175
135
  <View style={[styles.container, { backgroundColor: '#f2f2f2' }]}>
@@ -182,36 +142,18 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
182
142
  elevation="subtle"
183
143
  />
184
144
 
185
- <ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
145
+ <ScrollView
146
+ style={styles.content}
147
+ showsVerticalScrollIndicator={false}
148
+ removeClippedSubviews={true}
149
+ >
186
150
  {/* Current selection */}
187
- {currentLanguage && (
151
+ {currentLanguage && currentLanguageItems.length > 0 && (
188
152
  <Section title={t('language.current')} theme={theme} isFirst={true}>
189
- {(() => {
190
- const current = SUPPORTED_LANGUAGES.find(lang => lang.id === currentLanguage);
191
- if (!current) return null;
192
- return (
193
- <GroupedSection
194
- items={[
195
- {
196
- id: `current-${current.id}`,
197
- title: current.name,
198
- subtitle: current.nativeName,
199
- customIcon: (
200
- <View style={[styles.languageFlag, { backgroundColor: `${current.color}20` }]}>
201
- <Text style={styles.flagEmoji}>{current.flag}</Text>
202
- </View>
203
- ),
204
- iconColor: current.color,
205
- selected: false,
206
- showChevron: false,
207
- dense: true,
208
- disabled: true,
209
- },
210
- ]}
211
- theme={theme}
212
- />
213
- );
214
- })()}
153
+ <GroupedSection
154
+ items={currentLanguageItems}
155
+ theme={theme}
156
+ />
215
157
  </Section>
216
158
  )}
217
159
 
@@ -348,4 +290,5 @@ const styles = StyleSheet.create({
348
290
  },
349
291
  });
350
292
 
351
- export default LanguageSelectorScreen;
293
+ // Export memoized component to prevent unnecessary re-renders
294
+ export default React.memo(LanguageSelectorScreen);
@@ -1,5 +1,5 @@
1
1
  import type React from 'react';
2
- import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
2
+ import { useState, useMemo, useCallback } from 'react';
3
3
  import type { BaseScreenProps } from '../navigation/types';
4
4
  import { useOxy } from '../context/OxyContext';
5
5
  import { useThemeColors } from '../styles';
@@ -29,18 +29,9 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
29
29
  const [validationStatus, setValidationStatus] = useState<'idle' | 'validating' | 'valid' | 'invalid'>(
30
30
  initialUserProfile ? 'valid' : 'idle'
31
31
  );
32
+ const [existingSession, setExistingSession] = useState<any>(null);
32
33
 
33
- // Cache for validation results to prevent repeated API calls
34
- const validationCache = useRef<Map<string, { profile: any }>>(new Map());
35
-
36
- const { login, completeMfaLogin, isLoading, user, isAuthenticated, sessions, oxyServices } = useOxy();
37
-
38
- // Only log props in development mode to reduce console noise
39
- if (__DEV__) {
40
- console.log('SignInScreen props:', { initialStep, initialUsername, initialUserProfile });
41
- console.log('🔧 oxyServices available:', !!oxyServices);
42
- console.log('🔧 getProfileByUsername available:', typeof oxyServices?.getProfileByUsername);
43
- }
34
+ const { login, completeMfaLogin, isLoading, user, isAuthenticated, sessions, oxyServices, switchSession } = useOxy();
44
35
  const colors = useThemeColors(theme);
45
36
 
46
37
  // Check if this should be treated as "Add Account" mode
@@ -68,14 +59,13 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
68
59
  return false;
69
60
  }
70
61
 
71
- // Check cache first
72
- const cached = validationCache.current.get(usernameToValidate);
73
- if (cached) {
74
- if (__DEV__) console.log(' Username found in cache:', cached.profile);
75
- setUserProfile(cached.profile);
76
- setValidationStatus('valid');
77
- setErrorMessage('');
78
- return true;
62
+ const offlineDetected = typeof navigator !== 'undefined' && navigator.onLine === false;
63
+
64
+ if (offlineDetected) {
65
+ if (__DEV__) console.log('⚠️ Offline detected, skipping username validation');
66
+ setValidationStatus('invalid');
67
+ setErrorMessage('No connection. Check your internet connection and try again.');
68
+ return false;
79
69
  }
80
70
 
81
71
  if (__DEV__) console.log('🔄 Validating username with API...');
@@ -97,14 +87,24 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
97
87
 
98
88
  if (__DEV__) console.log('✅ Username is valid:', profileData);
99
89
  setUserProfile(profileData);
90
+
91
+ // Check if this account is already signed in
92
+ const profileUserId = profile.id?.toString();
93
+ const existing = sessions?.find(s => {
94
+ const sessionUserId = s.userId?.toString();
95
+ return sessionUserId === profileUserId;
96
+ });
97
+
98
+ if (existing) {
99
+ setExistingSession(existing);
100
+ if (__DEV__) console.log('✅ Account already signed in:', existing);
101
+ } else {
102
+ setExistingSession(null);
103
+ }
104
+
100
105
  setValidationStatus('valid');
101
106
  setErrorMessage('');
102
107
 
103
- // Cache the result
104
- validationCache.current.set(usernameToValidate, {
105
- profile: profileData
106
- });
107
-
108
108
  return true;
109
109
  } else {
110
110
  if (__DEV__) console.log('❌ Username not found');
@@ -116,25 +116,29 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
116
116
  if (__DEV__) console.log('🚨 Validation error:', error);
117
117
 
118
118
  // If user not found (404), username doesn't exist
119
- if (error.status === 404 || error.code === 'USER_NOT_FOUND') {
119
+ if (error?.status === 404 || error?.code === 'USER_NOT_FOUND') {
120
120
  console.log('❌ Username not found (404)');
121
121
  setValidationStatus('invalid');
122
122
  setErrorMessage('Username not found.');
123
123
  return false;
124
124
  }
125
125
 
126
- // For development/testing: if API fails, allow any 3+ character username
127
- if (__DEV__) {
128
- if (__DEV__) console.log('⚠️ Development mode: allowing username due to API error');
129
- setValidationStatus('valid');
130
- setErrorMessage('');
131
- return true;
132
- }
126
+ const isNetworkError =
127
+ error?.status === 0 ||
128
+ error?.code === 'ECONNABORTED' ||
129
+ error?.code === 'ERR_NETWORK' ||
130
+ error?.message?.toLowerCase?.().includes('network request failed') ||
131
+ error?.message?.toLowerCase?.().includes('network error') ||
132
+ error?.name === 'AbortError' ||
133
+ error?.type === 'network';
133
134
 
134
- // For other errors, show generic message
135
135
  console.error('Username validation error:', error);
136
136
  setValidationStatus('invalid');
137
- setErrorMessage('Unable to validate username. Please try again.');
137
+ setErrorMessage(
138
+ isNetworkError
139
+ ? 'No connection. Check your internet connection and try again.'
140
+ : 'Unable to validate username. Please try again.'
141
+ );
138
142
  return false;
139
143
  } finally {
140
144
  setIsValidating(false);
@@ -177,6 +181,22 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
177
181
 
178
182
  const [mfaToken, setMfaToken] = useState<string | null>(null);
179
183
 
184
+ const handleContinueWithExistingAccount = useCallback(async () => {
185
+ if (!existingSession) return;
186
+
187
+ try {
188
+ setErrorMessage('');
189
+ await switchSession(existingSession.sessionId);
190
+ // Get the user for the authenticated callback
191
+ const currentUser = await oxyServices.getUserBySession(existingSession.sessionId);
192
+ if (onAuthenticated) {
193
+ onAuthenticated(currentUser);
194
+ }
195
+ } catch (error: any) {
196
+ setErrorMessage(error.message || 'Failed to switch account');
197
+ }
198
+ }, [existingSession, switchSession, oxyServices, onAuthenticated]);
199
+
180
200
  const handleSignIn = useCallback(async () => {
181
201
  if (!password) {
182
202
  setErrorMessage('Please enter your password.');
@@ -186,6 +206,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
186
206
  setErrorMessage('Please enter a valid username first.');
187
207
  return;
188
208
  }
209
+
189
210
  try {
190
211
  setErrorMessage('');
191
212
  const user = await login(username, password);
@@ -201,13 +222,6 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
201
222
  }
202
223
  }, [username, password, login, onAuthenticated, userProfile]);
203
224
 
204
- // Simple cleanup on unmount - that's all we need for username validation
205
- useEffect(() => {
206
- return () => {
207
- validationCache.current.clear();
208
- };
209
- }, []);
210
-
211
225
  // Step configurations
212
226
  const steps: StepConfig[] = useMemo(() => {
213
227
  const base: StepConfig[] = [
@@ -259,6 +273,8 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
259
273
  handleInputBlur,
260
274
  handleSignIn, // Add sign-in function for password step
261
275
  mfaToken,
276
+ existingSession,
277
+ handleContinueWithExistingAccount,
262
278
  },
263
279
  ...(mfaToken ? [{
264
280
  username,
@@ -272,7 +288,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
272
288
  username, password, errorMessage, validationStatus, userProfile, mfaToken,
273
289
  isValidating, isInputFocused, isAddAccountMode, user, showPassword,
274
290
  isLoading, handleUsernameChange, handlePasswordChange, handleInputFocus, handleInputBlur,
275
- validateUsername, handleSignIn, completeMfaLogin
291
+ validateUsername, handleSignIn, completeMfaLogin, existingSession, handleContinueWithExistingAccount
276
292
  ]);
277
293
 
278
294
  return (
@@ -9,6 +9,7 @@ import SignUpWelcomeStep from './steps/SignUpWelcomeStep';
9
9
  import SignUpIdentityStep from './steps/SignUpIdentityStep';
10
10
  import SignUpSecurityStep from './steps/SignUpSecurityStep';
11
11
  import SignUpSummaryStep from './steps/SignUpSummaryStep';
12
+ import { TTLCache, registerCacheForCleanup } from '../../utils/cache';
12
13
 
13
14
  // Types for better type safety
14
15
  interface ValidationState {
@@ -51,8 +52,16 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
51
52
  // Error message state
52
53
  const [errorMessage, setErrorMessage] = useState('');
53
54
 
54
- // Username validation with caching
55
- const usernameCache = useRef<Map<string, { available: boolean; timestamp: number }>>(new Map());
55
+ // Username validation with caching - uses centralized cache
56
+ const usernameCache = useRef(new TTLCache<boolean>(5 * 60 * 1000)); // 5 minutes cache
57
+
58
+ // Register cache for cleanup on mount
59
+ useEffect(() => {
60
+ registerCacheForCleanup(usernameCache.current);
61
+ return () => {
62
+ usernameCache.current.clear();
63
+ };
64
+ }, []);
56
65
 
57
66
  const validateUsername = useCallback(async (usernameToValidate: string): Promise<boolean> => {
58
67
  if (!usernameToValidate || usernameToValidate.length < USERNAME_MIN_LENGTH) {
@@ -62,9 +71,8 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
62
71
 
63
72
  // Check cache first
64
73
  const cached = usernameCache.current.get(usernameToValidate);
65
- const now = Date.now();
66
- if (cached && (now - cached.timestamp) < 5 * 60 * 1000) {
67
- const isValid = cached.available;
74
+ if (cached !== null) {
75
+ const isValid = cached;
68
76
  setValidationState({
69
77
  status: isValid ? 'valid' : 'invalid',
70
78
  message: isValid ? '' : 'Username is already taken'
@@ -79,10 +87,7 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
79
87
  const isValid = result.available;
80
88
 
81
89
  // Cache the result
82
- usernameCache.current.set(usernameToValidate, {
83
- available: isValid,
84
- timestamp: now
85
- });
90
+ usernameCache.current.set(usernameToValidate, isValid);
86
91
 
87
92
  setValidationState({
88
93
  status: isValid ? 'valid' : 'invalid',
@@ -146,12 +151,6 @@ const SignUpScreen: React.FC<BaseScreenProps> = ({
146
151
  }
147
152
  }, [username, email, password, confirmPassword, validateEmail, validatePassword, signUp, navigate]);
148
153
 
149
- // Cleanup cache on unmount
150
- useEffect(() => {
151
- return () => {
152
- usernameCache.current.clear();
153
- };
154
- }, []);
155
154
 
156
155
  // Step configurations
157
156
  const steps: StepConfig[] = useMemo(() => [