@oxyhq/services 5.7.5 → 5.8.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 (303) hide show
  1. package/README.md +76 -76
  2. package/lib/commonjs/core/index.js +177 -102
  3. package/lib/commonjs/core/index.js.map +1 -1
  4. package/lib/commonjs/index.js +69 -28
  5. package/lib/commonjs/index.js.map +1 -1
  6. package/lib/commonjs/ui/components/Avatar.js +15 -6
  7. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  8. package/lib/commonjs/ui/components/FollowButton.js +100 -12
  9. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  10. package/lib/commonjs/ui/components/GroupedItem.js +58 -13
  11. package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
  12. package/lib/commonjs/ui/components/GroupedSection.js +7 -1
  13. package/lib/commonjs/ui/components/GroupedSection.js.map +1 -1
  14. package/lib/commonjs/ui/components/Header.js +356 -0
  15. package/lib/commonjs/ui/components/Header.js.map +1 -0
  16. package/lib/commonjs/ui/components/OxyProvider.js +28 -7
  17. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  18. package/lib/commonjs/ui/components/index.js +7 -0
  19. package/lib/commonjs/ui/components/index.js.map +1 -1
  20. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +1 -1
  21. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  22. package/lib/commonjs/ui/components/internal/TextField.js +606 -546
  23. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
  24. package/lib/commonjs/ui/components/internal/TextField.md +436 -0
  25. package/lib/commonjs/ui/context/OxyContext.js +181 -199
  26. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  27. package/lib/commonjs/ui/hooks/index.js +6 -0
  28. package/lib/commonjs/ui/hooks/index.js.map +1 -1
  29. package/lib/commonjs/ui/hooks/useFollow.js +59 -2
  30. package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
  31. package/lib/commonjs/ui/hooks/useSessionSocket.js +5 -2
  32. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  33. package/lib/commonjs/ui/navigation/OxyRouter.js +11 -1
  34. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  35. package/lib/commonjs/ui/screens/AccountCenterScreen.js +6 -6
  36. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
  38. package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
  39. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +241 -598
  40. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  41. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +1160 -406
  42. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  43. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +135 -237
  44. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  45. package/lib/commonjs/ui/screens/AppInfoScreen.js +246 -463
  46. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  47. package/lib/commonjs/ui/screens/FeedbackScreen.js +3 -3
  48. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +808 -650
  50. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/ProfileScreen.js +214 -37
  52. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/RecoverAccountScreen.js +51 -72
  54. package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SessionManagementScreen.js +11 -29
  56. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/SignInScreen.js +30 -303
  58. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  59. package/lib/commonjs/ui/screens/SignUpScreen.js +4 -4
  60. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  61. package/lib/commonjs/ui/screens/UserLinksScreen.js +90 -0
  62. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -0
  63. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +19 -31
  64. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  65. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +7 -10
  66. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  67. package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js +11 -5
  68. package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
  69. package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js +11 -4
  70. package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
  71. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +9 -6
  72. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  73. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +3 -30
  74. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  75. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +37 -46
  76. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  77. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
  78. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  79. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +9 -12
  80. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  81. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +9 -12
  82. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  83. package/lib/commonjs/ui/stores/authStore.js +36 -6
  84. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  85. package/lib/commonjs/ui/stores/followStore.js +106 -1
  86. package/lib/commonjs/ui/stores/followStore.js.map +1 -1
  87. package/lib/commonjs/ui/styles/authStyles.js +337 -0
  88. package/lib/commonjs/ui/styles/authStyles.js.map +1 -0
  89. package/lib/commonjs/ui/styles/index.js +11 -0
  90. package/lib/commonjs/ui/styles/index.js.map +1 -1
  91. package/lib/module/core/index.js +177 -41
  92. package/lib/module/core/index.js.map +1 -1
  93. package/lib/module/index.js +24 -4
  94. package/lib/module/index.js.map +1 -1
  95. package/lib/module/ui/components/Avatar.js +15 -6
  96. package/lib/module/ui/components/Avatar.js.map +1 -1
  97. package/lib/module/ui/components/FollowButton.js +101 -13
  98. package/lib/module/ui/components/FollowButton.js.map +1 -1
  99. package/lib/module/ui/components/GroupedItem.js +59 -14
  100. package/lib/module/ui/components/GroupedItem.js.map +1 -1
  101. package/lib/module/ui/components/GroupedSection.js +7 -1
  102. package/lib/module/ui/components/GroupedSection.js.map +1 -1
  103. package/lib/module/ui/components/Header.js +351 -0
  104. package/lib/module/ui/components/Header.js.map +1 -0
  105. package/lib/module/ui/components/OxyProvider.js +30 -9
  106. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  107. package/lib/module/ui/components/index.js +1 -0
  108. package/lib/module/ui/components/index.js.map +1 -1
  109. package/lib/module/ui/components/internal/GroupedPillButtons.js +1 -1
  110. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  111. package/lib/module/ui/components/internal/TextField.js +607 -547
  112. package/lib/module/ui/components/internal/TextField.js.map +1 -1
  113. package/lib/module/ui/components/internal/TextField.md +436 -0
  114. package/lib/module/ui/context/OxyContext.js +180 -198
  115. package/lib/module/ui/context/OxyContext.js.map +1 -1
  116. package/lib/module/ui/hooks/index.js +1 -1
  117. package/lib/module/ui/hooks/index.js.map +1 -1
  118. package/lib/module/ui/hooks/useFollow.js +57 -1
  119. package/lib/module/ui/hooks/useFollow.js.map +1 -1
  120. package/lib/module/ui/hooks/useSessionSocket.js +5 -2
  121. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  122. package/lib/module/ui/navigation/OxyRouter.js +11 -1
  123. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  124. package/lib/module/ui/screens/AccountCenterScreen.js +6 -6
  125. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  126. package/lib/module/ui/screens/AccountManagementDemo.js +3 -3
  127. package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
  128. package/lib/module/ui/screens/AccountOverviewScreen.js +242 -597
  129. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  130. package/lib/module/ui/screens/AccountSettingsScreen.js +1161 -407
  131. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  132. package/lib/module/ui/screens/AccountSwitcherScreen.js +135 -237
  133. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  134. package/lib/module/ui/screens/AppInfoScreen.js +248 -465
  135. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  136. package/lib/module/ui/screens/FeedbackScreen.js +3 -3
  137. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  138. package/lib/module/ui/screens/PaymentGatewayScreen.js +809 -651
  139. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  140. package/lib/module/ui/screens/ProfileScreen.js +214 -37
  141. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  142. package/lib/module/ui/screens/RecoverAccountScreen.js +53 -74
  143. package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
  144. package/lib/module/ui/screens/SessionManagementScreen.js +11 -29
  145. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  146. package/lib/module/ui/screens/SignInScreen.js +32 -305
  147. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  148. package/lib/module/ui/screens/SignUpScreen.js +5 -5
  149. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  150. package/lib/module/ui/screens/UserLinksScreen.js +85 -0
  151. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -0
  152. package/lib/module/ui/screens/internal/SignInPasswordStep.js +19 -31
  153. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  154. package/lib/module/ui/screens/internal/SignInUsernameStep.js +7 -10
  155. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  156. package/lib/module/ui/screens/internal/SignUpIdentityStep.js +11 -5
  157. package/lib/module/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
  158. package/lib/module/ui/screens/internal/SignUpSecurityStep.js +11 -4
  159. package/lib/module/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
  160. package/lib/module/ui/screens/karma/KarmaAboutScreen.js +9 -6
  161. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  162. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -30
  163. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  164. package/lib/module/ui/screens/karma/KarmaFAQScreen.js +37 -46
  165. package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  166. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
  167. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  168. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +9 -12
  169. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  170. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +9 -12
  171. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  172. package/lib/module/ui/stores/authStore.js +36 -6
  173. package/lib/module/ui/stores/authStore.js.map +1 -1
  174. package/lib/module/ui/stores/followStore.js +106 -1
  175. package/lib/module/ui/stores/followStore.js.map +1 -1
  176. package/lib/module/ui/styles/authStyles.js +332 -0
  177. package/lib/module/ui/styles/authStyles.js.map +1 -0
  178. package/lib/module/ui/styles/index.js +1 -0
  179. package/lib/module/ui/styles/index.js.map +1 -1
  180. package/lib/typescript/core/index.d.ts +68 -24
  181. package/lib/typescript/core/index.d.ts.map +1 -1
  182. package/lib/typescript/index.d.ts +13 -3
  183. package/lib/typescript/index.d.ts.map +1 -1
  184. package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
  185. package/lib/typescript/ui/components/FollowButton.d.ts +1 -0
  186. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  187. package/lib/typescript/ui/components/GroupedItem.d.ts +6 -0
  188. package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
  189. package/lib/typescript/ui/components/GroupedSection.d.ts +6 -0
  190. package/lib/typescript/ui/components/GroupedSection.d.ts.map +1 -1
  191. package/lib/typescript/ui/components/Header.d.ts +24 -0
  192. package/lib/typescript/ui/components/Header.d.ts.map +1 -0
  193. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  194. package/lib/typescript/ui/components/index.d.ts +1 -0
  195. package/lib/typescript/ui/components/index.d.ts.map +1 -1
  196. package/lib/typescript/ui/components/internal/TextField.d.ts +31 -16
  197. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
  198. package/lib/typescript/ui/context/OxyContext.d.ts +5 -2
  199. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  200. package/lib/typescript/ui/hooks/index.d.ts +1 -1
  201. package/lib/typescript/ui/hooks/index.d.ts.map +1 -1
  202. package/lib/typescript/ui/hooks/useFollow.d.ts +20 -0
  203. package/lib/typescript/ui/hooks/useFollow.d.ts.map +1 -1
  204. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  205. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  206. package/lib/typescript/ui/navigation/types.d.ts +9 -2
  207. package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
  208. package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  209. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  210. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  211. package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
  212. package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  213. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  214. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts +5 -1
  215. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
  216. package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  217. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  218. package/lib/typescript/ui/screens/UserLinksScreen.d.ts +15 -0
  219. package/lib/typescript/ui/screens/UserLinksScreen.d.ts.map +1 -0
  220. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +1 -1
  221. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  222. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts +0 -1
  223. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
  224. package/lib/typescript/ui/screens/internal/SignUpIdentityStep.d.ts.map +1 -1
  225. package/lib/typescript/ui/screens/internal/SignUpSecurityStep.d.ts.map +1 -1
  226. package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
  227. package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  228. package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
  229. package/lib/typescript/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
  230. package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
  231. package/lib/typescript/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
  232. package/lib/typescript/ui/stores/authStore.d.ts +3 -1
  233. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  234. package/lib/typescript/ui/stores/followStore.d.ts +10 -0
  235. package/lib/typescript/ui/stores/followStore.d.ts.map +1 -1
  236. package/lib/typescript/ui/styles/authStyles.d.ts +326 -0
  237. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -0
  238. package/lib/typescript/ui/styles/index.d.ts +1 -0
  239. package/lib/typescript/ui/styles/index.d.ts.map +1 -1
  240. package/package.json +1 -4
  241. package/src/core/index.ts +195 -41
  242. package/src/index.ts +64 -4
  243. package/src/ui/components/Avatar.tsx +11 -5
  244. package/src/ui/components/FollowButton.tsx +95 -11
  245. package/src/ui/components/GroupedItem.tsx +57 -9
  246. package/src/ui/components/GroupedSection.tsx +12 -0
  247. package/src/ui/components/Header.tsx +405 -0
  248. package/src/ui/components/OxyProvider.tsx +37 -15
  249. package/src/ui/components/index.ts +1 -0
  250. package/src/ui/components/internal/GroupedPillButtons.tsx +1 -1
  251. package/src/ui/components/internal/TextField.md +436 -0
  252. package/src/ui/components/internal/TextField.tsx +720 -620
  253. package/src/ui/context/OxyContext.tsx +211 -195
  254. package/src/ui/hooks/index.ts +1 -1
  255. package/src/ui/hooks/useFollow.ts +63 -0
  256. package/src/ui/hooks/useSessionSocket.ts +5 -2
  257. package/src/ui/navigation/OxyRouter.tsx +11 -1
  258. package/src/ui/navigation/types.ts +10 -2
  259. package/src/ui/screens/AccountCenterScreen.tsx +5 -5
  260. package/src/ui/screens/AccountManagementDemo.tsx +9 -9
  261. package/src/ui/screens/AccountOverviewScreen.tsx +265 -414
  262. package/src/ui/screens/AccountSettingsScreen.tsx +1173 -403
  263. package/src/ui/screens/AccountSwitcherScreen.tsx +158 -202
  264. package/src/ui/screens/AppInfoScreen.tsx +270 -497
  265. package/src/ui/screens/FeedbackScreen.tsx +3 -3
  266. package/src/ui/screens/PaymentGatewayScreen.tsx +668 -365
  267. package/src/ui/screens/ProfileScreen.tsx +196 -33
  268. package/src/ui/screens/RecoverAccountScreen.tsx +46 -74
  269. package/src/ui/screens/SessionManagementScreen.tsx +14 -22
  270. package/src/ui/screens/SignInScreen.tsx +27 -294
  271. package/src/ui/screens/SignUpScreen.tsx +5 -5
  272. package/src/ui/screens/UserLinksScreen.tsx +96 -0
  273. package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -22
  274. package/src/ui/screens/internal/SignInUsernameStep.tsx +3 -10
  275. package/src/ui/screens/internal/SignUpIdentityStep.tsx +2 -5
  276. package/src/ui/screens/internal/SignUpSecurityStep.tsx +3 -4
  277. package/src/ui/screens/karma/KarmaAboutScreen.tsx +9 -2
  278. package/src/ui/screens/karma/KarmaCenterScreen.tsx +1 -20
  279. package/src/ui/screens/karma/KarmaFAQScreen.tsx +40 -24
  280. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +9 -3
  281. package/src/ui/screens/karma/KarmaRewardsScreen.tsx +9 -3
  282. package/src/ui/screens/karma/KarmaRulesScreen.tsx +9 -3
  283. package/src/ui/stores/authStore.ts +34 -7
  284. package/src/ui/stores/followStore.ts +102 -1
  285. package/src/ui/styles/authStyles.ts +352 -0
  286. package/src/ui/styles/index.ts +1 -0
  287. package/lib/commonjs/core/auth-manager.js +0 -440
  288. package/lib/commonjs/core/auth-manager.js.map +0 -1
  289. package/lib/commonjs/core/use-auth.js +0 -244
  290. package/lib/commonjs/core/use-auth.js.map +0 -1
  291. package/lib/module/core/auth-manager.js +0 -432
  292. package/lib/module/core/auth-manager.js.map +0 -1
  293. package/lib/module/core/use-auth.js +0 -235
  294. package/lib/module/core/use-auth.js.map +0 -1
  295. package/lib/typescript/core/auth-manager.d.ts +0 -136
  296. package/lib/typescript/core/auth-manager.d.ts.map +0 -1
  297. package/lib/typescript/core/use-auth.d.ts +0 -79
  298. package/lib/typescript/core/use-auth.d.ts.map +0 -1
  299. package/src/__tests__/middleware.test.ts +0 -105
  300. package/src/__tests__/setup.ts +0 -10
  301. package/src/__tests__/zero-config-auth.test.ts +0 -607
  302. package/src/core/auth-manager.ts +0 -500
  303. package/src/core/use-auth.tsx +0 -245
