@oxyhq/services 5.11.11 → 5.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/README.md +48 -7
  2. package/lib/commonjs/core/OxyServices.js +162 -12
  3. package/lib/commonjs/core/OxyServices.js.map +1 -1
  4. package/lib/commonjs/i18n/index.js +40 -0
  5. package/lib/commonjs/i18n/index.js.map +1 -0
  6. package/lib/commonjs/i18n/locales/en-US.json +681 -0
  7. package/lib/commonjs/i18n/locales/es-ES.json +689 -0
  8. package/lib/commonjs/ui/components/FollowButton.js +1 -1
  9. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  10. package/lib/commonjs/ui/components/GroupedItem.js +2 -1
  11. package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
  12. package/lib/commonjs/ui/components/Header.js +4 -3
  13. package/lib/commonjs/ui/components/Header.js.map +1 -1
  14. package/lib/commonjs/ui/components/OxyProvider.js +112 -105
  15. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  16. package/lib/commonjs/ui/components/ProfileCard.js +5 -1
  17. package/lib/commonjs/ui/components/ProfileCard.js.map +1 -1
  18. package/lib/commonjs/ui/components/Section.js +1 -1
  19. package/lib/commonjs/ui/components/StepBasedScreen.js +17 -17
  20. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  21. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +15 -3
  22. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  23. package/lib/commonjs/ui/components/internal/PinInput.js +10 -4
  24. package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
  25. package/lib/commonjs/ui/context/OxyContext.js +128 -12
  26. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  27. package/lib/commonjs/ui/hooks/useI18n.js +22 -0
  28. package/lib/commonjs/ui/hooks/useI18n.js.map +1 -0
  29. package/lib/commonjs/ui/navigation/OxyRouter.js +11 -131
  30. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  31. package/lib/commonjs/ui/navigation/routes.js +127 -0
  32. package/lib/commonjs/ui/navigation/routes.js.map +1 -0
  33. package/lib/commonjs/ui/navigation/types.js +7 -0
  34. package/lib/commonjs/ui/navigation/types.js.map +1 -1
  35. package/lib/commonjs/ui/screens/AccountCenterScreen.js +55 -47
  36. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +69 -61
  38. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  39. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +378 -37
  40. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  41. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +52 -34
  42. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  43. package/lib/commonjs/ui/screens/FeedbackScreen.js +40 -36
  44. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  45. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +105 -78
  46. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  47. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +2 -2
  48. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +92 -60
  50. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/ProfileScreen.js +21 -11
  52. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/RecoverAccountScreen.js +30 -8
  54. package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SignInScreen.js +47 -26
  56. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +31 -24
  58. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  59. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +11 -7
  60. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  61. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +12 -6
  62. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  63. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +11 -7
  64. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  65. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +15 -11
  66. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  67. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +19 -27
  68. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  69. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +8 -4
  70. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  71. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +14 -10
  72. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  73. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +7 -3
  74. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  75. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +19 -14
  76. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  77. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +130 -0
  78. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -0
  79. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +13 -13
  80. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  81. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +14 -20
  82. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  83. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +22 -8
  84. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  85. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +161 -0
  86. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -0
  87. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +12 -6
  88. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  89. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +10 -6
  90. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  91. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +10 -6
  92. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  93. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +34 -4
  94. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  95. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +9 -10
  96. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  97. package/lib/commonjs/ui/styles/authStyles.js +1 -2
  98. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  99. package/lib/commonjs/utils/deviceManager.js +1 -1
  100. package/lib/commonjs/utils/deviceManager.js.map +1 -1
  101. package/lib/commonjs/utils/validationUtils.js +4 -2
  102. package/lib/commonjs/utils/validationUtils.js.map +1 -1
  103. package/lib/module/core/OxyServices.js +162 -12
  104. package/lib/module/core/OxyServices.js.map +1 -1
  105. package/lib/module/i18n/index.js +35 -0
  106. package/lib/module/i18n/index.js.map +1 -0
  107. package/lib/module/i18n/locales/en-US.json +681 -0
  108. package/lib/module/i18n/locales/es-ES.json +689 -0
  109. package/lib/module/ui/components/FollowButton.js +1 -1
  110. package/lib/module/ui/components/FollowButton.js.map +1 -1
  111. package/lib/module/ui/components/GroupedItem.js +2 -1
  112. package/lib/module/ui/components/GroupedItem.js.map +1 -1
  113. package/lib/module/ui/components/Header.js +4 -3
  114. package/lib/module/ui/components/Header.js.map +1 -1
  115. package/lib/module/ui/components/OxyProvider.js +111 -105
  116. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  117. package/lib/module/ui/components/ProfileCard.js +5 -1
  118. package/lib/module/ui/components/ProfileCard.js.map +1 -1
  119. package/lib/module/ui/components/Section.js +1 -1
  120. package/lib/module/ui/components/StepBasedScreen.js +17 -17
  121. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  122. package/lib/module/ui/components/internal/GroupedPillButtons.js +15 -3
  123. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  124. package/lib/module/ui/components/internal/PinInput.js +9 -4
  125. package/lib/module/ui/components/internal/PinInput.js.map +1 -1
  126. package/lib/module/ui/context/OxyContext.js +128 -12
  127. package/lib/module/ui/context/OxyContext.js.map +1 -1
  128. package/lib/module/ui/hooks/useI18n.js +18 -0
  129. package/lib/module/ui/hooks/useI18n.js.map +1 -0
  130. package/lib/module/ui/navigation/OxyRouter.js +7 -124
  131. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  132. package/lib/module/ui/navigation/routes.js +122 -0
  133. package/lib/module/ui/navigation/routes.js.map +1 -0
  134. package/lib/module/ui/navigation/types.js +19 -1
  135. package/lib/module/ui/navigation/types.js.map +1 -1
  136. package/lib/module/ui/screens/AccountCenterScreen.js +55 -47
  137. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  138. package/lib/module/ui/screens/AccountOverviewScreen.js +69 -61
  139. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  140. package/lib/module/ui/screens/AccountSettingsScreen.js +378 -37
  141. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  142. package/lib/module/ui/screens/AccountSwitcherScreen.js +52 -34
  143. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  144. package/lib/module/ui/screens/FeedbackScreen.js +40 -36
  145. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  146. package/lib/module/ui/screens/LanguageSelectorScreen.js +107 -80
  147. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  148. package/lib/module/ui/screens/PaymentGatewayScreen.js +2 -2
  149. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  150. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +92 -60
  151. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  152. package/lib/module/ui/screens/ProfileScreen.js +21 -11
  153. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  154. package/lib/module/ui/screens/RecoverAccountScreen.js +30 -8
  155. package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
  156. package/lib/module/ui/screens/SignInScreen.js +47 -26
  157. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  158. package/lib/module/ui/screens/WelcomeNewUserScreen.js +31 -24
  159. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  160. package/lib/module/ui/screens/internal/SignInPasswordStep.js +11 -7
  161. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  162. package/lib/module/ui/screens/internal/SignInUsernameStep.js +12 -6
  163. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  164. package/lib/module/ui/screens/karma/KarmaAboutScreen.js +11 -7
  165. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  166. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +15 -11
  167. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  168. package/lib/module/ui/screens/karma/KarmaFAQScreen.js +19 -27
  169. package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  170. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +8 -4
  171. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  172. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +14 -10
  173. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  174. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +7 -3
  175. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  176. package/lib/module/ui/screens/steps/RecoverRequestStep.js +19 -14
  177. package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  178. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +125 -0
  179. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -0
  180. package/lib/module/ui/screens/steps/RecoverSuccessStep.js +13 -13
  181. package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  182. package/lib/module/ui/screens/steps/RecoverVerifyStep.js +14 -20
  183. package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  184. package/lib/module/ui/screens/steps/SignInPasswordStep.js +22 -8
  185. package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  186. package/lib/module/ui/screens/steps/SignInTotpStep.js +156 -0
  187. package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -0
  188. package/lib/module/ui/screens/steps/SignInUsernameStep.js +12 -6
  189. package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  190. package/lib/module/ui/screens/steps/SignUpIdentityStep.js +10 -6
  191. package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  192. package/lib/module/ui/screens/steps/SignUpSecurityStep.js +10 -6
  193. package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  194. package/lib/module/ui/screens/steps/SignUpSummaryStep.js +34 -4
  195. package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  196. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +9 -10
  197. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  198. package/lib/module/ui/styles/authStyles.js +1 -2
  199. package/lib/module/ui/styles/authStyles.js.map +1 -1
  200. package/lib/module/utils/deviceManager.js +1 -1
  201. package/lib/module/utils/deviceManager.js.map +1 -1
  202. package/lib/module/utils/validationUtils.js +4 -2
  203. package/lib/module/utils/validationUtils.js.map +1 -1
  204. package/lib/typescript/core/OxyServices.d.ts +57 -3
  205. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  206. package/lib/typescript/i18n/index.d.ts +4 -0
  207. package/lib/typescript/i18n/index.d.ts.map +1 -0
  208. package/lib/typescript/models/interfaces.d.ts +4 -0
  209. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  210. package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
  211. package/lib/typescript/ui/components/Header.d.ts.map +1 -1
  212. package/lib/typescript/ui/components/OxyProvider.d.ts +1 -1
  213. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  214. package/lib/typescript/ui/components/ProfileCard.d.ts.map +1 -1
  215. package/lib/typescript/ui/components/StepBasedScreen.d.ts +2 -1
  216. package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
  217. package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
  218. package/lib/typescript/ui/components/internal/PinInput.d.ts +6 -3
  219. package/lib/typescript/ui/components/internal/PinInput.d.ts.map +1 -1
  220. package/lib/typescript/ui/context/OxyContext.d.ts +7 -4
  221. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  222. package/lib/typescript/ui/hooks/useI18n.d.ts +5 -0
  223. package/lib/typescript/ui/hooks/useI18n.d.ts.map +1 -0
  224. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  225. package/lib/typescript/ui/navigation/routes.d.ts +9 -0
  226. package/lib/typescript/ui/navigation/routes.d.ts.map +1 -0
  227. package/lib/typescript/ui/navigation/types.d.ts +24 -10
  228. package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
  229. package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  230. package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  231. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  232. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  233. package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -1
  234. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  235. package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  236. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  237. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
  238. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  239. package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  240. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +2 -1
  241. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  242. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
  243. package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
  244. package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  245. package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
  246. package/lib/typescript/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
  247. package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
  248. package/lib/typescript/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
  249. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts +4 -1
  250. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
  251. package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts +24 -0
  252. package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -0
  253. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts +2 -1
  254. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
  255. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts +3 -1
  256. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
  257. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +1 -0
  258. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
  259. package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts +19 -0
  260. package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -0
  261. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts +2 -1
  262. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
  263. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts +2 -1
  264. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
  265. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts +2 -1
  266. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
  267. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts +2 -1
  268. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
  269. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts +2 -1
  270. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
  271. package/lib/typescript/ui/styles/authStyles.d.ts +0 -1
  272. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
  273. package/lib/typescript/utils/validationUtils.d.ts.map +1 -1
  274. package/package.json +49 -15
  275. package/src/core/OxyServices.ts +138 -19
  276. package/src/i18n/index.ts +39 -0
  277. package/src/i18n/locales/en-US.json +681 -0
  278. package/src/i18n/locales/es-ES.json +689 -0
  279. package/src/models/interfaces.ts +6 -1
  280. package/src/ui/components/FollowButton.tsx +2 -2
  281. package/src/ui/components/GroupedItem.tsx +2 -1
  282. package/src/ui/components/Header.tsx +4 -3
  283. package/src/ui/components/OxyProvider.tsx +107 -114
  284. package/src/ui/components/ProfileCard.tsx +5 -1
  285. package/src/ui/components/Section.tsx +1 -1
  286. package/src/ui/components/StepBasedScreen.tsx +17 -14
  287. package/src/ui/components/internal/GroupedPillButtons.tsx +10 -6
  288. package/src/ui/components/internal/PinInput.tsx +15 -6
  289. package/src/ui/context/OxyContext.tsx +123 -20
  290. package/src/ui/hooks/useI18n.ts +12 -0
  291. package/src/ui/navigation/OxyRouter.tsx +15 -134
  292. package/src/ui/navigation/routes.ts +153 -0
  293. package/src/ui/navigation/types.ts +28 -10
  294. package/src/ui/screens/AccountCenterScreen.tsx +47 -45
  295. package/src/ui/screens/AccountOverviewScreen.tsx +68 -70
  296. package/src/ui/screens/AccountSettingsScreen.tsx +265 -41
  297. package/src/ui/screens/AccountSwitcherScreen.tsx +35 -33
  298. package/src/ui/screens/FeedbackScreen.tsx +39 -37
  299. package/src/ui/screens/LanguageSelectorScreen.tsx +99 -70
  300. package/src/ui/screens/PaymentGatewayScreen.tsx +6 -6
  301. package/src/ui/screens/PremiumSubscriptionScreen.tsx +56 -54
  302. package/src/ui/screens/ProfileScreen.tsx +14 -8
  303. package/src/ui/screens/RecoverAccountScreen.tsx +29 -8
  304. package/src/ui/screens/SignInScreen.tsx +39 -30
  305. package/src/ui/screens/WelcomeNewUserScreen.tsx +31 -17
  306. package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -8
  307. package/src/ui/screens/internal/SignInUsernameStep.tsx +10 -8
  308. package/src/ui/screens/karma/KarmaAboutScreen.tsx +23 -11
  309. package/src/ui/screens/karma/KarmaCenterScreen.tsx +21 -11
  310. package/src/ui/screens/karma/KarmaFAQScreen.tsx +15 -33
  311. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +6 -4
  312. package/src/ui/screens/karma/KarmaRewardsScreen.tsx +28 -10
  313. package/src/ui/screens/karma/KarmaRulesScreen.tsx +5 -3
  314. package/src/ui/screens/steps/RecoverRequestStep.tsx +20 -17
  315. package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +133 -0
  316. package/src/ui/screens/steps/RecoverSuccessStep.tsx +12 -19
  317. package/src/ui/screens/steps/RecoverVerifyStep.tsx +15 -24
  318. package/src/ui/screens/steps/SignInPasswordStep.tsx +19 -6
  319. package/src/ui/screens/steps/SignInTotpStep.tsx +129 -0
  320. package/src/ui/screens/steps/SignInUsernameStep.tsx +11 -10
  321. package/src/ui/screens/steps/SignUpIdentityStep.tsx +10 -11
  322. package/src/ui/screens/steps/SignUpSecurityStep.tsx +10 -11
  323. package/src/ui/screens/steps/SignUpSummaryStep.tsx +24 -9
  324. package/src/ui/screens/steps/SignUpWelcomeStep.tsx +8 -14
  325. package/src/ui/styles/authStyles.ts +0 -1
  326. package/src/utils/deviceManager.ts +1 -1
  327. package/src/utils/validationUtils.ts +5 -3
