@oxyhq/services 22.9.0 → 22.11.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 (584) hide show
  1. package/lib/commonjs/index.js +24 -5
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/components/AvatarCameraBadge.js +42 -0
  4. package/lib/commonjs/ui/components/AvatarCameraBadge.js.map +1 -0
  5. package/lib/commonjs/ui/components/{OxyAccountDialog.js → OxyAccountDialogScreen.js} +55 -133
  6. package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -0
  7. package/lib/commonjs/ui/components/OxyAuthChooser.js +657 -88
  8. package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
  9. package/lib/commonjs/ui/components/OxyConsentScreen.js +1 -1
  10. package/lib/commonjs/ui/components/ProfileButton.js +15 -1
  11. package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
  12. package/lib/commonjs/ui/components/ProfileSummaryCard.js +3 -23
  13. package/lib/commonjs/ui/components/ProfileSummaryCard.js.map +1 -1
  14. package/lib/commonjs/ui/components/RequireOxyAuth.js +1 -1
  15. package/lib/commonjs/ui/components/SurfaceHeaderAction.js +63 -0
  16. package/lib/commonjs/ui/components/SurfaceHeaderAction.js.map +1 -0
  17. package/lib/commonjs/ui/components/SurfaceScreen.js +91 -8
  18. package/lib/commonjs/ui/components/SurfaceScreen.js.map +1 -1
  19. package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js +46 -29
  20. package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
  21. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js +47 -23
  22. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js.map +1 -1
  23. package/lib/commonjs/ui/components/oxyAuthChooserStyles.js +81 -19
  24. package/lib/commonjs/ui/components/oxyAuthChooserStyles.js.map +1 -1
  25. package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js +83 -23
  26. package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
  27. package/lib/commonjs/ui/components/surfaces/ActionSheetSurface.js +83 -0
  28. package/lib/commonjs/ui/components/surfaces/ActionSheetSurface.js.map +1 -0
  29. package/lib/commonjs/ui/context/OxyContext.js +79 -29
  30. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  31. package/lib/commonjs/ui/hooks/queries/queryKeys.js +18 -1
  32. package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
  33. package/lib/commonjs/ui/hooks/queries/useFileQueries.js +129 -0
  34. package/lib/commonjs/ui/hooks/queries/useFileQueries.js.map +1 -0
  35. package/lib/commonjs/ui/hooks/useAvatarPicker.js +38 -55
  36. package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +1 -1
  37. package/lib/commonjs/ui/hooks/useReduceMotion.js +57 -0
  38. package/lib/commonjs/ui/hooks/useReduceMotion.js.map +1 -0
  39. package/lib/commonjs/ui/hooks/useSurfaceHeader.js +46 -0
  40. package/lib/commonjs/ui/hooks/useSurfaceHeader.js.map +1 -0
  41. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +1 -1
  42. package/lib/commonjs/ui/navigation/accountDialogManager.js +36 -2
  43. package/lib/commonjs/ui/navigation/accountDialogManager.js.map +1 -1
  44. package/lib/commonjs/ui/navigation/bottomSheetManager.js +5 -6
  45. package/lib/commonjs/ui/navigation/bottomSheetManager.js.map +1 -1
  46. package/lib/commonjs/ui/navigation/routes.js +4 -3
  47. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  48. package/lib/commonjs/ui/navigation/surfaceBackBridge.js +68 -0
  49. package/lib/commonjs/ui/navigation/surfaceBackBridge.js.map +1 -0
  50. package/lib/commonjs/ui/navigation/surfaceNavStack.js +62 -15
  51. package/lib/commonjs/ui/navigation/surfaceNavStack.js.map +1 -1
  52. package/lib/commonjs/ui/navigation/surfaceRegistry.js +84 -19
  53. package/lib/commonjs/ui/navigation/surfaceRegistry.js.map +1 -1
  54. package/lib/commonjs/ui/navigation/surfaces.js +139 -25
  55. package/lib/commonjs/ui/navigation/surfaces.js.map +1 -1
  56. package/lib/commonjs/ui/screens/AccountMembersScreen.js +214 -283
  57. package/lib/commonjs/ui/screens/AccountMembersScreen.js.map +1 -1
  58. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +88 -118
  59. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  60. package/lib/commonjs/ui/screens/AccountVerificationScreen.js +22 -36
  61. package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
  62. package/lib/commonjs/ui/screens/AppInfoScreen.js +219 -226
  63. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  64. package/lib/commonjs/ui/screens/AvatarCropScreen.js +287 -289
  65. package/lib/commonjs/ui/screens/AvatarCropScreen.js.map +1 -1
  66. package/lib/commonjs/ui/screens/ChangeAvatarScreen.js +301 -0
  67. package/lib/commonjs/ui/screens/ChangeAvatarScreen.js.map +1 -0
  68. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js +24 -39
  69. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js.map +1 -1
  70. package/lib/commonjs/ui/screens/CreateAccountScreen.js +136 -158
  71. package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
  72. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +29 -36
  73. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  74. package/lib/commonjs/ui/screens/EditProfileScreen.js +101 -109
  75. package/lib/commonjs/ui/screens/EditProfileScreen.js.map +1 -1
  76. package/lib/commonjs/ui/screens/FAQScreen.js +10 -15
  77. package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -1
  78. package/lib/commonjs/ui/screens/FeedbackScreen.js +8 -16
  79. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  80. package/lib/commonjs/ui/screens/FileManagementScreen.js +403 -627
  81. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  82. package/lib/commonjs/ui/screens/HelpSupportScreen.js +62 -69
  83. package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
  84. package/lib/commonjs/ui/screens/HistoryViewScreen.js +63 -79
  85. package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
  86. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +69 -98
  87. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  88. package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js +8 -14
  89. package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
  90. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +77 -94
  91. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
  92. package/lib/commonjs/ui/screens/ManageAccountScreen.js +99 -134
  93. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  94. package/lib/commonjs/ui/screens/NotificationsScreen.js +69 -76
  95. package/lib/commonjs/ui/screens/NotificationsScreen.js.map +1 -1
  96. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +3 -8
  97. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  98. package/lib/commonjs/ui/screens/PreferencesScreen.js +67 -74
  99. package/lib/commonjs/ui/screens/PreferencesScreen.js.map +1 -1
  100. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +55 -91
  101. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  102. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +291 -304
  103. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  104. package/lib/commonjs/ui/screens/ProfileScreen.js +100 -114
  105. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  106. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +38 -45
  107. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
  108. package/lib/commonjs/ui/screens/SearchSettingsScreen.js +44 -57
  109. package/lib/commonjs/ui/screens/SearchSettingsScreen.js.map +1 -1
  110. package/lib/commonjs/ui/screens/UserLinksScreen.js +24 -31
  111. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -1
  112. package/lib/commonjs/ui/screens/UserListScreen.js +14 -24
  113. package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
  114. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +16 -48
  115. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  116. package/lib/commonjs/ui/screens/fileManagement/FileLibraryError.js +63 -0
  117. package/lib/commonjs/ui/screens/fileManagement/FileLibraryError.js.map +1 -0
  118. package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +54 -41
  119. package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
  120. package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js +44 -81
  121. package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
  122. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js +66 -75
  123. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js.map +1 -1
  124. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +111 -139
  125. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  126. package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js +13 -20
  127. package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js.map +1 -1
  128. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +14 -27
  129. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  130. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +68 -85
  131. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  132. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +28 -36
  133. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  134. package/lib/commonjs/ui/stores/resetSessionScopedStores.js +8 -3
  135. package/lib/commonjs/ui/stores/resetSessionScopedStores.js.map +1 -1
  136. package/lib/commonjs/ui/utils/avatarUtils.js +11 -2
  137. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  138. package/lib/commonjs/ui/utils/fileManagement.js +0 -79
  139. package/lib/commonjs/ui/utils/fileManagement.js.map +1 -1
  140. package/lib/module/index.js +12 -5
  141. package/lib/module/index.js.map +1 -1
  142. package/lib/module/ui/components/AvatarCameraBadge.js +40 -0
  143. package/lib/module/ui/components/AvatarCameraBadge.js.map +1 -0
  144. package/lib/module/ui/components/{OxyAccountDialog.js → OxyAccountDialogScreen.js} +57 -135
  145. package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -0
  146. package/lib/module/ui/components/OxyAuthChooser.js +659 -91
  147. package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
  148. package/lib/module/ui/components/OxyConsentScreen.js +1 -1
  149. package/lib/module/ui/components/ProfileButton.js +16 -2
  150. package/lib/module/ui/components/ProfileButton.js.map +1 -1
  151. package/lib/module/ui/components/ProfileSummaryCard.js +2 -23
  152. package/lib/module/ui/components/ProfileSummaryCard.js.map +1 -1
  153. package/lib/module/ui/components/RequireOxyAuth.js +1 -1
  154. package/lib/module/ui/components/SurfaceHeaderAction.js +58 -0
  155. package/lib/module/ui/components/SurfaceHeaderAction.js.map +1 -0
  156. package/lib/module/ui/components/SurfaceScreen.js +93 -10
  157. package/lib/module/ui/components/SurfaceScreen.js.map +1 -1
  158. package/lib/module/ui/components/fileManagement/FileDetailsModal.js +46 -29
  159. package/lib/module/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
  160. package/lib/module/ui/components/modals/DeleteAccountModal.js +46 -23
  161. package/lib/module/ui/components/modals/DeleteAccountModal.js.map +1 -1
  162. package/lib/module/ui/components/oxyAuthChooserStyles.js +81 -19
  163. package/lib/module/ui/components/oxyAuthChooserStyles.js.map +1 -1
  164. package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js +83 -25
  165. package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
  166. package/lib/module/ui/components/surfaces/ActionSheetSurface.js +78 -0
  167. package/lib/module/ui/components/surfaces/ActionSheetSurface.js.map +1 -0
  168. package/lib/module/ui/context/OxyContext.js +80 -30
  169. package/lib/module/ui/context/OxyContext.js.map +1 -1
  170. package/lib/module/ui/hooks/queries/queryKeys.js +16 -0
  171. package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
  172. package/lib/module/ui/hooks/queries/useFileQueries.js +120 -0
  173. package/lib/module/ui/hooks/queries/useFileQueries.js.map +1 -0
  174. package/lib/module/ui/hooks/useAvatarPicker.js +38 -55
  175. package/lib/module/ui/hooks/useAvatarPicker.js.map +1 -1
  176. package/lib/module/ui/hooks/useReduceMotion.js +53 -0
  177. package/lib/module/ui/hooks/useReduceMotion.js.map +1 -0
  178. package/lib/module/ui/hooks/useSurfaceHeader.js +42 -0
  179. package/lib/module/ui/hooks/useSurfaceHeader.js.map +1 -0
  180. package/lib/module/ui/hooks/useSwitchableAccounts.js +1 -1
  181. package/lib/module/ui/navigation/accountDialogManager.js +34 -2
  182. package/lib/module/ui/navigation/accountDialogManager.js.map +1 -1
  183. package/lib/module/ui/navigation/bottomSheetManager.js +6 -7
  184. package/lib/module/ui/navigation/bottomSheetManager.js.map +1 -1
  185. package/lib/module/ui/navigation/routes.js +4 -3
  186. package/lib/module/ui/navigation/routes.js.map +1 -1
  187. package/lib/module/ui/navigation/surfaceBackBridge.js +63 -0
  188. package/lib/module/ui/navigation/surfaceBackBridge.js.map +1 -0
  189. package/lib/module/ui/navigation/surfaceNavStack.js +62 -15
  190. package/lib/module/ui/navigation/surfaceNavStack.js.map +1 -1
  191. package/lib/module/ui/navigation/surfaceRegistry.js +84 -19
  192. package/lib/module/ui/navigation/surfaceRegistry.js.map +1 -1
  193. package/lib/module/ui/navigation/surfaces.js +138 -26
  194. package/lib/module/ui/navigation/surfaces.js.map +1 -1
  195. package/lib/module/ui/screens/AccountMembersScreen.js +218 -286
  196. package/lib/module/ui/screens/AccountMembersScreen.js.map +1 -1
  197. package/lib/module/ui/screens/AccountSettingsScreen.js +92 -121
  198. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  199. package/lib/module/ui/screens/AccountVerificationScreen.js +25 -38
  200. package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
  201. package/lib/module/ui/screens/AppInfoScreen.js +220 -227
  202. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  203. package/lib/module/ui/screens/AvatarCropScreen.js +289 -291
  204. package/lib/module/ui/screens/AvatarCropScreen.js.map +1 -1
  205. package/lib/module/ui/screens/ChangeAvatarScreen.js +298 -0
  206. package/lib/module/ui/screens/ChangeAvatarScreen.js.map +1 -0
  207. package/lib/module/ui/screens/ConnectedAppsScreen.js +26 -40
  208. package/lib/module/ui/screens/ConnectedAppsScreen.js.map +1 -1
  209. package/lib/module/ui/screens/CreateAccountScreen.js +139 -160
  210. package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
  211. package/lib/module/ui/screens/EditProfileFieldScreen.js +32 -38
  212. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  213. package/lib/module/ui/screens/EditProfileScreen.js +102 -110
  214. package/lib/module/ui/screens/EditProfileScreen.js.map +1 -1
  215. package/lib/module/ui/screens/FAQScreen.js +11 -15
  216. package/lib/module/ui/screens/FAQScreen.js.map +1 -1
  217. package/lib/module/ui/screens/FeedbackScreen.js +10 -17
  218. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  219. package/lib/module/ui/screens/FileManagementScreen.js +408 -631
  220. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  221. package/lib/module/ui/screens/HelpSupportScreen.js +64 -70
  222. package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
  223. package/lib/module/ui/screens/HistoryViewScreen.js +65 -81
  224. package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
  225. package/lib/module/ui/screens/LanguageSelectorScreen.js +71 -99
  226. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  227. package/lib/module/ui/screens/LearnMoreUsernamesScreen.js +10 -15
  228. package/lib/module/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
  229. package/lib/module/ui/screens/LegalDocumentsScreen.js +78 -94
  230. package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
  231. package/lib/module/ui/screens/ManageAccountScreen.js +102 -137
  232. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  233. package/lib/module/ui/screens/NotificationsScreen.js +71 -77
  234. package/lib/module/ui/screens/NotificationsScreen.js.map +1 -1
  235. package/lib/module/ui/screens/PaymentGatewayScreen.js +4 -9
  236. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  237. package/lib/module/ui/screens/PreferencesScreen.js +69 -75
  238. package/lib/module/ui/screens/PreferencesScreen.js.map +1 -1
  239. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +58 -93
  240. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  241. package/lib/module/ui/screens/PrivacySettingsScreen.js +293 -305
  242. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  243. package/lib/module/ui/screens/ProfileScreen.js +102 -116
  244. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  245. package/lib/module/ui/screens/SavesCollectionsScreen.js +40 -46
  246. package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
  247. package/lib/module/ui/screens/SearchSettingsScreen.js +46 -58
  248. package/lib/module/ui/screens/SearchSettingsScreen.js.map +1 -1
  249. package/lib/module/ui/screens/UserLinksScreen.js +26 -32
  250. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -1
  251. package/lib/module/ui/screens/UserListScreen.js +14 -24
  252. package/lib/module/ui/screens/UserListScreen.js.map +1 -1
  253. package/lib/module/ui/screens/WelcomeNewUserScreen.js +17 -49
  254. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  255. package/lib/module/ui/screens/fileManagement/FileLibraryError.js +59 -0
  256. package/lib/module/ui/screens/fileManagement/FileLibraryError.js.map +1 -0
  257. package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +54 -42
  258. package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
  259. package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js +45 -81
  260. package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
  261. package/lib/module/ui/screens/trust/TrustAboutScreen.js +67 -75
  262. package/lib/module/ui/screens/trust/TrustAboutScreen.js.map +1 -1
  263. package/lib/module/ui/screens/trust/TrustCenterScreen.js +112 -139
  264. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  265. package/lib/module/ui/screens/trust/TrustFAQScreen.js +15 -21
  266. package/lib/module/ui/screens/trust/TrustFAQScreen.js.map +1 -1
  267. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +14 -26
  268. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  269. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +69 -85
  270. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  271. package/lib/module/ui/screens/trust/TrustRulesScreen.js +30 -37
  272. package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  273. package/lib/module/ui/stores/resetSessionScopedStores.js +8 -3
  274. package/lib/module/ui/stores/resetSessionScopedStores.js.map +1 -1
  275. package/lib/module/ui/utils/avatarUtils.js +11 -2
  276. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  277. package/lib/module/ui/utils/fileManagement.js +0 -78
  278. package/lib/module/ui/utils/fileManagement.js.map +1 -1
  279. package/lib/typescript/commonjs/index.d.ts +2 -0
  280. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  281. package/lib/typescript/commonjs/ui/components/AvatarCameraBadge.d.ts +4 -0
  282. package/lib/typescript/commonjs/ui/components/AvatarCameraBadge.d.ts.map +1 -0
  283. package/lib/typescript/{module/ui/components/OxyAccountDialog.d.ts → commonjs/ui/components/OxyAccountDialogScreen.d.ts} +5 -4
  284. package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -0
  285. package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts +3 -3
  286. package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
  287. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts +2 -2
  288. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -1
  289. package/lib/typescript/commonjs/ui/components/ProfileSummaryCard.d.ts.map +1 -1
  290. package/lib/typescript/commonjs/ui/components/RequireOxyAuth.d.ts +1 -1
  291. package/lib/typescript/commonjs/ui/components/SurfaceHeaderAction.d.ts +16 -0
  292. package/lib/typescript/commonjs/ui/components/SurfaceHeaderAction.d.ts.map +1 -0
  293. package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts +3 -4
  294. package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts.map +1 -1
  295. package/lib/typescript/commonjs/ui/components/fileManagement/FileDetailsModal.d.ts +14 -4
  296. package/lib/typescript/commonjs/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
  297. package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts +17 -2
  298. package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
  299. package/lib/typescript/commonjs/ui/components/oxyAuthChooserStyles.d.ts +75 -13
  300. package/lib/typescript/commonjs/ui/components/oxyAuthChooserStyles.d.ts.map +1 -1
  301. package/lib/typescript/commonjs/ui/components/photogrid/JustifiedPhotoGrid.d.ts +10 -8
  302. package/lib/typescript/commonjs/ui/components/photogrid/JustifiedPhotoGrid.d.ts.map +1 -1
  303. package/lib/typescript/commonjs/ui/components/surfaces/ActionSheetSurface.d.ts +38 -0
  304. package/lib/typescript/commonjs/ui/components/surfaces/ActionSheetSurface.d.ts.map +1 -0
  305. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  306. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +9 -0
  307. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  308. package/lib/typescript/commonjs/ui/hooks/queries/useFileQueries.d.ts +50 -0
  309. package/lib/typescript/commonjs/ui/hooks/queries/useFileQueries.d.ts.map +1 -0
  310. package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts +17 -16
  311. package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts.map +1 -1
  312. package/lib/typescript/commonjs/ui/hooks/useReduceMotion.d.ts +14 -0
  313. package/lib/typescript/commonjs/ui/hooks/useReduceMotion.d.ts.map +1 -0
  314. package/lib/typescript/commonjs/ui/hooks/useSurfaceHeader.d.ts +31 -0
  315. package/lib/typescript/commonjs/ui/hooks/useSurfaceHeader.d.ts.map +1 -0
  316. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +1 -1
  317. package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts +27 -2
  318. package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts.map +1 -1
  319. package/lib/typescript/commonjs/ui/navigation/bottomSheetManager.d.ts +4 -5
  320. package/lib/typescript/commonjs/ui/navigation/bottomSheetManager.d.ts.map +1 -1
  321. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
  322. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  323. package/lib/typescript/commonjs/ui/navigation/surfaceBackBridge.d.ts +16 -0
  324. package/lib/typescript/commonjs/ui/navigation/surfaceBackBridge.d.ts.map +1 -0
  325. package/lib/typescript/commonjs/ui/navigation/surfaceNavStack.d.ts +21 -0
  326. package/lib/typescript/commonjs/ui/navigation/surfaceNavStack.d.ts.map +1 -1
  327. package/lib/typescript/commonjs/ui/navigation/surfaceRegistry.d.ts +101 -23
  328. package/lib/typescript/commonjs/ui/navigation/surfaceRegistry.d.ts.map +1 -1
  329. package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts +42 -11
  330. package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts.map +1 -1
  331. package/lib/typescript/commonjs/ui/screens/AccountMembersScreen.d.ts.map +1 -1
  332. package/lib/typescript/commonjs/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  333. package/lib/typescript/commonjs/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
  334. package/lib/typescript/commonjs/ui/screens/AppInfoScreen.d.ts.map +1 -1
  335. package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts +18 -9
  336. package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts.map +1 -1
  337. package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts +34 -0
  338. package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts.map +1 -0
  339. package/lib/typescript/commonjs/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  340. package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  341. package/lib/typescript/commonjs/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  342. package/lib/typescript/commonjs/ui/screens/EditProfileScreen.d.ts.map +1 -1
  343. package/lib/typescript/commonjs/ui/screens/FAQScreen.d.ts.map +1 -1
  344. package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
  345. package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
  346. package/lib/typescript/commonjs/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  347. package/lib/typescript/commonjs/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  348. package/lib/typescript/commonjs/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  349. package/lib/typescript/commonjs/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
  350. package/lib/typescript/commonjs/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  351. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts +1 -1
  352. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  353. package/lib/typescript/commonjs/ui/screens/NotificationsScreen.d.ts.map +1 -1
  354. package/lib/typescript/commonjs/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  355. package/lib/typescript/commonjs/ui/screens/PreferencesScreen.d.ts.map +1 -1
  356. package/lib/typescript/commonjs/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  357. package/lib/typescript/commonjs/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  358. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  359. package/lib/typescript/commonjs/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  360. package/lib/typescript/commonjs/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  361. package/lib/typescript/commonjs/ui/screens/UserLinksScreen.d.ts.map +1 -1
  362. package/lib/typescript/commonjs/ui/screens/UserListScreen.d.ts.map +1 -1
  363. package/lib/typescript/commonjs/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  364. package/lib/typescript/commonjs/ui/screens/fileManagement/FileLibraryError.d.ts +23 -0
  365. package/lib/typescript/commonjs/ui/screens/fileManagement/FileLibraryError.d.ts.map +1 -0
  366. package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts +4 -0
  367. package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
  368. package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +10 -2
  369. package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
  370. package/lib/typescript/commonjs/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
  371. package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
  372. package/lib/typescript/commonjs/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
  373. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  374. package/lib/typescript/commonjs/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
  375. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  376. package/lib/typescript/commonjs/ui/stores/resetSessionScopedStores.d.ts +8 -1
  377. package/lib/typescript/commonjs/ui/stores/resetSessionScopedStores.d.ts.map +1 -1
  378. package/lib/typescript/commonjs/ui/types/navigation.d.ts +10 -0
  379. package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
  380. package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts.map +1 -1
  381. package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts +0 -48
  382. package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts.map +1 -1
  383. package/lib/typescript/module/index.d.ts +2 -0
  384. package/lib/typescript/module/index.d.ts.map +1 -1
  385. package/lib/typescript/module/ui/components/AvatarCameraBadge.d.ts +4 -0
  386. package/lib/typescript/module/ui/components/AvatarCameraBadge.d.ts.map +1 -0
  387. package/lib/typescript/{commonjs/ui/components/OxyAccountDialog.d.ts → module/ui/components/OxyAccountDialogScreen.d.ts} +5 -4
  388. package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -0
  389. package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts +3 -3
  390. package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
  391. package/lib/typescript/module/ui/components/ProfileButton.d.ts +2 -2
  392. package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -1
  393. package/lib/typescript/module/ui/components/ProfileSummaryCard.d.ts.map +1 -1
  394. package/lib/typescript/module/ui/components/RequireOxyAuth.d.ts +1 -1
  395. package/lib/typescript/module/ui/components/SurfaceHeaderAction.d.ts +16 -0
  396. package/lib/typescript/module/ui/components/SurfaceHeaderAction.d.ts.map +1 -0
  397. package/lib/typescript/module/ui/components/SurfaceScreen.d.ts +3 -4
  398. package/lib/typescript/module/ui/components/SurfaceScreen.d.ts.map +1 -1
  399. package/lib/typescript/module/ui/components/fileManagement/FileDetailsModal.d.ts +14 -4
  400. package/lib/typescript/module/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
  401. package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts +17 -2
  402. package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
  403. package/lib/typescript/module/ui/components/oxyAuthChooserStyles.d.ts +75 -13
  404. package/lib/typescript/module/ui/components/oxyAuthChooserStyles.d.ts.map +1 -1
  405. package/lib/typescript/module/ui/components/photogrid/JustifiedPhotoGrid.d.ts +10 -8
  406. package/lib/typescript/module/ui/components/photogrid/JustifiedPhotoGrid.d.ts.map +1 -1
  407. package/lib/typescript/module/ui/components/surfaces/ActionSheetSurface.d.ts +38 -0
  408. package/lib/typescript/module/ui/components/surfaces/ActionSheetSurface.d.ts.map +1 -0
  409. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  410. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +9 -0
  411. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  412. package/lib/typescript/module/ui/hooks/queries/useFileQueries.d.ts +50 -0
  413. package/lib/typescript/module/ui/hooks/queries/useFileQueries.d.ts.map +1 -0
  414. package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts +17 -16
  415. package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts.map +1 -1
  416. package/lib/typescript/module/ui/hooks/useReduceMotion.d.ts +14 -0
  417. package/lib/typescript/module/ui/hooks/useReduceMotion.d.ts.map +1 -0
  418. package/lib/typescript/module/ui/hooks/useSurfaceHeader.d.ts +31 -0
  419. package/lib/typescript/module/ui/hooks/useSurfaceHeader.d.ts.map +1 -0
  420. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +1 -1
  421. package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts +27 -2
  422. package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts.map +1 -1
  423. package/lib/typescript/module/ui/navigation/bottomSheetManager.d.ts +4 -5
  424. package/lib/typescript/module/ui/navigation/bottomSheetManager.d.ts.map +1 -1
  425. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  426. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  427. package/lib/typescript/module/ui/navigation/surfaceBackBridge.d.ts +16 -0
  428. package/lib/typescript/module/ui/navigation/surfaceBackBridge.d.ts.map +1 -0
  429. package/lib/typescript/module/ui/navigation/surfaceNavStack.d.ts +21 -0
  430. package/lib/typescript/module/ui/navigation/surfaceNavStack.d.ts.map +1 -1
  431. package/lib/typescript/module/ui/navigation/surfaceRegistry.d.ts +101 -23
  432. package/lib/typescript/module/ui/navigation/surfaceRegistry.d.ts.map +1 -1
  433. package/lib/typescript/module/ui/navigation/surfaces.d.ts +42 -11
  434. package/lib/typescript/module/ui/navigation/surfaces.d.ts.map +1 -1
  435. package/lib/typescript/module/ui/screens/AccountMembersScreen.d.ts.map +1 -1
  436. package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  437. package/lib/typescript/module/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
  438. package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts.map +1 -1
  439. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts +18 -9
  440. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts.map +1 -1
  441. package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts +34 -0
  442. package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts.map +1 -0
  443. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  444. package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  445. package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  446. package/lib/typescript/module/ui/screens/EditProfileScreen.d.ts.map +1 -1
  447. package/lib/typescript/module/ui/screens/FAQScreen.d.ts.map +1 -1
  448. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  449. package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
  450. package/lib/typescript/module/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  451. package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  452. package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  453. package/lib/typescript/module/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
  454. package/lib/typescript/module/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  455. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts +1 -1
  456. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  457. package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts.map +1 -1
  458. package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  459. package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts.map +1 -1
  460. package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  461. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  462. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  463. package/lib/typescript/module/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  464. package/lib/typescript/module/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  465. package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts.map +1 -1
  466. package/lib/typescript/module/ui/screens/UserListScreen.d.ts.map +1 -1
  467. package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  468. package/lib/typescript/module/ui/screens/fileManagement/FileLibraryError.d.ts +23 -0
  469. package/lib/typescript/module/ui/screens/fileManagement/FileLibraryError.d.ts.map +1 -0
  470. package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts +4 -0
  471. package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
  472. package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +10 -2
  473. package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
  474. package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
  475. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
  476. package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
  477. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  478. package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
  479. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  480. package/lib/typescript/module/ui/stores/resetSessionScopedStores.d.ts +8 -1
  481. package/lib/typescript/module/ui/stores/resetSessionScopedStores.d.ts.map +1 -1
  482. package/lib/typescript/module/ui/types/navigation.d.ts +10 -0
  483. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  484. package/lib/typescript/module/ui/utils/avatarUtils.d.ts.map +1 -1
  485. package/lib/typescript/module/ui/utils/fileManagement.d.ts +0 -48
  486. package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
  487. package/package.json +9 -5
  488. package/src/index.ts +12 -5
  489. package/src/ui/components/AvatarCameraBadge.tsx +35 -0
  490. package/src/ui/components/{OxyAccountDialog.tsx → OxyAccountDialogScreen.tsx} +50 -116
  491. package/src/ui/components/OxyAuthChooser.tsx +743 -86
  492. package/src/ui/components/OxyConsentScreen.tsx +1 -1
  493. package/src/ui/components/ProfileButton.tsx +18 -3
  494. package/src/ui/components/ProfileSummaryCard.tsx +2 -25
  495. package/src/ui/components/RequireOxyAuth.tsx +1 -1
  496. package/src/ui/components/SurfaceHeaderAction.tsx +60 -0
  497. package/src/ui/components/SurfaceScreen.tsx +108 -14
  498. package/src/ui/components/fileManagement/FileDetailsModal.tsx +50 -36
  499. package/src/ui/components/modals/DeleteAccountModal.tsx +47 -26
  500. package/src/ui/components/oxyAuthChooserStyles.ts +78 -16
  501. package/src/ui/components/photogrid/JustifiedPhotoGrid.tsx +158 -84
  502. package/src/ui/components/photogrid/__tests__/chunkPhotos.test.ts +51 -0
  503. package/src/ui/components/surfaces/ActionSheetSurface.tsx +98 -0
  504. package/src/ui/context/OxyContext.tsx +79 -25
  505. package/src/ui/hooks/queries/queryKeys.ts +15 -0
  506. package/src/ui/hooks/queries/useFileQueries.ts +162 -0
  507. package/src/ui/hooks/useAvatarPicker.ts +46 -74
  508. package/src/ui/hooks/useReduceMotion.ts +58 -0
  509. package/src/ui/hooks/useSurfaceHeader.ts +57 -0
  510. package/src/ui/hooks/useSwitchableAccounts.ts +1 -1
  511. package/src/ui/navigation/__tests__/getSurfaceConfig.test.ts +55 -7
  512. package/src/ui/navigation/__tests__/surfaceNavStack.test.ts +149 -0
  513. package/src/ui/navigation/accountDialogManager.ts +42 -2
  514. package/src/ui/navigation/bottomSheetManager.ts +6 -7
  515. package/src/ui/navigation/routes.ts +6 -4
  516. package/src/ui/navigation/surfaceBackBridge.ts +69 -0
  517. package/src/ui/navigation/surfaceNavStack.ts +72 -9
  518. package/src/ui/navigation/surfaceRegistry.ts +164 -24
  519. package/src/ui/navigation/surfaces.ts +137 -30
  520. package/src/ui/screens/AccountMembersScreen.tsx +39 -100
  521. package/src/ui/screens/AccountSettingsScreen.tsx +32 -54
  522. package/src/ui/screens/AccountVerificationScreen.tsx +23 -51
  523. package/src/ui/screens/AppInfoScreen.tsx +6 -13
  524. package/src/ui/screens/AvatarCropScreen.tsx +340 -311
  525. package/src/ui/screens/ChangeAvatarScreen.tsx +359 -0
  526. package/src/ui/screens/ConnectedAppsScreen.tsx +39 -60
  527. package/src/ui/screens/CreateAccountScreen.tsx +13 -39
  528. package/src/ui/screens/EditProfileFieldScreen.tsx +30 -48
  529. package/src/ui/screens/EditProfileScreen.tsx +7 -16
  530. package/src/ui/screens/FAQScreen.tsx +9 -13
  531. package/src/ui/screens/FeedbackScreen.tsx +8 -22
  532. package/src/ui/screens/FileManagementScreen.tsx +370 -610
  533. package/src/ui/screens/HelpSupportScreen.tsx +7 -13
  534. package/src/ui/screens/HistoryViewScreen.tsx +26 -31
  535. package/src/ui/screens/LanguageSelectorScreen.tsx +12 -46
  536. package/src/ui/screens/LearnMoreUsernamesScreen.tsx +8 -16
  537. package/src/ui/screens/LegalDocumentsScreen.tsx +7 -22
  538. package/src/ui/screens/ManageAccountScreen.tsx +96 -165
  539. package/src/ui/screens/NotificationsScreen.tsx +7 -13
  540. package/src/ui/screens/PaymentGatewayScreen.tsx +3 -10
  541. package/src/ui/screens/PreferencesScreen.tsx +7 -13
  542. package/src/ui/screens/PremiumSubscriptionScreen.tsx +52 -90
  543. package/src/ui/screens/PrivacySettingsScreen.tsx +9 -21
  544. package/src/ui/screens/ProfileScreen.tsx +9 -11
  545. package/src/ui/screens/SavesCollectionsScreen.tsx +7 -13
  546. package/src/ui/screens/SearchSettingsScreen.tsx +9 -21
  547. package/src/ui/screens/UserLinksScreen.tsx +7 -14
  548. package/src/ui/screens/UserListScreen.tsx +2 -5
  549. package/src/ui/screens/WelcomeNewUserScreen.tsx +18 -48
  550. package/src/ui/screens/fileManagement/FileLibraryError.tsx +56 -0
  551. package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +56 -46
  552. package/src/ui/screens/fileManagement/hooks/useFileUploadState.ts +55 -71
  553. package/src/ui/screens/trust/TrustAboutScreen.tsx +10 -17
  554. package/src/ui/screens/trust/TrustCenterScreen.tsx +9 -28
  555. package/src/ui/screens/trust/TrustFAQScreen.tsx +15 -18
  556. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +3 -5
  557. package/src/ui/screens/trust/TrustRewardsScreen.tsx +11 -26
  558. package/src/ui/screens/trust/TrustRulesScreen.tsx +10 -13
  559. package/src/ui/stores/resetSessionScopedStores.ts +8 -3
  560. package/src/ui/types/navigation.ts +10 -0
  561. package/src/ui/utils/avatarUtils.ts +11 -2
  562. package/src/ui/utils/fileManagement.ts +1 -101
  563. package/lib/commonjs/ui/components/Header.js +0 -305
  564. package/lib/commonjs/ui/components/Header.js.map +0 -1
  565. package/lib/commonjs/ui/components/OxyAccountDialog.js.map +0 -1
  566. package/lib/commonjs/ui/stores/fileStore.js +0 -153
  567. package/lib/commonjs/ui/stores/fileStore.js.map +0 -1
  568. package/lib/module/ui/components/Header.js +0 -299
  569. package/lib/module/ui/components/Header.js.map +0 -1
  570. package/lib/module/ui/components/OxyAccountDialog.js.map +0 -1
  571. package/lib/module/ui/stores/fileStore.js +0 -145
  572. package/lib/module/ui/stores/fileStore.js.map +0 -1
  573. package/lib/typescript/commonjs/ui/components/Header.d.ts +0 -33
  574. package/lib/typescript/commonjs/ui/components/Header.d.ts.map +0 -1
  575. package/lib/typescript/commonjs/ui/components/OxyAccountDialog.d.ts.map +0 -1
  576. package/lib/typescript/commonjs/ui/stores/fileStore.d.ts +0 -31
  577. package/lib/typescript/commonjs/ui/stores/fileStore.d.ts.map +0 -1
  578. package/lib/typescript/module/ui/components/Header.d.ts +0 -33
  579. package/lib/typescript/module/ui/components/Header.d.ts.map +0 -1
  580. package/lib/typescript/module/ui/components/OxyAccountDialog.d.ts.map +0 -1
  581. package/lib/typescript/module/ui/stores/fileStore.d.ts +0 -31
  582. package/lib/typescript/module/ui/stores/fileStore.d.ts.map +0 -1
  583. package/src/ui/components/Header.tsx +0 -224
  584. package/src/ui/stores/fileStore.ts +0 -118