@@ -1,8 +1,10 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { View, Text, StyleSheet, ActivityIndicator, ScrollView, TouchableOpacity } from 'react-native';
2
+ import { View, Text, StyleSheet, ActivityIndicator, ScrollView, TouchableOpacity, Image } from 'react-native';
3
3
  import { BaseScreenProps } from '../navigation/types';
4
4
  import { useOxy } from '../context/OxyContext';
5
5
  import Avatar from '../components/Avatar';
6
+ import { FollowButton } from '../components';
7
+ import { useFollow } from '../hooks/useFollow';
6
8
  import { Ionicons } from '@expo/vector-icons';
7
9
 
8
10
  interface ProfileScreenProps extends BaseScreenProps {
@@ -10,26 +12,44 @@ interface ProfileScreenProps extends BaseScreenProps {
10
12
  username?: string;
11
13
  }
12
14
 
13
- const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme, goBack }) => {
15
+ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme, goBack, navigate }) => {
14
16
  const { oxyServices, user: currentUser } = useOxy();
15
17
  const [profile, setProfile] = useState<any>(null);
16
18
  const [karmaTotal, setKarmaTotal] = useState<number | null>(null);
17
19
  const [postsCount, setPostsCount] = useState<number | null>(null);
18
20
  const [commentsCount, setCommentsCount] = useState<number | null>(null);
19
- const [followersCount, setFollowersCount] = useState<number | null>(null);
20
- const [followingCount, setFollowingCount] = useState<number | null>(null);
21
21
  const [isLoading, setIsLoading] = useState(true);
22
22
  const [error, setError] = useState<string | null>(null);
23
+ const [links, setLinks] = useState<Array<{
24
+ url: string;
25
+ title?: string;
26
+ description?: string;
27
+ image?: string;
28
+ id: string;
29
+ }>>([]);
30
+
31
+ // Use the follow hook for real follower data
32
+ const {
33
+ followerCount,
34
+ followingCount,
35
+ isLoadingCounts,
36
+ fetchUserCounts,
37
+ setFollowerCount,
38
+ setFollowingCount,
39
+ } = useFollow(userId);
23
40
 
24
41
  const isDarkTheme = theme === 'dark';
25
42
  const backgroundColor = isDarkTheme ? '#121212' : '#FFFFFF';
26
43
  const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
27
44
  const primaryColor = '#d169e5';
28
45
 
46
+ // Check if current user is viewing their own profile
47
+ const isOwnProfile = currentUser && currentUser.id === userId;
48
+
29
49
  useEffect(() => {
30
50
  console.log('ProfileScreen - userId:', userId);
31
51
  console.log('ProfileScreen - username:', username);
32
-
52
+
33
53
  if (!userId) {
34
54
  setError('No user ID provided');
35
55
  setIsLoading(false);
@@ -50,11 +70,11 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
50
70
  }
51
71
  throw err;
52
72
  }),
53
- oxyServices.getUserKarmaTotal ?
73
+ oxyServices.getUserKarmaTotal ?
54
74
  oxyServices.getUserKarmaTotal(userId).catch(err => {
55
75
  console.warn('getUserKarmaTotal error:', err);
56
76
  return { total: undefined };
57
- }) :
77
+ }) :
58
78
  Promise.resolve({ total: undefined })