@@ -23,6 +23,8 @@ import { fontFamilies } from '../styles/fonts';
23
23
  import { confirmAction } from '../utils/confirmAction';
24
24
  import { useAuthStore } from '../stores/authStore';
25
25
  import { Header, GroupedSection } from '../components';
26
+ import { useI18n } from '../hooks/useI18n';
27
+ import QRCode from 'react-native-qrcode-svg';
26
28
 
27
29
  const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
28
30
  onClose,
@@ -30,11 +32,20 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
30
32
  goBack,
31
33
  navigate,
32
34
  }) => {
33
- const { user, oxyServices, isLoading: authLoading, isAuthenticated, showBottomSheet } = useOxy();
35
+ const { user, oxyServices, isLoading: authLoading, isAuthenticated, showBottomSheet, activeSessionId } = useOxy();
36
+ const { t } = useI18n();
34
37
  const updateUser = useAuthStore((state) => state.updateUser);
35
38
  const [isLoading, setIsLoading] = useState(false);
36
39
  const [isSaving, setIsSaving] = useState(false);
37
40
 
41
+ // Two-Factor (TOTP) state
42
+ const [totpSetupUrl, setTotpSetupUrl] = useState<string | null>(null);
43
+ const [totpCode, setTotpCode] = useState('');
44
+ const [isTotpBusy, setIsTotpBusy] = useState(false);
45
+ const [showRecoveryModal, setShowRecoveryModal] = useState(false);
46
+ const [generatedBackupCodes, setGeneratedBackupCodes] = useState<string[] | null>(null);
47
+ const [generatedRecoveryKey, setGeneratedRecoveryKey] = useState<string | null>(null);
48
+
38
49
  // Animation refs
39
50
  const saveButtonScale = useRef(new Animated.Value(1)).current;
40
51
 
@@ -209,7 +220,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
209
220
  }
