@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,6 +1,6 @@
1
- import React, { createContext, useContext, useEffect, useCallback, ReactNode, useMemo } from 'react';
1
+ import React, { createContext, useContext, useEffect, useCallback, ReactNode, useMemo, useRef, useState } from 'react';
2
2
  import { OxyServices } from '../../core';
3
- import { User } from '../../models/interfaces';
3
+ import { User, ApiError } from '../../models/interfaces';
4
4
  import { SecureLoginResponse, SecureClientSession, MinimalUserData } from '../../models/secureSession';
5
5
  import { DeviceManager } from '../../utils/deviceManager';
6
6
  import { useSessionSocket } from '../hooks/useSessionSocket';
@@ -49,9 +49,11 @@ const OxyContext = createContext<OxyContextState | null>(null);
49
49
  // Props for the OxyContextProvider
50
50
  export interface OxyContextProviderProps {
51
51
  children: ReactNode;
52
- oxyServices: OxyServices;
52
+ oxyServices?: OxyServices; // Now optional - will be created automatically if not provided
53
+ baseURL?: string; // New: API base URL for automatic service creation
53
54
  storageKeyPrefix?: string;
54
55
  onAuthStateChange?: (user: User | null) => void;
56
+ onError?: (error: ApiError) => void; // New: Error callback
55
57
  bottomSheetRef?: React.RefObject<any>;
56
58
  }
57
59
 
@@ -110,17 +112,33 @@ const getStorage = async (): Promise<StorageInterface> => {
110
112
 
111
113
  // Storage keys for secure sessions
112
114
  const getSecureStorageKeys = (prefix = 'oxy_secure') => ({
113
- sessions: `${prefix}_sessions`, // Array of SecureClientSession objects
114
- activeSessionId: `${prefix}_active_session_id`, // ID of currently active session
115
+ activeSessionId: `${prefix}_active_session_id`, // Only store the active session ID
115
116
  });
116
117
 
117
- export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
118
+ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
118
119
  children,
119
- oxyServices,
120
+ oxyServices: providedOxyServices,
121
+ baseURL,
120
122
  storageKeyPrefix = 'oxy_secure',
121
123
  onAuthStateChange,
124
+ onError,
122
125
  bottomSheetRef,
123
126
  }) => {
127
+ // Create oxyServices automatically if not provided
128
+ const oxyServicesRef = useRef<OxyServices | null>(null);
129
+
130
+ if (!oxyServicesRef.current) {
131
+ if (providedOxyServices) {
132
+ oxyServicesRef.current = providedOxyServices;
133
+ } else if (baseURL) {
134
+ oxyServicesRef.current = new OxyServices({ baseURL });
135
+ } else {
136
+ throw new Error('Either oxyServices or baseURL must be provided to OxyContextProvider');
137
+ }
138
+ }
139
+
140
+ const oxyServices = oxyServicesRef.current;
141
+
124
142
  // Zustand state
125
143
  const user = useAuthStore((state) => state.user);
126
144
  const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
@@ -156,94 +174,60 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
156
174
  initStorage();
157
175
  }, []);
158
176
 