59
79
  ])
60
80
  .then(([profileRes, karmaRes]) => {
@@ -62,18 +82,56 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
62
82
  setProfile(profileRes);
63
83
  setKarmaTotal(typeof karmaRes.total === 'number' ? karmaRes.total : null);
64
84
 
65
- // Mock data for other stats
66
- // In a real app, these would come from API endpoints
85
+ // Extract links from profile data
86
+ if (profileRes.linksMetadata && Array.isArray(profileRes.linksMetadata)) {
87
+ const linksWithIds = profileRes.linksMetadata.map((link: any, index: number) => ({
88
+ ...link,
89
+ id: link.id || `existing-${index}`
90
+ }));
91
+ setLinks(linksWithIds);
92
+ } else if (Array.isArray(profileRes.links)) {
93
+ const simpleLinks = profileRes.links.map((l: any) => typeof l === 'string' ? l : l.link).filter(Boolean);
94
+ const linksWithMetadata = simpleLinks.map((url: string, index: number) => ({
95
+ url,
96
+ title: url.replace(/^https?:\/\//, '').replace(/\/$/, ''),
97
+ description: `Link to ${url}`,
98
+ image: undefined,
99
+ id: `existing-${index}`
100
+ }));
101
+ setLinks(linksWithMetadata);
102
+ } else if (profileRes.website) {
103
+ setLinks([{
104
+ url: profileRes.website,
105
+ title: profileRes.website.replace(/^https?:\/\//, '').replace(/\/$/, ''),
106
+ description: `Link to ${profileRes.website}`,
107
+ image: undefined,
108
+ id: 'existing-0'
109
+ }]);
110
+ } else {
111
+ setLinks([]);
112
+ }
113
+
114
+ // Set real follower counts from profile data if available
115
+ if (profileRes._count) {
116
+ setFollowerCount?.(profileRes._count.followers || 0);
117
+ setFollowingCount?.(profileRes._count.following || 0);
118
+ } else if (profileRes.stats) {
119
+ setFollowerCount?.(profileRes.stats.followers || 0);
120
+ setFollowingCount?.(profileRes.stats.following || 0);
121
+ } else {
122
+ // Fallback: fetch counts separately
123
+ fetchUserCounts?.();
124
+ }
125
+
126
+ // Mock data for other stats (these would come from separate API endpoints)
67
127
  setPostsCount(Math.floor(Math.random() * 50));
68
128
  setCommentsCount(Math.floor(Math.random() * 100));
69
- setFollowersCount(Math.floor(Math.random() * 200));
70
- setFollowingCount(Math.floor(Math.random() * 100));
71
129
  })
72
130
  .catch((err: any) => {
73
131
  console.error('Profile loading error:', err);
74
132
  // Provide user-friendly error messages based on the error type
75
133
  let errorMessage = 'Failed to load profile';
76
-
134
+
77
135
  if (err.status === 404 || err.message?.includes('not found') || err.message?.includes('Resource not found')) {
78
136
  if (currentUser && currentUser.id === userId) {
79
137
  errorMessage = 'Unable to load your profile from the server. This may be due to a temporary service issue.';
@@ -87,7 +145,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
87
145
  } else if (err.message) {
88
146
  errorMessage = err.message;
89
147
  }
90
-
148
+
91
149
  setError(errorMessage);
92
150
  })
93
151
  .finally(() => setIsLoading(false));
@@ -135,9 +193,25 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
135
193
  <View style={styles.avatarWrapper}>
136
194
  <Avatar uri={profile?.avatar?.url} name={profile?.username || username} size={96} theme={theme} />
137
195
  </View>
138
- {/* Edit Profile/Follow Button placeholder */}
196
+ {/* Conditional Action Button */}
139
197
  <View style={styles.actionButtonWrapper}>
140
- <Text style={styles.actionButton}>Edit Profile</Text>
198
+ {isOwnProfile ? (
199
+ <TouchableOpacity
200
+ style={styles.actionButton}
201
+ onPress={() => navigate?.('EditProfile')}
202
+ >
203
+ <Text style={styles.actionButtonText}>Edit Profile</Text>
204
+ </TouchableOpacity>
205
+ ) : (
206
+ <FollowButton
207
+ userId={userId}
208
+ theme={theme}
209
+ onFollowChange={(isFollowing) => {
210
+ // The follow button will automatically update counts via Zustand
211
+ console.log(`Follow status changed: ${isFollowing}`);
212
+ }}
213
+ />
214
+ )}
141
215
  </View>
142
216
  </View>
143
217
  {/* Profile Info */}
@@ -148,20 +222,67 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
148
222
  )}
149
223
  {/* Bio placeholder */}
150
224
  <Text style={[styles.bio, { color: textColor }]}>{profile?.bio || 'This user has no bio yet.'}</Text>
151
- {/* Email and Join Date Row */}
152
- <View style={styles.infoRow}>
153
- {profile?.email && (
154
- <View style={styles.infoItem}>
155
- <Ionicons name="mail-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 4 }} />
156
- <Text style={[styles.infoText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>{profile.email}</Text>
225
+
226
+ {/* Info Grid Row */}
227
+ <View style={styles.infoGrid}>
228
+ {profile?.createdAt && (
229
+ <View style={styles.infoGridItem}>
230
+ <Ionicons name="calendar-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
231
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>Joined {new Date(profile.createdAt).toLocaleDateString()}</Text>
157
232
  </View>
158
233
  )}
159
- {profile?.createdAt && (
160
- <View style={styles.infoItem}>
161
- <Ionicons name="calendar-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 4 }} />
162
- <Text style={[styles.infoText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>Joined {new Date(profile.createdAt).toLocaleDateString()}</Text>
234
+ {profile?.location && (
235
+ <View style={styles.infoGridItem}>
236
+ <Ionicons name="location-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
237
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]} numberOfLines={1}>{profile.location}</Text>
238
+ </View>
239
+ )}
240
+ {profile?.website && (
241
+ <View style={styles.infoGridItem}>
242
+ <Ionicons name="globe-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
243
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]} numberOfLines={1}>{profile.website}</Text>
244
+ </View>
245
+ )}
246
+ {profile?.company && (
247
+ <View style={styles.infoGridItem}>
248
+ <Ionicons name="business-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
249
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]} numberOfLines={1}>{profile.company}</Text>
250
+ </View>
251
+ )}
252
+ {profile?.jobTitle && (
253
+ <View style={styles.infoGridItem}>
254
+ <Ionicons name="briefcase-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
255
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]} numberOfLines={1}>{profile.jobTitle}</Text>
256
+ </View>
257
+ )}
258
+ {profile?.education && (
259
+ <View style={styles.infoGridItem}>
260
+ <Ionicons name="school-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
261
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]} numberOfLines={1}>{profile.education}</Text>
262
+ </View>
263
+ )}
264
+ {profile?.birthday && (
265
+ <View style={styles.infoGridItem}>
266
+ <Ionicons name="gift-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
267
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>Born {new Date(profile.birthday).toLocaleDateString()}</Text>
163
268
  </View>
164
269
  )}
