@oxyhq/services 10.2.0 → 10.2.1

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 (232) hide show
  1. package/README.md +2 -2
  2. package/lib/commonjs/index.js +10 -0
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/ui/components/AccountMenu.js +297 -226
  5. package/lib/commonjs/ui/components/AccountMenu.js.map +1 -1
  6. package/lib/commonjs/ui/components/AccountMenuButton.js.map +1 -1
  7. package/lib/commonjs/ui/components/OxySignInButton.js +1 -1
  8. package/lib/commonjs/ui/components/SignInModal.js +11 -12
  9. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  10. package/lib/commonjs/ui/components/accountMenuRows.js +18 -30
  11. package/lib/commonjs/ui/components/accountMenuRows.js.map +1 -1
  12. package/lib/commonjs/ui/context/OxyContext.js +33 -65
  13. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  14. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +7 -13
  15. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  16. package/lib/commonjs/ui/hooks/useAuth.js +9 -39
  17. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  18. package/lib/commonjs/ui/hooks/useDeviceAccounts.js +285 -0
  19. package/lib/commonjs/ui/hooks/useDeviceAccounts.js.map +1 -0
  20. package/lib/commonjs/ui/hooks/useSessionManagement.js +5 -6
  21. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  22. package/lib/commonjs/ui/hooks/useSessionSocket.js +4 -5
  23. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  24. package/lib/commonjs/ui/hooks/useWebSSO.js +1 -1
  25. package/lib/commonjs/ui/navigation/routes.js +7 -7
  26. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  27. package/lib/commonjs/ui/screens/OxyAuthScreen.js +6 -7
  28. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  29. package/lib/commonjs/ui/screens/ProfileScreen.js +18 -20
  30. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  31. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +4 -4
  32. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  33. package/lib/commonjs/ui/screens/{karma/KarmaAboutScreen.js → trust/TrustAboutScreen.js} +11 -11
  34. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js.map +1 -0
  35. package/lib/commonjs/ui/screens/{karma/KarmaCenterScreen.js → trust/TrustCenterScreen.js} +91 -41
  36. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -0
  37. package/lib/commonjs/ui/screens/{karma/KarmaFAQScreen.js → trust/TrustFAQScreen.js} +11 -11
  38. package/lib/commonjs/ui/screens/{karma/KarmaFAQScreen.js.map → trust/TrustFAQScreen.js.map} +1 -1
  39. package/lib/commonjs/ui/screens/{karma/KarmaLeaderboardScreen.js → trust/TrustLeaderboardScreen.js} +63 -42
  40. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -0
  41. package/lib/commonjs/ui/screens/{karma/KarmaRewardsScreen.js → trust/TrustRewardsScreen.js} +54 -54
  42. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -0
  43. package/lib/commonjs/ui/screens/{karma/KarmaRulesScreen.js → trust/TrustRulesScreen.js} +45 -16
  44. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -0
  45. package/lib/commonjs/ui/screens/trust/trustTier.js +23 -0
  46. package/lib/commonjs/ui/screens/trust/trustTier.js.map +1 -0
  47. package/lib/commonjs/utils/deviceFlowSignIn.js +12 -10
  48. package/lib/commonjs/utils/deviceFlowSignIn.js.map +1 -1
  49. package/lib/module/index.js +3 -0
  50. package/lib/module/index.js.map +1 -1
  51. package/lib/module/ui/components/AccountMenu.js +297 -226
  52. package/lib/module/ui/components/AccountMenu.js.map +1 -1
  53. package/lib/module/ui/components/AccountMenuButton.js.map +1 -1
  54. package/lib/module/ui/components/OxySignInButton.js +1 -1
  55. package/lib/module/ui/components/SignInModal.js +11 -12
  56. package/lib/module/ui/components/SignInModal.js.map +1 -1
  57. package/lib/module/ui/components/accountMenuRows.js +18 -30
  58. package/lib/module/ui/components/accountMenuRows.js.map +1 -1
  59. package/lib/module/ui/context/OxyContext.js +33 -65
  60. package/lib/module/ui/context/OxyContext.js.map +1 -1
  61. package/lib/module/ui/context/hooks/useAuthOperations.js +7 -13
  62. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  63. package/lib/module/ui/hooks/useAuth.js +9 -39
  64. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  65. package/lib/module/ui/hooks/useDeviceAccounts.js +281 -0
  66. package/lib/module/ui/hooks/useDeviceAccounts.js.map +1 -0
  67. package/lib/module/ui/hooks/useSessionManagement.js +5 -6
  68. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  69. package/lib/module/ui/hooks/useSessionSocket.js +4 -5
  70. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  71. package/lib/module/ui/hooks/useWebSSO.js +1 -1
  72. package/lib/module/ui/navigation/routes.js +7 -7
  73. package/lib/module/ui/navigation/routes.js.map +1 -1
  74. package/lib/module/ui/screens/OxyAuthScreen.js +6 -7
  75. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  76. package/lib/module/ui/screens/ProfileScreen.js +18 -20
  77. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  78. package/lib/module/ui/screens/WelcomeNewUserScreen.js +4 -4
  79. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  80. package/lib/module/ui/screens/{karma/KarmaAboutScreen.js → trust/TrustAboutScreen.js} +11 -11
  81. package/lib/module/ui/screens/trust/TrustAboutScreen.js.map +1 -0
  82. package/lib/module/ui/screens/{karma/KarmaCenterScreen.js → trust/TrustCenterScreen.js} +92 -42
  83. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -0
  84. package/lib/module/ui/screens/{karma/KarmaFAQScreen.js → trust/TrustFAQScreen.js} +11 -11
  85. package/lib/module/ui/screens/{karma/KarmaFAQScreen.js.map → trust/TrustFAQScreen.js.map} +1 -1
  86. package/lib/module/ui/screens/{karma/KarmaLeaderboardScreen.js → trust/TrustLeaderboardScreen.js} +63 -42
  87. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -0
  88. package/lib/module/ui/screens/{karma/KarmaRewardsScreen.js → trust/TrustRewardsScreen.js} +54 -54
  89. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -0
  90. package/lib/module/ui/screens/{karma/KarmaRulesScreen.js → trust/TrustRulesScreen.js} +45 -16
  91. package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -0
  92. package/lib/module/ui/screens/trust/trustTier.js +19 -0
  93. package/lib/module/ui/screens/trust/trustTier.js.map +1 -0
  94. package/lib/module/utils/deviceFlowSignIn.js +13 -10
  95. package/lib/module/utils/deviceFlowSignIn.js.map +1 -1
  96. package/lib/typescript/commonjs/index.d.ts +3 -1
  97. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +30 -10
  99. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts +1 -1
  101. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  102. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts +19 -12
  103. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +3 -3
  105. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  107. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +1 -7
  108. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  109. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts +3 -7
  110. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  111. package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts +133 -0
  112. package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  114. package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts +1 -1
  116. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
  117. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  118. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/screens/trust/TrustAboutScreen.d.ts +5 -0
  120. package/lib/typescript/commonjs/ui/screens/{karma/KarmaAboutScreen.d.ts.map → trust/TrustAboutScreen.d.ts.map} +1 -1
  121. package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts +5 -0
  122. package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -0
  123. package/lib/typescript/{module/ui/screens/karma/KarmaFAQScreen.d.ts → commonjs/ui/screens/trust/TrustFAQScreen.d.ts} +1 -1
  124. package/lib/typescript/commonjs/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts +5 -0
  126. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/ui/screens/trust/TrustRewardsScreen.d.ts +5 -0
  128. package/lib/typescript/commonjs/ui/screens/{karma/KarmaRewardsScreen.d.ts.map → trust/TrustRewardsScreen.d.ts.map} +1 -1
  129. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts +5 -0
  130. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts +9 -0
  132. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/ui/types/navigation.d.ts +1 -1
  134. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts +11 -9
  135. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts.map +1 -1
  136. package/lib/typescript/module/index.d.ts +3 -1
  137. package/lib/typescript/module/index.d.ts.map +1 -1
  138. package/lib/typescript/module/ui/components/AccountMenu.d.ts +30 -10
  139. package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -1
  140. package/lib/typescript/module/ui/components/SignInModal.d.ts +1 -1
  141. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  142. package/lib/typescript/module/ui/components/accountMenuRows.d.ts +19 -12
  143. package/lib/typescript/module/ui/components/accountMenuRows.d.ts.map +1 -1
  144. package/lib/typescript/module/ui/context/OxyContext.d.ts +3 -3
  145. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  146. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  147. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +1 -7
  148. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  149. package/lib/typescript/module/ui/hooks/useAuth.d.ts +3 -7
  150. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  151. package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts +133 -0
  152. package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts.map +1 -0
  153. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  154. package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts.map +1 -1
  155. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts +1 -1
  156. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  157. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  158. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  159. package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts +5 -0
  160. package/lib/typescript/module/ui/screens/{karma/KarmaAboutScreen.d.ts.map → trust/TrustAboutScreen.d.ts.map} +1 -1
  161. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts +5 -0
  162. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -0
  163. package/lib/typescript/{commonjs/ui/screens/karma/KarmaFAQScreen.d.ts → module/ui/screens/trust/TrustFAQScreen.d.ts} +1 -1
  164. package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -0
  165. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts +5 -0
  166. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -0
  167. package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts +5 -0
  168. package/lib/typescript/module/ui/screens/{karma/KarmaRewardsScreen.d.ts.map → trust/TrustRewardsScreen.d.ts.map} +1 -1
  169. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts +5 -0
  170. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -0
  171. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts +9 -0
  172. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts.map +1 -0
  173. package/lib/typescript/module/ui/types/navigation.d.ts +1 -1
  174. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts +11 -9
  175. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts.map +1 -1
  176. package/package.json +1 -1
  177. package/src/index.ts +10 -1
  178. package/src/ui/components/AccountMenu.tsx +311 -253
  179. package/src/ui/components/AccountMenuButton.tsx +2 -2
  180. package/src/ui/components/OxySignInButton.tsx +1 -1
  181. package/src/ui/components/SignInModal.tsx +13 -14
  182. package/src/ui/components/accountMenuRows.ts +28 -40
  183. package/src/ui/context/OxyContext.tsx +43 -61
  184. package/src/ui/context/hooks/useAuthOperations.ts +7 -13
  185. package/src/ui/hooks/useAuth.ts +11 -48
  186. package/src/ui/hooks/useDeviceAccounts.ts +348 -0
  187. package/src/ui/hooks/useSessionManagement.ts +5 -14
  188. package/src/ui/hooks/useSessionSocket.ts +4 -5
  189. package/src/ui/hooks/useWebSSO.ts +1 -1
  190. package/src/ui/navigation/routes.ts +13 -13
  191. package/src/ui/screens/OxyAuthScreen.tsx +6 -7
  192. package/src/ui/screens/ProfileScreen.tsx +15 -17
  193. package/src/ui/screens/WelcomeNewUserScreen.tsx +2 -2
  194. package/src/ui/screens/{karma/KarmaAboutScreen.tsx → trust/TrustAboutScreen.tsx} +15 -15
  195. package/src/ui/screens/{karma/KarmaCenterScreen.tsx → trust/TrustCenterScreen.tsx} +87 -41
  196. package/src/ui/screens/{karma/KarmaFAQScreen.tsx → trust/TrustFAQScreen.tsx} +10 -10
  197. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +101 -0
  198. package/src/ui/screens/{karma/KarmaRewardsScreen.tsx → trust/TrustRewardsScreen.tsx} +54 -54
  199. package/src/ui/screens/{karma/KarmaRulesScreen.tsx → trust/TrustRulesScreen.tsx} +27 -13
  200. package/src/ui/screens/trust/trustTier.ts +20 -0
  201. package/src/ui/types/navigation.ts +1 -2
  202. package/src/utils/__tests__/deviceFlowSignIn.test.ts +2 -3
  203. package/src/utils/deviceFlowSignIn.ts +18 -12
  204. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +0 -1
  205. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +0 -1
  206. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +0 -1
  207. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +0 -1
  208. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +0 -1
  209. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +0 -1
  210. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +0 -1
  211. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +0 -1
  212. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +0 -1
  213. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +0 -1
  214. package/lib/typescript/commonjs/ui/screens/karma/KarmaAboutScreen.d.ts +0 -5
  215. package/lib/typescript/commonjs/ui/screens/karma/KarmaCenterScreen.d.ts +0 -5
  216. package/lib/typescript/commonjs/ui/screens/karma/KarmaCenterScreen.d.ts.map +0 -1
  217. package/lib/typescript/commonjs/ui/screens/karma/KarmaFAQScreen.d.ts.map +0 -1
  218. package/lib/typescript/commonjs/ui/screens/karma/KarmaLeaderboardScreen.d.ts +0 -5
  219. package/lib/typescript/commonjs/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +0 -1
  220. package/lib/typescript/commonjs/ui/screens/karma/KarmaRewardsScreen.d.ts +0 -5
  221. package/lib/typescript/commonjs/ui/screens/karma/KarmaRulesScreen.d.ts +0 -5
  222. package/lib/typescript/commonjs/ui/screens/karma/KarmaRulesScreen.d.ts.map +0 -1
  223. package/lib/typescript/module/ui/screens/karma/KarmaAboutScreen.d.ts +0 -5
  224. package/lib/typescript/module/ui/screens/karma/KarmaCenterScreen.d.ts +0 -5
  225. package/lib/typescript/module/ui/screens/karma/KarmaCenterScreen.d.ts.map +0 -1
  226. package/lib/typescript/module/ui/screens/karma/KarmaFAQScreen.d.ts.map +0 -1
  227. package/lib/typescript/module/ui/screens/karma/KarmaLeaderboardScreen.d.ts +0 -5
  228. package/lib/typescript/module/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +0 -1
  229. package/lib/typescript/module/ui/screens/karma/KarmaRewardsScreen.d.ts +0 -5
  230. package/lib/typescript/module/ui/screens/karma/KarmaRulesScreen.d.ts +0 -5
  231. package/lib/typescript/module/ui/screens/karma/KarmaRulesScreen.d.ts.map +0 -1
  232. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +0 -88