@@ -7,11 +7,17 @@
7
7
  * but before the avatar is uploaded. Inspired by iOS Photos, Google Photos and
8
8
  * Instagram crop tools.
9
9
  *
10
+ * Reached ONLY by navigating within a `ChangeAvatar` surface, so the panel
11
+ * morphs from the source list into the editor. The surface owns the chrome: this
12
+ * screen declares its title and its "Use photo" action through `useSurfaceHeader`
13
+ * and renders no bar of its own — the nav bar's back arrow is Cancel, and it
14
+ * returns to the source list.
15
+ *
10
16
  * Architecture:
11
- * - Full-bleed black canvas, independent of theme, so photos always read well.
12
- * - Translucent top bar with Cancel / Title / Done (primary CTA).
13
- * - Circular viewport with white ring, outer 50% black mask, and a 3x3
14
- * rule-of-thirds grid that appears during gestures and fades after 800ms.
17
+ * - A dark crop stage, independent of theme, so photos always read well, inset
18
+ * inside the surface's own themed panel.
19
+ * - Circular viewport with white ring and a 3x3 rule-of-thirds grid that
20
+ * appears during gestures and fades after 800ms.
15
21
  * - Floating zoom chip during pinch.
16
22
  * - Pan + pinch via Gesture Handler, transform driven by Reanimated.
