@oxyhq/services 13.0.2 → 13.1.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 (403) hide show
  1. package/lib/commonjs/index.js +18 -11
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/components/AccountMenuButton.js +8 -10
  4. package/lib/commonjs/ui/components/AccountMenuButton.js.map +1 -1
  5. package/lib/commonjs/ui/components/AccountSwitcher.js +65 -35
  6. package/lib/commonjs/ui/components/AccountSwitcher.js.map +1 -1
  7. package/lib/commonjs/ui/components/ProfileButton.js +233 -0
  8. package/lib/commonjs/ui/components/ProfileButton.js.map +1 -0
  9. package/lib/commonjs/ui/components/ProfileMenu.js +374 -0
  10. package/lib/commonjs/ui/components/ProfileMenu.js.map +1 -0
  11. package/lib/commonjs/ui/context/OxyContext.js +213 -101
  12. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  13. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +28 -1
  14. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  15. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +2 -2
  16. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  17. package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js +12 -12
  18. package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js.map +1 -1
  19. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +8 -7
  20. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
  21. package/lib/commonjs/ui/index.js +14 -0
  22. package/lib/commonjs/ui/index.js.map +1 -1
  23. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +11 -6
  24. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  25. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +3 -3
  26. package/lib/commonjs/ui/screens/CreateAccountScreen.js +6 -4
  27. package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
  28. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +8 -7
  29. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  30. package/lib/commonjs/ui/screens/FileManagementScreen.js +13 -13
  31. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  32. package/lib/commonjs/ui/screens/HistoryViewScreen.js +7 -7
  33. package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
  34. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +5 -5
  35. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  36. package/lib/commonjs/ui/screens/ManageAccountScreen.js +17 -18
  37. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  38. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +3 -3
  39. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  40. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +9 -9
  41. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  42. package/lib/commonjs/ui/screens/ProfileScreen.js +1 -1
  43. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  44. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +4 -4
  45. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
  46. package/lib/commonjs/ui/screens/SearchSettingsScreen.js +6 -6
  47. package/lib/commonjs/ui/screens/SearchSettingsScreen.js.map +1 -1
  48. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +6 -6
  49. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  50. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +4 -4
  51. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  52. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +4 -4
  53. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  54. package/lib/commonjs/ui/utils/activeAuthuser.js +76 -8
  55. package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -1
  56. package/lib/module/index.js +5 -5
  57. package/lib/module/index.js.map +1 -1
  58. package/lib/module/ui/components/AccountMenuButton.js +8 -10
  59. package/lib/module/ui/components/AccountMenuButton.js.map +1 -1
  60. package/lib/module/ui/components/AccountSwitcher.js +65 -35
  61. package/lib/module/ui/components/AccountSwitcher.js.map +1 -1
  62. package/lib/module/ui/components/ProfileButton.js +228 -0
  63. package/lib/module/ui/components/ProfileButton.js.map +1 -0
  64. package/lib/module/ui/components/ProfileMenu.js +370 -0
  65. package/lib/module/ui/components/ProfileMenu.js.map +1 -0
  66. package/lib/module/ui/context/OxyContext.js +214 -102
  67. package/lib/module/ui/context/OxyContext.js.map +1 -1
  68. package/lib/module/ui/context/hooks/useAuthOperations.js +29 -2
  69. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  70. package/lib/module/ui/hooks/queries/useAccountQueries.js +2 -2
  71. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  72. package/lib/module/ui/hooks/queries/usePaymentQueries.js +12 -12
  73. package/lib/module/ui/hooks/queries/usePaymentQueries.js.map +1 -1
  74. package/lib/module/ui/hooks/queries/useServicesQueries.js +9 -7
  75. package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
  76. package/lib/module/ui/index.js +2 -0
  77. package/lib/module/ui/index.js.map +1 -1
  78. package/lib/module/ui/screens/AccountSettingsScreen.js +11 -6
  79. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  80. package/lib/module/ui/screens/AccountSwitcherScreen.js +3 -3
  81. package/lib/module/ui/screens/CreateAccountScreen.js +6 -4
  82. package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
  83. package/lib/module/ui/screens/EditProfileFieldScreen.js +8 -7
  84. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  85. package/lib/module/ui/screens/FileManagementScreen.js +13 -13
  86. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  87. package/lib/module/ui/screens/HistoryViewScreen.js +7 -7
  88. package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
  89. package/lib/module/ui/screens/LanguageSelectorScreen.js +5 -5
  90. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  91. package/lib/module/ui/screens/ManageAccountScreen.js +17 -18
  92. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  93. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +3 -3
  94. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  95. package/lib/module/ui/screens/PrivacySettingsScreen.js +9 -9
  96. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  97. package/lib/module/ui/screens/ProfileScreen.js +1 -1
  98. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  99. package/lib/module/ui/screens/SavesCollectionsScreen.js +4 -4
  100. package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
  101. package/lib/module/ui/screens/SearchSettingsScreen.js +6 -6
  102. package/lib/module/ui/screens/SearchSettingsScreen.js.map +1 -1
  103. package/lib/module/ui/screens/WelcomeNewUserScreen.js +6 -6
  104. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  105. package/lib/module/ui/screens/trust/TrustCenterScreen.js +4 -4
  106. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  107. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +4 -4
  108. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  109. package/lib/module/ui/utils/activeAuthuser.js +74 -9
  110. package/lib/module/ui/utils/activeAuthuser.js.map +1 -1
  111. package/lib/typescript/commonjs/index.d.ts +4 -1
  112. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  113. package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts +5 -7
  114. package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts.map +1 -1
  116. package/lib/typescript/commonjs/ui/components/ActivityIndicator.d.ts +1 -1
  117. package/lib/typescript/commonjs/ui/components/ActivityIndicator.d.ts.map +1 -1
  118. package/lib/typescript/commonjs/ui/components/CrossFadeIcon.d.ts +2 -1
  119. package/lib/typescript/commonjs/ui/components/CrossFadeIcon.d.ts.map +1 -1
  120. package/lib/typescript/commonjs/ui/components/FontLoader.d.ts +1 -1
  121. package/lib/typescript/commonjs/ui/components/FontLoader.d.ts.map +1 -1
  122. package/lib/typescript/commonjs/ui/components/HelperText.d.ts +1 -1
  123. package/lib/typescript/commonjs/ui/components/HelperText.d.ts.map +1 -1
  124. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts +46 -0
  125. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -0
  126. package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts +39 -0
  127. package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts.map +1 -0
  128. package/lib/typescript/commonjs/ui/components/TextField/Addons/Outline.d.ts +2 -1
  129. package/lib/typescript/commonjs/ui/components/TextField/Addons/Outline.d.ts.map +1 -1
  130. package/lib/typescript/commonjs/ui/components/TextField/Addons/Underline.d.ts +2 -1
  131. package/lib/typescript/commonjs/ui/components/TextField/Addons/Underline.d.ts.map +1 -1
  132. package/lib/typescript/commonjs/ui/components/TextField/Adornment/TextFieldAffix.d.ts +1 -1
  133. package/lib/typescript/commonjs/ui/components/TextField/Adornment/TextFieldIcon.d.ts +1 -1
  134. package/lib/typescript/commonjs/ui/components/TextField/Label/InputLabel.d.ts +1 -1
  135. package/lib/typescript/commonjs/ui/components/TextField/Label/LabelBackground.d.ts +2 -1
  136. package/lib/typescript/commonjs/ui/components/TextField/Label/LabelBackground.d.ts.map +1 -1
  137. package/lib/typescript/commonjs/ui/components/TextField/TextFieldFlat.d.ts +2 -1
  138. package/lib/typescript/commonjs/ui/components/TextField/TextFieldFlat.d.ts.map +1 -1
  139. package/lib/typescript/commonjs/ui/components/TextField/TextFieldOutlined.d.ts +2 -1
  140. package/lib/typescript/commonjs/ui/components/TextField/TextFieldOutlined.d.ts.map +1 -1
  141. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +11 -26
  142. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/ui/context/ThemeContext.d.ts +1 -1
  144. package/lib/typescript/commonjs/ui/context/ThemeContext.d.ts.map +1 -1
  145. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  146. package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  147. package/lib/typescript/commonjs/ui/index.d.ts +2 -0
  148. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  149. package/lib/typescript/commonjs/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  150. package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts +3 -3
  151. package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  152. package/lib/typescript/commonjs/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  153. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  154. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts +24 -0
  155. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -1
  156. package/lib/typescript/module/index.d.ts +64 -61
  157. package/lib/typescript/module/index.d.ts.map +1 -1
  158. package/lib/typescript/module/ui/client.d.ts +26 -26
  159. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  160. package/lib/typescript/module/ui/components/AccountMenuButton.d.ts +5 -7
  161. package/lib/typescript/module/ui/components/AccountMenuButton.d.ts.map +1 -1
  162. package/lib/typescript/module/ui/components/AccountSwitcher.d.ts +1 -1
  163. package/lib/typescript/module/ui/components/AccountSwitcher.d.ts.map +1 -1
  164. package/lib/typescript/module/ui/components/ActivityIndicator.d.ts +2 -2
  165. package/lib/typescript/module/ui/components/ActivityIndicator.d.ts.map +1 -1
  166. package/lib/typescript/module/ui/components/BottomSheetRouter.d.ts +1 -1
  167. package/lib/typescript/module/ui/components/BottomSheetRouter.d.ts.map +1 -1
  168. package/lib/typescript/module/ui/components/CrossFadeIcon.d.ts +4 -3
  169. package/lib/typescript/module/ui/components/CrossFadeIcon.d.ts.map +1 -1
  170. package/lib/typescript/module/ui/components/FontLoader.d.ts +1 -1
  171. package/lib/typescript/module/ui/components/FontLoader.d.ts.map +1 -1
  172. package/lib/typescript/module/ui/components/HelperText.d.ts +1 -1
  173. package/lib/typescript/module/ui/components/HelperText.d.ts.map +1 -1
  174. package/lib/typescript/module/ui/components/Icon.d.ts +1 -1
  175. package/lib/typescript/module/ui/components/Icon.d.ts.map +1 -1
  176. package/lib/typescript/module/ui/components/IconButton/IconButton.d.ts +3 -3
  177. package/lib/typescript/module/ui/components/IconButton/IconButton.d.ts.map +1 -1
  178. package/lib/typescript/module/ui/components/IconButton/utils.d.ts +1 -1
  179. package/lib/typescript/module/ui/components/IconButton/utils.d.ts.map +1 -1
  180. package/lib/typescript/module/ui/components/OxyPayButton.d.ts +1 -1
  181. package/lib/typescript/module/ui/components/OxyPayButton.d.ts.map +1 -1
  182. package/lib/typescript/module/ui/components/OxyProvider.d.ts +1 -1
  183. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  184. package/lib/typescript/module/ui/components/ProfileButton.d.ts +46 -0
  185. package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -0
  186. package/lib/typescript/module/ui/components/ProfileMenu.d.ts +39 -0
  187. package/lib/typescript/module/ui/components/ProfileMenu.d.ts.map +1 -0
  188. package/lib/typescript/module/ui/components/StepBasedScreen.d.ts +2 -2
  189. package/lib/typescript/module/ui/components/StepBasedScreen.d.ts.map +1 -1
  190. package/lib/typescript/module/ui/components/Surface.d.ts +2 -2
  191. package/lib/typescript/module/ui/components/Surface.d.ts.map +1 -1
  192. package/lib/typescript/module/ui/components/TextField/Addons/Outline.d.ts +3 -2
  193. package/lib/typescript/module/ui/components/TextField/Addons/Outline.d.ts.map +1 -1
  194. package/lib/typescript/module/ui/components/TextField/Addons/Underline.d.ts +3 -2
  195. package/lib/typescript/module/ui/components/TextField/Addons/Underline.d.ts.map +1 -1
  196. package/lib/typescript/module/ui/components/TextField/Adornment/TextFieldAdornment.d.ts +3 -3
  197. package/lib/typescript/module/ui/components/TextField/Adornment/TextFieldAdornment.d.ts.map +1 -1
  198. package/lib/typescript/module/ui/components/TextField/Adornment/TextFieldAffix.d.ts +3 -3
  199. package/lib/typescript/module/ui/components/TextField/Adornment/TextFieldAffix.d.ts.map +1 -1
  200. package/lib/typescript/module/ui/components/TextField/Adornment/TextFieldIcon.d.ts +4 -4
  201. package/lib/typescript/module/ui/components/TextField/Adornment/TextFieldIcon.d.ts.map +1 -1
  202. package/lib/typescript/module/ui/components/TextField/Adornment/types.d.ts +1 -1
  203. package/lib/typescript/module/ui/components/TextField/Adornment/types.d.ts.map +1 -1
  204. package/lib/typescript/module/ui/components/TextField/Adornment/utils.d.ts +1 -1
  205. package/lib/typescript/module/ui/components/TextField/Adornment/utils.d.ts.map +1 -1
  206. package/lib/typescript/module/ui/components/TextField/Label/InputLabel.d.ts +2 -2
  207. package/lib/typescript/module/ui/components/TextField/Label/InputLabel.d.ts.map +1 -1
  208. package/lib/typescript/module/ui/components/TextField/Label/LabelBackground.d.ts +3 -2
  209. package/lib/typescript/module/ui/components/TextField/Label/LabelBackground.d.ts.map +1 -1
  210. package/lib/typescript/module/ui/components/TextField/TextFieldFlat.d.ts +3 -2
  211. package/lib/typescript/module/ui/components/TextField/TextFieldFlat.d.ts.map +1 -1
  212. package/lib/typescript/module/ui/components/TextField/TextFieldOutlined.d.ts +3 -2
  213. package/lib/typescript/module/ui/components/TextField/TextFieldOutlined.d.ts.map +1 -1
  214. package/lib/typescript/module/ui/components/TextField/helpers.d.ts +3 -3
  215. package/lib/typescript/module/ui/components/TextField/helpers.d.ts.map +1 -1
  216. package/lib/typescript/module/ui/components/TextField/types.d.ts +1 -1
  217. package/lib/typescript/module/ui/components/TextField/types.d.ts.map +1 -1
  218. package/lib/typescript/module/ui/components/TextField.d.ts +4 -4
  219. package/lib/typescript/module/ui/components/TextField.d.ts.map +1 -1
  220. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.d.ts +3 -3
  221. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.d.ts.map +1 -1
  222. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts +3 -3
  223. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts.map +1 -1
  224. package/lib/typescript/module/ui/components/TouchableRipple/utils.d.ts +1 -1
  225. package/lib/typescript/module/ui/components/TouchableRipple/utils.d.ts.map +1 -1
  226. package/lib/typescript/module/ui/components/Typography/AnimatedText.d.ts +3 -3
  227. package/lib/typescript/module/ui/components/Typography/AnimatedText.d.ts.map +1 -1
  228. package/lib/typescript/module/ui/components/accountMenuRows.d.ts +1 -1
  229. package/lib/typescript/module/ui/components/accountMenuRows.d.ts.map +1 -1
  230. package/lib/typescript/module/ui/components/feedback/ProgressIndicator.d.ts +1 -1
  231. package/lib/typescript/module/ui/components/feedback/ProgressIndicator.d.ts.map +1 -1
  232. package/lib/typescript/module/ui/components/feedback/constants.d.ts +1 -1
  233. package/lib/typescript/module/ui/components/feedback/constants.d.ts.map +1 -1
  234. package/lib/typescript/module/ui/components/feedback/useFeedbackForm.d.ts +1 -1
  235. package/lib/typescript/module/ui/components/feedback/useFeedbackForm.d.ts.map +1 -1
  236. package/lib/typescript/module/ui/components/payment/PaymentDetailsStep.d.ts +1 -1
  237. package/lib/typescript/module/ui/components/payment/PaymentDetailsStep.d.ts.map +1 -1
  238. package/lib/typescript/module/ui/components/payment/PaymentMethodStep.d.ts +1 -1
  239. package/lib/typescript/module/ui/components/payment/PaymentMethodStep.d.ts.map +1 -1
  240. package/lib/typescript/module/ui/components/payment/PaymentReviewStep.d.ts +1 -1
  241. package/lib/typescript/module/ui/components/payment/PaymentReviewStep.d.ts.map +1 -1
  242. package/lib/typescript/module/ui/components/payment/PaymentSuccessStep.d.ts +1 -1
  243. package/lib/typescript/module/ui/components/payment/PaymentSuccessStep.d.ts.map +1 -1
  244. package/lib/typescript/module/ui/components/payment/PaymentSummaryStep.d.ts +1 -1
  245. package/lib/typescript/module/ui/components/payment/PaymentSummaryStep.d.ts.map +1 -1
  246. package/lib/typescript/module/ui/components/payment/constants.d.ts +1 -1
  247. package/lib/typescript/module/ui/components/payment/constants.d.ts.map +1 -1
  248. package/lib/typescript/module/ui/components/payment/paymentStyles.d.ts +1 -1
  249. package/lib/typescript/module/ui/components/payment/paymentStyles.d.ts.map +1 -1
  250. package/lib/typescript/module/ui/components/theming.d.ts +1 -1
  251. package/lib/typescript/module/ui/components/theming.d.ts.map +1 -1
  252. package/lib/typescript/module/ui/context/OxyContext.d.ts +14 -29
  253. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  254. package/lib/typescript/module/ui/context/ThemeContext.d.ts +1 -1
  255. package/lib/typescript/module/ui/context/ThemeContext.d.ts.map +1 -1
  256. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +2 -2
  257. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  258. package/lib/typescript/module/ui/hooks/queries/usePaymentQueries.d.ts +1 -1
  259. package/lib/typescript/module/ui/hooks/queries/usePaymentQueries.d.ts.map +1 -1
  260. package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  261. package/lib/typescript/module/ui/hooks/queryClient.d.ts +1 -1
  262. package/lib/typescript/module/ui/hooks/queryClient.d.ts.map +1 -1
  263. package/lib/typescript/module/ui/hooks/useAuth.d.ts +1 -1
  264. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  265. package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts +1 -1
  266. package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts.map +1 -1
  267. package/lib/typescript/module/ui/hooks/useLanguageManagement.d.ts +1 -1
  268. package/lib/typescript/module/ui/hooks/useLanguageManagement.d.ts.map +1 -1
  269. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +1 -1
  270. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  271. package/lib/typescript/module/ui/hooks/useStorage.d.ts +1 -1
  272. package/lib/typescript/module/ui/hooks/useStorage.d.ts.map +1 -1
  273. package/lib/typescript/module/ui/index.d.ts +30 -28
  274. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  275. package/lib/typescript/module/ui/navigation/bottomSheetManager.d.ts +1 -1
  276. package/lib/typescript/module/ui/navigation/bottomSheetManager.d.ts.map +1 -1
  277. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  278. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  279. package/lib/typescript/module/ui/screens/AccountMembersScreen.d.ts +1 -1
  280. package/lib/typescript/module/ui/screens/AccountMembersScreen.d.ts.map +1 -1
  281. package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts +1 -1
  282. package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  283. package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts +4 -4
  284. package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  285. package/lib/typescript/module/ui/screens/AccountVerificationScreen.d.ts +1 -1
  286. package/lib/typescript/module/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
  287. package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts +1 -1
  288. package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts.map +1 -1
  289. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts +1 -1
  290. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts.map +1 -1
  291. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts +1 -1
  292. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  293. package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts +1 -1
  294. package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  295. package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts +1 -1
  296. package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  297. package/lib/typescript/module/ui/screens/FAQScreen.d.ts +1 -1
  298. package/lib/typescript/module/ui/screens/FAQScreen.d.ts.map +1 -1
  299. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts +1 -1
  300. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  301. package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts +1 -1
  302. package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
  303. package/lib/typescript/module/ui/screens/FollowersListScreen.d.ts +1 -1
  304. package/lib/typescript/module/ui/screens/FollowersListScreen.d.ts.map +1 -1
  305. package/lib/typescript/module/ui/screens/FollowingListScreen.d.ts +1 -1
  306. package/lib/typescript/module/ui/screens/FollowingListScreen.d.ts.map +1 -1
  307. package/lib/typescript/module/ui/screens/HelpSupportScreen.d.ts +1 -1
  308. package/lib/typescript/module/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  309. package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts +1 -1
  310. package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  311. package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts +1 -1
  312. package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  313. package/lib/typescript/module/ui/screens/LearnMoreUsernamesScreen.d.ts +1 -1
  314. package/lib/typescript/module/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
  315. package/lib/typescript/module/ui/screens/LegalDocumentsScreen.d.ts +1 -1
  316. package/lib/typescript/module/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  317. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts +1 -1
  318. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  319. package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts +1 -1
  320. package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts.map +1 -1
  321. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts +1 -1
  322. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  323. package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts +2 -2
  324. package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  325. package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts +1 -1
  326. package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts.map +1 -1
  327. package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts +1 -1
  328. package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  329. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts +1 -1
  330. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  331. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts +1 -1
  332. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  333. package/lib/typescript/module/ui/screens/SavesCollectionsScreen.d.ts +1 -1
  334. package/lib/typescript/module/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  335. package/lib/typescript/module/ui/screens/SearchSettingsScreen.d.ts +1 -1
  336. package/lib/typescript/module/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  337. package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts +1 -1
  338. package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts.map +1 -1
  339. package/lib/typescript/module/ui/screens/UserListScreen.d.ts +1 -1
  340. package/lib/typescript/module/ui/screens/UserListScreen.d.ts.map +1 -1
  341. package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts +1 -1
  342. package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  343. package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts +1 -1
  344. package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
  345. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts +1 -1
  346. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
  347. package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts +1 -1
  348. package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
  349. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts +1 -1
  350. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  351. package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts +1 -1
  352. package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
  353. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts +1 -1
  354. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  355. package/lib/typescript/module/ui/server.d.ts +2 -2
  356. package/lib/typescript/module/ui/server.d.ts.map +1 -1
  357. package/lib/typescript/module/ui/types/fileManagement.d.ts +1 -1
  358. package/lib/typescript/module/ui/types/fileManagement.d.ts.map +1 -1
  359. package/lib/typescript/module/ui/types/navigation.d.ts +1 -1
  360. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  361. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts +24 -0
  362. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -1
  363. package/lib/typescript/module/ui/utils/fileManagement.d.ts +1 -1
  364. package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
  365. package/package.json +21 -20
  366. package/src/index.ts +8 -5
  367. package/src/ui/components/AccountMenuButton.tsx +9 -11
  368. package/src/ui/components/AccountSwitcher.tsx +71 -37
  369. package/src/ui/components/ProfileButton.tsx +270 -0
  370. package/src/ui/components/ProfileMenu.tsx +416 -0
  371. package/src/ui/context/OxyContext.tsx +217 -130
  372. package/src/ui/context/hooks/useAuthOperations.ts +35 -2
  373. package/src/ui/hooks/queries/useAccountQueries.ts +2 -2
  374. package/src/ui/hooks/queries/usePaymentQueries.ts +12 -12
  375. package/src/ui/hooks/queries/useServicesQueries.ts +9 -6
  376. package/src/ui/index.ts +2 -0
  377. package/src/ui/screens/AccountSettingsScreen.tsx +9 -5
  378. package/src/ui/screens/AccountSwitcherScreen.tsx +3 -3
  379. package/src/ui/screens/CreateAccountScreen.tsx +6 -4
  380. package/src/ui/screens/EditProfileFieldScreen.tsx +8 -7
  381. package/src/ui/screens/FileManagementScreen.tsx +13 -13
  382. package/src/ui/screens/HistoryViewScreen.tsx +7 -7
  383. package/src/ui/screens/LanguageSelectorScreen.tsx +5 -5
  384. package/src/ui/screens/ManageAccountScreen.tsx +17 -18
  385. package/src/ui/screens/PremiumSubscriptionScreen.tsx +3 -3
  386. package/src/ui/screens/PrivacySettingsScreen.tsx +9 -9
  387. package/src/ui/screens/ProfileScreen.tsx +1 -1
  388. package/src/ui/screens/SavesCollectionsScreen.tsx +5 -5
  389. package/src/ui/screens/SearchSettingsScreen.tsx +6 -6
  390. package/src/ui/screens/WelcomeNewUserScreen.tsx +6 -6
  391. package/src/ui/screens/trust/TrustCenterScreen.tsx +5 -5
  392. package/src/ui/screens/trust/TrustRewardsScreen.tsx +4 -4
  393. package/src/ui/utils/__tests__/activeAuthuser.test.ts +75 -0
  394. package/src/ui/utils/activeAuthuser.ts +74 -8
  395. package/lib/commonjs/ui/components/ActiveAccountBanner.js +0 -144
  396. package/lib/commonjs/ui/components/ActiveAccountBanner.js.map +0 -1
  397. package/lib/module/ui/components/ActiveAccountBanner.js +0 -141
  398. package/lib/module/ui/components/ActiveAccountBanner.js.map +0 -1
  399. package/lib/typescript/commonjs/ui/components/ActiveAccountBanner.d.ts +0 -4
  400. package/lib/typescript/commonjs/ui/components/ActiveAccountBanner.d.ts.map +0 -1
  401. package/lib/typescript/module/ui/components/ActiveAccountBanner.d.ts +0 -4
  402. package/lib/typescript/module/ui/components/ActiveAccountBanner.d.ts.map +0 -1
  403. package/src/ui/components/ActiveAccountBanner.tsx +0 -130