@@ -14,31 +14,61 @@ import {
14
14
  } from 'react-native';
15
15
  import { Ionicons } from '@expo/vector-icons';
16
16
  import { toast, useDialogControl, Dialog } from '@oxyhq/bloom';
17
+ import { Divider } from '@oxyhq/bloom/divider';
17
18
  import { useTheme } from '@oxyhq/bloom/theme';
18
19
  import Avatar from './Avatar';
19
20
  import { useOxy } from '../context/OxyContext';
20
21
  import { useI18n } from '../hooks/useI18n';
21
22
  import { logger as loggerUtil } from '@oxyhq/core';
22
23
  import { buildAccountRows, type AccountRow } from './accountMenuRows';
24
+ import { useDeviceAccounts } from '../hooks/useDeviceAccounts';
25
+
26
+ /**
27
+ * Web-only anchor for the popover panel. Each field anchors the panel against
28
+ * one viewport edge, so the popover can be placed against ANY corner: a
29
+ * top-right avatar chip opens downward/right-aligned (`{ top, right }`), while a
30
+ * bottom-left account button opens upward/left-aligned (`{ bottom, left }`).
31
+ *
32
+ * Callers MUST supply at most one vertical edge (`top` XOR `bottom`) and at most
33
+ * one horizontal edge (`left` XOR `right`). The panel has a fixed width and
34
+ * `maxHeight`, so a single vertical + single horizontal edge fully positions it.
35
+ * Supplying both opposite edges (e.g. `top` AND `bottom`) would stretch the
36
+ * panel on RN-Web and is unsupported.
37
+ */
38
+ export interface AccountMenuAnchor {
39
+ /** Distance from the viewport top, when anchoring the panel's TOP edge. */
40
+ top?: number;
41
+ /** Distance from the viewport bottom, when anchoring the panel's BOTTOM edge (opens upward). */
42
+ bottom?: number;
43
+ /** Distance from the viewport left, when anchoring the panel's LEFT edge. */
44
+ left?: number;
45
+ /** Distance from the viewport right, when anchoring the panel's RIGHT edge. */
46
+ right?: number;
47
+ }
23
48
 