159
- // Effect to initialize authentication state
177
+ // Effect to initialize authentication state - only store session ID
160
178
  useEffect(() => {
161
179
  const initAuth = async () => {
162
180
  if (!storage) return;
163
181
 
164
182
  useAuthStore.setState({ isLoading: true });
165
183
  try {
166
- // Load stored sessions
167
- const sessionsData = await storage.getItem(keys.sessions);
184
+ // Only load the active session ID from storage
168
185
  const storedActiveSessionId = await storage.getItem(keys.activeSessionId);
169
186
 
170
- console.log('SecureAuth - sessionsData:', sessionsData);
171
187
  console.log('SecureAuth - activeSessionId:', storedActiveSessionId);
172
188
 
173
- if (sessionsData) {
174
- const parsedSessions: SecureClientSession[] = JSON.parse(sessionsData);
175
-
176
- // Migrate old session format to include user info
177
- const migratedSessions: SecureClientSession[] = [];
178
- let shouldUpdateStorage = false;
179
-
180
- for (const session of parsedSessions) {
181
- if (!session.userId) {
182
- // Session is missing user info, try to fetch it
183
- try {
184
- const sessionUser = await oxyServices.getUserBySession(session.sessionId);
185
- migratedSessions.push({
186
- ...session,
187
- userId: sessionUser.id
188
- });
189
- shouldUpdateStorage = true;
190
- console.log(`Migrated session ${session.sessionId} for user ${sessionUser.id}`);
191
- } catch (error) {
192
- // Session might be invalid, skip it
193
- console.log(`Removing invalid session ${session.sessionId}:`, error);
194
- shouldUpdateStorage = true;
189
+ if (storedActiveSessionId) {
190
+ // Validate the stored session with the backend
191
+ try {
192
+ const validation = await oxyServices.validateSession(storedActiveSessionId);
193
+
194
+ if (validation.valid) {
195
+ console.log('SecureAuth - session validated successfully');
196
+ setActiveSessionId(storedActiveSessionId);
197
+
198
+ // Get access token for API calls
199
+ await oxyServices.getTokenBySession(storedActiveSessionId);
200
+
201
+ // Load full user data from backend
202
+ const fullUser = await oxyServices.getUserBySession(storedActiveSessionId);
203
+ loginSuccess(fullUser);
204
+ setMinimalUser({
205
+ id: fullUser.id,
206
+ username: fullUser.username,
207
+ avatar: fullUser.avatar
208
+ });
209
+
210
+ // Load sessions from backend
211
+ const serverSessions = await oxyServices.getSessionsBySessionId(storedActiveSessionId);
212
+ const clientSessions: SecureClientSession[] = serverSessions.map(serverSession => ({
213
+ sessionId: serverSession.sessionId,
214
+ deviceId: serverSession.deviceId,
215
+ expiresAt: serverSession.expiresAt || new Date().toISOString(),
216
+ lastActive: serverSession.lastActive || new Date().toISOString(),
217
+ userId: serverSession.userId || fullUser.id
218
+ }));
219
+ setSessions(clientSessions);
220
+
221
+ if (onAuthStateChange) {
222
+ onAuthStateChange(fullUser);
195
223
  }
196
224
  } else {
197
- // Session already has user info
198
- migratedSessions.push(session);
199
- }
200
- }
201
-
202
- // Update storage if we made changes
203
- if (shouldUpdateStorage) {
204
- await saveSessionsToStorage(migratedSessions);
205
- }
206
-
207
- setSessions(migratedSessions);
208
-
209
- if (storedActiveSessionId && migratedSessions.length > 0) {
210
- const activeSession = migratedSessions.find(s => s.sessionId === storedActiveSessionId);
211
-
212
- if (activeSession) {
213
- console.log('SecureAuth - activeSession found:', activeSession);
214
-
215
- // Validate session
216
- try {
217
- const validation = await oxyServices.validateSession(activeSession.sessionId);
218
-
219
- if (validation.valid) {
220
- console.log('SecureAuth - session validated successfully');
221
- setActiveSessionId(activeSession.sessionId);
222
-
223
- // Get access token for API calls
224
- await oxyServices.getTokenBySession(activeSession.sessionId);
225
-
226
- // Load full user data
227
- const fullUser = await oxyServices.getUserBySession(activeSession.sessionId);
228
- loginSuccess(fullUser);
229
- setMinimalUser({
230
- id: fullUser.id,
231
- username: fullUser.username,
232
- avatar: fullUser.avatar
233
- });
234
-
235
- if (onAuthStateChange) {
236
- onAuthStateChange(fullUser);
237
- }
238
- } else {
239
- console.log('SecureAuth - session invalid, removing');
240
- await removeInvalidSession(activeSession.sessionId);
241
- }
242
- } catch (error) {
243
- console.error('SecureAuth - session validation error:', error);
244
- await removeInvalidSession(activeSession.sessionId);
245
- }
225
+ console.log('SecureAuth - session invalid, clearing storage');
226
+ await clearAllStorage();
246
227
  }
228
+ } catch (error) {
229
+ console.error('SecureAuth - session validation error:', error);
230
+ await clearAllStorage();
247
231
  }
248
232
  }
249
233
  } catch (err) {
@@ -257,33 +241,15 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
257
241
  if (storage) {
258
242
  initAuth();
259
243
  }
260
- }, [storage, oxyServices, keys, onAuthStateChange]);
244
+ }, [storage, oxyServices, keys, onAuthStateChange, loginSuccess, setMinimalUser]);
261
245
 
262
- // Effect to restore token on app load or session switch
263
- useEffect(() => {
264
- const restoreToken = async () => {
265
- if (activeSessionId && oxyServices) {
266
- try {
267
- await oxyServices.getTokenBySession(activeSessionId);
268
- setTokenReady(true);
269
- } catch (err) {
270
- // If token restoration fails, force logout
271
- await logout();
272
- setTokenReady(false);
273
- }
274
- } else {
275
- setTokenReady(true); // No session, so token is not needed
276
- }
277
- };
278
- restoreToken();
279
- // Only run when activeSessionId or oxyServices changes
280
- }, [activeSessionId, oxyServices]);
281
246
 
282
- // Remove invalid session
247
+
248
+ // Remove invalid session - refresh sessions from backend
283
249
  const removeInvalidSession = useCallback(async (sessionId: string): Promise<void> => {
250
+ // Remove from local state
284
251
  const filteredSessions = sessions.filter(s => s.sessionId !== sessionId);
285
252
  setSessions(filteredSessions);
286
- await saveSessionsToStorage(filteredSessions);
287
253
 
288
254
  // If there are other sessions, switch to the first one
289
255
  if (filteredSessions.length > 0) {
@@ -301,13 +267,7 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
301
267
  }
302
268
  }, [sessions, storage, keys, onAuthStateChange, logoutStore]);
303
269
 
304
- // Save sessions to storage
305
- const saveSessionsToStorage = useCallback(async (sessionsList: SecureClientSession[]): Promise<void> => {
306
- if (!storage) return;
307
- await storage.setItem(keys.sessions, JSON.stringify(sessionsList));
308
- }, [storage, keys.sessions]);
309
-
310
- // Save active session ID to storage
270
+ // Save active session ID to storage (only session ID, no user data)
311
271
  const saveActiveSessionId = useCallback(async (sessionId: string): Promise<void> => {
312
272
  if (!storage) return;
313
273
  await storage.setItem(keys.activeSessionId, sessionId);
@@ -317,7 +277,6 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
317
277
  const clearAllStorage = useCallback(async (): Promise<void> => {
318
278
  if (!storage) return;
319
279
  try {
320
- await storage.removeItem(keys.sessions);
321
280
  await storage.removeItem(keys.activeSessionId);
322
281
  } catch (err) {
323
282
  console.error('Clear secure storage error:', err);
@@ -356,8 +315,8 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
356
315
  }
357
316
  }, [oxyServices, onAuthStateChange, loginSuccess, saveActiveSessionId]);
358
317
 
359
- // Secure login method
360
- const login = async (username: string, password: string, deviceName?: string): Promise<User> => {
318
+ // Secure login method - only store session ID, retrieve data from backend
319
+ const login = useCallback(async (username: string, password: string, deviceName?: string): Promise<User> => {
361
320
  if (!storage) throw new Error('Storage not initialized');
362
321
  useAuthStore.setState({ isLoading: true, error: null });
363
322
 
@@ -378,56 +337,29 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
378
337
  deviceFingerprint
379
338
  );
380
339
 
381
- // Create client session object with user info for duplicate detection
382
- const clientSession: SecureClientSession = {
383
- sessionId: response.sessionId,
384
- deviceId: response.deviceId,
385
- expiresAt: response.expiresAt,
386
- lastActive: new Date().toISOString(),
387
- userId: response.user.id
388
- };
389
-
390
- // Check if this user already has a session (prevent duplicate accounts)
391
- const existingUserSessionIndex = sessions.findIndex(s =>
392
- s.userId === response.user.id
393
- );
394
-
395
- let updatedSessions: SecureClientSession[];
396
-
397
- if (existingUserSessionIndex !== -1) {
398
- // User already has a session - replace it with the new one (reused session scenario)
399
- const existingSession = sessions[existingUserSessionIndex];
400
- updatedSessions = [...sessions];
401
- updatedSessions[existingUserSessionIndex] = clientSession;
402
-
403
- console.log(`Reusing/updating existing session for user ${response.user.id}. Previous session: ${existingSession.sessionId}, New session: ${response.sessionId}`);
404
-
405
- // If the replaced session was the active one, update active session
406
- if (activeSessionId === existingSession.sessionId) {
407
- setActiveSessionId(response.sessionId);
408
- await saveActiveSessionId(response.sessionId);
409
- }
410
- } else {
411
- // Add new session for new user
412
- updatedSessions = [...sessions, clientSession];
413
- console.log(`Added new session for user ${response.user.id} on device ${response.deviceId}`);
414
- }
415
-
416
- setSessions(updatedSessions);
417
- await saveSessionsToStorage(updatedSessions);
418
-
419
- // Set as active session
340
+ // Set as active session (only store session ID)
420
341
  setActiveSessionId(response.sessionId);
421
342
  await saveActiveSessionId(response.sessionId);
422
343
 
423
344
  // Get access token for API calls
424
345
  await oxyServices.getTokenBySession(response.sessionId);
425
346
 
426
- // Load full user data
347
+ // Load full user data from backend
427
348
  const fullUser = await oxyServices.getUserBySession(response.sessionId);
428
349
  loginSuccess(fullUser);
429
350
  setMinimalUser(response.user);
430
351
 
352
+ // Load sessions from backend
353
+ const serverSessions = await oxyServices.getSessionsBySessionId(response.sessionId);
354
+ const clientSessions: SecureClientSession[] = serverSessions.map(serverSession => ({
355
+ sessionId: serverSession.sessionId,
356
+ deviceId: serverSession.deviceId,
357
+ expiresAt: serverSession.expiresAt || new Date().toISOString(),
358
+ lastActive: serverSession.lastActive || new Date().toISOString(),
359
+ userId: serverSession.userId || fullUser.id
360
+ }));
361
+ setSessions(clientSessions);
362
+
431
363
  if (onAuthStateChange) {
432
364
  onAuthStateChange(fullUser);
433
365
  }
@@ -439,20 +371,19 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
439
371
  } finally {
440
372
  useAuthStore.setState({ isLoading: false });
441
373
  }
442
- };
374
+ }, [storage, oxyServices, saveActiveSessionId, loginSuccess, setMinimalUser, onAuthStateChange, loginFailure]);
443
375
 
444
376
  // Logout method
445
- const logout = async (targetSessionId?: string): Promise<void> => {
377
+ const logout = useCallback(async (targetSessionId?: string): Promise<void> => {
446
378
  if (!activeSessionId) return;
447
379
 
448
380
  try {
449
381
  const sessionToLogout = targetSessionId || activeSessionId;
450
382
  await oxyServices.logoutSecureSession(activeSessionId, sessionToLogout);
451
383
 
452
- // Remove session from local storage
384
+ // Remove session from local state
453
385
  const filteredSessions = sessions.filter(s => s.sessionId !== sessionToLogout);
454
386
  setSessions(filteredSessions);
455
- await saveSessionsToStorage(filteredSessions);
456
387
 
457
388
  // If logging out active session
458
389
  if (sessionToLogout === activeSessionId) {
@@ -475,10 +406,10 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
475
406
  console.error('Logout error:', error);
476
407
  useAuthStore.setState({ error: 'Logout failed' });
477
408
  }
478
- };
409
+ }, [activeSessionId, oxyServices, sessions, switchToSession, logoutStore, setMinimalUser, storage, keys.activeSessionId, onAuthStateChange]);
479
410
 
480
411
  // Logout all sessions
481
- const logoutAll = async (): Promise<void> => {
412
+ const logoutAll = useCallback(async (): Promise<void> => {
482
413
  console.log('logoutAll called with activeSessionId:', activeSessionId);
483
414
 
484
415
  if (!activeSessionId) {
@@ -515,10 +446,30 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
515
446
  useAuthStore.setState({ error: `Logout all failed: ${error instanceof Error ? error.message : 'Unknown error'}` });
516
447
  throw error;
517
448
  }
518
- };
449
+ }, [activeSessionId, oxyServices, logoutStore, setMinimalUser, clearAllStorage, onAuthStateChange]);
450
+
451
+ // Effect to restore token on app load or session switch
452
+ useEffect(() => {
453
+ const restoreToken = async () => {
454
+ if (activeSessionId && oxyServices) {
455
+ try {
456
+ await oxyServices.getTokenBySession(activeSessionId);
457
+ setTokenReady(true);
458
+ } catch (err) {
459
+ // If token restoration fails, force logout
460
+ await logout();
461
+ setTokenReady(false);
462
+ }
463
+ } else {
464
+ setTokenReady(true); // No session, so token is not needed
465
+ }
466
+ };
467
+ restoreToken();
468
+ // Only run when activeSessionId or oxyServices changes
469
+ }, [activeSessionId, oxyServices, logout]);
519
470
 
520
471
  // Sign up method
521
- const signUp = async (username: string, email: string, password: string): Promise<User> => {
472
+ const signUp = useCallback(async (username: string, email: string, password: string): Promise<User> => {
522
473
  if (!storage) throw new Error('Storage not initialized');
523
474
 
524
475
  useAuthStore.setState({ isLoading: true, error: null });
@@ -540,42 +491,82 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
540
491
  } finally {
541
492
  useAuthStore.setState({ isLoading: false });
542
493
  }
543
- };
494
+ }, [storage, oxyServices, login, loginFailure]);
544
495
 
545
496
  // Switch session method
546
- const switchSession = async (sessionId: string): Promise<void> => {
497
+ const switchSession = useCallback(async (sessionId: string): Promise<void> => {
547
498
  await switchToSession(sessionId);
548
- };
499
+ }, [switchToSession]);
549
500
 
550
501
  // Remove session method
551
- const removeSession = async (sessionId: string): Promise<void> => {
502
+ const removeSession = useCallback(async (sessionId: string): Promise<void> => {
552
503
  await logout(sessionId);
553
- };
504
+ }, [logout]);
554
505
 
555
506
  // Refresh sessions method
556
- const refreshSessions = async (): Promise<void> => {
557
- if (!activeSessionId) return;
507
+ const refreshSessions = useCallback(async (): Promise<void> => {
508
+ console.log('refreshSessions called with activeSessionId:', activeSessionId);
509
+
510
+ if (!activeSessionId) {
511
+ console.log('refreshSessions: No activeSessionId, returning');
512
+ return;
513
+ }
558
514
 
559
515
  try {
516
+ console.log('refreshSessions: Calling getSessionsBySessionId...');
560
517
  const serverSessions = await oxyServices.getSessionsBySessionId(activeSessionId);
518
+ console.log('refreshSessions: Server sessions received:', serverSessions);
561
519
 
562
520
  // Update local sessions with server data
563
521
  const updatedSessions: SecureClientSession[] = serverSessions.map(serverSession => ({
564
522
  sessionId: serverSession.sessionId,
565
523
  deviceId: serverSession.deviceId,
566
- expiresAt: new Date().toISOString(), // You might want to get this from server
567
- lastActive: new Date().toISOString()
524
+ expiresAt: serverSession.expiresAt || new Date().toISOString(),
525
+ lastActive: serverSession.lastActive || new Date().toISOString(),
526
+ userId: serverSession.userId || user?.id
568
527
  }));
569
528
 
529
+ console.log('refreshSessions: Updated sessions:', updatedSessions);
570
530
  setSessions(updatedSessions);
571
- await saveSessionsToStorage(updatedSessions);
531
+ console.log('refreshSessions: Sessions updated in state');
572
532
  } catch (error) {
573
533
  console.error('Refresh sessions error:', error);
534
+
535
+ // If the current session is invalid, try to find another valid session
536
+ if (sessions.length > 1) {
537
+ console.log('Current session invalid, trying to switch to another session...');
538
+ const otherSessions = sessions.filter(s => s.sessionId !== activeSessionId);
539
+
540
+ for (const session of otherSessions) {
541
+ try {
542
+ // Try to validate this session
543
+ await oxyServices.validateSession(session.sessionId);
544
+ console.log('Found valid session, switching to:', session.sessionId);
545
+ await switchToSession(session.sessionId);
546
+ return; // Successfully switched to another session
547
+ } catch (sessionError) {
548
+ console.log('Session validation failed for:', session.sessionId, sessionError);
549
+ continue; // Try next session
550
+ }
551
+ }
552
+ }
553
+
554
+ // If no valid sessions found, clear all sessions
555
+ console.log('No valid sessions found, clearing all sessions');
556
+ setSessions([]);
557
+ setActiveSessionId(null);
558
+ logoutStore();
559
+ setMinimalUser(null);
560
+ await clearAllStorage();
561
+
562
+ if (onAuthStateChange) {
563
+ onAuthStateChange(null);
564
+ }
574
565
  }
575
- };
566
+ }, [activeSessionId, oxyServices, user?.id, sessions, switchToSession, logoutStore, setMinimalUser, clearAllStorage, onAuthStateChange]);
576
567
 
577
568
  // Device management methods
578
- const getDeviceSessions = async (): Promise<any[]> => {
569
+ const getDeviceSessions = useCallback(async (): Promise<any[]> => {
579
570
  if (!activeSessionId) throw new Error('No active session');
580
571
 
581
572
  try {
@@ -584,9 +575,9 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
584
575
  console.error('Get device sessions error:', error);
585
576
  throw error;
586
577
  }
587
- };
578
+ }, [activeSessionId, oxyServices]);
588
579
 
589
- const logoutAllDeviceSessions = async (): Promise<void> => {
580
+ const logoutAllDeviceSessions = useCallback(async (): Promise<void> => {
590
581
  if (!activeSessionId) throw new Error('No active session');
591
582
 
592
583
  try {
@@ -606,9 +597,9 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
606
597
  console.error('Logout all device sessions error:', error);
607
598
  throw error;
608
599
  }
609
- };
600
+ }, [activeSessionId, oxyServices, logoutStore, setMinimalUser, clearAllStorage, onAuthStateChange]);
610
601
 
611
- const updateDeviceName = async (deviceName: string): Promise<void> => {
602
+ const updateDeviceName = useCallback(async (deviceName: string): Promise<void> => {
612
603
  if (!activeSessionId) throw new Error('No active session');
613
604
 
614
605
  try {
@@ -620,7 +611,7 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
620
611
  console.error('Update device name error:', error);
621
612
  throw error;
622
613
  }
623
- };
614
+ }, [activeSessionId, oxyServices]);
624
615
 
625
616
  // Bottom sheet control methods
626
617
  const showBottomSheet = useCallback((screenOrConfig?: string | { screen: string; props?: Record<string, any> }) => {
@@ -638,6 +629,7 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
638
629
  bottomSheetRef.current.present();
639
630
  } else {
640
631
  console.warn('No expand or present method available on bottomSheetRef');
632
+ console.log('Available methods on bottomSheetRef.current:', Object.keys(bottomSheetRef.current));
641
633
  }
642
634
 
643
635
  // Then navigate to the specified screen if provided
@@ -657,6 +649,8 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
657
649
  }
658
650
  } else {
659
651
  console.warn('bottomSheetRef is not available');
652
+ console.warn('To fix this, ensure you pass a bottomSheetRef to OxyProvider:');
653
+ console.warn('<OxyProvider baseURL="..." bottomSheetRef={yourBottomSheetRef}>');
660
654
  }
661
655
  }, [bottomSheetRef]);
662
656
 
@@ -672,16 +666,38 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
672
666
  userId: user?.id,
673
667
  activeSessionId,
674
668
  refreshSessions,
675
- logout: () => logout(),
669
+ logout,
676
670
  baseURL: oxyServices.getBaseURL(),
677
- onRemoteSignOut: () => {
671
+ onRemoteSignOut: useCallback(() => {
678
672
  toast.info('You have been signed out remotely.');
679
673
  logout();
680
- },
674
+ }, [logout]),
681
675
  });