270
+ {links.length > 0 && (
271
+ <TouchableOpacity
272
+ style={styles.infoGridItem}
273
+ onPress={() => navigate?.('UserLinks', { userId, links })}
274
+ >
275
+ <Ionicons name="link-outline" size={16} color={isDarkTheme ? '#BBBBBB' : '#888888'} style={{ marginRight: 6 }} />
276
+ <Text style={[styles.infoGridText, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]} numberOfLines={1}>
277
+ {links[0].url}
278
+ </Text>
279
+ {links.length > 1 && (
280
+ <Text style={[styles.linksMore, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>
281
+ + {links.length - 1} more
282
+ </Text>
283
+ )}
284
+ </TouchableOpacity>
285
+ )}
165
286
  </View>
166
287
  {/* Divider */}
167
288
  <View style={styles.divider} />
@@ -172,11 +293,19 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
172
293
  <Text style={[styles.karmaLabel, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>Karma</Text>
173
294
  </View>
174
295
  <View style={styles.statItem}>
175
- <Text style={[styles.karmaAmount, { color: textColor }]}>{followersCount !== null ? followersCount : '--'}</Text>
296
+ {isLoadingCounts ? (
297
+ <ActivityIndicator size="small" color={textColor} />
298
+ ) : (
299
+ <Text style={[styles.karmaAmount, { color: textColor }]}>{followerCount !== null ? followerCount : '--'}</Text>
300
+ )}
176
301
  <Text style={[styles.karmaLabel, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>Followers</Text>
177
302
  </View>
178
303
  <View style={styles.statItem}>
179
- <Text style={[styles.karmaAmount, { color: textColor }]}>{followingCount !== null ? followingCount : '--'}</Text>
304
+ {isLoadingCounts ? (
305
+ <ActivityIndicator size="small" color={textColor} />
306
+ ) : (
307
+ <Text style={[styles.karmaAmount, { color: textColor }]}>{followingCount !== null ? followingCount : '--'}</Text>
308
+ )}
180
309
  <Text style={[styles.karmaLabel, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>Following</Text>
181
310
  </View>
182
311
  </View>
@@ -194,15 +323,49 @@ const styles = StyleSheet.create({
194
323
  avatarRow: { flexDirection: 'row', alignItems: 'flex-end', marginTop: -56, paddingHorizontal: 20, justifyContent: 'space-between', zIndex: 2 },
195
324
  avatarWrapper: { borderWidth: 5, borderColor: '#fff', borderRadius: 64, overflow: 'hidden', backgroundColor: '#fff', },
196
325
  actionButtonWrapper: { flex: 1, alignItems: 'flex-end', justifyContent: 'flex-end' },
197
- actionButton: { backgroundColor: '#fff', color: '#d169e5', borderWidth: 1, borderColor: '#d169e5', borderRadius: 24, paddingVertical: 7, paddingHorizontal: 22, fontWeight: 'bold', fontSize: 16, marginBottom: 8, elevation: 2, shadowColor: '#d169e5', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.08, shadowRadius: 2 },
198
- header: { alignItems: 'flex-start', paddingTop: 18, paddingBottom: 24, width: '100%', paddingHorizontal: 20 },
326
+ actionButton: {
327
+ backgroundColor: '#fff',
328
+ borderWidth: 1,
329
+ borderColor: '#d169e5',
330
+ borderRadius: 24,
331
+ paddingVertical: 7,
332
+ paddingHorizontal: 22,
333
+ marginBottom: 8,
334
+ elevation: 2,
335
+ shadowColor: '#d169e5',
336
+ shadowOffset: { width: 0, height: 1 },
337
+ shadowOpacity: 0.08,
338
+ shadowRadius: 2
339
+ },
340
+ actionButtonText: {
341
+ color: '#d169e5',
342
+ fontWeight: 'bold',
343
+ fontSize: 16
344
+ },
345
+ header: { alignItems: 'flex-start', width: '100%', paddingHorizontal: 20 },
199
346
  displayName: { fontSize: 24, fontWeight: 'bold', marginTop: 10, marginBottom: 2, letterSpacing: 0.1 },
200
347
  subText: { fontSize: 16, marginBottom: 2, color: '#a0a0a0' },
201
- bio: { fontSize: 16, marginTop: 10, marginBottom: 10, color: '#666', fontStyle: 'italic', lineHeight: 22 },
202
- infoRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 10, flexWrap: 'wrap' },
203
- infoItem: { flexDirection: 'row', alignItems: 'center', marginRight: 28, marginBottom: 4, minWidth: 120 },
204
- infoText: { fontSize: 15 },
348
+ bio: { fontSize: 16, marginTop: 10, marginBottom: 10, color: '#666', lineHeight: 22 },
349
+ infoGrid: {
350
+ flexDirection: 'row',
351
+ alignItems: 'center',
352
+ marginBottom: 10,
353
+ flexWrap: 'wrap'
354
+ },
355
+ infoGridItem: {
356
+ flexDirection: 'row',
357
+ alignItems: 'center',
358
+ marginRight: 24,
359
+ marginBottom: 4
360
+ },
361
+ infoGridText: {
362
+ fontSize: 15
363
+ },
205
364
  divider: { height: 1, backgroundColor: '#e0e0e0', width: '100%', marginVertical: 14 },
365
+ linksMore: {
366
+ fontSize: 15,
367
+ marginLeft: 4
368
+ },
206
369
  statsRow: { width: '100%', flex: 1, flexDirection: 'row', alignItems: 'center', marginTop: 6, marginBottom: 2, justifyContent: 'space-between' },
207
370
  statItem: { flex: 1, alignItems: 'center', minWidth: 50, marginBottom: 12 },
208
371
  karmaLabel: { fontSize: 14, marginBottom: 2, textAlign: 'center', color: '#a0a0a0' },
@@ -4,17 +4,21 @@ import { Ionicons } from '@expo/vector-icons';
4
4
  import TextField from '../components/internal/TextField';
5
5
  import GroupedPillButtons from '../components/internal/GroupedPillButtons';
6
6
  import HighFive from '../../assets/illustrations/HighFive';
7
- import { useThemeColors } from '../styles';
7
+ import { useThemeColors, createAuthStyles } from '../styles';
8
8
  import PinInput from '../components/internal/PinInput';
9
9
 
10
10
  interface RecoverAccountScreenProps {
11
- navigate: (screen: string) => void;
11
+ navigate: (screen: string, props?: Record<string, any>) => void;
12
+ goBack: () => void;
12
13
  theme: string;
14
+ returnTo?: string;
15
+ returnStep?: number;
16
+ returnData?: Record<string, any>;
13
17
  }
14
18
 
15
19
  const PIN_LENGTH = 6;
16
20
 
17
- const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, theme }) => {
21
+ const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, goBack, theme, returnTo, returnStep, returnData }) => {
18
22
  const [identifier, setIdentifier] = useState('');
19
23
  const [isLoading, setIsLoading] = useState(false);
20
24
  const [errorMessage, setErrorMessage] = useState('');
@@ -24,7 +28,7 @@ const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, t
24
28
  const fadeAnim = useRef(new Animated.Value(1)).current;
25
29
  const slideAnim = useRef(new Animated.Value(0)).current;
26
30
  const colors = useThemeColors(theme as 'light' | 'dark');
27
- const styles = createStyles(colors);
31
+ const styles = createAuthStyles(colors, theme);
28
32
  const identifierRef = useRef<TextInput>(null);
29
33
  const handleRequestWithFocus = () => {
30
34
  if (!identifier) {
@@ -69,6 +73,37 @@ const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, t
69
73
  }, 1200);
70
74
  };
71
75
 
76
+ // Helper function to determine back action based on current step
77
+ const handleBack = () => {
78
+ console.log('RecoverAccount handleBack:', { step, returnTo, returnStep, returnData });
79
+
80
+ if (step === 'code') {
81
+ setStep('request');
82
+ } else if (step === 'done') {
83
+ // If we have return information, use it; otherwise go to SignIn
84
+ if (returnTo && returnStep !== undefined) {
85
+ console.log('Navigating back to', returnTo, 'with step', returnStep, 'and data', returnData);
86
+ navigate(returnTo, {
87
+ initialStep: returnStep,
88
+ ...returnData
89
+ });
90
+ } else {
91
+ navigate('SignIn');
92
+ }
93
+ } else {
94
+ // For 'request' step, if we have return information, use it; otherwise go back
95
+ if (returnTo && returnStep !== undefined) {
96
+ console.log('Navigating back to', returnTo, 'with step', returnStep, 'and data', returnData);
97
+ navigate(returnTo, {
98
+ initialStep: returnStep,
99
+ ...returnData
100
+ });
101
+ } else {
102
+ goBack();
103
+ }
104
+ }
105
+ };
106
+
72
107
  return (
73
108
  <KeyboardAvoidingView
74
109
  style={[styles.container, { backgroundColor: colors.background }]}
@@ -97,25 +132,23 @@ const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, t
97
132
  <TextField
98
133
  ref={identifierRef}
99
134
  label="Email or Username"
100
- icon="mail-outline"
135
+ leading={<Ionicons name="mail-outline" size={24} color={colors.secondaryText} />}
101
136
  value={identifier}
102
137
  onChangeText={setIdentifier}
103
138
  autoCapitalize="none"
104
139
  autoCorrect={false}
105
- colors={colors}
106
140
  variant="filled"
107
141
  error={errorMessage || undefined}
108
142
  editable={!isLoading}
109
143
  autoFocus
110
144
  testID="recover-identifier-input"
111
- validMessage={successMessage || undefined}
112
145
  onSubmitEditing={handleRequestWithFocus}
113
146
  />
114
147
  <GroupedPillButtons
115
148
  buttons={[
116
149
  {
117
- text: 'Back to Sign In',
118
- onPress: () => navigate('SignIn'),
150
+ text: 'Back',
151
+ onPress: handleBack,
119
152
  icon: 'arrow-back',
120
153
  variant: 'transparent',
121
154
  },
@@ -155,7 +188,7 @@ const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, t
155
188
  buttons={[
156
189
  {
157
190
  text: 'Back',
158
- onPress: () => setStep('request'),
191
+ onPress: handleBack,
159
192
  icon: 'arrow-back',
160
193
  variant: 'transparent',
161
194
  },
@@ -178,8 +211,8 @@ const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, t
178
211
  <GroupedPillButtons
179
212
  buttons={[
180
213
  {
181
- text: 'Back to Sign In',
182
- onPress: () => navigate('SignIn'),
214
+ text: 'Back',
215
+ onPress: handleBack,
183
216
  icon: 'arrow-back',
184
217
  variant: 'primary',
185
218
  },
@@ -194,67 +227,6 @@ const RecoverAccountScreen: React.FC<RecoverAccountScreenProps> = ({ navigate, t
194
227
  );
195
228
  };
196
229
 
197
- const createStyles = (colors: any) => StyleSheet.create({
198
- container: {
199
- flex: 1,
200
- },
201
- scrollContent: {
202
- flexGrow: 1,
203
- paddingHorizontal: 24,
204
- paddingTop: 4,
205
- paddingBottom: 20,
206
- },
207
- stepContainer: {
208
- flex: 1,
209
- justifyContent: 'flex-start',
210
- alignItems: 'flex-start',
211
- },
212
- modernHeader: {
213
- alignItems: 'flex-start',
214
- width: '100%',
215
- marginBottom: 24,
216
- },
217
- modernTitle: {
218
- fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
219
- fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
220
- fontSize: 62,
221
- lineHeight: 48,
222
- marginBottom: 18,
223
- textAlign: 'left',
224
- letterSpacing: -1,
225
- },
226
- modernSubtitle: {
227
- fontSize: 18,
228
- lineHeight: 24,
229
- textAlign: 'left',
230
- opacity: 0.8,
231
- marginBottom: 24,
232
- },
233
- successCard: {
234
- flexDirection: 'row',
235
- alignItems: 'center',
236
- padding: 16,
237
- borderRadius: 16,
238
- marginBottom: 24,
239
- gap: 12,
240
- width: '100%',
241
- },
242
- belowInputMessage: {
243
- flexDirection: 'row',
244
- alignItems: 'center',
245
- marginTop: 4,
246
- marginBottom: 0,
247
- gap: 6,
248
- },
249
- belowInputText: {
250
- fontSize: 13,
251
- fontWeight: '500',
252
- },
253
- successText: {
254
- fontSize: 14,
255
- fontWeight: '500',
256
- flex: 1,
257
- },
258
- });
230
+
259
231
 
260
232
  export default RecoverAccountScreen;
@@ -15,14 +15,17 @@ import { useOxy } from '../context/OxyContext';
15
15
  import { fontFamilies } from '../styles/fonts';
16
16
  import { toast } from '../../lib/sonner';
17
17
  import { Ionicons } from '@expo/vector-icons';
18
+ import OxyIcon from '../components/icon/OxyIcon';
18
19
  import { SecureClientSession } from '../../models/secureSession';
19
20
  import { confirmAction } from '../utils/confirmAction';
21
+ import { Header } from '../components';
20
22
 
21
23
  const SessionManagementScreen: React.FC<BaseScreenProps> = ({
22
24
  onClose,
23
25
  theme,
26
+ goBack,
24
27
  }) => {
25
- const { sessions: userSessions, activeSessionId, refreshSessions, logout, oxyServices } = useOxy();
28
+ const { sessions: userSessions, activeSessionId, refreshSessions, logout, logoutAll, oxyServices } = useOxy();
26
29
  const [loading, setLoading] = useState(true);
27
30
  const [refreshing, setRefreshing] = useState(false);
28
31
  const [actionLoading, setActionLoading] = useState<string | null>(null);
@@ -112,7 +115,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
112
115
  async () => {
113
116
  try {
114
117
  setActionLoading('all');
115
- await oxyServices.logoutAllSessions();
118
+ await logoutAll();
116
119
  } catch (error) {
117
120
  console.error('Logout all sessions failed:', error);
118
121
  toast.error('Failed to logout all sessions. Please try again.');
@@ -166,10 +169,13 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
166
169
 
167
170
  return (
168
171
  <View style={[styles.container, { backgroundColor }]}>
169
- <View style={styles.header}>
170
- <Text style={[styles.title, { color: textColor }]}>Active Sessions</Text>
171
- <Text style={[styles.subtitle, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>Manage your active sessions across all devices</Text>
172
- </View>
172
+ <Header
173
+ title="Active Sessions"
174
+ subtitle="Manage your active sessions across all devices"
175
+ theme={theme}
176
+ onBack={goBack || onClose}
177
+ elevation="subtle"
178
+ />
173
179
  <ScrollView
174
180
  style={styles.scrollView}
175
181
  contentContainerStyle={styles.scrollContainer}
@@ -274,22 +280,8 @@ const styles = StyleSheet.create({
274
280
  justifyContent: 'center',
275
281
  alignItems: 'center',
276
282
  },
277
- header: {
278
- padding: 20,
279
- paddingBottom: 16,
280
- },
281
- title: {
282
- fontFamily: Platform.OS === 'web'
283
- ? 'Phudu'
284
- : 'phuduSemiBold',
285
- fontWeight: Platform.OS === 'web' ? '600' : undefined,
286
- fontSize: 24,
287
- marginBottom: 8,
288
- },
289
- subtitle: {
290
- fontSize: 16,
291
- lineHeight: 20,
292
- },
283
+
284
+
293
285
  scrollView: {
294
286
  flex: 1,
295
287
  },