17
23
  * - Reduced-motion aware entrance animation.
@@ -22,14 +28,18 @@
22
28
  * error; missing haptics simply degrades silently.
23
29
  */
24
30
 
25
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
26
- import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Image, Platform, AccessibilityInfo, Pressable } from 'react-native';
31
+ import { useCallback, useMemo, useRef, useState } from 'react';
32
+ import { View, Text, StyleSheet, ActivityIndicator, Image, Platform, AccessibilityInfo, Pressable } from 'react-native';
27
33
  import { Gesture, GestureDetector } from 'react-native-gesture-handler';
28
34
  import Animated, { Easing, runOnJS, useAnimatedStyle, useSharedValue, withDelay, withSpring, withTiming } from 'react-native-reanimated';
29
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
35
+ import { useQuery, keepPreviousData } from '@tanstack/react-query';
30
36
  import { useTheme } from '@oxyhq/bloom/theme';
37
+ import { Button } from '@oxyhq/bloom/button';
31
38
  import { logger } from '@oxyhq/core';
39
+ import { useOxy } from "../context/OxyContext.js";
32
40
  import { useI18n } from "../hooks/useI18n.js";
41
+ import { useReduceMotion } from "../hooks/useReduceMotion.js";
42
+ import { useSurfaceHeader } from "../hooks/useSurfaceHeader.js";
33
43
  import { toast } from '@oxyhq/bloom';