210
221
 
211
222
  await updateUser(updates, oxyServices);
212
- toast.success('Profile updated successfully');
223
+ toast.success(t('editProfile.toasts.profileUpdated') || 'Profile updated successfully');
213
224
 
214
225
  animateSaveButton(1); // Scale back to normal
215
226
 
@@ -219,7 +230,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
219
230
  goBack();
220
231
  }
221
232
  } catch (error: any) {
222
- toast.error(error.message || 'Failed to update profile');
233
+ toast.error(error.message || t('editProfile.toasts.updateFailed') || 'Failed to update profile');
223
234
  animateSaveButton(1); // Scale back to normal on error
224
235
  } finally {
225
236
  setIsSaving(false);
@@ -227,9 +238,9 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
227
238
  };
228
239
 
229
240
  const handleAvatarRemove = () => {
230
- confirmAction('Remove your profile picture?', () => {
241
+ confirmAction(t('editProfile.confirms.removeAvatar') || 'Remove your profile picture?', () => {
231
242
  setAvatarFileId('');
232
- toast.success('Avatar removed');
243
+ toast.success(t('editProfile.toasts.avatarRemoved') || 'Avatar removed');
233
244
  });
234
245
  };
235
246
 
@@ -242,16 +253,16 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
242
253
  afterSelect: 'back',
243
254
  onSelect: (file: FileMetadata) => {
244
255
  if (!file.contentType.startsWith('image/')) {
245
- toast.error('Please select an image file');
256
+ toast.error(t('editProfile.toasts.selectImage') || 'Please select an image file');
246
257
  return;
247
258
  }
248
259
  // If already selected, do nothing
249
260
  if (file.id === avatarFileId) {
250
- toast.info?.('Avatar unchanged');
261
+ toast.info?.(t('editProfile.toasts.avatarUnchanged') || 'Avatar unchanged');
251
262
  return;
252
263
  }
253
264
  setAvatarFileId(file.id);
254
- toast.success('Avatar selected');
265
+ toast.success(t('editProfile.toasts.avatarSelected') || 'Avatar selected');
255
266
  // Auto-save avatar immediately (does not close edit profile screen)
256
267
  (async () => {
257
268
  try {
@@ -260,10 +271,10 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
260
271
  await updateUser({ avatar: file.id }, oxyServices);
261
272
  // Force refresh current user cache (updateUser already does a fetch with force=true internally)
262
273
  // Extra safeguard: ensure avatarFileId reflects saved id (already set) and trigger any dependent UI.
263
- toast.success('Avatar updated');
274
+ toast.success(t('editProfile.toasts.avatarUpdated') || 'Avatar updated');
264
275
  } catch (e: any) {
265
276
  console.error('[AccountSettings] Failed to auto-save avatar', e);
266
- toast.error(e.message || 'Failed to update avatar');
277
+ toast.error(e.message || t('editProfile.toasts.updateAvatarFailed') || 'Failed to update avatar');
267
278
  } finally {
268
279
  setIsSaving(false);
269
280
  }
@@ -297,6 +308,11 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
297
308
  // Don't reset the metadata - keep the existing rich metadata
298
309
  // The tempLinksWithMetadata should already contain the rich data from the database
299
310
  break;
311
+ case 'twoFactor':
312
+ // Reset TOTP temp state
313
+ setTotpSetupUrl(null);
314
+ setTotpCode('');
315
+ break;
300
316
  }
301
317
  setEditingField(type);
302
318
  };
@@ -457,6 +473,131 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
457
473
  };
458
474
 
459
475
  const renderEditingField = (type: string) => {
476
+ if (type === 'twoFactor') {
477
+ const enabled = !!user?.privacySettings?.twoFactorEnabled;
478
+ return (
479
+ <View style={[styles.editingFieldContainer, { backgroundColor: themeStyles.backgroundColor }]}>
480
+ <View style={styles.editingFieldContent}>
481
+ <View style={styles.newValueSection}>
482
+ <View style={styles.editingFieldHeader}>
483
+ <Text style={[styles.editingFieldLabel, { color: themeStyles.isDarkTheme ? '#FFFFFF' : '#1A1A1A' }]}>Two‑Factor Authentication (TOTP)</Text>
484
+ </View>
485
+
486
+ {!enabled ? (
487
+ <>
488
+ <Text style={styles.editingFieldDescription}>
489
+ Protect your account with a 6‑digit code from an authenticator app. Scan the QR code then enter the code to enable.
490
+ </Text>
491
+ {!totpSetupUrl ? (
492
+ <TouchableOpacity
493
+ style={styles.primaryButton}
494
+ disabled={isTotpBusy}
495
+ onPress={async () => {
496
+ if (!activeSessionId) { toast.error(t('editProfile.toasts.noActiveSession') || 'No active session'); return; }
497
+ setIsTotpBusy(true);
498
+ try {
499
+ const { otpauthUrl } = await oxyServices.startTotpEnrollment(activeSessionId);
500
+ setTotpSetupUrl(otpauthUrl);
501
+ } catch (e: any) {
502
+ toast.error(e?.message || (t('editProfile.toasts.totpStartFailed') || 'Failed to start TOTP enrollment'));
503
+ } finally {
504
+ setIsTotpBusy(false);
505
+ }
506
+ }}
507
+ >
508
+ <Ionicons name="shield-checkmark" size={18} color="#fff" />
509
+ <Text style={styles.primaryButtonText}>Generate QR Code</Text>
510
+ </TouchableOpacity>
511
+ ) : (
512
+ <View style={{ alignItems: 'center', gap: 16 }}>
513
+ <View style={{ padding: 16, backgroundColor: '#fff', borderRadius: 12 }}>
514
+ <QRCode value={totpSetupUrl} size={180} />
515
+ </View>
516
+ <View>
517
+ <Text style={styles.editingFieldLabel}>Enter 6‑digit code</Text>
518
+ <TextInput
519
+ style={styles.editingFieldInput}
520
+ keyboardType="number-pad"
521
+ placeholder="123456"
522
+ value={totpCode}
523
+ onChangeText={setTotpCode}
524
+ maxLength={6}
525
+ />
526
+ </View>
527
+ <TouchableOpacity
528
+ style={styles.primaryButton}
529
+ disabled={isTotpBusy || totpCode.length !== 6}
530
+ onPress={async () => {
531
+ if (!activeSessionId) { toast.error(t('editProfile.toasts.noActiveSession') || 'No active session'); return; }
532
+ setIsTotpBusy(true);
533
+ try {
534
+ const result = await oxyServices.verifyTotpEnrollment(activeSessionId, totpCode);
535
+ await updateUser({ privacySettings: { twoFactorEnabled: true } }, oxyServices);
536
+ if (result?.backupCodes || result?.recoveryKey) {
537
+ setGeneratedBackupCodes(result.backupCodes || null);
538
+ setGeneratedRecoveryKey(result.recoveryKey || null);
539
+ setShowRecoveryModal(true);
540
+ } else {
541
+ toast.success(t('editProfile.toasts.twoFactorEnabled') || 'Two‑Factor Authentication enabled');
542
+ setEditingField(null);
543
+ }
544
+ } catch (e: any) {
545
+ toast.error(e?.message || (t('editProfile.toasts.invalidCode') || 'Invalid code'));
546
+ } finally {
547
+ setIsTotpBusy(false);
548
+ }
549
+ }}
550
+ >
551
+ <Ionicons name="checkmark-circle" size={18} color="#fff" />
552
+ <Text style={styles.primaryButtonText}>Verify & Enable</Text>
553
+ </TouchableOpacity>
554
+ </View>
555
+ )}
556
+ </>
557
+ ) : (
558
+ <>
559
+ <Text style={styles.editingFieldDescription}>
560
+ Two‑Factor Authentication is currently enabled. To disable, enter a code from your authenticator app.
561
+ </Text>
562
+ <View>
563
+ <Text style={styles.editingFieldLabel}>Enter 6‑digit code</Text>
564
+ <TextInput
565
+ style={styles.editingFieldInput}
566
+ keyboardType="number-pad"
567
+ placeholder="123456"
568
+ value={totpCode}
569
+ onChangeText={setTotpCode}
570
+ maxLength={6}
571
+ />
572
+ </View>
573
+ <TouchableOpacity
574
+ style={[styles.primaryButton, { backgroundColor: '#d9534f' }]}
575
+ disabled={isTotpBusy || totpCode.length !== 6}
576
+ onPress={async () => {
577
+ if (!activeSessionId) { toast.error(t('editProfile.toasts.noActiveSession') || 'No active session'); return; }
578
+ setIsTotpBusy(true);
579
+ try {
580
+ await oxyServices.disableTotp(activeSessionId, totpCode);
581
+ await updateUser({ privacySettings: { twoFactorEnabled: false } }, oxyServices);
582
+ toast.success(t('editProfile.toasts.twoFactorDisabled') || 'Two‑Factor Authentication disabled');
583
+ setEditingField(null);
584
+ } catch (e: any) {
585
+ toast.error(e?.message || t('editProfile.toasts.disableFailed') || 'Failed to disable');
586
+ } finally {
587
+ setIsTotpBusy(false);
588
+ }
589
+ }}
590
+ >
591
+ <Ionicons name="close-circle" size={18} color="#fff" />
592
+ <Text style={styles.primaryButtonText}>Disable 2FA</Text>
593
+ </TouchableOpacity>
594
+ </>
595
+ )}
596
+ </View>
597
+ </View>
598
+ </View>
599
+ );
600
+ }
460
601
  if (type === 'displayName') {
461
602
  return (
462
603
  <View style={[styles.editingFieldContainer, { backgroundColor: themeStyles.backgroundColor }]}>
@@ -877,18 +1018,18 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
877
1018
  style={styles.editingBottomIcon}
878
1019
  />
879
1020
  <Text style={[styles.editingBottomTitle, { color: themeStyles.isDarkTheme ? '#FFFFFF' : '#1A1A1A' }]}>
880
- {editingField === 'displayName' ? 'Display Name' :
881
- editingField === 'username' ? 'Username' :
882
- editingField === 'email' ? 'Email' :
883
- editingField === 'bio' ? 'Bio' :
884
- editingField === 'location' ? 'Location' :
885
- editingField === 'links' ? 'Links' : 'Field'}
1021
+ {editingField === 'displayName' ? (t('editProfile.items.displayName.title') || 'Display Name') :
1022
+ editingField === 'username' ? (t('editProfile.items.username.title') || 'Username') :
1023
+ editingField === 'email' ? (t('editProfile.items.email.title') || 'Email') :
1024
+ editingField === 'bio' ? (t('editProfile.items.bio.title') || 'Bio') :
1025
+ editingField === 'location' ? (t('editProfile.items.locations.title') || 'Location') :
1026
+ editingField === 'links' ? (t('editProfile.items.links.title') || 'Links') : 'Field'}
886
1027
  </Text>
887
1028
  </View>
888
1029
  </View>
889
1030
  ) : (
890
1031
  <Header
891
- title="Edit Profile"
1032
+ title={t('editProfile.title') || 'Edit Profile'}
892
1033
  theme={theme}
893
1034
  onBack={goBack || onClose}
894
1035
  rightAction={{
@@ -910,9 +1051,44 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
910
1051
  ) : (
911
1052
  // Show all settings when not editing
912
1053
  <>
1054
+ {showRecoveryModal && (
1055
+ <View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.6)', zIndex: 50, padding: 16, justifyContent: 'center' }}>
1056
+ <View style={{ backgroundColor: '#fff', borderRadius: 16, padding: 20, maxHeight: '80%' }}>
1057
+ <Text style={{ fontSize: 18, fontWeight: '700', marginBottom: 12 }}>Save These Codes Now</Text>
1058
+ <Text style={{ fontSize: 14, color: '#444', marginBottom: 12 }}>
1059
+ Backup codes and your Recovery Key are shown only once. Store them securely (paper or password manager).
1060
+ </Text>
1061
+ {generatedBackupCodes && generatedBackupCodes.length > 0 && (
1062
+ <View style={{ marginBottom: 12 }}>
1063
+ <Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 8 }}>Backup Codes</Text>
1064
+ <View style={{ backgroundColor: '#F8F9FA', borderRadius: 8, padding: 12 }}>
1065
+ {generatedBackupCodes.map((c, idx) => (
1066
+ <Text key={idx} style={{ fontFamily: Platform.OS === 'web' ? 'monospace' as any : 'monospace', fontSize: 14, marginBottom: 4 }}>{c}</Text>
1067
+ ))}
1068
+ </View>
1069
+ </View>
1070
+ )}
1071
+ {generatedRecoveryKey && (
1072
+ <View style={{ marginBottom: 12 }}>
1073
+ <Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 8 }}>Recovery Key</Text>
1074
+ <View style={{ backgroundColor: '#F8F9FA', borderRadius: 8, padding: 12 }}>
1075
+ <Text style={{ fontFamily: Platform.OS === 'web' ? 'monospace' as any : 'monospace', fontSize: 14 }}>{generatedRecoveryKey}</Text>
1076
+ </View>
1077
+ </View>
1078
+ )}
1079
+ <TouchableOpacity
1080
+ style={[styles.primaryButton, { alignSelf: 'flex-end', marginTop: 8 }]}
1081
+ onPress={() => { setShowRecoveryModal(false); setEditingField(null); toast.success(t('editProfile.toasts.twoFactorEnabled') || 'Two‑Factor Authentication enabled'); }}
1082
+ >
1083
+ <Ionicons name="checkmark" size={18} color="#fff" />
1084
+ <Text style={styles.primaryButtonText}>I saved them</Text>
1085
+ </TouchableOpacity>
1086
+ </View>
1087
+ </View>
1088
+ )}
913
1089
  {/* Profile Picture Section */}
914
1090
  <View style={styles.section}>
915
- <Text style={styles.sectionTitle}>Profile Picture</Text>
1091
+ <Text style={styles.sectionTitle}>{t('editProfile.sections.profilePicture') || 'Profile Picture'}</Text>
916
1092
  <GroupedSection
917
1093
  items={[
918
1094
  {
@@ -943,7 +1119,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
943
1119
 
944
1120
  {/* Basic Information */}
945
1121
  <View style={styles.section}>
946
- <Text style={styles.sectionTitle}>Basic Information</Text>
1122
+ <Text style={styles.sectionTitle}>{t('editProfile.sections.basicInfo') || 'Basic Information'}</Text>
947
1123
 
948
1124
  <GroupedSection
949
1125
  items={[
@@ -951,24 +1127,24 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
951
1127
  id: 'display-name',
952
1128
  icon: 'person',
953
1129
  iconColor: '#007AFF',
954
- title: 'Display Name',
955
- subtitle: [displayName, lastName].filter(Boolean).join(' ') || 'Add your display name',
1130
+ title: t('editProfile.items.displayName.title') || 'Display Name',
1131
+ subtitle: [displayName, lastName].filter(Boolean).join(' ') || (t('editProfile.items.displayName.add') || 'Add your display name'),
956
1132
  onPress: () => startEditing('displayName', ''),
957
1133
  },
958
1134
  {
959
1135
  id: 'username',
960
1136
  icon: 'at',
961
1137
  iconColor: '#5856D6',
962
- title: 'Username',
963
- subtitle: username || 'Choose a username',
1138
+ title: t('editProfile.items.username.title') || 'Username',
1139
+ subtitle: username || (t('editProfile.items.username.choose') || 'Choose a username'),
964
1140
  onPress: () => startEditing('username', username),
965
1141
  },
966
1142
  {
967
1143
  id: 'email',
968
1144
  icon: 'mail',
969
1145
  iconColor: '#FF9500',
970
- title: 'Email',
971
- subtitle: email || 'Add your email address',
1146
+ title: t('editProfile.items.email.title') || 'Email',
1147
+ subtitle: email || (t('editProfile.items.email.add') || 'Add your email address'),
972
1148
  onPress: () => startEditing('email', email),
973
1149
  },
974
1150
  ]}
@@ -978,7 +1154,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
978
1154
 
979
1155
  {/* About You */}
980
1156
  <View style={styles.section}>
981
- <Text style={styles.sectionTitle}>About You</Text>
1157
+ <Text style={styles.sectionTitle}>{t('editProfile.sections.about') || 'About You'}</Text>
982
1158
 
983
1159
  <GroupedSection
984
1160
  items={[
@@ -986,16 +1162,20 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
986
1162
  id: 'bio',
987
1163
  icon: 'document-text',
988
1164
  iconColor: '#34C759',
989
- title: 'Bio',
990
- subtitle: bio || 'Tell people about yourself',
1165
+ title: t('editProfile.items.bio.title') || 'Bio',
1166
+ subtitle: bio || (t('editProfile.items.bio.placeholder') || 'Tell people about yourself'),
991
1167
  onPress: () => startEditing('bio', bio),
992
1168
  },
993
1169
  {
994
1170
  id: 'locations',
995
1171
  icon: 'location',
996
1172
  iconColor: '#FF3B30',
997
- title: 'Locations',
998
- subtitle: tempLocations.length > 0 ? `${tempLocations.length} location${tempLocations.length !== 1 ? 's' : ''} added` : 'Add your locations',
1173
+ title: t('editProfile.items.locations.title') || 'Locations',
1174
+ subtitle: tempLocations.length > 0
1175
+ ? (tempLocations.length === 1
1176
+ ? (t('editProfile.items.locations.count', { count: tempLocations.length }) || `${tempLocations.length} location added`)
1177
+ : (t('editProfile.items.locations.count_plural', { count: tempLocations.length }) || `${tempLocations.length} locations added`))
1178
+ : (t('editProfile.items.locations.add') || 'Add your locations'),
999
1179
  onPress: () => startEditing('location', ''),
1000
1180
  customContentBelow: tempLocations.length > 0 && (
1001
1181
  <View style={styles.linksPreviewContainer}>
@@ -1030,8 +1210,12 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
1030
1210
  id: 'links',
1031
1211
  icon: 'link',
1032
1212
  iconColor: '#32D74B',
1033
- title: 'Links',
1034
- subtitle: tempLinksWithMetadata.length > 0 ? `${tempLinksWithMetadata.length} link${tempLinksWithMetadata.length !== 1 ? 's' : ''} added` : 'Add your links',
1213
+ title: t('editProfile.items.links.title') || 'Links',
1214
+ subtitle: tempLinksWithMetadata.length > 0
1215
+ ? (tempLinksWithMetadata.length === 1
1216
+ ? (t('editProfile.items.links.count', { count: tempLinksWithMetadata.length }) || `${tempLinksWithMetadata.length} link added`)
1217
+ : (t('editProfile.items.links.count_plural', { count: tempLinksWithMetadata.length }) || `${tempLinksWithMetadata.length} links added`))
1218
+ : (t('editProfile.items.links.add') || 'Add your links'),
1035
1219
  onPress: () => startEditing('links', ''),
1036
1220
  multiRow: true,
1037
1221
  customContentBelow: tempLinksWithMetadata.length > 0 && (
@@ -1067,7 +1251,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
1067
1251
 
1068
1252
  {/* Quick Actions */}
1069
1253
  <View style={styles.section}>
1070
- <Text style={styles.sectionTitle}>Quick Actions</Text>
1254
+ <Text style={styles.sectionTitle}>{t('editProfile.sections.quickActions') || 'Quick Actions'}</Text>
1071
1255
 
1072
1256
  <GroupedSection
1073
1257
  items={[
@@ -1075,25 +1259,45 @@ const AccountSettingsScreen: React.FC<BaseScreenProps> = ({
1075
1259
  id: 'preview-profile',
1076
1260
  icon: 'eye',
1077
1261
  iconColor: '#007AFF',
1078
- title: 'Preview Profile',
1079
- subtitle: 'See how your profile looks to others',
1262
+ title: t('editProfile.items.previewProfile.title') || 'Preview Profile',
1263
+ subtitle: t('editProfile.items.previewProfile.subtitle') || 'See how your profile looks to others',
1080
1264
  onPress: () => navigate?.('Profile', { userId: user?.id }),
1081
1265
  },
1082
1266
  {
1083
1267
  id: 'privacy-settings',
1084
1268
  icon: 'shield-checkmark',
1085
1269
  iconColor: '#8E8E93',
1086
- title: 'Privacy Settings',
1087
- subtitle: 'Control who can see your profile',
1088
- onPress: () => toast.info('Privacy settings coming soon!'),
1270
+ title: t('editProfile.items.privacySettings.title') || 'Privacy Settings',
1271
+ subtitle: t('editProfile.items.privacySettings.subtitle') || 'Control who can see your profile',
1272
+ onPress: () => toast.info(t('editProfile.items.privacySettings.coming') || 'Privacy settings coming soon!'),
1089
1273
  },
1090
1274
  {
1091
1275
  id: 'verify-account',
1092
1276
  icon: 'checkmark-circle',
1093
1277
  iconColor: '#30D158',
1094
- title: 'Verify Account',
1095
- subtitle: 'Get a verified badge',
1096
- onPress: () => toast.info('Account verification coming soon!'),
1278
+ title: t('editProfile.items.verifyAccount.title') || 'Verify Account',
1279
+ subtitle: t('editProfile.items.verifyAccount.subtitle') || 'Get a verified badge',
1280
+ onPress: () => toast.info(t('editProfile.items.verifyAccount.coming') || 'Account verification coming soon!'),
1281
+ },
1282
+ ]}
1283
+ theme={theme}
1284
+ />
1285
+ </View>
1286
+
1287
+ {/* Security */}
1288
+ <View style={styles.section}>
1289
+ <Text style={styles.sectionTitle}>{t('editProfile.sections.security') || 'Security'}</Text>
1290
+ <GroupedSection
1291
+ items={[
1292
+ {
1293
+ id: 'two-factor',
1294
+ icon: 'shield-checkmark',
1295
+ iconColor: '#007AFF',
1296
+ title: t('editProfile.items.twoFactor.title') || 'Two‑Factor Authentication',
1297
+ subtitle: user?.privacySettings?.twoFactorEnabled
1298
+ ? (t('editProfile.items.twoFactor.enabled') || 'Enabled')
1299
+ : (t('editProfile.items.twoFactor.disabled') || 'Disabled (recommended)'),
1300
+ onPress: () => startEditing('twoFactor', ''),
1097
1301
  },
1098
1302
  ]}
1099
1303
  theme={theme}
@@ -1183,6 +1387,26 @@ const styles = StyleSheet.create({
1183
1387
  minHeight: 52,
1184
1388
  fontWeight: '400',
1185
1389
  },
1390
+ editingFieldDescription: {
1391
+ fontSize: 14,
1392
+ color: '#666',
1393
+ marginBottom: 16,
1394
+ },
1395
+ primaryButton: {
1396
+ flexDirection: 'row',
1397
+ alignItems: 'center',
1398
+ justifyContent: 'center',
1399
+ gap: 8,
1400
+ backgroundColor: '#007AFF',
1401
+ paddingVertical: 12,
1402
+ paddingHorizontal: 16,
1403
+ borderRadius: 10,
1404
+ },
1405
+ primaryButtonText: {
1406
+ color: '#fff',
1407
+ fontSize: 16,
1408
+ fontWeight: '600',
1409
+ },
1186
1410
  editingFieldTextArea: {
1187
1411
  backgroundColor: '#fff',
1188
1412
  borderWidth: 2,