24
49
  export interface AccountMenuProps {
25
50
  open: boolean;
26
51
  onClose: () => void;
27
52
  onNavigateManage: () => void;
28
53
  onAddAccount: () => void;
29
- /** Optional anchor coords (web only). Native ignores this and uses bottom-sheet style. */
30
- anchor?: { top: number; right: number } | null;
54
+ /** Optional anchor (web only). Native ignores this and uses bottom-sheet style. */
55
+ anchor?: AccountMenuAnchor | null;
31
56
  }
32
57
 
33
58
  const isWeb = Platform.OS === 'web';
34
59
 
60
+ /** Fixed popover width on web. Callers that compute an anchor (e.g. inbox's
61
+ * MailboxDrawer) key their gutter math off this — keep them consistent. */
62
+ const PANEL_WIDTH = 360;
63
+
35
64
  /**
36
- * Reusable account menu modeled after the Google account chooser. Opens from
37
- * the avatar entry point (`AccountMenuButton`) or any other trigger.
65
+ * Unified, canonical account switcher for the Oxy ecosystem. Gmail-style: the
66
+ * accounts list sits at the top (current account first, with a checkmark), then
67
+ * "Add another account", "Manage account", and the sign-out actions.
38
68
  *
39
- * Reads everything it needs from `useOxy()` — never receive a session via
40
- * props. Renders as a popover anchored to the trigger on web, and as a
41
- * full-width bottom-sheet style modal on native.
69
+ * Reads everything it needs from `useOxy()` / `useDeviceAccounts()` — never
70
+ * receives a session via props. Renders as a popover anchored to the trigger on
71
+ * web, and as a full-width bottom-sheet style modal on native.
42
72
  */