@@ -0,0 +1,270 @@
1
+ import type React from 'react';
2
+ import { useCallback, useRef, useState } from 'react';
3
+ import {
4
+ View,
5
+ Pressable,
6
+ Platform,
7
+ type StyleProp,
8
+ type ViewStyle,
9
+ } from 'react-native';
10
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
11
+ import { Avatar } from '@oxyhq/bloom/avatar';
12
+ import { Text } from '@oxyhq/bloom/typography';
13
+ import { useTheme } from '@oxyhq/bloom/theme';
14
+ import { getAccountDisplayName, getAccountFallbackHandle } from '@oxyhq/core';
15
+ import { useAuth } from '../hooks/useAuth';
16
+ import { useI18n } from '../hooks/useI18n';
17
+ import ProfileMenu, { type ProfileMenuAnchor } from './ProfileMenu';
18
+
19
+ const isWeb = Platform.OS === 'web';
20
+
21
+ /**
22
+ * Fixed popover width used by {@link ProfileMenu} on web. `ProfileButton`
23
+ * mirrors this constant when computing the trigger-relative anchor so the
24
+ * left-edge clamp keeps the panel fully on-screen. Keep the two in sync.
25
+ */
26
+ const MENU_WIDTH = 300;
27
+
28
+ /** Gutter, in px, kept between the popover and the viewport edges on web. */
29
+ const VIEWPORT_GUTTER = 8;
30
+
31
+ export interface ProfileButtonProps {
32
+ /**
33
+ * Expanded row (avatar + name + handle + chevron) when `true` (default), or a
34
+ * bare avatar-only trigger when `false` (collapsed sidebar).
35
+ */
36
+ expanded?: boolean;
37
+ /**
38
+ * Avatar diameter in px. Defaults to 40 when expanded, 32 when collapsed.
39
+ */
40
+ avatarSize?: number;
41
+ /** Navigate to the "Manage account" surface (settings). */
42
+ onNavigateManage: () => void;
43
+ /** Start the add-account / sign-in flow for an additional account. */
44
+ onAddAccount: () => void;
45
+ /** Optional: navigate to the signed-in user's own profile. */
46
+ onNavigateProfile?: () => void;
47
+ /** Called before the active identity changes so apps can clear scoped state. */
48
+ onBeforeSessionChange?: () => void | Promise<void>;
49
+ /** Extra className applied to the outer trigger. */
50
+ className?: string;
51
+ /** Extra style applied to the outer trigger. */
52
+ style?: StyleProp<ViewStyle>;
53
+ }
54
+
55
+ /**
56
+ * Self-contained sidebar account trigger, modeled on Bluesky's ProfileCard and
57
+ * the Oxy inbox's `MailboxDrawer` footer. Owns its own open state + anchor
58
+ * measurement, and renders {@link ProfileMenu} (the device-account switcher).
59
+ *
60
+ * Three auth states from {@link useAuth}:
61
+ * - **Undetermined** (`!isAuthResolved || isPrivateApiPending`): a neutral
62
+ * avatar-sized skeleton circle, no press.
63
+ * - **Signed in**: a pressable row — Bloom `Avatar` + display name + `@handle`
64
+ * + an `unfold-more-horizontal` chevron. Press opens the menu upward (web)
65
+ * against the measured trigger, or as a bottom sheet (native).
66
+ * - **Signed out**: a "Sign in" row that calls `useAuth().signIn()`.
67
+ *
68
+ * All display strings resolve through `@oxyhq/core`'s
69
+ * `getAccountDisplayName` / `getAccountFallbackHandle` — no hand-rolled name
70
+ * fallbacks. Avatars pass the bare file id as `source` + `variant="thumb"`, so
71
+ * the app's registered `ImageResolver` builds the thumbnail URL.
72
+ */
73
+ const ProfileButton: React.FC<ProfileButtonProps> = ({
74
+ expanded = true,
75
+ avatarSize,
76
+ onNavigateManage,
77
+ onAddAccount,
78
+ onNavigateProfile,
79
+ onBeforeSessionChange,
80
+ className,
81
+ style,
82
+ }) => {
83
+ const {
84
+ user,
85
+ isAuthenticated,
86
+ isAuthResolved,
87
+ isPrivateApiPending,
88
+ signIn,
89
+ } = useAuth();
90
+ const { colors } = useTheme();
91
+ const { t, locale } = useI18n();
92
+
93
+ const [menuOpen, setMenuOpen] = useState(false);
94
+ const [anchor, setAnchor] = useState<ProfileMenuAnchor | null>(null);
95
+
96
+ // Trigger ref for the web anchor measurement. RN-Web exposes `measure()` on
97
+ // host views, so we anchor the popover to the button rect and open upward.
98
+ const triggerRef = useRef<View | null>(null);
99
+
100
+ const resolvedAvatarSize = avatarSize ?? (expanded ? 40 : 32);
101
+
102
+ const openMenu = useCallback(() => {
103
+ if (!isWeb) {
104
+ setAnchor(null);
105
+ setMenuOpen(true);
106
+ return;
107
+ }
108
+ const node = triggerRef.current;
109
+ if (!node || typeof node.measure !== 'function' || typeof window === 'undefined') {
110
+ setAnchor(null);
111
+ setMenuOpen(true);
112
+ return;
113
+ }
114
+ node.measure((_x, _y, _w, _h, pageX, pageY) => {
115
+ if (typeof pageX !== 'number' || typeof pageY !== 'number') {
116
+ setAnchor(null);
117
+ } else {
118
+ // Clamp the panel's left edge inside the viewport gutter.
119
+ const maxLeft = Math.max(
120
+ VIEWPORT_GUTTER,
121
+ window.innerWidth - MENU_WIDTH - VIEWPORT_GUTTER,
122
+ );
123
+ const left = Math.min(Math.max(VIEWPORT_GUTTER, pageX), maxLeft);
124
+ // Anchor the panel's BOTTOM edge just above the trigger top so
125
+ // the menu opens upward from this footer button.
126
+ const bottom = Math.max(
127
+ VIEWPORT_GUTTER,
128
+ window.innerHeight - pageY + VIEWPORT_GUTTER,
129
+ );
130
+ setAnchor({ left, bottom });
131
+ }
132
+ setMenuOpen(true);
133
+ });
134
+ }, []);
135
+
136
+ const handleClose = useCallback(() => {
137
+ setMenuOpen(false);
138
+ }, []);
139
+
140
+ // ── Undetermined: skeleton circle, no interaction. ──────────────────────
141
+ if (!isAuthResolved || isPrivateApiPending) {
142
+ return (
143
+ <View
144
+ className={className}
145
+ style={style}
146
+ accessibilityElementsHidden
147
+ importantForAccessibility="no-hide-descendants"
148
+ >
149
+ <View
150
+ className="rounded-full bg-secondary"
151
+ style={{ width: resolvedAvatarSize, height: resolvedAvatarSize }}
152
+ />
153
+ </View>
154
+ );
155
+ }
156
+
157
+ // ── Signed out: "Sign in" row. ──────────────────────────────────────────
158
+ if (!isAuthenticated || !user) {
159
+ const signInLabel = t('common.actions.signIn') || 'Sign in';
160
+ return (
161
+ <Pressable
162
+ className={`flex-row items-center gap-3 rounded-full px-2 py-2 ${className ?? ''}`}
163
+ style={style}
164
+ onPress={() => { void signIn(); }}
165
+ accessibilityRole="button"
166
+ accessibilityLabel={signInLabel}
167
+ >
168
+ <View
169
+ className="items-center justify-center rounded-full bg-secondary"
170
+ style={{ width: resolvedAvatarSize, height: resolvedAvatarSize }}
171
+ >
172
+ <MaterialCommunityIcons
173
+ name="login"
174
+ size={Math.round(resolvedAvatarSize * 0.5)}
175
+ color={colors.icon}
176
+ />
177
+ </View>
178
+ {expanded ? (
179
+ <Text
180
+ className="flex-1 font-semibold text-foreground"
181
+ numberOfLines={1}
182
+ >
183
+ {signInLabel}
184
+ </Text>
185
+ ) : null}
186
+ </Pressable>
187
+ );
188
+ }
189
+
190
+ // ── Signed in: avatar + identity + chevron. ─────────────────────────────
191
+ const displayName = getAccountDisplayName(user, locale);
192
+ const handle = getAccountFallbackHandle(user);
193
+ const handleLine = handle ? `@${handle}` : null;
194
+
195
+ const avatarNode = (
196
+ <Avatar
197
+ source={user.avatar ?? undefined}
198
+ variant="thumb"
199
+ name={displayName}
200
+ size={resolvedAvatarSize}
201
+ />
202
+ );
203
+
204
+ if (!expanded) {
205
+ return (
206
+ <View className={className} style={style}>
207
+ <Pressable
208
+ ref={triggerRef}
209
+ className="rounded-full"
210
+ onPress={openMenu}
211
+ accessibilityRole="button"
212
+ accessibilityLabel={t('accountSwitcher.switchWhileSignedInAs', { name: displayName })
213
+ || `Switch account, signed in as ${displayName}`}
214
+ >
215
+ {avatarNode}
216
+ </Pressable>
217
+ <ProfileMenu
218
+ open={menuOpen}
219
+ onClose={handleClose}
220
+ anchor={anchor}
221
+ onNavigateManage={onNavigateManage}
222
+ onAddAccount={onAddAccount}
223
+ onNavigateProfile={onNavigateProfile}
224
+ onBeforeSessionChange={onBeforeSessionChange}
225
+ />
226
+ </View>
227
+ );
228
+ }
229
+
230
+ return (
231
+ <View className={className} style={style}>
232
+ <Pressable
233
+ ref={triggerRef}
234
+ className="flex-row items-center gap-3 rounded-full px-2 py-2"
235
+ onPress={openMenu}
236
+ accessibilityRole="button"
237
+ accessibilityLabel={t('accountSwitcher.switchWhileSignedInAs', { name: displayName })
238
+ || `Switch account, signed in as ${displayName}`}
239
+ >
240
+ {avatarNode}
241
+ <View className="min-w-0 flex-1">
242
+ <Text className="font-bold text-foreground" numberOfLines={1}>
243
+ {displayName}
244
+ </Text>
245
+ {handleLine ? (
246
+ <Text className="text-xs text-muted-foreground" numberOfLines={1}>
247
+ {handleLine}
248
+ </Text>
249
+ ) : null}
250
+ </View>
251
+ <MaterialCommunityIcons
252
+ name="unfold-more-horizontal"
253
+ size={18}
254
+ color={colors.textSecondary}
255
+ />
256
+ </Pressable>
257
+ <ProfileMenu
258
+ open={menuOpen}
259
+ onClose={handleClose}
260
+ anchor={anchor}
261
+ onNavigateManage={onNavigateManage}
262
+ onAddAccount={onAddAccount}
263
+ onNavigateProfile={onNavigateProfile}
264
+ onBeforeSessionChange={onBeforeSessionChange}
265
+ />
266
+ </View>
267
+ );
268
+ };
269
+
270
+ export default ProfileButton;
@@ -0,0 +1,416 @@
1
+ import type React from 'react';
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ import {
4
+ View,
5
+ Pressable,
6
+ Modal,
7
+ ScrollView,
8
+ ActivityIndicator,
9
+ Platform,
10
+ type ViewStyle,
11
+ } from 'react-native';
12
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
13
+ import { Avatar } from '@oxyhq/bloom/avatar';
14
+ import { Text } from '@oxyhq/bloom/typography';
15
+ import { useTheme } from '@oxyhq/bloom/theme';
16
+ import { toast, useDialogControl, Dialog } from '@oxyhq/bloom';
17
+ import { Divider } from '@oxyhq/bloom/divider';
18
+ import { isDev, logger as loggerUtil } from '@oxyhq/core';
19
+ import { useOxy } from '../context/OxyContext';
20
+ import { useI18n } from '../hooks/useI18n';
21
+ import { useDeviceAccounts } from '../hooks/useDeviceAccounts';
22
+
23
+ const isWeb = Platform.OS === 'web';
24
+
25
+ /** Fixed popover width on web. `ProfileButton` mirrors this when anchoring. */
26
+ const MENU_WIDTH = 300;
27
+
28
+ /**
29
+ * Web-only anchor. `ProfileButton` measures its trigger and anchors the panel's
30
+ * BOTTOM-LEFT corner so the menu opens UPWARD from the sidebar footer. Native
31
+ * ignores the anchor and docks the panel to the bottom as a sheet.
32
+ */
33
+ export interface ProfileMenuAnchor {
34
+ /** Distance from the viewport left, for the panel's LEFT edge. */
35
+ left: number;
36
+ /** Distance from the viewport bottom, for the panel's BOTTOM edge (opens upward). */
37
+ bottom: number;
38
+ }
39
+
40
+ export interface ProfileMenuProps {
41
+ open: boolean;
42
+ onClose: () => void;
43
+ /** Web-only trigger anchor. Native ignores this (bottom-sheet style). */
44
+ anchor?: ProfileMenuAnchor | null;
45
+ /** Navigate to the "Manage account" surface (settings). */
46
+ onNavigateManage: () => void;
47
+ /** Start the add-account / sign-in flow for an additional account. */
48
+ onAddAccount: () => void;
49
+ /** Optional: navigate to the signed-in user's own profile. */
50
+ onNavigateProfile?: () => void;
51
+ /** Called before the active identity changes so apps can clear scoped state. */
52
+ onBeforeSessionChange?: () => void | Promise<void>;
53
+ }
54
+
55
+ /**
56
+ * Clean device-account switcher, modeled on the inbox `AccountMenu` but written
57
+ * fresh with NativeWind classNames + Bloom primitives. Lists every account
58
+ * signed in on this device (from {@link useDeviceAccounts}); tapping a row
59
+ * switches, and each inactive row carries a sign-out icon. Below the list:
60
+ * Add account, Manage account, optional View profile, and Sign out of all.
61
+ *
62
+ * Renders as an upward-opening popover anchored to the trigger on web, and a
63
+ * bottom-sheet style modal on native.
64
+ */
65
+ const ProfileMenu: React.FC<ProfileMenuProps> = ({
66
+ open,
67
+ onClose,
68
+ anchor,
69
+ onNavigateManage,
70
+ onAddAccount,
71
+ onNavigateProfile,
72
+ onBeforeSessionChange,
73
+ }) => {
74
+ const {
75
+ activeSessionId,
76
+ switchSession,
77
+ logoutAll,
78
+ removeSession,
79
+ } = useOxy();
80
+ const { t } = useI18n();
81
+ const { colors } = useTheme();
82
+
83
+ const { accounts } = useDeviceAccounts();
84
+
85
+ const [busySessionId, setBusySessionId] = useState<string | null>(null);
86
+ const [removingSessionId, setRemovingSessionId] = useState<string | null>(null);
87
+ const [signingOutAll, setSigningOutAll] = useState(false);
88
+
89
+ const signOutAllDialog = useDialogControl();
90
+
91
+ const isSwitching = busySessionId !== null;
92
+ const actionDisabled = isSwitching || removingSessionId !== null || signingOutAll;
93
+
94
+ // Switch to a non-active account through the SDK's canonical switch path.
95
+ const handleSwitch = useCallback(async (sessionId: string) => {
96
+ if (sessionId === activeSessionId || busySessionId) {
97
+ return;
98
+ }
99
+ setBusySessionId(sessionId);
100
+ try {
101
+ await onBeforeSessionChange?.();
102
+ await switchSession(sessionId);
103
+ toast.success(t('accountSwitcher.toasts.switchSuccess') || 'Switched account');
104
+ onClose();
105
+ } catch (error) {
106
+ if (!isDev()) {
107
+ loggerUtil.warn('Switch account failed', { component: 'ProfileMenu' }, error as unknown);
108
+ }
109
+ toast.error(t('accountSwitcher.toasts.switchFailed') || 'Failed to switch account');
110
+ } finally {
111
+ setBusySessionId(null);
112
+ }
113
+ }, [activeSessionId, busySessionId, switchSession, t, onClose, onBeforeSessionChange]);
114
+
115
+ // Sign out a specific inactive account without switching/clearing the active
116
+ // one. The menu stays open so the user can keep managing accounts.
117
+ const handleRemove = useCallback(async (sessionId: string) => {
118
+ if (sessionId === activeSessionId || removingSessionId) {
119
+ return;
120
+ }
121
+ setRemovingSessionId(sessionId);
122
+ try {
123
+ await removeSession(sessionId);
124
+ toast.success(t('common.actions.signedOut') || 'Signed out');
125
+ } catch (error) {
126
+ loggerUtil.warn('Remove account failed', { component: 'ProfileMenu' }, error as unknown);
127
+ toast.error(t('common.errors.signOutFailed') || 'Failed to sign out');
128
+ } finally {
129
+ setRemovingSessionId(null);
130
+ }
131
+ }, [activeSessionId, removingSessionId, removeSession, t]);
132
+
133
+ const performSignOutAll = useCallback(async () => {
134
+ if (signingOutAll) {
135
+ return;
136
+ }
137
+ setSigningOutAll(true);
138
+ try {
139
+ await onBeforeSessionChange?.();
140
+ await logoutAll();
141
+ toast.success(t('accountSwitcher.toasts.signOutAllSuccess') || 'Signed out of all accounts');
142
+ onClose();
143
+ } catch (error) {
144
+ loggerUtil.warn('Sign out all failed', { component: 'ProfileMenu' }, error as unknown);
145
+ toast.error(t('common.errors.signOutAllFailed') || 'Failed to sign out of all accounts');
146
+ } finally {
147
+ setSigningOutAll(false);
148
+ }
149
+ }, [signingOutAll, logoutAll, t, onClose, onBeforeSessionChange]);
150
+
151
+ // Escape-to-close (web only).
152
+ useEffect(() => {
153
+ if (!open || !isWeb || typeof document === 'undefined') {
154
+ return undefined;
155
+ }
156
+ const onKey = (event: KeyboardEvent) => {
157
+ if (event.key === 'Escape') {
158
+ event.stopPropagation();
159
+ onClose();
160
+ }
161
+ };
162
+ document.addEventListener('keydown', onKey, true);
163
+ return () => document.removeEventListener('keydown', onKey, true);
164
+ }, [open, onClose]);
165
+
166
+ if (!open) {
167
+ return null;
168
+ }
169
+
170
+ // Web: anchor the panel's bottom-left corner to the measured trigger, falling
171
+ // back to a bottom-left placement when no anchor was captured. Native ignores
172
+ // this (the panel docks to the bottom via the overlay's flex-end).
173
+ const panelAnchorStyle: ViewStyle | undefined = isWeb
174
+ ? {
175
+ position: 'absolute',
176
+ width: MENU_WIDTH,
177
+ left: anchor?.left ?? 8,
178
+ bottom: anchor?.bottom ?? 8,
179
+ }
180
+ : undefined;
181
+
182
+ const content = (
183
+ <Pressable
184
+ // Swallow taps inside the panel so they never reach the overlay's
185
+ // outside-tap-to-close handler.
186
+ onPress={() => undefined}
187
+ className={
188
+ isWeb
189
+ ? 'overflow-hidden rounded-2xl border border-border bg-background'
190
+ : 'overflow-hidden rounded-t-3xl bg-background pb-3'
191
+ }
192
+ style={[
193
+ panelAnchorStyle,
194
+ !isWeb ? { maxHeight: '85%' } : { maxHeight: '85%' },
195
+ styles.shadow,
196
+ ]}
197
+ accessibilityRole="menu"
198
+ accessibilityLabel={t('accountMenu.label') || 'Account menu'}
199
+ >
200
+ <ScrollView
201
+ className="grow-0"
202
+ contentContainerClassName="py-1"
203
+ showsVerticalScrollIndicator={false}
204
+ >
205
+ {/* 1) Device accounts — active first (checkmark), others switchable. */}
206
+ {accounts.map((account) => {
207
+ const isActive = account.isCurrent;
208
+ const isBusy = busySessionId === account.sessionId;
209
+ const isRemoving = removingSessionId === account.sessionId;
210
+ return (
211
+ <Pressable
212
+ key={`account-${account.sessionId}`}
213
+ accessibilityRole="menuitem"
214
+ accessibilityLabel={account.displayName}
215
+ accessibilityState={{ selected: isActive }}
216
+ onPress={() => handleSwitch(account.sessionId)}
217
+ disabled={isActive || isBusy || isSwitching}
218
+ className={`flex-row items-center gap-3 px-4 py-2.5 ${
219
+ isActive ? 'bg-secondary' : ''
220
+ } ${isSwitching && !isActive ? 'opacity-40' : ''}`}
221
+ >
222
+ <Avatar
223
+ source={account.user.avatar ?? undefined}
224
+ uri={account.avatarUrl}
225
+ variant="thumb"
226
+ name={account.displayName}
227
+ size={isActive ? 40 : 32}
228
+ />
229
+ <View className="min-w-0 flex-1">
230
+ <Text
231
+ className={`text-foreground ${isActive ? 'font-semibold' : 'font-medium'}`}
232
+ numberOfLines={1}
233
+ >
234
+ {account.displayName}
235
+ </Text>
236
+ {account.email ? (
237
+ <Text
238
+ className="text-xs text-muted-foreground"
239
+ numberOfLines={1}
240
+ >
241
+ {account.email}
242
+ </Text>
243
+ ) : null}
244
+ </View>
245
+ {isBusy ? (
246
+ <ActivityIndicator color={colors.primary} size="small" />
247
+ ) : isActive ? (
248
+ <MaterialCommunityIcons name="check" size={20} color={colors.primary} />
249
+ ) : isRemoving ? (
250
+ <ActivityIndicator color={colors.textSecondary} size="small" />
251
+ ) : (
252
+ <Pressable
253
+ accessibilityRole="button"
254
+ accessibilityLabel={
255
+ t('accountMenu.signOutAccount', { name: account.displayName })
256
+ || `Sign out ${account.displayName}`
257
+ }
258
+ onPress={() => handleRemove(account.sessionId)}
259
+ disabled={actionDisabled}
260
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
261
+ className="h-7 w-7 items-center justify-center rounded-full opacity-60"
262
+ >
263
+ <MaterialCommunityIcons
264
+ name="logout"
265
+ size={18}
266
+ color={colors.textSecondary}
267
+ />
268
+ </Pressable>
269
+ )}
270
+ </Pressable>
271
+ );
272
+ })}
273
+
274
+ {/* 2) Switching indicator. */}
275
+ {isSwitching ? (
276
+ <View className="flex-row items-center justify-center gap-2 py-2">
277
+ <ActivityIndicator color={colors.textSecondary} size="small" />
278
+ <Text className="text-xs font-medium text-muted-foreground">
279
+ {t('accountMenu.switching') || 'Switching account…'}
280
+ </Text>
281
+ </View>
282
+ ) : null}
283
+
284
+ <Divider color={colors.border} spacing={4} />
285
+
286
+ {/* 3) Add another account. */}
287
+ <ActionRow
288
+ icon="account-plus-outline"
289
+ iconColor={colors.icon}
290
+ label={t('accountMenu.addAnother') || 'Add another account'}
291
+ disabled={actionDisabled}
292
+ onPress={() => {
293
+ onClose();
294
+ onAddAccount();
295
+ }}
296
+ />
297
+
298
+ {/* 4) Manage account. */}
299
+ <ActionRow
300
+ icon="cog-outline"
301
+ iconColor={colors.icon}
302
+ label={t('accountMenu.manage') || 'Manage your Oxy Account'}
303
+ disabled={actionDisabled}
304
+ onPress={() => {
305
+ onClose();
306
+ onNavigateManage();
307
+ }}
308
+ />
309
+
310
+ {/* 5) View profile (optional). */}
311
+ {onNavigateProfile ? (
312
+ <ActionRow
313
+ icon="account-outline"
314
+ iconColor={colors.icon}
315
+ label={t('accountMenu.viewProfile') || 'View profile'}
316
+ disabled={actionDisabled}
317
+ onPress={() => {
318
+ onClose();
319
+ onNavigateProfile();
320
+ }}
321
+ />
322
+ ) : null}
323
+
324
+ {/* 6) Sign out of all accounts. */}
325
+ <Divider color={colors.border} spacing={4} />
326
+ <Pressable
327
+ accessibilityRole="menuitem"
328
+ accessibilityLabel={t('accountMenu.signOutAll') || 'Sign out of all accounts'}
329
+ onPress={() => signOutAllDialog.open()}
330
+ disabled={actionDisabled}
331
+ className={`flex-row items-center gap-3 px-4 py-3 ${actionDisabled ? 'opacity-40' : ''}`}
332
+ >
333
+ {signingOutAll ? (
334
+ <ActivityIndicator color={colors.error} size="small" />
335
+ ) : (
336
+ <MaterialCommunityIcons name="logout" size={18} color={colors.error} />
337
+ )}
338
+ <Text className="font-medium" style={{ color: colors.error }}>
339
+ {t('accountMenu.signOutAll') || 'Sign out of all accounts'}
340
+ </Text>
341
+ </Pressable>
342
+ </ScrollView>
343
+ </Pressable>
344
+ );
345
+
346
+ return (
347
+ <Modal
348
+ visible={open}
349
+ transparent
350
+ animationType={isWeb ? 'fade' : 'slide'}
351
+ onRequestClose={onClose}
352
+ >
353
+ <Pressable
354
+ accessibilityRole="button"
355
+ accessibilityLabel={t('common.actions.close') || 'Close'}
356
+ onPress={onClose}
357
+ className={isWeb ? 'flex-1 relative' : 'flex-1 justify-end'}
358
+ style={!isWeb ? styles.nativeScrim : undefined}
359
+ >
360
+ {content}
361
+ </Pressable>
362
+
363
+ <Dialog
364
+ control={signOutAllDialog}
365
+ title={t('accountMenu.signOutAll') || 'Sign out of all accounts'}
366
+ description={t('common.confirms.signOutAll') || 'Are you sure you want to sign out of all accounts?'}
367
+ actions={[
368
+ {
369
+ label: t('accountMenu.signOutAll') || 'Sign out of all accounts',
370
+ color: 'destructive',
371
+ onPress: performSignOutAll,
372
+ },
373
+ { label: t('common.cancel') || 'Cancel', color: 'cancel' },
374
+ ]}
375
+ />
376
+ </Modal>
377
+ );
378
+ };
379
+
380
+ /** Bottom-section action row (Add account / Manage / View profile). */
381
+ const ActionRow: React.FC<{
382
+ icon: string;
383
+ iconColor: string;
384
+ label: string;
385
+ disabled: boolean;
386
+ onPress: () => void;
387
+ }> = ({ icon, iconColor, label, disabled, onPress }) => (
388
+ <Pressable
389
+ accessibilityRole="menuitem"
390
+ accessibilityLabel={label}
391
+ onPress={onPress}
392
+ disabled={disabled}
393
+ className={`flex-row items-center gap-3 px-4 py-3 ${disabled ? 'opacity-40' : ''}`}
394
+ >
395
+ <MaterialCommunityIcons name={icon} size={20} color={iconColor} />
396
+ <Text className="font-medium text-foreground">{label}</Text>
397
+ </Pressable>
398
+ );
399
+
400
+ // The panel's drop shadow and the native scrim are the only values with no
401
+ // NativeWind class equivalent in this package (dynamic elevation + rgba scrim),
402
+ // so they stay as small inline objects rather than raw class-replaceable styles.
403
+ const styles = {
404
+ shadow: {
405
+ shadowColor: '#000',
406
+ shadowOpacity: 0.18,
407
+ shadowRadius: 24,
408
+ shadowOffset: { width: 0, height: 8 },
409
+ elevation: 12,
410
+ } satisfies ViewStyle,
411
+ nativeScrim: {
412
+ backgroundColor: 'rgba(0,0,0,0.32)',
413
+ } satisfies ViewStyle,
414
+ };
415
+
416
+ export default ProfileMenu;