34
44
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
35
45
  /** Component name used in `logger` context for filtered diagnostics. */
@@ -42,14 +52,20 @@ const VIEWPORT_SIZE = 320;
42
52
  const OUTPUT_SIZE = 512;
43
53
  const MIN_SCALE = 1;
44
54
  const MAX_SCALE = 4;
55
+ /** Zoom increment per +/- button press (web, where there is no pinch). */
56
+ const ZOOM_STEP = 0.5;
57
+ /** Tween duration for a button-driven zoom (collapses to 0 under reduce-motion). */
58
+ const ZOOM_BUTTON_DURATION_MS = 180;
45
59
  /** Duration (ms) that the rule-of-thirds grid lingers after a gesture ends. */
46
60
  const GRID_FADE_DELAY_MS = 800;
47
61
  const GRID_FADE_DURATION_MS = 220;
48
62
  /** Duration the zoom chip stays visible after a pinch ends. */
49
63
  const ZOOM_CHIP_FADE_DELAY_MS = 600;
50
64
  const ZOOM_CHIP_FADE_DURATION_MS = 200;
51
- /** Backdrop color is fixed independent of theme so the photo always reads well. */
65
+ /** Stage color is fixed independent of theme so the photo always reads well. */
52
66
  const CANVAS_BG = '#000000';