682
676
 
683
677
  // Context value
684
- const contextValue: OxyContextState = {
678
+ const contextValue: OxyContextState = useMemo(() => ({
679
+ user,
680
+ minimalUser,
681
+ sessions,
682
+ activeSessionId,
683
+ isAuthenticated,
684
+ isLoading,
685
+ error,
686
+ login,
687
+ logout,
688
+ logoutAll,
689
+ signUp,
690
+ switchSession,
691
+ removeSession,
692
+ refreshSessions,
693
+ getDeviceSessions,
694
+ logoutAllDeviceSessions,
695
+ updateDeviceName,
696
+ oxyServices,
697
+ bottomSheetRef,
698
+ showBottomSheet,
699
+ hideBottomSheet,
700
+ }), [
685
701
  user,
686
702
  minimalUser,
687
703
  sessions,
@@ -691,22 +707,19 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
691
707
  error,
692
708
  login,
693
709
  logout,
694
- logoutAll: async () => { await logout(); },
695
- signUp: async (username, email, password) => {
696
- await signUp(username, email, password);
697
- return user as User; // Return the latest user from Zustand
698
- },
699
- switchSession: async (sessionId) => { await switchToSession(sessionId); },
700
- removeSession: async (sessionId) => { await removeSession(sessionId); },
701
- refreshSessions: async () => { await refreshSessions(); },
702
- getDeviceSessions: async () => { return await getDeviceSessions(); },
703
- logoutAllDeviceSessions: async () => { await logoutAllDeviceSessions(); },
704
- updateDeviceName: async (deviceName) => { await updateDeviceName(deviceName); },
710
+ logoutAll,
711
+ signUp,
712
+ switchSession,
713
+ removeSession,
714
+ refreshSessions,
715
+ getDeviceSessions,
716
+ logoutAllDeviceSessions,
717
+ updateDeviceName,
705
718
  oxyServices,
706
719
  bottomSheetRef,
707
720
  showBottomSheet,
708
721
  hideBottomSheet,
709
- };
722
+ ]);
710
723
 
711
724
  // Wrap children rendering to block until token is ready
712
725
  if (!tokenReady) {
@@ -720,6 +733,9 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
720
733
  );
721
734
  };
722
735
 
736
+ // Alias for backward compatibility
737
+ export const OxyContextProvider = OxyProvider;
738
+
723
739
  // Hook to use the context
724
740
  export const useOxy = (): OxyContextState => {
725
741
  const context = useContext(OxyContext);
@@ -1 +1 @@
1
- export { useFollow } from './useFollow';
1
+ export { useFollow, useFollowerCounts } from './useFollow';