43
73
  const AccountMenu: React.FC<AccountMenuProps> = ({
44
74
  open,
@@ -48,18 +78,25 @@ const AccountMenu: React.FC<AccountMenuProps> = ({
48
78
  anchor,
49
79
  }) => {
50
80
  const {
51
- user,
52
- sessions,
53
81
  activeSessionId,
54
82
  switchSession,
55
83
  logout,
56
84
  logoutAll,
57
- oxyServices,
85
+ removeSession,
58
86
  } = useOxy();
59
- const { t, locale } = useI18n();
87
+ const { t } = useI18n();
60
88
  const bloomTheme = useTheme();
89
+ const colors = bloomTheme.colors;
90
+
91
+ // Source EVERY account's real name/email/avatar/color from the unified
92
+ // device-account hook (shared apex `refresh-all` path on `*.oxy.so`, local
93
+ // `useOxy()` fallback on cross-domain web / native). This also synthesises a
94
+ // live-user row when the probe is empty, so the signed-in user is always
95
+ // represented (no "Not signed in" false negative).
96
+ const { accounts: deviceAccounts } = useDeviceAccounts();
61
97
 
62
98
  const [busySessionId, setBusySessionId] = useState<string | null>(null);
99
+ const [removingSessionId, setRemovingSessionId] = useState<string | null>(null);
63
100
  const [signingOut, setSigningOut] = useState(false);
64
101
  const [signingOutAll, setSigningOutAll] = useState(false);
65
102
 
@@ -67,24 +104,27 @@ const AccountMenu: React.FC<AccountMenuProps> = ({
67
104
  const signOutAllDialog = useDialogControl();
68
105
 
69
106
  const containerRef = useRef<View | null>(null);
70
- const firstActionRef = useRef<View | null>(null);
71
-
72
- const rows = useMemo<AccountRow[]>(() => buildAccountRows({
73
- sessions,
74
- activeSessionId,
75
- user,
76
- locale,
77
- getAvatarUrl: (avatarId) => oxyServices.getFileDownloadUrl(avatarId, 'thumb'),
78
- }), [sessions, activeSessionId, user, locale, oxyServices]);
79
107
 
80
- const activeRow = useMemo<AccountRow | null>(() => {
81
- return rows.find((r) => r.isActive) ?? null;
82
- }, [rows]);
108
+ // Current account first, then the rest in their existing order — matching
109
+ // the Gmail-style chooser the inbox design ports from.
110
+ const rows = useMemo<AccountRow[]>(() => {
111
+ const built = buildAccountRows({ accounts: deviceAccounts });
112
+ const current = built.filter((row) => row.isActive);
113
+ const others = built.filter((row) => !row.isActive);
114
+ return [...current, ...others];
115
+ }, [deviceAccounts]);
83
116
 
84
- const inactiveRows = useMemo<AccountRow[]>(() => {
85
- return rows.filter((r) => !r.isActive);
86
- }, [rows]);
117
+ const isSwitching = busySessionId !== null;
87
118
 
119
+ // Switch to a non-active account. We route ALL rows through
120
+ // `useOxy().switchSession(sessionId)` — the SDK's canonical switch path. On
121
+ // WEB it already performs the same silent activation the auth chooser uses:
122
+ // when the target `ClientSession` carries an `authuser` slot, it rotates that
123
+ // slot via `oxyServices.refreshTokenViaCookie({ authuser })` and plants the
124
+ // fresh access token before validating (see `useSessionManagement.switchSession`).
125
+ // On NATIVE it validates the session id directly. There is no separate
126
+ // "activate by authuser" SDK entry point, so reusing `switchSession`
127
+ // (rather than inventing a parallel mechanism) keeps a single source of truth.
88
128
  const handleSwitch = useCallback(async (sessionId: string) => {
89
129
  if (sessionId === activeSessionId || busySessionId) {
90
130
  return;
@@ -104,6 +144,27 @@ const AccountMenu: React.FC<AccountMenuProps> = ({
104
144
  }
105
145
  }, [activeSessionId, busySessionId, switchSession, t, onClose]);
106
146
 
147
+ // Sign out a SPECIFIC inactive account from its per-row icon. `removeSession`
148
+ // is the SDK's canonical per-session sign-out: it targets the given session
149
+ // id (cookie-cleared logout via `authuser` slot on web, bearer logout
150
+ // otherwise) and removes ONLY that account without switching/clearing the
151
+ // active session. The menu stays open so the user can keep managing accounts.
152
+ const handleRemove = useCallback(async (sessionId: string) => {
153
+ if (sessionId === activeSessionId || removingSessionId) {
154
+ return;
155
+ }
156
+ setRemovingSessionId(sessionId);
157
+ try {
158
+ await removeSession(sessionId);
159
+ toast.success(t('common.actions.signedOut') || 'Signed out');
160
+ } catch (error) {
161
+ loggerUtil.warn('Remove account failed', { component: 'AccountMenu' }, error as unknown);
162
+ toast.error(t('common.errors.signOutFailed') || 'Failed to sign out');
163
+ } finally {
164
+ setRemovingSessionId(null);
165
+ }
166
+ }, [activeSessionId, removingSessionId, removeSession, t]);
167
+
107
168
  const performSignOut = useCallback(async () => {
108
169
  if (signingOut) {
109
170
  return;
@@ -161,200 +222,215 @@ const AccountMenu: React.FC<AccountMenuProps> = ({
161
222
  ? styles.webOverlay
162
223
  : styles.nativeOverlay;
163
224
 
225
+ // Apply ONLY the edges the anchor supplies (so the panel never sets
226
+ // conflicting opposite edges). When no anchor is provided, fall back to the
227
+ // historical top-right placement used by `AccountMenuButton`.
228
+ const anchorStyle: ViewStyle = anchor
229
+ ? {
230
+ ...(anchor.top !== undefined ? { top: anchor.top } : null),
231
+ ...(anchor.bottom !== undefined ? { bottom: anchor.bottom } : null),
232
+ ...(anchor.left !== undefined ? { left: anchor.left } : null),
233
+ ...(anchor.right !== undefined ? { right: anchor.right } : null),
234
+ }
235
+ : { top: 64, right: 16 };
236
+
164
237
  const panelStyles: ViewStyle[] = isWeb
165
238
  ? [
166
239
  styles.panelBase,
167
240
  styles.panelWeb,
168
- anchor
169
- ? { top: anchor.top, right: anchor.right }
170
- : { top: 64, right: 16 },
171
- { backgroundColor: bloomTheme.colors.background, borderColor: bloomTheme.colors.border },
241
+ anchorStyle,
242
+ { backgroundColor: colors.background, borderColor: colors.border },
172
243
  ]
173
244
  : [
174
245
  styles.panelBase,
175
246
  styles.panelNative,
176
- { backgroundColor: bloomTheme.colors.background },
247
+ { backgroundColor: colors.background },
177
248
  ];
178
249
 
250
+ const actionDisabled = isSwitching || signingOut || signingOutAll;
251
+
179
252
  const content = (
180
- <View
253
+ <Pressable
181
254
  ref={containerRef}
255
+ // Swallow taps inside the panel so they never reach the overlay's
256
+ // outside-tap-to-close handler. (On web the panel is a direct,
257
+ // absolutely-positioned child of the overlay so the anchor resolves
258
+ // against the viewport.)
259
+ onPress={() => undefined}
182
260
  style={panelStyles}
183
261
  accessibilityRole="menu"
184
262
  accessibilityLabel={t('accountMenu.label') || 'Account menu'}
185
263
  >
186
- {/* 1) Header */}
187
- {activeRow ? (
188
- <View style={styles.header}>
189
- <Avatar
190
- uri={activeRow.avatarUri}
191
- name={activeRow.displayName}
192
- size={64}
193
- />
194
- <Text
195
- style={[styles.headerName, { color: bloomTheme.colors.text }]}
196
- numberOfLines={1}
197
- >
198
- {activeRow.displayName}
199
- </Text>
200
- {activeRow.secondary ? (
201
- <Text
202
- style={[styles.headerSecondary, { color: bloomTheme.colors.textSecondary }]}
203
- numberOfLines={1}
204
- >
205
- {activeRow.secondary}
206
- </Text>
207
- ) : null}
208
- </View>
209
- ) : (
210
- <View style={styles.header}>
211
- <Text style={[styles.headerName, { color: bloomTheme.colors.text }]}>
212
- {t('common.status.notSignedIn') || 'Not signed in'}
213
- </Text>
214
- </View>
215
- )}
216
-
217
- {/* 2) Manage account */}
218
- <TouchableOpacity
219
- ref={firstActionRef as React.RefObject<View>}
220
- accessibilityRole="menuitem"
221
- accessibilityLabel={t('accountMenu.manage') || 'Manage your Oxy Account'}
222
- style={[styles.primaryButton, { borderColor: bloomTheme.colors.border }]}
223
- onPress={() => {
224
- onClose();
225
- onNavigateManage();
226
- }}
264
+ <ScrollView
265
+ style={styles.scroll}
266
+ contentContainerStyle={styles.scrollContent}
267
+ showsVerticalScrollIndicator={false}
227
268
  >
228
- <Text style={[styles.primaryButtonText, { color: bloomTheme.colors.primary }]}>
229
- {t('accountMenu.manage') || 'Manage your Oxy Account'}
230
- </Text>
231
- </TouchableOpacity>
232
-
233
- {/* 3) Account list */}
234
- {rows.length > 0 ? (
235
- <ScrollView
236
- style={styles.list}
237
- contentContainerStyle={styles.listContent}
238
- showsVerticalScrollIndicator={false}
239
- >
240
- {rows.map((row) => {
241
- const isBusy = busySessionId === row.sessionId;
242
- return (
243
- <TouchableOpacity
244
- key={`account-${row.sessionId}`}
245
- accessibilityRole="menuitem"
246
- accessibilityLabel={row.displayName}
247
- accessibilityState={{ selected: row.isActive }}
248
- onPress={() => handleSwitch(row.sessionId)}
249
- disabled={row.isActive || isBusy}
250
- style={[
251
- styles.row,
252
- row.isActive && {
253
- backgroundColor: bloomTheme.colors.primarySubtle,
254
- },
255
- ]}
256
- >
257
- <Avatar
258
- uri={row.avatarUri}
259
- name={row.displayName}
260
- size={36}
261
- />
262
- <View style={styles.rowInfo}>
269
+ {/* 1) Accounts list — current first (checkmark), then others. */}
270
+ {rows.map((row) => {
271
+ const isBusy = busySessionId === row.sessionId;
272
+ const isRemoving = removingSessionId === row.sessionId;
273
+ return (
274
+ <TouchableOpacity
275
+ key={`account-${row.sessionId}`}
276
+ accessibilityRole="menuitem"
277
+ accessibilityLabel={row.displayName}
278
+ accessibilityState={{ selected: row.isActive }}
279
+ onPress={() => handleSwitch(row.sessionId)}
280
+ disabled={row.isActive || isBusy || isSwitching}
281
+ activeOpacity={0.6}
282
+ style={[
283
+ styles.accountRow,
284
+ row.isActive && { backgroundColor: colors.primarySubtle },
285
+ isSwitching && !row.isActive && styles.rowDisabled,
286
+ ]}
287
+ >
288
+ <Avatar
289
+ uri={row.avatarUri}
290
+ name={row.displayName}
291
+ size={row.isActive ? 40 : 32}
292
+ />
293
+ <View style={styles.accountInfo}>
294
+ <Text
295
+ style={[
296
+ styles.accountName,
297
+ { color: colors.text },
298
+ row.isActive && styles.accountNameActive,
299
+ ]}
300
+ numberOfLines={1}
301
+ >
302
+ {row.displayName}
303
+ </Text>
304
+ {row.secondary ? (
263
305
  <Text
264
- style={[styles.rowName, { color: bloomTheme.colors.text }]}
306
+ style={[styles.accountEmail, { color: colors.textSecondary }]}
265
307
  numberOfLines={1}
266
308
  >
267
- {row.displayName}
309
+ {row.secondary}
268
310
  </Text>
269
- {row.secondary ? (
270
- <Text
271
- style={[styles.rowSecondary, { color: bloomTheme.colors.textSecondary }]}
272
- numberOfLines={1}
273
- >
274
- {row.secondary}
275
- </Text>
276
- ) : null}
277
- </View>
278
- {isBusy ? (
279
- <ActivityIndicator color={bloomTheme.colors.primary} size="small" />
280
- ) : row.isActive ? (
311
+ ) : null}
312
+ </View>
313
+ {isBusy ? (
314
+ <ActivityIndicator color={colors.primary} size="small" />
315
+ ) : row.isActive ? (
316
+ <Ionicons name="checkmark" size={20} color={colors.primary} />
317
+ ) : isRemoving ? (
318
+ <ActivityIndicator color={colors.textSecondary} size="small" />
319
+ ) : (
320
+ <TouchableOpacity
321
+ accessibilityRole="button"
322
+ accessibilityLabel={
323
+ t('accountMenu.signOutAccount', { name: row.displayName })
324
+ || `Sign out ${row.displayName}`
325
+ }
326
+ onPress={() => handleRemove(row.sessionId)}
327
+ disabled={isSwitching || removingSessionId !== null}
328
+ activeOpacity={0.6}
329
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
330
+ style={styles.rowSignOutButton}
331
+ >
281
332
  <Ionicons
282
- name="checkmark-circle"
283
- size={20}
284
- color={bloomTheme.colors.primary}
333
+ name="log-out-outline"
334
+ size={18}
335
+ color={colors.textSecondary}
285
336
  />
286
- ) : null}
287
- </TouchableOpacity>
288
- );
289
- })}
290
- </ScrollView>
291
- ) : null}
292
-
293
- {/* 4) Add another account */}
294
- <TouchableOpacity
295
- accessibilityRole="menuitem"
296
- accessibilityLabel={t('accountMenu.addAnother') || 'Add another account'}
297
- onPress={() => {
298
- onClose();
299
- onAddAccount();
300
- }}
301
- style={[styles.row, styles.actionRow]}
302
- >
303
- <View
304
- style={[
305
- styles.actionIcon,
306
- { backgroundColor: bloomTheme.colors.primarySubtle },
307
- ]}
337
+ </TouchableOpacity>
338
+ )}
339
+ </TouchableOpacity>
340
+ );
341
+ })}
342
+
343
+ {/* 2) Switching indicator. */}
344
+ {isSwitching ? (
345
+ <View style={styles.switchingRow}>
346
+ <ActivityIndicator color={colors.textSecondary} size="small" />
347
+ <Text style={[styles.switchingText, { color: colors.textSecondary }]}>
348
+ {t('accountMenu.switching') || 'Switching account…'}
349
+ </Text>
350
+ </View>
351
+ ) : null}
352
+
353
+ <Divider color={colors.border} spacing={4} />
354
+
355
+ {/* 3) Add another account. */}
356
+ <TouchableOpacity
357
+ accessibilityRole="menuitem"
358
+ accessibilityLabel={t('accountMenu.addAnother') || 'Add another account'}
359
+ onPress={() => {
360
+ onClose();
361
+ onAddAccount();
362
+ }}
363
+ disabled={actionDisabled}
364
+ activeOpacity={0.6}
365
+ style={[styles.actionRow, actionDisabled && styles.rowDisabled]}
308
366
  >
309
- <Ionicons
310
- name="person-add-outline"
311
- size={18}
312
- color={bloomTheme.colors.primary}
313
- />
314
- </View>
315
- <View style={styles.rowInfo}>
316
- <Text style={[styles.rowName, { color: bloomTheme.colors.text }]}>
367
+ <Ionicons name="person-add-outline" size={20} color={colors.icon} />
368
+ <Text style={[styles.actionText, { color: colors.text }]}>
317
369
  {t('accountMenu.addAnother') || 'Add another account'}
318
370
  </Text>
319
- </View>
320
- </TouchableOpacity>
371
+ </TouchableOpacity>
372
+
373
+ <Divider color={colors.border} spacing={4} />
374
+
375
+ {/* 4) Manage account / Settings. */}
376
+ <TouchableOpacity
377
+ accessibilityRole="menuitem"
378
+ accessibilityLabel={t('accountMenu.manage') || 'Manage your Oxy Account'}
379
+ onPress={() => {
380
+ onClose();
381
+ onNavigateManage();
382
+ }}
383
+ disabled={actionDisabled}
384
+ activeOpacity={0.6}
385
+ style={[styles.actionRow, actionDisabled && styles.rowDisabled]}
386
+ >
387
+ <Ionicons name="settings-outline" size={18} color={colors.icon} />
388
+ <Text style={[styles.actionText, { color: colors.text }]}>
389
+ {t('accountMenu.manage') || 'Manage your Oxy Account'}
390
+ </Text>
391
+ </TouchableOpacity>
321
392
 
322
- {/* 5) Sign out + sign out of all */}
323
- <View style={[styles.footer, { borderTopColor: bloomTheme.colors.border }]}>
393
+ {/* 5) Sign out (current). */}
324
394
  <TouchableOpacity
325
395
  accessibilityRole="menuitem"
326
396
  accessibilityLabel={t('common.actions.signOut') || 'Sign out'}
327
397
  onPress={() => signOutDialog.open()}
328
- disabled={signingOut || signingOutAll}
329
- style={styles.footerButton}
398
+ disabled={actionDisabled}
399
+ activeOpacity={0.6}
400
+ style={[styles.actionRow, actionDisabled && styles.rowDisabled]}
330
401
  >
331
402
  {signingOut ? (
332
- <ActivityIndicator color={bloomTheme.colors.error} size="small" />
403
+ <ActivityIndicator color={colors.error} size="small" />
333
404
  ) : (
334
- <Text style={[styles.footerButtonText, { color: bloomTheme.colors.error }]}>
335
- {t('common.actions.signOut') || 'Sign out'}
336
- </Text>
405
+ <Ionicons name="log-out-outline" size={18} color={colors.error} />
337
406
  )}
407
+ <Text style={[styles.actionText, { color: colors.error }]}>
408
+ {t('common.actions.signOut') || 'Sign out'}
409
+ </Text>
338
410
  </TouchableOpacity>
411
+
412
+ {/* 6) Sign out of all accounts (only when >1 account). */}
339
413
  {rows.length > 1 ? (
340
414
  <TouchableOpacity
341
415
  accessibilityRole="menuitem"
342
416
  accessibilityLabel={t('accountMenu.signOutAll') || 'Sign out of all accounts'}
343
417
  onPress={() => signOutAllDialog.open()}
344
- disabled={signingOut || signingOutAll}
345
- style={styles.footerButton}
418
+ disabled={actionDisabled}
419
+ activeOpacity={0.6}
420
+ style={[styles.actionRow, actionDisabled && styles.rowDisabled]}
346
421
  >
347
422
  {signingOutAll ? (
348
- <ActivityIndicator color={bloomTheme.colors.error} size="small" />
423
+ <ActivityIndicator color={colors.error} size="small" />
349
424
  ) : (
350
- <Text style={[styles.footerButtonText, { color: bloomTheme.colors.error }]}>
351
- {t('accountMenu.signOutAll') || 'Sign out of all accounts'}
352
- </Text>
425
+ <Ionicons name="log-out-outline" size={18} color={colors.error} />
353
426
  )}
427
+ <Text style={[styles.actionText, { color: colors.error }]}>
428
+ {t('accountMenu.signOutAll') || 'Sign out of all accounts'}
429
+ </Text>
354
430
  </TouchableOpacity>
355
431
  ) : null}
356
- </View>
357
- </View>
432
+ </ScrollView>
433
+ </Pressable>
358
434
  );
359
435
 
360
436
  return (
@@ -370,10 +446,15 @@ const AccountMenu: React.FC<AccountMenuProps> = ({
370
446
  onPress={onClose}
371
447
  style={overlayStyles}
372
448
  >
373
- {/* Stop propagation: tapping the panel must not close it. */}
374
- <Pressable onPress={() => undefined} style={styles.panelTouchable}>
375
- {content}
376
- </Pressable>
449
+ {/*
450
+ * Web: the panel is `position: absolute` and rendered as a DIRECT
451
+ * child of the full-viewport overlay, so its anchor edges resolve
452
+ * against the viewport. The panel swallows its own taps.
453
+ *
454
+ * Native: the overlay is `justify-content: flex-end`, so the
455
+ * (statically positioned) panel docks to the bottom as a sheet.
456
+ */}
457
+ {content}
377
458
  </Pressable>
378
459
 
379
460
  <Dialog
@@ -410,18 +491,19 @@ const styles = StyleSheet.create({
410
491
  webOverlay: {
411
492
  flex: 1,
412
493
  backgroundColor: 'transparent',
494
+ // Explicit positioning context: the absolutely-positioned panel is a
495
+ // direct child and resolves its anchor edges (top/bottom/left/right)
496
+ // against this full-viewport overlay — matching the trigger-rect math
497
+ // callers compute from `window.innerWidth` / `window.innerHeight`.
498
+ position: 'relative',
413
499
  },
414
500
  nativeOverlay: {
415
501
  flex: 1,
416
502
  backgroundColor: 'rgba(0,0,0,0.32)',
417
503
  justifyContent: 'flex-end',
418
504
  },
419
- panelTouchable: {
420
- // Pressable wrapper that owns no styling — just absorbs taps.
421
- },
422
505
  panelBase: {
423
- borderRadius: 24,
424
- paddingVertical: 12,
506
+ borderRadius: 12,
425
507
  shadowColor: '#000',
426
508
  shadowOpacity: 0.18,
427
509
  shadowRadius: 24,
@@ -431,103 +513,79 @@ const styles = StyleSheet.create({
431
513
  },
432
514
  panelWeb: {
433
515
  position: 'absolute',
434
- width: 360,
516
+ width: PANEL_WIDTH,
435
517
  maxHeight: '85%',
436
518
  borderWidth: 1,
437
519
  },
438
520
  panelNative: {
439
521
  marginHorizontal: 0,
440
- borderTopLeftRadius: 28,
441
- borderTopRightRadius: 28,
522
+ borderTopLeftRadius: 20,
523
+ borderTopRightRadius: 20,
442
524
  borderBottomLeftRadius: 0,
443
525
  borderBottomRightRadius: 0,
444
- paddingTop: 20,
445
- paddingBottom: 24,
526
+ paddingBottom: 12,
446
527
  maxHeight: '85%',
447
528
  },
448
- header: {
449
- alignItems: 'center',
450
- paddingHorizontal: 20,
451
- paddingVertical: 16,
452
- },
453
- headerName: {
454
- fontSize: 18,
455
- fontWeight: '600',
456
- marginTop: 12,
457
- textAlign: 'center',
529
+ scroll: {
530
+ flexGrow: 0,
458
531
  },
459
- headerSecondary: {
460
- fontSize: 14,
461
- marginTop: 4,
462
- textAlign: 'center',
532
+ scrollContent: {
533
+ paddingVertical: 4,
463
534
  },
464
- primaryButton: {
465
- marginHorizontal: 20,
466
- marginBottom: 12,
467
- paddingVertical: 12,
468
- paddingHorizontal: 16,
469
- borderRadius: 999,
470
- borderWidth: 1,
535
+ accountRow: {
536
+ flexDirection: 'row',
471
537
  alignItems: 'center',
538
+ paddingHorizontal: 14,
539
+ paddingVertical: 10,
540
+ gap: 10,
472
541
  },
473
- primaryButtonText: {
474
- fontSize: 14,
475
- fontWeight: '600',
542
+ rowDisabled: {
543
+ opacity: 0.4,
476
544
  },
477
- list: {
478
- maxHeight: 280,
545
+ accountInfo: {
546
+ flex: 1,
547
+ minWidth: 0,
479
548
  },
480
- listContent: {
481
- paddingHorizontal: 12,
482
- paddingBottom: 4,
549
+ accountName: {
550
+ fontSize: 13,
551
+ fontWeight: '500',
483
552
  },
484
- row: {
485
- flexDirection: 'row',
486
- alignItems: 'center',
487
- paddingVertical: 10,
488
- paddingHorizontal: 12,
489
- borderRadius: 16,
490
- marginVertical: 2,
553
+ accountNameActive: {
554
+ fontWeight: '600',
491
555
  },
492
- actionRow: {
493
- marginHorizontal: 12,
494
- marginTop: 4,
556
+ accountEmail: {
557
+ fontSize: 11,
558
+ marginTop: 1,
495
559
  },
496
- actionIcon: {
497
- width: 36,
498
- height: 36,
499
- borderRadius: 18,
560
+ rowSignOutButton: {
561
+ width: 28,
562
+ height: 28,
500
563
  alignItems: 'center',
501
564
  justifyContent: 'center',
565
+ borderRadius: 14,
566
+ opacity: 0.6,
502
567
  },
503
- rowInfo: {
504
- flex: 1,
505
- marginLeft: 12,
568
+ switchingRow: {
569
+ flexDirection: 'row',
570
+ alignItems: 'center',
571
+ justifyContent: 'center',
572
+ paddingVertical: 8,
573
+ gap: 8,
506
574
  },
507
- rowName: {
508
- fontSize: 15,
575
+ switchingText: {
576
+ fontSize: 12,
509
577
  fontWeight: '500',
510
578
  },
511
- rowSecondary: {
512
- fontSize: 13,
513
- marginTop: 2,
514
- },
515
- footer: {
516
- marginTop: 12,
517
- paddingTop: 8,
518
- paddingHorizontal: 12,
519
- borderTopWidth: StyleSheet.hairlineWidth,
579
+ actionRow: {
520
580
  flexDirection: 'row',
521
- flexWrap: 'wrap',
522
- justifyContent: 'space-around',
523
- },
524
- footerButton: {
525
- paddingVertical: 10,
526
- paddingHorizontal: 12,
581
+ alignItems: 'center',
582
+ paddingHorizontal: 14,
583
+ paddingVertical: 12,
584
+ gap: 10,
527
585
  },
528
- footerButtonText: {
529
- fontSize: 14,
530
- fontWeight: '600',
586
+ actionText: {
587
+ fontSize: 13,
588
+ fontWeight: '500',
531
589
  },
532
590
  });
533
591