67
+ /** Corner radius of the dark stage block inside the surface's themed panel. */
68
+ const STAGE_RADIUS = 24;
53
69
  const RING_COLOR = '#ffffff';
54
70
  const RING_WIDTH = 2;
55
71
  const REMOTE_HTTP_URI_PATTERN = /^https?:\/\//i;
@@ -71,6 +87,26 @@ function clampTranslation(tx, ty, s, baseW, baseH) {
71
87
  ty: Math.min(Math.max(ty, -maxY), maxY)
72
88
  };
73
89
  }
90
+ /**
91
+ * Measure an image's intrinsic size via `Image.getSize`, wrapped as a Promise so
92
+ * it can be a React Query `queryFn` (no component state / effects). Rejects on a
93
+ * platform failure or degenerate dimensions so the query surfaces `isError`.
94
+ * Mirrors the `measurePhotoDimensions` helper the photo grid uses.
95
+ */
96
+ function measureImageSize(uri) {
97
+ return new Promise((resolve, reject) => {
98
+ Image.getSize(uri, (width, height) => {
99
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
100
+ reject(new Error('Image reported invalid dimensions'));
101
+ return;
102
+ }
103
+ resolve({
104
+ width,
105
+ height
106
+ });
107
+ }, () => reject(new Error('Image measurement failed')));
108
+ });
109
+ }
74
110
 
75
111
  /**
76
112
  * Lazy-loaded reference to the expo-image-manipulator module. The module is an
@@ -191,31 +227,86 @@ async function hapticSelection() {
191
227
  }
192
228
  }
193
229
  const AvatarCropScreen = ({
230
+ dismiss,
194
231
  goBack,
195
- onClose,
196
232
  imageUri,
233
+ imageFileId,
197
234
  sourceWidth,
198
- sourceHeight,
199
- onConfirm,
200
- onCancel
235
+ sourceHeight
201
236
  }) => {
202
237
  const theme = useTheme();
203
238
  const {
204
239
  t
205
240
  } = useI18n();
206
- const insets = useSafeAreaInsets();
207
-
208
- // Natural size of the source image. May be known up front (passed in) or
209
- // measured lazily via Image.getSize once the image loads.
210
- const [naturalSize, setNaturalSize] = useState(sourceWidth && sourceHeight ? {
211
- width: sourceWidth,
212
- height: sourceHeight
213
- } : null);
241
+ const {
242
+ oxyServices
243
+ } = useOxy();
244
+ // Reactive OS reduce-motion preference (useSyncExternalStore, no effect). Pins
245
+ // the entrance spring off. Declared before `entrance` so its initial rest value
246
+ // is correct under reduce-motion.
247
+ const reduceMotion = useReduceMotion();
248
+
249
+ // The "My Oxy files" source hands us a file ID instead of a ready URL. Its
250
+ // download URL is usually private, so it must be resolved through the SDK
251
+ // (which throws on failure). Resolving it HERE — not in the source list — is
252
+ // what keeps the list from lingering on screen for the round-trip: this screen
253
+ // shows its own spinner on the dark canvas while the URL resolves. A React
254
+ // Query read (not an effect) so it stays declarative and cached.
255
+ const shouldResolveFile = !imageUri && !!imageFileId;
256
+ const sourceQuery = useQuery({
257
+ queryKey: ['avatarCropSource', imageFileId],
258
+ enabled: shouldResolveFile,
259
+ staleTime: Number.POSITIVE_INFINITY,
260
+ retry: false,
261
+ queryFn: async () => {
262
+ if (!imageFileId) {
263
+ throw new Error('No file id to resolve for cropping');
264
+ }
265
+ const resolved = await oxyServices.assetGetUrl(imageFileId);
266
+ if (!resolved?.url) {
267
+ throw new Error('No download URL returned for the selected image');
268
+ }
269
+ return resolved.url;
270
+ }
271
+ });
272
+
273
+ // The URL the cropper actually loads: the passed `imageUri`, else the URL the
274
+ // file-ID query resolved. While it resolves, `effectiveUri` is undefined and
275
+ // the stage shows its own spinner (never the empty state).
276
+ const effectiveUri = imageUri ?? sourceQuery.data;
277
+ const isResolvingSource = shouldResolveFile && !sourceQuery.data && !sourceQuery.isError;
278
+ const sourceErrorMessage = sourceQuery.isError ? t('changeAvatar.errors.loadImageFailed') || 'Could not load the selected image' : null;
279
+
280
+ // Natural size of the source image. Known up front (device/camera sources pass
281
+ // the dimensions) OR measured lazily from `effectiveUri` via a React Query read
282
+ // (no effect) — the same Image.getSize→useQuery pattern the photo grid uses.
283
+ const hasPassedDimensions = !!(sourceWidth && sourceHeight);
284
+ const measureQuery = useQuery({
285
+ queryKey: ['avatarCropMeasure', effectiveUri],
286
+ enabled: !!effectiveUri && !hasPassedDimensions,
287
+ queryFn: () => {
288
+ if (!effectiveUri) {
289
+ throw new Error('No image to measure');
290
+ }
291
+ return measureImageSize(effectiveUri);
292
+ },
293
+ staleTime: Number.POSITIVE_INFINITY,
294
+ retry: false,
295
+ placeholderData: keepPreviousData
296
+ });
297
+ const naturalSize = useMemo(() => {
298
+ if (sourceWidth && sourceHeight) return {
299
+ width: sourceWidth,
300
+ height: sourceHeight
301
+ };
302
+ return measureQuery.data ?? null;
303
+ }, [sourceWidth, sourceHeight, measureQuery.data]);
304
+ /** Measurement failed (bad dimensions / getSize error) — surfaced via the empty UI. */
305
+ const measureErrorMessage = measureQuery.isError ? t('editProfile.toasts.cropMeasureFailed') || 'Could not measure the image' : null;
214
306
  const [isProcessing, setIsProcessing] = useState(false);
215
307
  const [zoomLabel, setZoomLabel] = useState('1.0');
216
308
  /** True when scale != MIN_SCALE OR translate != 0 — used to reveal the reset link. */
217
309
  const [isModified, setIsModified] = useState(false);
218
- const [reduceMotion, setReduceMotion] = useState(false);
219
310
 
220
311
  // Shared values for the active gesture transform.
221
312
  const scale = useSharedValue(MIN_SCALE);
@@ -265,99 +356,18 @@ const AvatarCropScreen = ({
265
356
  };
266
357
  }, [naturalSize]);
267
358
 
268
- // Track in-flight measurement to avoid duplicate Image.getSize calls when
269
- // the component re-renders before the previous getSize callback fires.
270
- const measuringUriRef = useRef(null);
271
- /** Failure state for measurement, surfaced to the user via the empty UI. */
272
- const [measureError, setMeasureError] = useState(null);
273
- const handleImageMeasured = useCallback(uri => {
274
- if (measuringUriRef.current === uri) return;
275
- measuringUriRef.current = uri;
276
- // `logger.debug` is dev-gated upstream (no-op in production).
277
- // We deliberately don't log the full file URI in any production
278
- // path — only in debug builds — to avoid leaking on-device file
279
- // paths into logcat / Sentry breadcrumbs.
280
- logger.debug('Measuring image', {
281
- component: LOG_COMPONENT
282
- });
283
- Image.getSize(uri, (w, h) => {
284
- logger.debug('Image measured', {
285
- component: LOG_COMPONENT
286
- }, {
287
- width: w,
288
- height: h
289
- });
290
- if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) {
291
- const message = t('editProfile.toasts.cropMeasureFailed') || 'Could not measure the image';
292
- setMeasureError(message);
293
- toast.error(message);
294
- measuringUriRef.current = null;
295
- return;
296
- }
297
- setMeasureError(null);
298
- setNaturalSize({
299
- width: w,
300
- height: h
301
- });
302
- }, () => {
303
- logger.error('Image.getSize failed', new Error('Image measurement failed'), {
304
- component: LOG_COMPONENT
305
- });
306
- const message = t('editProfile.toasts.cropMeasureFailed') || 'Could not measure the image';
307
- setMeasureError(message);
308
- toast.error(message);
309
- measuringUriRef.current = null;
310
- });
311
- }, [t]);
312
-
313
- // Kick off measurement once per imageUri. Using useEffect (not a render-body
314
- // side effect) so the call is scheduled exactly when the URI changes,
315
- // rather than being re-fired on every parent re-render.
316
- useEffect(() => {
317
- if (!imageUri) return;
318
- if (sourceWidth && sourceHeight) return;
319
- if (naturalSize) return;
320
- handleImageMeasured(imageUri);
321
- }, [handleImageMeasured, imageUri, naturalSize, sourceHeight, sourceWidth]);
322
-
323
- // Dev-only one-time mount breadcrumb. `logger.debug` is dev-gated so
324
- // this is a no-op in production releases; we additionally avoid logging
325
- // the full `imageUri` to prevent leaking on-device file paths into any
326
- // breadcrumb sink that picks up debug output.
327
- useEffect(() => {
328
- logger.debug('mount', {
329
- component: LOG_COMPONENT
330
- }, {
331
- hasImageUri: !!imageUri,
332
- hasSourceDimensions: !!(sourceWidth && sourceHeight)
333
- });
334
- }, [imageUri, sourceHeight, sourceWidth]);
335
-
336
- // Detect reduce-motion preference once on mount + subscribe to changes.
337
- useEffect(() => {
338
- let cancelled = false;
339
- AccessibilityInfo.isReduceMotionEnabled().then(enabled => {
340
- if (cancelled) return;
341
- setReduceMotion(enabled);
342
- if (enabled) {
343
- entrance.value = 1;
344
- }
345
- }).catch(() => {
346
- // Best-effort — fall back to motion enabled.
347
- });
348
- const sub = AccessibilityInfo.addEventListener('reduceMotionChanged', enabled => {
349
- setReduceMotion(enabled);
350
- if (enabled) entrance.value = 1;
351
- });
352
- return () => {
353
- cancelled = true;
354
- sub.remove();
355
- };
356
- }, [entrance]);
357
-
358
- // Play the entrance pulse exactly once when motion is allowed.
359
- useEffect(() => {
360
- if (reduceMotion) return;
359
+ // Entrance pulse, driven from the crop frame's ref callback (fires on mount)
360
+ // rather than an effect the media-cleanup `startEntrance` pattern. Reduce
361
+ // motion pins the frame at rest; otherwise it springs in from 0.95→1. The
362
+ // callback depends on `reduceMotion`, so if that preference resolves/flips the
363
+ // callback re-runs with the node and re-pins (snap to 1) — matching the old
364
+ // effect that snapped the entrance to rest when reduce-motion turned on.
365
+ const startEntrance = useCallback(node => {
366
+ if (!node) return; // unmount
367
+ if (reduceMotion) {
368
+ entrance.value = 1;
369
+ return;
370
+ }
361
371
  entrance.value = withSpring(1, {
362
372
  damping: 14,
363
373
  stiffness: 180,
@@ -476,6 +486,11 @@ const AvatarCropScreen = ({
476
486
  runOnJS(hideZoomChip)();
477
487
  }), [baseFit, commitTransform, hideGrid, hideZoomChip, logGestureStart, notifyMaxBoundHit, notifyMinBoundHit, resetPinchBounds, savedScale, scale, showGrid, showZoomChip, translateX, translateY, updateZoomLabel]);
478
488
  const composedGesture = useMemo(() => Gesture.Simultaneous(panGesture, pinchGesture), [panGesture, pinchGesture]);
489
+
490
+ // Deps list every shared value the mapper reads so it re-runs on web (RN-Web
491
+ // has no worklets plugin — a mapper omitting its driver SVs freezes at the
492
+ // first frame, which would leave the button-driven zoom stuck). Native
493
+ // auto-tracks and ignores the extra deps, so this is safe cross-platform.
479
494
  const imageAnimatedStyle = useAnimatedStyle(() => ({
480
495
  transform: [{
481
496
  translateX: translateX.value
@@ -484,12 +499,15 @@ const AvatarCropScreen = ({
484
499
  }, {
485
500
  scale: scale.value
486
501
  }]
487
- }));
502
+ }), [translateX, translateY, scale]);
503
+
504
+ // `[entrance]` in deps so the ref-callback-driven entrance spring ticks on
505
+ // RN-Web (no worklets plugin); native auto-tracks and ignores the extra dep.
488
506
  const cropFrameAnimatedStyle = useAnimatedStyle(() => ({
489
507
  transform: [{
490
508
  scale: entrance.value
491
509
  }]
492
- }));
510
+ }), [entrance]);
493
511
  const gridAnimatedStyle = useAnimatedStyle(() => ({
494
512
  opacity: gridOpacity.value
495
513
  }));
@@ -512,6 +530,43 @@ const AvatarCropScreen = ({
512
530
  AccessibilityInfo.announceForAccessibility(t('editProfile.crop.a11yResetAnnouncement') || 'Crop reset');
513
531
  }, [commitTransform, reduceMotion, scale, t, translateX, translateY]);
514
532
 
533
+ /**
534
+ * Web zoom controls. A desktop pointer has no pinch, so the +/- buttons drive
535
+ * the SAME `scale` shared value the pinch gesture does — clamped to the same
536
+ * bounds, with translation re-clamped through the shared {@link clampTranslation}
537
+ * helper so the image never leaves the viewport. Native keeps pinch (the
538
+ * buttons are hidden there). Reduced motion collapses the tween to an instant
539
+ * set. Reads the committed transform (refs) at press time, never during render.
540
+ */
541
+ const applyZoom = useCallback(direction => {
542
+ if (!baseFit || isProcessing) return;
543
+ const current = committedScale.current;
544
+ const target = Math.min(MAX_SCALE, Math.max(MIN_SCALE, current + direction * ZOOM_STEP));
545
+ if (Math.abs(target - current) < 0.001) {
546
+ // Already at the bound — a soft selection tick, no transform change.
547
+ void hapticSelection();
548
+ return;
549
+ }
550
+ const clamped = clampTranslation(committedTranslateX.current, committedTranslateY.current, target, baseFit.width, baseFit.height);
551
+ const duration = reduceMotion ? 0 : ZOOM_BUTTON_DURATION_MS;
552
+ scale.value = withTiming(target, {
553
+ duration
554
+ });
555
+ translateX.value = withTiming(clamped.tx, {
556
+ duration
557
+ });
558
+ translateY.value = withTiming(clamped.ty, {
559
+ duration
560
+ });
561
+ commitTransform(target, clamped.tx, clamped.ty);
562
+ void hapticImpact('light');
563
+ // Mirror the pinch's transient chrome so the buttons feel identical.
564
+ showGrid();
565
+ hideGrid();
566
+ showZoomChip();
567
+ hideZoomChip();
568
+ }, [baseFit, commitTransform, hideGrid, hideZoomChip, isProcessing, reduceMotion, scale, showGrid, showZoomChip, translateX, translateY]);
569
+
515
570
  /**
516
571
  * Convert the on-screen transform into pixel-space crop coordinates
517
572
  * relative to the source image, then invoke expo-image-manipulator to
@@ -529,7 +584,7 @@ const AvatarCropScreen = ({
529
584
  committedTranslateX: committedTranslateX.current,
530
585
  committedTranslateY: committedTranslateY.current
531
586
  });
532
- if (!imageUri || !baseFit || !naturalSize) {
587
+ if (!effectiveUri || !baseFit || !naturalSize) {
533
588
  toast.error(t('editProfile.toasts.cropNotReady') || 'Image not ready yet');
534
589
  return;
535
590
  }
@@ -572,7 +627,7 @@ const AvatarCropScreen = ({
572
627
  cropSize,
573
628
  outputSize: OUTPUT_SIZE
574
629
  });
575
- const preparedImage = await prepareImageForManipulator(imageUri);
630
+ const preparedImage = await prepareImageForManipulator(effectiveUri);
576
631
  preparedImageCleanup = preparedImage.cleanup;
577
632
  const result = await manipulateAsync(preparedImage.uri, [{
578
633
  crop: {
@@ -599,16 +654,16 @@ const AvatarCropScreen = ({
599
654
  height: result.height
600
655
  });
601
656
  void hapticNotification('success');
602
- await onConfirm?.({
657
+
658
+ // Resolve the surface's present() promise with the cropped JPEG and
659
+ // close it. The awaiting caller (`useAvatarPicker`) handles the
660
+ // upload + any success toast.
661
+ dismiss?.({
603
662
  uri: result.uri,
604
663
  width: result.width,
605
664
  height: result.height,
606
665
  mime: 'image/jpeg'
607
666
  });
608
-
609
- // Close the sheet on success. The caller is responsible for any
610
- // success toast (uploads typically toast their own outcome).
611
- onClose?.();
612
667
  } catch (err) {
613
668
  const normalizedError = normalizeCropError(err);
614
669
  logger.error('handleConfirm failed', normalizedError, {
@@ -620,86 +675,48 @@ const AvatarCropScreen = ({
620
675
  preparedImageCleanup?.();
621
676
  setIsProcessing(false);
622
677
  }
623
- }, [baseFit, imageUri, naturalSize, onClose, onConfirm, t]);
624
- const handleCancel = useCallback(() => {
625
- onCancel?.();
626
- goBack?.();
627
- }, [goBack, onCancel]);
628
- const topInset = Platform.OS === 'ios' ? Math.max(insets.top, 12) : Math.max(insets.top, 16);
629
- const bottomInset = Math.max(insets.bottom, 16);
678
+ }, [baseFit, effectiveUri, naturalSize, dismiss, t]);
679
+
680
+ /**
681
+ * The surface's primary action, mounted into the Dialog nav bar's right slot
682
+ * (which is why it must stay referentially stable). While processing it keeps
683
+ * its width and shows a spinner; the a11y label carries the "Saving…" state
684
+ * the visible label can no longer show.
685
+ */
686
+ const doneAction = useMemo(() => /*#__PURE__*/_jsx(Button, {
687
+ variant: "primary",
688
+ size: "small",
689
+ onPress: () => void handleConfirm(),
690
+ disabled: isProcessing || !baseFit,
691
+ loading: isProcessing,
692
+ accessibilityLabel: isProcessing ? t('editProfile.crop.saving') : t('editProfile.crop.confirm'),
693
+ children: t('editProfile.crop.confirm')
694
+ }), [baseFit, handleConfirm, isProcessing, t]);
695
+
696
+ // No bar of our own: the surface owns the chrome. `goBack` pops back to the
697
+ // ChangeAvatar source list (and dismisses the surface if this is somehow the
698
+ // root frame), which is exactly Cancel.
699
+ useSurfaceHeader({
700
+ title: t('editProfile.crop.title'),
701
+ largeTitle: false,
702
+ right: doneAction,
703
+ onBack: goBack
704
+ });
630
705
  const styles = useMemo(() => StyleSheet.create({
631
706
  container: {
632
- flex: 1,
633
- backgroundColor: CANVAS_BG
634
- },
635
- topBar: {
636
- paddingTop: topInset,
637
- paddingHorizontal: 12,
638
- paddingBottom: 10,
639
- flexDirection: 'row',
640
- alignItems: 'center',
641
- justifyContent: 'space-between',
642
- backgroundColor: 'rgba(0,0,0,0.6)',
643
- zIndex: 10
644
- },
645
- topBarTitleWrap: {
646
- flex: 1,
647
- alignItems: 'center',
648
- justifyContent: 'center',
649
- paddingHorizontal: 4
650
- },
651
- topBarTitle: {
652
- color: '#ffffff',
653
- fontSize: 17,
654
- letterSpacing: -0.2,
655
- ...(Platform.OS === 'web' ? {
656
- fontWeight: '600'
657
- } : null)
658
- },
659
- cancelBtn: {
660
- minWidth: 64,
661
- paddingHorizontal: 10,
662
- paddingVertical: 8,
663
- borderRadius: 18,
664
- alignItems: 'flex-start',
665
- justifyContent: 'center'
666
- },
667
- cancelLabel: {
668
- color: '#ffffff',
669
- fontSize: 15,
670
- opacity: 0.85
671
- },
672
- doneBtn: {
673
- minWidth: 76,
674
- paddingHorizontal: 14,
675
- paddingVertical: 8,
676
- borderRadius: 18,
677
- alignItems: 'center',
678
- justifyContent: 'center',
679
- backgroundColor: theme.colors.primary
680
- },
681
- doneBtnDisabled: {
682
- opacity: 0.5
683
- },
684
- doneLabel: {
685
- color: '#ffffff',
686
- fontSize: 15,
687
- letterSpacing: -0.1,
688
- ...(Platform.OS === 'web' ? {
689
- fontWeight: '600'
690
- } : null)
691
- },
692
- doneLabelLoading: {
693
- flexDirection: 'row',
694
- alignItems: 'center',
695
- justifyContent: 'center',
696
- gap: 8
707
+ backgroundColor: theme.colors.background
697
708
  },
698
709
  stage: {
699
- flex: 1,
710
+ backgroundColor: CANVAS_BG,
711
+ borderRadius: STAGE_RADIUS,
712
+ overflow: 'hidden',
713
+ // Top padding clears the zoom chip, which floats 44dp above
714
+ // the crop frame and would otherwise be clipped by `overflow`.
715
+ paddingTop: 60,
716
+ paddingBottom: 28,
717
+ paddingHorizontal: 16,
700
718
  alignItems: 'center',
701
- justifyContent: 'center',
702
- paddingHorizontal: 16
719
+ justifyContent: 'center'
703
720
  },
704
721
  cropFrame: {
705
722
  width: VIEWPORT_SIZE,
@@ -784,17 +801,14 @@ const AvatarCropScreen = ({
784
801
  letterSpacing: 0.2
785
802
  },
786
803
  helperBlock: {
787
- paddingHorizontal: 24,
788
- paddingTop: 24,
789
- paddingBottom: bottomInset,
804
+ paddingTop: 16,
790
805
  alignItems: 'center',
791
- justifyContent: 'flex-end',
792
- gap: 10
806
+ gap: 8
793
807
  },
794
808
  helper: {
795
809
  fontSize: 13,
796
810
  lineHeight: 18,
797
- color: 'rgba(255,255,255,0.6)',
811
+ color: theme.colors.textSecondary,
798
812
  textAlign: 'center',
799
813
  maxWidth: 320
800
814
  },
@@ -804,123 +818,72 @@ const AvatarCropScreen = ({
804
818
  },
805
819
  resetLinkText: {
806
820
  fontSize: 13,
807
- color: '#ffffff',
808
- opacity: 0.85,
821
+ color: theme.colors.primary,
809
822
  textDecorationLine: 'underline'
810
823
  },
811
824
  emptyState: {
812
- flex: 1,
813
825
  alignItems: 'center',
814
826
  justifyContent: 'center',
815
- padding: 24
827
+ paddingVertical: 48
816
828
  },
817
829
  emptyLabel: {
818
830
  fontSize: 14,
819
- color: 'rgba(255,255,255,0.7)',
831
+ color: theme.colors.textSecondary,
820
832
  textAlign: 'center'
821
833
  }
822
- }), [baseFit, bottomInset, theme, topInset]);
834
+ }), [baseFit, theme]);
823
835
 
824
836
  // Reset link reveal — only show when the image is not at the default
825
837
  // transform. Use derived display state to avoid mounting/unmounting jank.
826
838
  const resetLinkOpacity = isModified ? 1 : 0;
827
839
 
828
- // No image supplied OR measurement failed render a minimal empty state.
829
- if (!imageUri || measureError) {
830
- const emptyMessage = !imageUri ? t('editProfile.crop.noImage') || 'No image to crop' : measureError;
831
- return /*#__PURE__*/_jsxs(View, {
840
+ // Zoom-button state is derived from `zoomLabel` (reactive state, set on every
841
+ // commit) rather than the committed-scale ref, so it stays correct across
842
+ // renders without reading mutable state during render. The +/- pair is web-only
843
+ // (native has pinch).
844
+ const currentZoom = Number.parseFloat(zoomLabel) || MIN_SCALE;
845
+ const canZoomOut = currentZoom > MIN_SCALE + 0.001;
846
+ const canZoomIn = currentZoom < MAX_SCALE - 0.001;
847
+ const showZoomControls = Platform.OS === 'web';
848
+ const zoomOutDisabled = !canZoomOut || !baseFit || isProcessing;
849
+ const zoomInDisabled = !canZoomIn || !baseFit || isProcessing;
850
+
851
+ // No source at all (and none resolving), a resolution failure, or a
852
+ // measurement failure — render a minimal empty state. While a file ID is still
853
+ // resolving, fall THROUGH to the stage so its own spinner shows, not this.
854
+ // The surface's nav bar (back = cancel) is the only chrome needed here.
855
+ if (!effectiveUri && !isResolvingSource || sourceErrorMessage || measureErrorMessage) {
856
+ const emptyMessage = sourceErrorMessage ? sourceErrorMessage : measureErrorMessage ? measureErrorMessage : t('editProfile.crop.noImage');
857
+ return /*#__PURE__*/_jsx(View, {
832
858
  style: styles.container,
833
- children: [/*#__PURE__*/_jsxs(View, {
834
- style: styles.topBar,
835
- children: [/*#__PURE__*/_jsx(TouchableOpacity, {
836
- accessibilityLabel: t('editProfile.crop.cancel') || 'Cancel',
837
- accessibilityRole: "button",
838
- style: styles.cancelBtn,
839
- onPress: handleCancel,
840
- activeOpacity: 0.6,
841
- children: /*#__PURE__*/_jsx(Text, {
842
- style: styles.cancelLabel,
843
- children: t('editProfile.crop.cancel') || 'Cancel'
844
- })
845
- }), /*#__PURE__*/_jsx(View, {
846
- style: styles.topBarTitleWrap,
847
- children: /*#__PURE__*/_jsx(Text, {
848
- style: styles.topBarTitle,
849
- children: t('editProfile.crop.title') || 'Crop avatar'
850
- })
851
- }), /*#__PURE__*/_jsx(View, {
852
- style: styles.cancelBtn
853
- })]
854
- }), /*#__PURE__*/_jsx(View, {
859
+ className: "px-screen-margin pb-space-24",
860
+ children: /*#__PURE__*/_jsx(View, {
855
861
  style: styles.emptyState,
856
862
  children: /*#__PURE__*/_jsx(Text, {
857
863
  style: styles.emptyLabel,
858
864
  children: emptyMessage
859
865
  })
860
- })]
866
+ })
861
867
  });
862
868
  }
863
869
  return /*#__PURE__*/_jsxs(View, {
864
870
  style: styles.container,
871
+ className: "px-screen-margin pb-space-24",
865
872
  children: [/*#__PURE__*/_jsxs(View, {
866
- style: styles.topBar,
867
- children: [/*#__PURE__*/_jsx(TouchableOpacity, {
868
- accessibilityLabel: t('editProfile.crop.cancel') || 'Cancel',
869
- accessibilityRole: "button",
870
- style: styles.cancelBtn,
871
- onPress: handleCancel,
872
- disabled: isProcessing,
873
- activeOpacity: 0.6,
874
- children: /*#__PURE__*/_jsx(Text, {
875
- style: styles.cancelLabel,
876
- children: t('editProfile.crop.cancel') || 'Cancel'
877
- })
878
- }), /*#__PURE__*/_jsx(View, {
879
- style: styles.topBarTitleWrap,
880
- children: /*#__PURE__*/_jsx(Text, {
881
- style: styles.topBarTitle,
882
- numberOfLines: 1,
883
- children: t('editProfile.crop.title') || 'Crop avatar'
884
- })
885
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
886
- accessibilityLabel: t('editProfile.crop.confirm') || 'Use photo',
887
- accessibilityRole: "button",
888
- accessibilityState: {
889
- disabled: isProcessing || !baseFit,
890
- busy: isProcessing
891
- },
892
- style: [styles.doneBtn, (isProcessing || !baseFit) && styles.doneBtnDisabled],
893
- onPress: handleConfirm,
894
- disabled: isProcessing || !baseFit,
895
- activeOpacity: 0.85,
896
- children: isProcessing ? /*#__PURE__*/_jsxs(View, {
897
- style: styles.doneLabelLoading,
898
- children: [/*#__PURE__*/_jsx(ActivityIndicator, {
899
- size: "small",
900
- color: "#ffffff"
901
- }), /*#__PURE__*/_jsx(Text, {
902
- style: styles.doneLabel,
903
- children: t('editProfile.crop.saving') || 'Saving…'
904
- })]
905
- }) : /*#__PURE__*/_jsx(Text, {
906
- style: styles.doneLabel,
907
- children: t('editProfile.crop.confirm') || 'Use photo'
908
- })
909
- })]
910
- }), /*#__PURE__*/_jsx(View, {
911
873
  style: styles.stage,
912
- children: /*#__PURE__*/_jsxs(Animated.View, {
874
+ children: [/*#__PURE__*/_jsxs(Animated.View, {
875
+ ref: startEntrance,
913
876
  style: [styles.cropFrame, cropFrameAnimatedStyle],
914
877
  accessible: true,
915
878
  accessibilityRole: "image",
916
- accessibilityLabel: t('editProfile.crop.a11yImage') || 'Crop preview. Pinch to zoom and drag to reposition the image.',
879
+ accessibilityLabel: t('editProfile.crop.a11yImage'),
917
880
  children: [/*#__PURE__*/_jsx(GestureDetector, {
918
881
  gesture: composedGesture,
919
882
  children: /*#__PURE__*/_jsx(View, {
920
883
  style: styles.viewport,
921
- children: baseFit ? /*#__PURE__*/_jsx(Animated.Image, {
884
+ children: baseFit && effectiveUri ? /*#__PURE__*/_jsx(Animated.Image, {
922
885
  source: {
923
- uri: imageUri
886
+ uri: effectiveUri
924
887
  },
925
888
  style: [styles.image, imageAnimatedStyle],
926
889
  resizeMode: "cover"
@@ -958,17 +921,52 @@ const AvatarCropScreen = ({
958
921
  style: styles.zoomChipText,
959
922
  children: t('editProfile.crop.zoom', {
960
923
  value: zoomLabel
961
- }) || `${zoomLabel}×`
924
+ })
962
925
  })
963
926
  })]
964
- })
927
+ }), showZoomControls ? /*#__PURE__*/_jsx(View, {
928
+ className: "absolute bottom-4 left-0 right-0 items-center",
929
+ pointerEvents: "box-none",
930
+ children: /*#__PURE__*/_jsxs(View, {
931
+ className: "flex-row overflow-hidden rounded-full bg-black/70",
932
+ children: [/*#__PURE__*/_jsx(Pressable, {
933
+ accessibilityRole: "button",
934
+ accessibilityLabel: t('editProfile.crop.zoomOut'),
935
+ accessibilityState: {
936
+ disabled: zoomOutDisabled
937
+ },
938
+ disabled: zoomOutDisabled,
939
+ onPress: () => applyZoom(-1),
940
+ className: `h-10 w-[52px] items-center justify-center active:bg-white/10${zoomOutDisabled ? ' opacity-40' : ''}`,
941
+ children: /*#__PURE__*/_jsx(Text, {
942
+ className: "text-white text-[22px] font-medium leading-[24px]",
943
+ children: '−'
944
+ })
945
+ }), /*#__PURE__*/_jsx(View, {
946
+ className: "w-px self-stretch bg-white/25"
947
+ }), /*#__PURE__*/_jsx(Pressable, {
948
+ accessibilityRole: "button",
949
+ accessibilityLabel: t('editProfile.crop.zoomIn'),
950
+ accessibilityState: {
951
+ disabled: zoomInDisabled
952
+ },
953
+ disabled: zoomInDisabled,
954
+ onPress: () => applyZoom(1),
955
+ className: `h-10 w-[52px] items-center justify-center active:bg-white/10${zoomInDisabled ? ' opacity-40' : ''}`,
956
+ children: /*#__PURE__*/_jsx(Text, {
957
+ className: "text-white text-[22px] font-medium leading-[24px]",
958
+ children: '+'
959
+ })
960
+ })]
961
+ })
962
+ }) : null]
965
963
  }), /*#__PURE__*/_jsxs(View, {
966
964
  style: styles.helperBlock,
967
965
  children: [/*#__PURE__*/_jsx(Text, {
968
966
  style: styles.helper,
969
- children: t('editProfile.crop.helper') || 'The cropped circle is what will appear on your profile. Pinch to zoom, drag to position.'
967
+ children: t('editProfile.crop.helper')
970
968
  }), /*#__PURE__*/_jsx(Pressable, {
971
- accessibilityLabel: t('editProfile.crop.a11yReset') || 'Reset crop to default position',
969
+ accessibilityLabel: t('editProfile.crop.a11yReset'),
972
970
  accessibilityRole: "button",
973
971
  accessibilityState: {
974
972
  disabled: !isModified || isProcessing
@@ -980,7 +978,7 @@ const AvatarCropScreen = ({
980
978
  }],
981
979
  children: /*#__PURE__*/_jsx(Text, {
982
980
  style: styles.resetLinkText,
983
- children: t('editProfile.crop.resetToCenter') || 'Reset to center'
981
+ children: t('editProfile.crop.resetToCenter')
984
982
  })
985
983
  })]
986
984
  })]