@oxyhq/services 6.9.46 → 6.10.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 (812) hide show
  1. package/lib/commonjs/index.js +36 -13
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/client.js +0 -20
  4. package/lib/commonjs/ui/client.js.map +1 -1
  5. package/lib/commonjs/ui/components/ActingAsBanner.js +0 -4
  6. package/lib/commonjs/ui/components/ActingAsBanner.js.map +1 -1
  7. package/lib/commonjs/ui/components/ActivityIndicator.js +1 -1
  8. package/lib/commonjs/ui/components/ActivityIndicator.js.map +1 -1
  9. package/lib/commonjs/ui/components/Avatar.js +0 -2
  10. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  11. package/lib/commonjs/ui/components/BottomSheet.js +33 -398
  12. package/lib/commonjs/ui/components/BottomSheet.js.map +1 -1
  13. package/lib/commonjs/ui/components/BottomSheetRouter.js +8 -0
  14. package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
  15. package/lib/commonjs/ui/components/FollowButton.js +3 -5
  16. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  17. package/lib/commonjs/ui/components/Header.js +0 -5
  18. package/lib/commonjs/ui/components/Header.js.map +1 -1
  19. package/lib/commonjs/ui/components/Icon.js +6 -7
  20. package/lib/commonjs/ui/components/Icon.js.map +1 -1
  21. package/lib/commonjs/ui/components/IconButton/IconButton.js +1 -5
  22. package/lib/commonjs/ui/components/IconButton/IconButton.js.map +1 -1
  23. package/lib/commonjs/ui/components/OxyPayButton.js +0 -2
  24. package/lib/commonjs/ui/components/OxyPayButton.js.map +1 -1
  25. package/lib/commonjs/ui/components/OxyProvider.js +100 -37
  26. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  27. package/lib/commonjs/ui/components/OxySignInButton.js +23 -9
  28. package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
  29. package/lib/commonjs/ui/components/ProfileCard.js +11 -8
  30. package/lib/commonjs/ui/components/ProfileCard.js.map +1 -1
  31. package/lib/commonjs/ui/components/QuickActions.js +2 -2
  32. package/lib/commonjs/ui/components/QuickActions.js.map +1 -1
  33. package/lib/commonjs/ui/components/SignInModal.js +139 -284
  34. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  35. package/lib/commonjs/ui/components/StepBasedScreen.js +0 -2
  36. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  37. package/lib/commonjs/ui/components/TextField.js +0 -1
  38. package/lib/commonjs/ui/components/TextField.js.map +1 -1
  39. package/lib/commonjs/ui/components/TouchableRipple/TouchableRipple.native.js +1 -1
  40. package/lib/commonjs/ui/components/TouchableRipple/TouchableRipple.native.js.map +1 -1
  41. package/lib/commonjs/ui/components/feedback/feedbackStyles.js +0 -2
  42. package/lib/commonjs/ui/components/feedback/feedbackStyles.js.map +1 -1
  43. package/lib/commonjs/ui/components/fileManagement/AnimatedButton.js +0 -2
  44. package/lib/commonjs/ui/components/fileManagement/AnimatedButton.js.map +1 -1
  45. package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js +80 -76
  46. package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
  47. package/lib/commonjs/ui/components/fileManagement/FileViewer.js +6 -8
  48. package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
  49. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js +18 -23
  50. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
  51. package/lib/commonjs/ui/components/fileManagement/styles.js +213 -25
  52. package/lib/commonjs/ui/components/fileManagement/styles.js.map +1 -1
  53. package/lib/commonjs/ui/components/logo/LogoIcon.js +63 -0
  54. package/lib/commonjs/ui/components/logo/LogoIcon.js.map +1 -0
  55. package/lib/commonjs/ui/components/logo/LogoText.js +50 -0
  56. package/lib/commonjs/ui/components/logo/LogoText.js.map +1 -0
  57. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js +54 -88
  58. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js.map +1 -1
  59. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js +2 -2
  60. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js.map +1 -1
  61. package/lib/commonjs/ui/components/payment/PaymentReviewStep.js +1 -1
  62. package/lib/commonjs/ui/components/payment/PaymentReviewStep.js.map +1 -1
  63. package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js +1 -1
  64. package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js.map +1 -1
  65. package/lib/commonjs/ui/components/payment/paymentStyles.js +2 -10
  66. package/lib/commonjs/ui/components/payment/paymentStyles.js.map +1 -1
  67. package/lib/commonjs/ui/components/styles/overlay.js +7 -9
  68. package/lib/commonjs/ui/components/styles/overlay.js.map +1 -1
  69. package/lib/commonjs/ui/components/theming.js +0 -1
  70. package/lib/commonjs/ui/components/theming.js.map +1 -1
  71. package/lib/commonjs/ui/context/OxyContext.js +34 -21
  72. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  73. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +1 -3
  74. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  75. package/lib/commonjs/ui/hooks/index.js +32 -12
  76. package/lib/commonjs/ui/hooks/index.js.map +1 -1
  77. package/lib/commonjs/ui/hooks/mutations/mutationFactory.js +10 -5
  78. package/lib/commonjs/ui/hooks/mutations/mutationFactory.js.map +1 -1
  79. package/lib/commonjs/ui/hooks/mutations/mutationKeys.js +34 -0
  80. package/lib/commonjs/ui/hooks/mutations/mutationKeys.js.map +1 -0
  81. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +235 -57
  82. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  83. package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js +17 -13
  84. package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js.map +1 -1
  85. package/lib/commonjs/ui/hooks/queries/index.js +6 -0
  86. package/lib/commonjs/ui/hooks/queries/index.js.map +1 -1
  87. package/lib/commonjs/ui/hooks/queries/queryKeys.js +2 -1
  88. package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
  89. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +80 -3
  90. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  91. package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js +36 -1
  92. package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js.map +1 -1
  93. package/lib/commonjs/ui/hooks/queryClient.js +168 -70
  94. package/lib/commonjs/ui/hooks/queryClient.js.map +1 -1
  95. package/lib/commonjs/ui/hooks/useAsyncAction.js +7 -7
  96. package/lib/commonjs/ui/hooks/useAsyncAction.js.map +1 -1
  97. package/lib/commonjs/ui/hooks/useAuth.js +0 -8
  98. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  99. package/lib/commonjs/ui/hooks/useAvatarPicker.js +71 -20
  100. package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +1 -1
  101. package/lib/commonjs/ui/hooks/useFileDownloadUrl.js +12 -41
  102. package/lib/commonjs/ui/hooks/useFileDownloadUrl.js.map +1 -1
  103. package/lib/commonjs/ui/hooks/useMutationStatus.js +86 -0
  104. package/lib/commonjs/ui/hooks/useMutationStatus.js.map +1 -0
  105. package/lib/commonjs/ui/hooks/useOnlineStatus.js +33 -0
  106. package/lib/commonjs/ui/hooks/useOnlineStatus.js.map +1 -0
  107. package/lib/commonjs/ui/hooks/useSessionSocket.js +101 -130
  108. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  109. package/lib/commonjs/ui/hooks/useSettingToggle.js +4 -4
  110. package/lib/commonjs/ui/hooks/useSettingToggle.js.map +1 -1
  111. package/lib/commonjs/ui/index.js +1 -11
  112. package/lib/commonjs/ui/index.js.map +1 -1
  113. package/lib/commonjs/ui/navigation/routes.js +55 -3
  114. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  115. package/lib/commonjs/ui/screens/AccountCenterScreen.js +16 -16
  116. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  117. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +108 -123
  118. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  119. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +20 -19
  120. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  121. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +204 -161
  122. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  123. package/lib/commonjs/ui/screens/AccountVerificationScreen.js +18 -18
  124. package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
  125. package/lib/commonjs/ui/screens/AppInfoScreen.js +22 -23
  126. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  127. package/lib/commonjs/ui/screens/AvatarCropScreen.js +939 -0
  128. package/lib/commonjs/ui/screens/AvatarCropScreen.js.map +1 -0
  129. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js +13 -20
  130. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  131. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +10 -13
  132. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  133. package/lib/commonjs/ui/screens/FAQScreen.js +4 -4
  134. package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -1
  135. package/lib/commonjs/ui/screens/FeedbackScreen.js +17 -15
  136. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  137. package/lib/commonjs/ui/screens/FileManagementScreen.js +797 -159
  138. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  139. package/lib/commonjs/ui/screens/HelpSupportScreen.js +8 -9
  140. package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
  141. package/lib/commonjs/ui/screens/HistoryViewScreen.js +29 -21
  142. package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
  143. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +3 -5
  144. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  145. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +5 -5
  146. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
  147. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +2 -2
  148. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +75 -73
  149. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  150. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +32 -21
  151. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  152. package/lib/commonjs/ui/screens/ProfileScreen.js +4 -3
  153. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  154. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +3 -3
  155. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
  156. package/lib/commonjs/ui/screens/SessionManagementScreen.js +57 -56
  157. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  158. package/lib/commonjs/ui/screens/UserLinksScreen.js +2 -3
  159. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -1
  160. package/lib/commonjs/ui/screens/UserListScreen.js +39 -22
  161. package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
  162. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +18 -21
  163. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  164. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +0 -3
  165. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  166. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +6 -10
  167. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  168. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +1 -1
  169. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  170. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +6 -6
  171. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  172. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +13 -19
  173. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  174. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +5 -5
  175. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  176. package/lib/commonjs/ui/server.js +0 -5
  177. package/lib/commonjs/ui/server.js.map +1 -1
  178. package/lib/commonjs/ui/styles/authStyles.js +0 -5
  179. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  180. package/lib/commonjs/ui/styles/index.js +0 -11
  181. package/lib/commonjs/ui/styles/index.js.map +1 -1
  182. package/lib/commonjs/ui/styles/spacing.js +1 -42
  183. package/lib/commonjs/ui/styles/spacing.js.map +1 -1
  184. package/lib/commonjs/ui/styles/theme.js +0 -4
  185. package/lib/commonjs/ui/styles/theme.js.map +1 -1
  186. package/lib/commonjs/ui/utils/fileManagement.js +58 -39
  187. package/lib/commonjs/ui/utils/fileManagement.js.map +1 -1
  188. package/lib/commonjs/ui/utils/sessionHelpers.js +3 -1
  189. package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
  190. package/lib/commonjs/ui/utils/userUtils.js +33 -16
  191. package/lib/commonjs/ui/utils/userUtils.js.map +1 -1
  192. package/lib/module/index.js +9 -5
  193. package/lib/module/index.js.map +1 -1
  194. package/lib/module/ui/client.js +0 -6
  195. package/lib/module/ui/client.js.map +1 -1
  196. package/lib/module/ui/components/ActingAsBanner.js +0 -4
  197. package/lib/module/ui/components/ActingAsBanner.js.map +1 -1
  198. package/lib/module/ui/components/ActivityIndicator.js +1 -1
  199. package/lib/module/ui/components/ActivityIndicator.js.map +1 -1
  200. package/lib/module/ui/components/Avatar.js +0 -2
  201. package/lib/module/ui/components/Avatar.js.map +1 -1
  202. package/lib/module/ui/components/BottomSheet.js +35 -400
  203. package/lib/module/ui/components/BottomSheet.js.map +1 -1
  204. package/lib/module/ui/components/BottomSheetRouter.js +9 -1
  205. package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
  206. package/lib/module/ui/components/FollowButton.js +2 -4
  207. package/lib/module/ui/components/FollowButton.js.map +1 -1
  208. package/lib/module/ui/components/Header.js +0 -5
  209. package/lib/module/ui/components/Header.js.map +1 -1
  210. package/lib/module/ui/components/Icon.js +6 -7
  211. package/lib/module/ui/components/Icon.js.map +1 -1
  212. package/lib/module/ui/components/IconButton/IconButton.js +1 -5
  213. package/lib/module/ui/components/IconButton/IconButton.js.map +1 -1
  214. package/lib/module/ui/components/OxyPayButton.js +0 -2
  215. package/lib/module/ui/components/OxyPayButton.js.map +1 -1
  216. package/lib/module/ui/components/OxyProvider.js +103 -40
  217. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  218. package/lib/module/ui/components/OxySignInButton.js +23 -9
  219. package/lib/module/ui/components/OxySignInButton.js.map +1 -1
  220. package/lib/module/ui/components/ProfileCard.js +11 -8
  221. package/lib/module/ui/components/ProfileCard.js.map +1 -1
  222. package/lib/module/ui/components/QuickActions.js +2 -2
  223. package/lib/module/ui/components/QuickActions.js.map +1 -1
  224. package/lib/module/ui/components/SignInModal.js +137 -284
  225. package/lib/module/ui/components/SignInModal.js.map +1 -1
  226. package/lib/module/ui/components/StepBasedScreen.js +0 -2
  227. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  228. package/lib/module/ui/components/TextField.js +0 -1
  229. package/lib/module/ui/components/TextField.js.map +1 -1
  230. package/lib/module/ui/components/TouchableRipple/TouchableRipple.native.js +1 -1
  231. package/lib/module/ui/components/TouchableRipple/TouchableRipple.native.js.map +1 -1
  232. package/lib/module/ui/components/feedback/feedbackStyles.js +0 -2
  233. package/lib/module/ui/components/feedback/feedbackStyles.js.map +1 -1
  234. package/lib/module/ui/components/fileManagement/AnimatedButton.js +0 -1
  235. package/lib/module/ui/components/fileManagement/AnimatedButton.js.map +1 -1
  236. package/lib/module/ui/components/fileManagement/FileDetailsModal.js +80 -75
  237. package/lib/module/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
  238. package/lib/module/ui/components/fileManagement/FileViewer.js +6 -7
  239. package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
  240. package/lib/module/ui/components/fileManagement/UploadPreview.js +18 -22
  241. package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
  242. package/lib/module/ui/components/fileManagement/styles.js +212 -24
  243. package/lib/module/ui/components/fileManagement/styles.js.map +1 -1
  244. package/lib/module/ui/components/logo/LogoIcon.js +56 -0
  245. package/lib/module/ui/components/logo/LogoIcon.js.map +1 -0
  246. package/lib/module/ui/components/logo/LogoText.js +43 -0
  247. package/lib/module/ui/components/logo/LogoText.js.map +1 -0
  248. package/lib/module/ui/components/modals/DeleteAccountModal.js +55 -88
  249. package/lib/module/ui/components/modals/DeleteAccountModal.js.map +1 -1
  250. package/lib/module/ui/components/payment/PaymentDetailsStep.js +1 -1
  251. package/lib/module/ui/components/payment/PaymentDetailsStep.js.map +1 -1
  252. package/lib/module/ui/components/payment/PaymentReviewStep.js +1 -1
  253. package/lib/module/ui/components/payment/PaymentReviewStep.js.map +1 -1
  254. package/lib/module/ui/components/payment/PaymentSuccessStep.js +1 -1
  255. package/lib/module/ui/components/payment/PaymentSuccessStep.js.map +1 -1
  256. package/lib/module/ui/components/payment/paymentStyles.js +2 -10
  257. package/lib/module/ui/components/payment/paymentStyles.js.map +1 -1
  258. package/lib/module/ui/components/styles/overlay.js +8 -8
  259. package/lib/module/ui/components/styles/overlay.js.map +1 -1
  260. package/lib/module/ui/components/theming.js +0 -1
  261. package/lib/module/ui/components/theming.js.map +1 -1
  262. package/lib/module/ui/context/OxyContext.js +32 -19
  263. package/lib/module/ui/context/OxyContext.js.map +1 -1
  264. package/lib/module/ui/context/hooks/useAuthOperations.js +1 -3
  265. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  266. package/lib/module/ui/hooks/index.js +5 -3
  267. package/lib/module/ui/hooks/index.js.map +1 -1
  268. package/lib/module/ui/hooks/mutations/mutationFactory.js +6 -1
  269. package/lib/module/ui/hooks/mutations/mutationFactory.js.map +1 -1
  270. package/lib/module/ui/hooks/mutations/mutationKeys.js +30 -0
  271. package/lib/module/ui/hooks/mutations/mutationKeys.js.map +1 -0
  272. package/lib/module/ui/hooks/mutations/useAccountMutations.js +231 -52
  273. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  274. package/lib/module/ui/hooks/mutations/useServicesMutations.js +9 -5
  275. package/lib/module/ui/hooks/mutations/useServicesMutations.js.map +1 -1
  276. package/lib/module/ui/hooks/queries/index.js +1 -1
  277. package/lib/module/ui/hooks/queries/index.js.map +1 -1
  278. package/lib/module/ui/hooks/queries/queryKeys.js +2 -1
  279. package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
  280. package/lib/module/ui/hooks/queries/useAccountQueries.js +80 -3
  281. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  282. package/lib/module/ui/hooks/queries/useSecurityQueries.js +35 -1
  283. package/lib/module/ui/hooks/queries/useSecurityQueries.js.map +1 -1
  284. package/lib/module/ui/hooks/queryClient.js +166 -68
  285. package/lib/module/ui/hooks/queryClient.js.map +1 -1
  286. package/lib/module/ui/hooks/useAsyncAction.js +3 -3
  287. package/lib/module/ui/hooks/useAsyncAction.js.map +1 -1
  288. package/lib/module/ui/hooks/useAuth.js +0 -3
  289. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  290. package/lib/module/ui/hooks/useAvatarPicker.js +73 -22
  291. package/lib/module/ui/hooks/useAvatarPicker.js.map +1 -1
  292. package/lib/module/ui/hooks/useFileDownloadUrl.js +11 -39
  293. package/lib/module/ui/hooks/useFileDownloadUrl.js.map +1 -1
  294. package/lib/module/ui/hooks/useMutationStatus.js +82 -0
  295. package/lib/module/ui/hooks/useMutationStatus.js.map +1 -0
  296. package/lib/module/ui/hooks/useOnlineStatus.js +29 -0
  297. package/lib/module/ui/hooks/useOnlineStatus.js.map +1 -0
  298. package/lib/module/ui/hooks/useSessionSocket.js +101 -130
  299. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  300. package/lib/module/ui/hooks/useSettingToggle.js +1 -1
  301. package/lib/module/ui/hooks/useSettingToggle.js.map +1 -1
  302. package/lib/module/ui/index.js +1 -10
  303. package/lib/module/ui/index.js.map +1 -1
  304. package/lib/module/ui/navigation/routes.js +54 -2
  305. package/lib/module/ui/navigation/routes.js.map +1 -1
  306. package/lib/module/ui/screens/AccountCenterScreen.js +15 -14
  307. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  308. package/lib/module/ui/screens/AccountOverviewScreen.js +96 -111
  309. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  310. package/lib/module/ui/screens/AccountSettingsScreen.js +19 -18
  311. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  312. package/lib/module/ui/screens/AccountSwitcherScreen.js +189 -145
  313. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  314. package/lib/module/ui/screens/AccountVerificationScreen.js +15 -15
  315. package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
  316. package/lib/module/ui/screens/AppInfoScreen.js +14 -15
  317. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  318. package/lib/module/ui/screens/AvatarCropScreen.js +936 -0
  319. package/lib/module/ui/screens/AvatarCropScreen.js.map +1 -0
  320. package/lib/module/ui/screens/CreateManagedAccountScreen.js +11 -18
  321. package/lib/module/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  322. package/lib/module/ui/screens/EditProfileFieldScreen.js +8 -11
  323. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  324. package/lib/module/ui/screens/FAQScreen.js +3 -3
  325. package/lib/module/ui/screens/FAQScreen.js.map +1 -1
  326. package/lib/module/ui/screens/FeedbackScreen.js +14 -12
  327. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  328. package/lib/module/ui/screens/FileManagementScreen.js +764 -125
  329. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  330. package/lib/module/ui/screens/HelpSupportScreen.js +2 -3
  331. package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
  332. package/lib/module/ui/screens/HistoryViewScreen.js +26 -17
  333. package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
  334. package/lib/module/ui/screens/LanguageSelectorScreen.js +1 -3
  335. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  336. package/lib/module/ui/screens/LegalDocumentsScreen.js +3 -3
  337. package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
  338. package/lib/module/ui/screens/PaymentGatewayScreen.js +2 -2
  339. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +60 -57
  340. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  341. package/lib/module/ui/screens/PrivacySettingsScreen.js +27 -16
  342. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  343. package/lib/module/ui/screens/ProfileScreen.js +4 -3
  344. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  345. package/lib/module/ui/screens/SavesCollectionsScreen.js +2 -2
  346. package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
  347. package/lib/module/ui/screens/SessionManagementScreen.js +48 -47
  348. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  349. package/lib/module/ui/screens/UserLinksScreen.js +2 -3
  350. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -1
  351. package/lib/module/ui/screens/UserListScreen.js +40 -23
  352. package/lib/module/ui/screens/UserListScreen.js.map +1 -1
  353. package/lib/module/ui/screens/WelcomeNewUserScreen.js +16 -19
  354. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  355. package/lib/module/ui/screens/karma/KarmaAboutScreen.js +0 -3
  356. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  357. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +6 -10
  358. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  359. package/lib/module/ui/screens/karma/KarmaFAQScreen.js +1 -1
  360. package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  361. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +6 -6
  362. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  363. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +13 -19
  364. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  365. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +5 -5
  366. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  367. package/lib/module/ui/server.js +0 -4
  368. package/lib/module/ui/server.js.map +1 -1
  369. package/lib/module/ui/styles/authStyles.js +0 -5
  370. package/lib/module/ui/styles/authStyles.js.map +1 -1
  371. package/lib/module/ui/styles/index.js +0 -1
  372. package/lib/module/ui/styles/index.js.map +1 -1
  373. package/lib/module/ui/styles/spacing.js +0 -42
  374. package/lib/module/ui/styles/spacing.js.map +1 -1
  375. package/lib/module/ui/styles/theme.js +0 -4
  376. package/lib/module/ui/styles/theme.js.map +1 -1
  377. package/lib/module/ui/utils/fileManagement.js +54 -36
  378. package/lib/module/ui/utils/fileManagement.js.map +1 -1
  379. package/lib/module/ui/utils/sessionHelpers.js +3 -1
  380. package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
  381. package/lib/module/ui/utils/userUtils.js +34 -16
  382. package/lib/module/ui/utils/userUtils.js.map +1 -1
  383. package/lib/typescript/commonjs/index.d.ts +7 -3
  384. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  385. package/lib/typescript/commonjs/ui/client.d.ts +0 -2
  386. package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
  387. package/lib/typescript/commonjs/ui/components/ActingAsBanner.d.ts.map +1 -1
  388. package/lib/typescript/commonjs/ui/components/Avatar.d.ts.map +1 -1
  389. package/lib/typescript/commonjs/ui/components/BottomSheet.d.ts +27 -27
  390. package/lib/typescript/commonjs/ui/components/BottomSheet.d.ts.map +1 -1
  391. package/lib/typescript/commonjs/ui/components/BottomSheetRouter.d.ts.map +1 -1
  392. package/lib/typescript/commonjs/ui/components/FollowButton.d.ts.map +1 -1
  393. package/lib/typescript/commonjs/ui/components/Header.d.ts.map +1 -1
  394. package/lib/typescript/commonjs/ui/components/Icon.d.ts +3 -2
  395. package/lib/typescript/commonjs/ui/components/Icon.d.ts.map +1 -1
  396. package/lib/typescript/commonjs/ui/components/IconButton/IconButton.d.ts.map +1 -1
  397. package/lib/typescript/commonjs/ui/components/OxyPayButton.d.ts.map +1 -1
  398. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  399. package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts.map +1 -1
  400. package/lib/typescript/commonjs/ui/components/ProfileCard.d.ts +4 -1
  401. package/lib/typescript/commonjs/ui/components/ProfileCard.d.ts.map +1 -1
  402. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  403. package/lib/typescript/commonjs/ui/components/StepBasedScreen.d.ts.map +1 -1
  404. package/lib/typescript/commonjs/ui/components/TextField/Addons/Outline.d.ts +2 -2
  405. package/lib/typescript/commonjs/ui/components/TextField/helpers.d.ts +2 -2
  406. package/lib/typescript/commonjs/ui/components/TextField/types.d.ts +0 -1
  407. package/lib/typescript/commonjs/ui/components/TextField/types.d.ts.map +1 -1
  408. package/lib/typescript/commonjs/ui/components/TextField.d.ts +1 -1
  409. package/lib/typescript/commonjs/ui/components/TextField.d.ts.map +1 -1
  410. package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts +0 -1
  411. package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts.map +1 -1
  412. package/lib/typescript/commonjs/ui/components/fileManagement/AnimatedButton.d.ts.map +1 -1
  413. package/lib/typescript/commonjs/ui/components/fileManagement/FileDetailsModal.d.ts +1 -1
  414. package/lib/typescript/commonjs/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
  415. package/lib/typescript/commonjs/ui/components/fileManagement/FileViewer.d.ts +0 -2
  416. package/lib/typescript/commonjs/ui/components/fileManagement/FileViewer.d.ts.map +1 -1
  417. package/lib/typescript/commonjs/ui/components/fileManagement/UploadPreview.d.ts +3 -2
  418. package/lib/typescript/commonjs/ui/components/fileManagement/UploadPreview.d.ts.map +1 -1
  419. package/lib/typescript/commonjs/ui/components/fileManagement/styles.d.ts +200 -17
  420. package/lib/typescript/commonjs/ui/components/fileManagement/styles.d.ts.map +1 -1
  421. package/lib/typescript/commonjs/ui/components/logo/LogoIcon.d.ts +22 -0
  422. package/lib/typescript/commonjs/ui/components/logo/LogoIcon.d.ts.map +1 -0
  423. package/lib/typescript/commonjs/ui/components/logo/LogoText.d.ts +22 -0
  424. package/lib/typescript/commonjs/ui/components/logo/LogoText.d.ts.map +1 -0
  425. package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts +2 -2
  426. package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
  427. package/lib/typescript/commonjs/ui/components/payment/paymentStyles.d.ts +0 -7
  428. package/lib/typescript/commonjs/ui/components/payment/paymentStyles.d.ts.map +1 -1
  429. package/lib/typescript/commonjs/ui/components/styles/overlay.d.ts +3 -1
  430. package/lib/typescript/commonjs/ui/components/styles/overlay.d.ts.map +1 -1
  431. package/lib/typescript/commonjs/ui/components/theming.d.ts.map +1 -1
  432. package/lib/typescript/commonjs/ui/components/types.d.ts.map +1 -1
  433. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  434. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  435. package/lib/typescript/commonjs/ui/hooks/index.d.ts +5 -3
  436. package/lib/typescript/commonjs/ui/hooks/index.d.ts.map +1 -1
  437. package/lib/typescript/commonjs/ui/hooks/mutations/mutationFactory.d.ts +11 -0
  438. package/lib/typescript/commonjs/ui/hooks/mutations/mutationFactory.d.ts.map +1 -1
  439. package/lib/typescript/commonjs/ui/hooks/mutations/mutationKeys.d.ts +25 -0
  440. package/lib/typescript/commonjs/ui/hooks/mutations/mutationKeys.d.ts.map +1 -0
  441. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +161 -9
  442. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  443. package/lib/typescript/commonjs/ui/hooks/mutations/useServicesMutations.d.ts.map +1 -1
  444. package/lib/typescript/commonjs/ui/hooks/queries/index.d.ts +1 -1
  445. package/lib/typescript/commonjs/ui/hooks/queries/index.d.ts.map +1 -1
  446. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +1 -0
  447. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  448. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts +22 -8
  449. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  450. package/lib/typescript/commonjs/ui/hooks/queries/useSecurityQueries.d.ts +13 -3
  451. package/lib/typescript/commonjs/ui/hooks/queries/useSecurityQueries.d.ts.map +1 -1
  452. package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts +7 -5
  453. package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  454. package/lib/typescript/commonjs/ui/hooks/queryClient.d.ts +57 -9
  455. package/lib/typescript/commonjs/ui/hooks/queryClient.d.ts.map +1 -1
  456. package/lib/typescript/commonjs/ui/hooks/useAssets.d.ts +1 -1
  457. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts +0 -1
  458. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  459. package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts +10 -2
  460. package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts.map +1 -1
  461. package/lib/typescript/commonjs/ui/hooks/useFileDownloadUrl.d.ts +2 -6
  462. package/lib/typescript/commonjs/ui/hooks/useFileDownloadUrl.d.ts.map +1 -1
  463. package/lib/typescript/commonjs/ui/hooks/useMutationStatus.d.ts +23 -0
  464. package/lib/typescript/commonjs/ui/hooks/useMutationStatus.d.ts.map +1 -0
  465. package/lib/typescript/commonjs/ui/hooks/useOnlineStatus.d.ts +13 -0
  466. package/lib/typescript/commonjs/ui/hooks/useOnlineStatus.d.ts.map +1 -0
  467. package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts +1 -2
  468. package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts.map +1 -1
  469. package/lib/typescript/commonjs/ui/index.d.ts +1 -4
  470. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  471. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +48 -2
  472. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  473. package/lib/typescript/commonjs/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  474. package/lib/typescript/commonjs/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  475. package/lib/typescript/commonjs/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  476. package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  477. package/lib/typescript/commonjs/ui/screens/AppInfoScreen.d.ts.map +1 -1
  478. package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts +49 -0
  479. package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts.map +1 -0
  480. package/lib/typescript/commonjs/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
  481. package/lib/typescript/commonjs/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  482. package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
  483. package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
  484. package/lib/typescript/commonjs/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  485. package/lib/typescript/commonjs/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  486. package/lib/typescript/commonjs/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  487. package/lib/typescript/commonjs/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  488. package/lib/typescript/commonjs/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  489. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  490. package/lib/typescript/commonjs/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  491. package/lib/typescript/commonjs/ui/screens/UserLinksScreen.d.ts.map +1 -1
  492. package/lib/typescript/commonjs/ui/screens/UserListScreen.d.ts.map +1 -1
  493. package/lib/typescript/commonjs/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  494. package/lib/typescript/commonjs/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
  495. package/lib/typescript/commonjs/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  496. package/lib/typescript/commonjs/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
  497. package/lib/typescript/commonjs/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
  498. package/lib/typescript/commonjs/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
  499. package/lib/typescript/commonjs/ui/server.d.ts +0 -2
  500. package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
  501. package/lib/typescript/commonjs/ui/styles/authStyles.d.ts +0 -4
  502. package/lib/typescript/commonjs/ui/styles/authStyles.d.ts.map +1 -1
  503. package/lib/typescript/commonjs/ui/styles/index.d.ts +0 -1
  504. package/lib/typescript/commonjs/ui/styles/index.d.ts.map +1 -1
  505. package/lib/typescript/commonjs/ui/styles/spacing.d.ts +0 -36
  506. package/lib/typescript/commonjs/ui/styles/spacing.d.ts.map +1 -1
  507. package/lib/typescript/commonjs/ui/styles/theme.d.ts +0 -1
  508. package/lib/typescript/commonjs/ui/styles/theme.d.ts.map +1 -1
  509. package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts +39 -12
  510. package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts.map +1 -1
  511. package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts +3 -1
  512. package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts.map +1 -1
  513. package/lib/typescript/commonjs/ui/utils/userUtils.d.ts +19 -18
  514. package/lib/typescript/commonjs/ui/utils/userUtils.d.ts.map +1 -1
  515. package/lib/typescript/module/index.d.ts +7 -3
  516. package/lib/typescript/module/index.d.ts.map +1 -1
  517. package/lib/typescript/module/ui/client.d.ts +0 -2
  518. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  519. package/lib/typescript/module/ui/components/ActingAsBanner.d.ts.map +1 -1
  520. package/lib/typescript/module/ui/components/Avatar.d.ts.map +1 -1
  521. package/lib/typescript/module/ui/components/BottomSheet.d.ts +27 -27
  522. package/lib/typescript/module/ui/components/BottomSheet.d.ts.map +1 -1
  523. package/lib/typescript/module/ui/components/BottomSheetRouter.d.ts.map +1 -1
  524. package/lib/typescript/module/ui/components/FollowButton.d.ts.map +1 -1
  525. package/lib/typescript/module/ui/components/Header.d.ts.map +1 -1
  526. package/lib/typescript/module/ui/components/Icon.d.ts +3 -2
  527. package/lib/typescript/module/ui/components/Icon.d.ts.map +1 -1
  528. package/lib/typescript/module/ui/components/IconButton/IconButton.d.ts.map +1 -1
  529. package/lib/typescript/module/ui/components/OxyPayButton.d.ts.map +1 -1
  530. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  531. package/lib/typescript/module/ui/components/OxySignInButton.d.ts.map +1 -1
  532. package/lib/typescript/module/ui/components/ProfileCard.d.ts +4 -1
  533. package/lib/typescript/module/ui/components/ProfileCard.d.ts.map +1 -1
  534. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  535. package/lib/typescript/module/ui/components/StepBasedScreen.d.ts.map +1 -1
  536. package/lib/typescript/module/ui/components/TextField/Addons/Outline.d.ts +2 -2
  537. package/lib/typescript/module/ui/components/TextField/helpers.d.ts +2 -2
  538. package/lib/typescript/module/ui/components/TextField/types.d.ts +0 -1
  539. package/lib/typescript/module/ui/components/TextField/types.d.ts.map +1 -1
  540. package/lib/typescript/module/ui/components/TextField.d.ts +1 -1
  541. package/lib/typescript/module/ui/components/TextField.d.ts.map +1 -1
  542. package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts +0 -1
  543. package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts.map +1 -1
  544. package/lib/typescript/module/ui/components/fileManagement/AnimatedButton.d.ts.map +1 -1
  545. package/lib/typescript/module/ui/components/fileManagement/FileDetailsModal.d.ts +1 -1
  546. package/lib/typescript/module/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
  547. package/lib/typescript/module/ui/components/fileManagement/FileViewer.d.ts +0 -2
  548. package/lib/typescript/module/ui/components/fileManagement/FileViewer.d.ts.map +1 -1
  549. package/lib/typescript/module/ui/components/fileManagement/UploadPreview.d.ts +3 -2
  550. package/lib/typescript/module/ui/components/fileManagement/UploadPreview.d.ts.map +1 -1
  551. package/lib/typescript/module/ui/components/fileManagement/styles.d.ts +200 -17
  552. package/lib/typescript/module/ui/components/fileManagement/styles.d.ts.map +1 -1
  553. package/lib/typescript/module/ui/components/logo/LogoIcon.d.ts +22 -0
  554. package/lib/typescript/module/ui/components/logo/LogoIcon.d.ts.map +1 -0
  555. package/lib/typescript/module/ui/components/logo/LogoText.d.ts +22 -0
  556. package/lib/typescript/module/ui/components/logo/LogoText.d.ts.map +1 -0
  557. package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts +2 -2
  558. package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
  559. package/lib/typescript/module/ui/components/payment/paymentStyles.d.ts +0 -7
  560. package/lib/typescript/module/ui/components/payment/paymentStyles.d.ts.map +1 -1
  561. package/lib/typescript/module/ui/components/styles/overlay.d.ts +3 -1
  562. package/lib/typescript/module/ui/components/styles/overlay.d.ts.map +1 -1
  563. package/lib/typescript/module/ui/components/theming.d.ts.map +1 -1
  564. package/lib/typescript/module/ui/components/types.d.ts.map +1 -1
  565. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  566. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  567. package/lib/typescript/module/ui/hooks/index.d.ts +5 -3
  568. package/lib/typescript/module/ui/hooks/index.d.ts.map +1 -1
  569. package/lib/typescript/module/ui/hooks/mutations/mutationFactory.d.ts +11 -0
  570. package/lib/typescript/module/ui/hooks/mutations/mutationFactory.d.ts.map +1 -1
  571. package/lib/typescript/module/ui/hooks/mutations/mutationKeys.d.ts +25 -0
  572. package/lib/typescript/module/ui/hooks/mutations/mutationKeys.d.ts.map +1 -0
  573. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +161 -9
  574. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  575. package/lib/typescript/module/ui/hooks/mutations/useServicesMutations.d.ts.map +1 -1
  576. package/lib/typescript/module/ui/hooks/queries/index.d.ts +1 -1
  577. package/lib/typescript/module/ui/hooks/queries/index.d.ts.map +1 -1
  578. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +1 -0
  579. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  580. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts +22 -8
  581. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  582. package/lib/typescript/module/ui/hooks/queries/useSecurityQueries.d.ts +13 -3
  583. package/lib/typescript/module/ui/hooks/queries/useSecurityQueries.d.ts.map +1 -1
  584. package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts +7 -5
  585. package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  586. package/lib/typescript/module/ui/hooks/queryClient.d.ts +57 -9
  587. package/lib/typescript/module/ui/hooks/queryClient.d.ts.map +1 -1
  588. package/lib/typescript/module/ui/hooks/useAssets.d.ts +1 -1
  589. package/lib/typescript/module/ui/hooks/useAuth.d.ts +0 -1
  590. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  591. package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts +10 -2
  592. package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts.map +1 -1
  593. package/lib/typescript/module/ui/hooks/useFileDownloadUrl.d.ts +2 -6
  594. package/lib/typescript/module/ui/hooks/useFileDownloadUrl.d.ts.map +1 -1
  595. package/lib/typescript/module/ui/hooks/useMutationStatus.d.ts +23 -0
  596. package/lib/typescript/module/ui/hooks/useMutationStatus.d.ts.map +1 -0
  597. package/lib/typescript/module/ui/hooks/useOnlineStatus.d.ts +13 -0
  598. package/lib/typescript/module/ui/hooks/useOnlineStatus.d.ts.map +1 -0
  599. package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts +1 -2
  600. package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts.map +1 -1
  601. package/lib/typescript/module/ui/index.d.ts +1 -4
  602. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  603. package/lib/typescript/module/ui/navigation/routes.d.ts +48 -2
  604. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  605. package/lib/typescript/module/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  606. package/lib/typescript/module/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  607. package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  608. package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  609. package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts.map +1 -1
  610. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts +49 -0
  611. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts.map +1 -0
  612. package/lib/typescript/module/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
  613. package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  614. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  615. package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
  616. package/lib/typescript/module/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  617. package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  618. package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  619. package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  620. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  621. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  622. package/lib/typescript/module/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  623. package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts.map +1 -1
  624. package/lib/typescript/module/ui/screens/UserListScreen.d.ts.map +1 -1
  625. package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  626. package/lib/typescript/module/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
  627. package/lib/typescript/module/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  628. package/lib/typescript/module/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
  629. package/lib/typescript/module/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
  630. package/lib/typescript/module/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
  631. package/lib/typescript/module/ui/server.d.ts +0 -2
  632. package/lib/typescript/module/ui/server.d.ts.map +1 -1
  633. package/lib/typescript/module/ui/styles/authStyles.d.ts +0 -4
  634. package/lib/typescript/module/ui/styles/authStyles.d.ts.map +1 -1
  635. package/lib/typescript/module/ui/styles/index.d.ts +0 -1
  636. package/lib/typescript/module/ui/styles/index.d.ts.map +1 -1
  637. package/lib/typescript/module/ui/styles/spacing.d.ts +0 -36
  638. package/lib/typescript/module/ui/styles/spacing.d.ts.map +1 -1
  639. package/lib/typescript/module/ui/styles/theme.d.ts +0 -1
  640. package/lib/typescript/module/ui/styles/theme.d.ts.map +1 -1
  641. package/lib/typescript/module/ui/utils/fileManagement.d.ts +39 -12
  642. package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
  643. package/lib/typescript/module/ui/utils/sessionHelpers.d.ts +3 -1
  644. package/lib/typescript/module/ui/utils/sessionHelpers.d.ts.map +1 -1
  645. package/lib/typescript/module/ui/utils/userUtils.d.ts +19 -18
  646. package/lib/typescript/module/ui/utils/userUtils.d.ts.map +1 -1
  647. package/lib/typescript/types/expo-vector-icons.d.ts +7 -4
  648. package/package.json +64 -31
  649. package/src/index.ts +11 -4
  650. package/src/types/expo-vector-icons.d.ts +7 -4
  651. package/src/ui/client.ts +0 -6
  652. package/src/ui/components/ActingAsBanner.tsx +0 -4
  653. package/src/ui/components/ActivityIndicator.tsx +1 -1
  654. package/src/ui/components/Avatar.tsx +0 -2
  655. package/src/ui/components/BottomSheet.tsx +41 -440
  656. package/src/ui/components/BottomSheetRouter.tsx +12 -1
  657. package/src/ui/components/FollowButton.tsx +2 -4
  658. package/src/ui/components/Header.tsx +0 -5
  659. package/src/ui/components/Icon.tsx +12 -6
  660. package/src/ui/components/IconButton/IconButton.tsx +0 -3
  661. package/src/ui/components/OxyPayButton.tsx +0 -2
  662. package/src/ui/components/OxyProvider.tsx +127 -48
  663. package/src/ui/components/OxySignInButton.tsx +21 -9
  664. package/src/ui/components/ProfileCard.tsx +13 -10
  665. package/src/ui/components/QuickActions.tsx +2 -2
  666. package/src/ui/components/SignInModal.tsx +80 -199
  667. package/src/ui/components/StepBasedScreen.tsx +0 -2
  668. package/src/ui/components/TextField/Addons/Outline.tsx +2 -2
  669. package/src/ui/components/TextField/helpers.tsx +2 -2
  670. package/src/ui/components/TextField/types.tsx +0 -1
  671. package/src/ui/components/TextField.tsx +1 -2
  672. package/src/ui/components/TouchableRipple/TouchableRipple.native.tsx +1 -1
  673. package/src/ui/components/feedback/feedbackStyles.ts +0 -2
  674. package/src/ui/components/fileManagement/AnimatedButton.tsx +0 -1
  675. package/src/ui/components/fileManagement/FileDetailsModal.tsx +71 -65
  676. package/src/ui/components/fileManagement/FileViewer.tsx +6 -9
  677. package/src/ui/components/fileManagement/UploadPreview.tsx +21 -25
  678. package/src/ui/components/fileManagement/styles.ts +206 -18
  679. package/src/ui/components/logo/LogoIcon.tsx +70 -0
  680. package/src/ui/components/logo/LogoText.tsx +70 -0
  681. package/src/ui/components/modals/DeleteAccountModal.tsx +56 -91
  682. package/src/ui/components/payment/PaymentDetailsStep.tsx +1 -1
  683. package/src/ui/components/payment/PaymentReviewStep.tsx +1 -1
  684. package/src/ui/components/payment/PaymentSuccessStep.tsx +1 -1
  685. package/src/ui/components/payment/paymentStyles.ts +0 -8
  686. package/src/ui/components/styles/overlay.tsx +17 -8
  687. package/src/ui/components/theming.tsx +0 -1
  688. package/src/ui/components/types.tsx +3 -2
  689. package/src/ui/context/OxyContext.tsx +34 -19
  690. package/src/ui/context/hooks/useAuthOperations.ts +1 -3
  691. package/src/ui/hooks/index.ts +11 -4
  692. package/src/ui/hooks/mutations/mutationFactory.ts +16 -1
  693. package/src/ui/hooks/mutations/mutationKeys.ts +28 -0
  694. package/src/ui/hooks/mutations/useAccountMutations.ts +251 -59
  695. package/src/ui/hooks/mutations/useServicesMutations.ts +10 -4
  696. package/src/ui/hooks/queries/index.ts +1 -0
  697. package/src/ui/hooks/queries/queryKeys.ts +2 -0
  698. package/src/ui/hooks/queries/useAccountQueries.ts +83 -3
  699. package/src/ui/hooks/queries/useSecurityQueries.ts +42 -2
  700. package/src/ui/hooks/queryClient.ts +194 -69
  701. package/src/ui/hooks/useAsyncAction.ts +3 -3
  702. package/src/ui/hooks/useAuth.ts +0 -2
  703. package/src/ui/hooks/useAvatarPicker.ts +108 -27
  704. package/src/ui/hooks/useFileDownloadUrl.ts +15 -39
  705. package/src/ui/hooks/useMutationStatus.ts +111 -0
  706. package/src/ui/hooks/useOnlineStatus.ts +29 -0
  707. package/src/ui/hooks/useSessionSocket.ts +136 -126
  708. package/src/ui/hooks/useSettingToggle.ts +1 -1
  709. package/src/ui/index.ts +0 -12
  710. package/src/ui/navigation/routes.ts +93 -2
  711. package/src/ui/screens/AccountCenterScreen.tsx +15 -13
  712. package/src/ui/screens/AccountOverviewScreen.tsx +94 -104
  713. package/src/ui/screens/AccountSettingsScreen.tsx +18 -17
  714. package/src/ui/screens/AccountSwitcherScreen.tsx +331 -298
  715. package/src/ui/screens/AccountVerificationScreen.tsx +15 -15
  716. package/src/ui/screens/AppInfoScreen.tsx +8 -13
  717. package/src/ui/screens/AvatarCropScreen.tsx +1073 -0
  718. package/src/ui/screens/CreateManagedAccountScreen.tsx +5 -16
  719. package/src/ui/screens/EditProfileFieldScreen.tsx +5 -10
  720. package/src/ui/screens/FAQScreen.tsx +3 -3
  721. package/src/ui/screens/FeedbackScreen.tsx +14 -12
  722. package/src/ui/screens/FileManagementScreen.tsx +885 -124
  723. package/src/ui/screens/HelpSupportScreen.tsx +2 -3
  724. package/src/ui/screens/HistoryViewScreen.tsx +24 -9
  725. package/src/ui/screens/LanguageSelectorScreen.tsx +1 -3
  726. package/src/ui/screens/LegalDocumentsScreen.tsx +3 -3
  727. package/src/ui/screens/PaymentGatewayScreen.tsx +2 -2
  728. package/src/ui/screens/PremiumSubscriptionScreen.tsx +51 -56
  729. package/src/ui/screens/PrivacySettingsScreen.tsx +22 -20
  730. package/src/ui/screens/ProfileScreen.tsx +1 -2
  731. package/src/ui/screens/SavesCollectionsScreen.tsx +2 -2
  732. package/src/ui/screens/SessionManagementScreen.tsx +35 -47
  733. package/src/ui/screens/UserLinksScreen.tsx +1 -2
  734. package/src/ui/screens/UserListScreen.tsx +30 -19
  735. package/src/ui/screens/WelcomeNewUserScreen.tsx +14 -18
  736. package/src/ui/screens/karma/KarmaAboutScreen.tsx +0 -3
  737. package/src/ui/screens/karma/KarmaCenterScreen.tsx +4 -8
  738. package/src/ui/screens/karma/KarmaFAQScreen.tsx +1 -1
  739. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +3 -4
  740. package/src/ui/screens/karma/KarmaRewardsScreen.tsx +13 -18
  741. package/src/ui/screens/karma/KarmaRulesScreen.tsx +3 -4
  742. package/src/ui/server.ts +0 -4
  743. package/src/ui/styles/authStyles.ts +0 -5
  744. package/src/ui/styles/index.ts +0 -1
  745. package/src/ui/styles/spacing.ts +0 -43
  746. package/src/ui/styles/theme.ts +0 -4
  747. package/src/ui/utils/fileManagement.ts +66 -38
  748. package/src/ui/utils/sessionHelpers.ts +3 -1
  749. package/src/ui/utils/userUtils.ts +45 -29
  750. package/lib/commonjs/lib/sonner-safe.js +0 -32
  751. package/lib/commonjs/lib/sonner-safe.js.map +0 -1
  752. package/lib/commonjs/lib/sonner.js +0 -19
  753. package/lib/commonjs/lib/sonner.js.map +0 -1
  754. package/lib/commonjs/lib/sonner.native.js +0 -24
  755. package/lib/commonjs/lib/sonner.native.js.map +0 -1
  756. package/lib/commonjs/lib/sonner.web.js +0 -24
  757. package/lib/commonjs/lib/sonner.web.js.map +0 -1
  758. package/lib/commonjs/ui/hooks/useThemeColors.js +0 -33
  759. package/lib/commonjs/ui/hooks/useThemeColors.js.map +0 -1
  760. package/lib/commonjs/ui/hooks/useThemeStyles.js +0 -38
  761. package/lib/commonjs/ui/hooks/useThemeStyles.js.map +0 -1
  762. package/lib/commonjs/ui/styles/fonts.js +0 -84
  763. package/lib/commonjs/ui/styles/fonts.js.map +0 -1
  764. package/lib/module/lib/sonner-safe.js +0 -29
  765. package/lib/module/lib/sonner-safe.js.map +0 -1
  766. package/lib/module/lib/sonner.js +0 -14
  767. package/lib/module/lib/sonner.js.map +0 -1
  768. package/lib/module/lib/sonner.native.js +0 -19
  769. package/lib/module/lib/sonner.native.js.map +0 -1
  770. package/lib/module/lib/sonner.web.js +0 -19
  771. package/lib/module/lib/sonner.web.js.map +0 -1
  772. package/lib/module/ui/hooks/useThemeColors.js +0 -29
  773. package/lib/module/ui/hooks/useThemeColors.js.map +0 -1
  774. package/lib/module/ui/hooks/useThemeStyles.js +0 -33
  775. package/lib/module/ui/hooks/useThemeStyles.js.map +0 -1
  776. package/lib/module/ui/styles/fonts.js +0 -81
  777. package/lib/module/ui/styles/fonts.js.map +0 -1
  778. package/lib/typescript/commonjs/lib/sonner-safe.d.ts +0 -9
  779. package/lib/typescript/commonjs/lib/sonner-safe.d.ts.map +0 -1
  780. package/lib/typescript/commonjs/lib/sonner.d.ts +0 -12
  781. package/lib/typescript/commonjs/lib/sonner.d.ts.map +0 -1
  782. package/lib/typescript/commonjs/lib/sonner.native.d.ts +0 -15
  783. package/lib/typescript/commonjs/lib/sonner.native.d.ts.map +0 -1
  784. package/lib/typescript/commonjs/lib/sonner.web.d.ts +0 -15
  785. package/lib/typescript/commonjs/lib/sonner.web.d.ts.map +0 -1
  786. package/lib/typescript/commonjs/ui/hooks/useThemeColors.d.ts +0 -87
  787. package/lib/typescript/commonjs/ui/hooks/useThemeColors.d.ts.map +0 -1
  788. package/lib/typescript/commonjs/ui/hooks/useThemeStyles.d.ts +0 -22
  789. package/lib/typescript/commonjs/ui/hooks/useThemeStyles.d.ts.map +0 -1
  790. package/lib/typescript/commonjs/ui/styles/fonts.d.ts +0 -21
  791. package/lib/typescript/commonjs/ui/styles/fonts.d.ts.map +0 -1
  792. package/lib/typescript/module/lib/sonner-safe.d.ts +0 -9
  793. package/lib/typescript/module/lib/sonner-safe.d.ts.map +0 -1
  794. package/lib/typescript/module/lib/sonner.d.ts +0 -12
  795. package/lib/typescript/module/lib/sonner.d.ts.map +0 -1
  796. package/lib/typescript/module/lib/sonner.native.d.ts +0 -15
  797. package/lib/typescript/module/lib/sonner.native.d.ts.map +0 -1
  798. package/lib/typescript/module/lib/sonner.web.d.ts +0 -15
  799. package/lib/typescript/module/lib/sonner.web.d.ts.map +0 -1
  800. package/lib/typescript/module/ui/hooks/useThemeColors.d.ts +0 -87
  801. package/lib/typescript/module/ui/hooks/useThemeColors.d.ts.map +0 -1
  802. package/lib/typescript/module/ui/hooks/useThemeStyles.d.ts +0 -22
  803. package/lib/typescript/module/ui/hooks/useThemeStyles.d.ts.map +0 -1
  804. package/lib/typescript/module/ui/styles/fonts.d.ts +0 -21
  805. package/lib/typescript/module/ui/styles/fonts.d.ts.map +0 -1
  806. package/src/lib/sonner-safe.ts +0 -31
  807. package/src/lib/sonner.native.ts +0 -28
  808. package/src/lib/sonner.ts +0 -11
  809. package/src/lib/sonner.web.ts +0 -28
  810. package/src/ui/hooks/useThemeColors.ts +0 -27
  811. package/src/ui/hooks/useThemeStyles.ts +0 -50
  812. package/src/ui/styles/fonts.ts +0 -77
@@ -11,8 +11,20 @@ import {
11
11
  Image,
12
12
  Animated,
13
13
  Easing,
14
+ FlatList,
15
+ AccessibilityInfo,
16
+ Platform,
17
+ useWindowDimensions,
14
18
  } from 'react-native';
15
19
  import { Image as ExpoImage } from 'expo-image';
20
+ import Reanimated, {
21
+ FadeIn,
22
+ useAnimatedStyle,
23
+ useSharedValue,
24
+ withSequence,
25
+ withSpring,
26
+ withTiming,
27
+ } from 'react-native-reanimated';
16
28
  import type { FileManagementScreenProps } from '../types/fileManagement';
17
29
 
18
30
  // Lazy load expo-document-picker (optional dependency)
@@ -27,13 +39,10 @@ const loadDocumentPicker = async () => {
27
39
  throw new Error('expo-document-picker is not installed. Please install it: npx expo install expo-document-picker');
28
40
  }
29
41
  };
30
- import { toast } from '../../lib/sonner';
31
- import * as Prompt from '@oxyhq/bloom/prompt';
32
- import { usePromptControl } from '@oxyhq/bloom/prompt';
33
- import { Ionicons } from '@expo/vector-icons';
34
- // @ts-ignore - MaterialCommunityIcons is available at runtime
35
- import { MaterialCommunityIcons } from '@expo/vector-icons';
36
- import type { FileMetadata } from '@oxyhq/core';
42
+ import { Dialog, toast, useDialogControl } from '@oxyhq/bloom';
43
+ import { Ionicons, MaterialCommunityIcons } from '@expo/vector-icons';
44
+ import type { AssetUploadInput, FileMetadata, RNFileDescriptor } from '@oxyhq/core';
45
+ import { getErrorMessage as getOxyErrorMessage } from '@oxyhq/core';
37
46
  import { useFileStore, useFiles, useUploading as useUploadingStore, useUploadAggregateProgress, useDeleting as useDeletingStore } from '../stores/fileStore';
38
47
  import Header from '../components/Header';
39
48
  import JustifiedPhotoGrid from '../components/photogrid/JustifiedPhotoGrid';
@@ -51,13 +60,123 @@ import {
51
60
  import { FileViewer } from '../components/fileManagement/FileViewer';
52
61
  import { FileDetailsModal } from '../components/fileManagement/FileDetailsModal';
53
62
  import { UploadPreview } from '../components/fileManagement/UploadPreview';
54
- import { useDialogControl } from '@oxyhq/bloom/dialog';
55
- import { fileManagementStyles } from '../components/fileManagement/styles';
63
+ import { fileManagementStyles, photoPickerStyles } from '../components/fileManagement/styles';
56
64
  import type { OnConfirmFileSelection } from '../types/fileManagement';
57
65
 
58
- /** Extract error message from unknown error type */
59
- const getErrorMessage = (error: unknown): string | undefined =>
60
- error instanceof Error ? getErrorMessage(error) : typeof error === 'string' ? error : undefined;
66
+ /**
67
+ * Extract error message from unknown error type.
68
+ * Delegates to the canonical `getErrorMessage` in `@oxyhq/core` and returns
69
+ * `undefined` for empty results (so callers can fall back to a translated
70
+ * message via `||`).
71
+ */
72
+ const getErrorMessage = (error: unknown): string | undefined => {
73
+ if (error == null) return undefined;
74
+ const message = getOxyErrorMessage(error, '');
75
+ return message ? message : undefined;
76
+ };
77
+
78
+ /**
79
+ * A picker-produced file ready to upload. On web this is a real `File`
80
+ * (carrying an optional `uri` for preview). On native, it's an
81
+ * {@link RNFileDescriptor} — passed straight to FormData by `assetUpload`.
82
+ */
83
+ type UploadCandidate = (File & { uri?: string }) | RNFileDescriptor;
84
+
85
+ /** Returns the display name for either a web File or an RN descriptor. */
86
+ const candidateName = (candidate: UploadCandidate, fallback: string): string =>
87
+ (candidate.name && typeof candidate.name === 'string' ? candidate.name : fallback);
88
+
89
+ /** Returns the byte size for either a web File or an RN descriptor (0 if unknown). */
90
+ const candidateSize = (candidate: UploadCandidate): number => {
91
+ const size = (candidate as { size?: number }).size;
92
+ return typeof size === 'number' && Number.isFinite(size) ? size : 0;
93
+ };
94
+
95
+ /** Returns the mime type for either a web File or an RN descriptor. */
96
+ const candidateType = (candidate: UploadCandidate): string => {
97
+ const value = (candidate as { type?: string }).type;
98
+ return typeof value === 'string' && value.length > 0 ? value : 'application/octet-stream';
99
+ };
100
+
101
+ /** Returns the preview URI for an upload candidate, if available. */
102
+ const candidateUri = (candidate: UploadCandidate): string | undefined => {
103
+ const uri = (candidate as { uri?: string }).uri;
104
+ return typeof uri === 'string' && uri.length > 0 ? uri : undefined;
105
+ };
106
+
107
+ /**
108
+ * Haptic feedback wrapper. `expo-haptics` is an optional dependency — when not
109
+ * installed (or on web), all calls degrade silently. We resolve the module
110
+ * once and cache the promise so subsequent calls don't repeat the dynamic
111
+ * import. Matches the pattern used by AvatarCropScreen.
112
+ */
113
+ type HapticImpact = 'light' | 'medium' | 'heavy';
114
+ type HapticNotification = 'success' | 'warning' | 'error';
115
+ interface HapticsModule {
116
+ impactAsync: (style: unknown) => Promise<void>;
117
+ notificationAsync: (type: unknown) => Promise<void>;
118
+ selectionAsync: () => Promise<void>;
119
+ ImpactFeedbackStyle: { Light: unknown; Medium: unknown; Heavy: unknown };
120
+ NotificationFeedbackType: { Success: unknown; Warning: unknown; Error: unknown };
121
+ }
122
+
123
+ let hapticsModulePromise: Promise<HapticsModule | null> | null = null;
124
+ const getHaptics = (): Promise<HapticsModule | null> => {
125
+ if (Platform.OS === 'web') return Promise.resolve(null);
126
+ if (hapticsModulePromise) return hapticsModulePromise;
127
+ hapticsModulePromise = (async () => {
128
+ try {
129
+ const mod = (await import('expo-haptics')) as unknown as HapticsModule;
130
+ if (!mod || typeof mod.impactAsync !== 'function') return null;
131
+ return mod;
132
+ } catch {
133
+ return null;
134
+ }
135
+ })();
136
+ return hapticsModulePromise;
137
+ };
138
+
139
+ const hapticImpact = async (style: HapticImpact): Promise<void> => {
140
+ const h = await getHaptics();
141
+ if (!h) return;
142
+ const styleEnum =
143
+ style === 'heavy'
144
+ ? h.ImpactFeedbackStyle.Heavy
145
+ : style === 'medium'
146
+ ? h.ImpactFeedbackStyle.Medium
147
+ : h.ImpactFeedbackStyle.Light;
148
+ try {
149
+ await h.impactAsync(styleEnum);
150
+ } catch {
151
+ // Silent — haptics are non-critical UX polish.
152
+ }
153
+ };
154
+
155
+ const hapticSelection = async (): Promise<void> => {
156
+ const h = await getHaptics();
157
+ if (!h) return;
158
+ try {
159
+ await h.selectionAsync();
160
+ } catch {
161
+ // Silent.
162
+ }
163
+ };
164
+
165
+ const hapticNotification = async (type: HapticNotification): Promise<void> => {
166
+ const h = await getHaptics();
167
+ if (!h) return;
168
+ const typeEnum =
169
+ type === 'error'
170
+ ? h.NotificationFeedbackType.Error
171
+ : type === 'warning'
172
+ ? h.NotificationFeedbackType.Warning
173
+ : h.NotificationFeedbackType.Success;
174
+ try {
175
+ await h.notificationAsync(typeEnum);
176
+ } catch {
177
+ // Silent.
178
+ }
179
+ };
61
180
 
62
181
  // Animated button component for smooth transitions
63
182
  const AnimatedButton: React.FC<{
@@ -67,7 +186,8 @@ const AnimatedButton: React.FC<{
67
186
  primaryColor: string;
68
187
  textColor: string;
69
188
  style: Record<string, unknown>;
70
- }> = ({ isSelected, onPress, icon, primaryColor, textColor, style }) => {
189
+ accessibilityLabel: string;
190
+ }> = ({ isSelected, onPress, icon, primaryColor, textColor, style, accessibilityLabel }) => {
71
191
  const animatedValue = useRef(new Animated.Value(isSelected ? 1 : 0)).current;
72
192
 
73
193
  useEffect(() => {
@@ -84,13 +204,14 @@ const AnimatedButton: React.FC<{
84
204
  outputRange: ['transparent', primaryColor],
85
205
  });
86
206
 
87
- const iconColor = animatedValue.interpolate({
88
- inputRange: [0, 1],
89
- outputRange: [textColor, '#FFFFFF'],
90
- });
91
-
92
207
  return (
93
- <TouchableOpacity onPress={onPress} activeOpacity={0.7}>
208
+ <TouchableOpacity
209
+ onPress={onPress}
210
+ activeOpacity={0.7}
211
+ accessibilityRole="button"
212
+ accessibilityLabel={accessibilityLabel}
213
+ accessibilityState={{ selected: isSelected }}
214
+ >
94
215
  <Animated.View
95
216
  style={[
96
217
  style,
@@ -111,6 +232,518 @@ const AnimatedButton: React.FC<{
111
232
  );
112
233
  };
113
234
 
235
+ /**
236
+ * Props for the dedicated photo picker view. Used by FileManagementScreen
237
+ * only when `selectMode + image-only` is active. All callbacks are wired by
238
+ * the parent — this component is purely presentational.
239
+ */
240
+ interface PhotoPickerViewProps {
241
+ photos: FileMetadata[];
242
+ selectedIds: Set<string>;
243
+ multiSelect: boolean;
244
+ maxSelection?: number;
245
+ allowUpload: boolean;
246
+ refreshing: boolean;
247
+ uploading: boolean;
248
+ isPickingDocument: boolean;
249
+ uploadProgress: { current: number; total: number } | null;
250
+ hasMore: boolean;
251
+ loadingMore: boolean;
252
+ reduceMotion: boolean;
253
+ getThumbUrl: (file: FileMetadata, variant?: string) => string;
254
+ primaryColor: string;
255
+ isOwner: boolean;
256
+ onTogglePhoto: (photo: FileMetadata) => void;
257
+ onPreviewPhoto: (photo: FileMetadata) => void;
258
+ onUpload: () => void;
259
+ onRefresh: () => void;
260
+ onLoadMore: () => void;
261
+ onCancel: () => void;
262
+ onConfirm: () => void;
263
+ t: (key: string, vars?: Record<string, string | number>) => string;
264
+ }
265
+
266
+ /**
267
+ * A single photo cell. Memoized so re-renders during selection only touch
268
+ * affected cells — selection of one photo must not redraw the whole grid.
269
+ *
270
+ * Apple Photos pattern: when any cell is selected, *non-selected* siblings
271
+ * fade to 0.6 opacity to focus attention on the active selection.
272
+ */
273
+ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: {
274
+ photo: FileMetadata;
275
+ size: number;
276
+ marginRight: number;
277
+ marginBottom: number;
278
+ isSelected: boolean;
279
+ selectionIndex: number; // 1-based for badge; 0 if not selected
280
+ dim: boolean; // any selection exists and this cell is not selected
281
+ primaryColor: string;
282
+ thumbUrl: string;
283
+ enterIndex: number;
284
+ reduceMotion: boolean;
285
+ onPress: () => void;
286
+ onLongPress: () => void;
287
+ a11yLabel: string;
288
+ }) {
289
+ const {
290
+ photo, size, marginRight, marginBottom, isSelected, selectionIndex,
291
+ dim, primaryColor, thumbUrl, enterIndex, reduceMotion, onPress,
292
+ onLongPress, a11yLabel,
293
+ } = props;
294
+
295
+ // Cap the cumulative stagger at ~800ms total so the very long grid does
296
+ // not keep fading in late tiles. Beyond ~53 tiles the delay maxes out.
297
+ const STAGGER_PER_CELL_MS = 15;
298
+ const MAX_TOTAL_STAGGER_MS = 800;
299
+ const delay = Math.min(enterIndex * STAGGER_PER_CELL_MS, MAX_TOTAL_STAGGER_MS);
300
+
301
+ // Selection ring pulse animation: 1.0 → 1.05 → 1.0 on transition to
302
+ // selected. Plays at most once per selection change; reduce-motion skips.
303
+ const ringScale = useSharedValue(1);
304
+ const prevSelected = useRef(isSelected);
305
+ useEffect(() => {
306
+ if (prevSelected.current === isSelected) return;
307
+ prevSelected.current = isSelected;
308
+ if (!isSelected) {
309
+ ringScale.value = 1;
310
+ return;
311
+ }
312
+ if (reduceMotion) {
313
+ ringScale.value = 1;
314
+ return;
315
+ }
316
+ ringScale.value = withSequence(
317
+ withTiming(1.05, { duration: 110 }),
318
+ withSpring(1, { damping: 14, stiffness: 200 }),
319
+ );
320
+ }, [isSelected, reduceMotion, ringScale]);
321
+
322
+ const ringAnimatedStyle = useAnimatedStyle(() => ({
323
+ transform: [{ scale: ringScale.value }],
324
+ }));
325
+
326
+ const inner = (
327
+ <>
328
+ <View style={[photoPickerStyles.cellInner, dim && photoPickerStyles.cellDim]}>
329
+ <ExpoImage
330
+ source={{ uri: thumbUrl }}
331
+ style={photoPickerStyles.cellImage}
332
+ contentFit="cover"
333
+ transition={120}
334
+ cachePolicy="memory-disk"
335
+ accessibilityLabel={photo.filename}
336
+ />
337
+ </View>
338
+ {isSelected && (
339
+ <Reanimated.View
340
+ pointerEvents="none"
341
+ style={[
342
+ photoPickerStyles.cellRing,
343
+ { borderColor: primaryColor },
344
+ ringAnimatedStyle,
345
+ ]}
346
+ />
347
+ )}
348
+ {isSelected && (
349
+ <View
350
+ pointerEvents="none"
351
+ style={[photoPickerStyles.cellBadge, { backgroundColor: primaryColor }]}
352
+ >
353
+ <Text style={photoPickerStyles.cellBadgeText}>
354
+ {selectionIndex > 0 ? String(selectionIndex) : ''}
355
+ </Text>
356
+ </View>
357
+ )}
358
+ </>
359
+ );
360
+
361
+ const cellWrapperStyle = {
362
+ width: size,
363
+ height: size,
364
+ marginRight,
365
+ marginBottom,
366
+ };
367
+
368
+ if (reduceMotion) {
369
+ return (
370
+ <TouchableOpacity
371
+ activeOpacity={0.85}
372
+ onPress={onPress}
373
+ onLongPress={onLongPress}
374
+ style={[photoPickerStyles.cellWrapper, cellWrapperStyle]}
375
+ accessibilityRole="button"
376
+ accessibilityLabel={a11yLabel}
377
+ accessibilityState={{ selected: isSelected }}
378
+ >
379
+ {inner}
380
+ </TouchableOpacity>
381
+ );
382
+ }
383
+
384
+ return (
385
+ <Reanimated.View
386
+ entering={FadeIn.delay(delay).duration(200)}
387
+ style={[photoPickerStyles.cellWrapper, cellWrapperStyle]}
388
+ >
389
+ <TouchableOpacity
390
+ activeOpacity={0.85}
391
+ onPress={onPress}
392
+ onLongPress={onLongPress}
393
+ style={{ flex: 1 }}
394
+ accessibilityRole="button"
395
+ accessibilityLabel={a11yLabel}
396
+ accessibilityState={{ selected: isSelected }}
397
+ >
398
+ {inner}
399
+ </TouchableOpacity>
400
+ </Reanimated.View>
401
+ );
402
+ });
403
+
404
+ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
405
+ photos,
406
+ selectedIds,
407
+ multiSelect,
408
+ maxSelection,
409
+ allowUpload,
410
+ refreshing,
411
+ uploading,
412
+ isPickingDocument,
413
+ uploadProgress,
414
+ hasMore,
415
+ loadingMore,
416
+ reduceMotion,
417
+ getThumbUrl,
418
+ primaryColor,
419
+ isOwner,
420
+ onTogglePhoto,
421
+ onPreviewPhoto,
422
+ onUpload,
423
+ onRefresh,
424
+ onLoadMore,
425
+ onCancel,
426
+ onConfirm,
427
+ t,
428
+ }) => {
429
+ const { width: windowWidth, height: windowHeight } = useWindowDimensions();
430
+
431
+ // Layout: 3 columns phone portrait, 2 columns phone landscape,
432
+ // 4 columns tablet (>= 600 width). Apple Photos-ish.
433
+ const columns = useMemo(() => {
434
+ if (windowWidth >= 600) return 4;
435
+ // Landscape phone: width > height
436
+ if (windowWidth > windowHeight) return 2;
437
+ return 3;
438
+ }, [windowWidth, windowHeight]);
439
+
440
+ const GUTTER = 2;
441
+ const cellSize = useMemo(() => {
442
+ // (windowWidth - (columns - 1) * GUTTER) / columns, but
443
+ // FlatList in 3-col layout means each row has 2 inter-cell gutters.
444
+ return Math.floor((windowWidth - GUTTER * (columns - 1)) / columns);
445
+ }, [windowWidth, columns]);
446
+
447
+ // Map selectedIds → 1-based selection order for the badge. We freeze a
448
+ // stable order at the time of selection: the order is the insertion
449
+ // order of the Set (which JS preserves natively).
450
+ const selectionOrder = useMemo(() => {
451
+ const map = new Map<string, number>();
452
+ let i = 1;
453
+ for (const id of selectedIds) {
454
+ map.set(id, i++);
455
+ }
456
+ return map;
457
+ }, [selectedIds]);
458
+
459
+ const hasAnySelection = selectedIds.size > 0;
460
+
461
+ // Compact icon-only upload pill on narrow screens; full pill otherwise.
462
+ const showUploadLabel = windowWidth >= 360;
463
+
464
+ // The bottom sheet renders below the status bar already (its `maxHeight`
465
+ // is capped by `SCREEN_HEIGHT - insets.top`), so the picker MUST NOT add
466
+ // an additional safe-area inset to the header. Header layout:
467
+ // • 28dp drag-handle hit area floats at the very top of the sheet
468
+ // • 56dp app bar sits immediately below the handle
469
+ // Total header zone = 28 + 56 = 84dp from sheet top.
470
+ const HANDLE_ZONE = 28;
471
+ const APP_BAR_HEIGHT = 56;
472
+ const headerHeight = HANDLE_ZONE + APP_BAR_HEIGHT;
473
+ const contentPaddingTop = headerHeight + 4;
474
+
475
+ const isEmpty = photos.length === 0;
476
+ const a11yColumnsAnnouncement = useRef<number>(columns);
477
+
478
+ useEffect(() => {
479
+ if (a11yColumnsAnnouncement.current !== columns) {
480
+ a11yColumnsAnnouncement.current = columns;
481
+ }
482
+ }, [columns]);
483
+
484
+ const handleCellPress = useCallback(
485
+ (photo: FileMetadata) => {
486
+ if (Platform.OS !== 'web') {
487
+ void hapticImpact('light');
488
+ }
489
+ onTogglePhoto(photo);
490
+ },
491
+ [onTogglePhoto],
492
+ );
493
+
494
+ const handleCellLongPress = useCallback(
495
+ (photo: FileMetadata) => {
496
+ if (Platform.OS !== 'web') {
497
+ void hapticSelection();
498
+ }
499
+ onPreviewPhoto(photo);
500
+ },
501
+ [onPreviewPhoto],
502
+ );
503
+
504
+ const handleConfirm = useCallback(() => {
505
+ if (multiSelect) {
506
+ if (selectedIds.size === 0) return;
507
+ if (Platform.OS !== 'web') {
508
+ void hapticNotification('success');
509
+ }
510
+ }
511
+ onConfirm();
512
+ }, [multiSelect, selectedIds.size, onConfirm]);
513
+
514
+ // FlatList renderItem: each cell knows its enterIndex (for stagger).
515
+ const renderItem = useCallback(
516
+ ({ item, index }: { item: FileMetadata; index: number }) => {
517
+ const isSelected = selectedIds.has(item.id);
518
+ const selIndex = isSelected ? (selectionOrder.get(item.id) || 0) : 0;
519
+ // Last column gets no right margin; last row no bottom margin
520
+ // (FlatList handles row breaks via numColumns).
521
+ const isLastInRow = (index + 1) % columns === 0;
522
+ const a11yLabel = t(
523
+ isSelected
524
+ ? 'fileManagement.a11y.photoCellSelected'
525
+ : 'fileManagement.a11y.photoCellUnselected',
526
+ { name: item.filename || 'photo' },
527
+ );
528
+ return (
529
+ <PhotoPickerCell
530
+ photo={item}
531
+ size={cellSize}
532
+ marginRight={isLastInRow ? 0 : GUTTER}
533
+ marginBottom={GUTTER}
534
+ isSelected={isSelected}
535
+ selectionIndex={selIndex}
536
+ dim={multiSelect && hasAnySelection && !isSelected}
537
+ primaryColor={primaryColor}
538
+ thumbUrl={getThumbUrl(item, 'thumb')}
539
+ enterIndex={index}
540
+ reduceMotion={reduceMotion}
541
+ onPress={() => handleCellPress(item)}
542
+ onLongPress={() => handleCellLongPress(item)}
543
+ a11yLabel={a11yLabel}
544
+ />
545
+ );
546
+ },
547
+ [
548
+ selectedIds, selectionOrder, columns, cellSize, multiSelect, hasAnySelection,
549
+ primaryColor, getThumbUrl, reduceMotion, handleCellPress, handleCellLongPress, t,
550
+ ],
551
+ );
552
+
553
+ const keyExtractor = useCallback((item: FileMetadata) => item.id, []);
554
+
555
+ const listFooter = useMemo(() => {
556
+ if (!loadingMore) return null;
557
+ return (
558
+ <View style={{ paddingVertical: 16, alignItems: 'center' }}>
559
+ <ActivityIndicator size="small" color="#FFFFFF" />
560
+ </View>
561
+ );
562
+ }, [loadingMore]);
563
+
564
+ const handleEndReached = useCallback(() => {
565
+ if (loadingMore || !hasMore) return;
566
+ onLoadMore();
567
+ }, [loadingMore, hasMore, onLoadMore]);
568
+
569
+ const confirmDisabled = multiSelect && selectedIds.size === 0;
570
+ const confirmLabel = multiSelect
571
+ ? t('fileManagement.doneWithCount', { count: selectedIds.size })
572
+ : t('fileManagement.done');
573
+
574
+ // The progress fill width. Guard against zero division.
575
+ const progressFraction = uploadProgress && uploadProgress.total > 0
576
+ ? Math.min(1, Math.max(0, uploadProgress.current / uploadProgress.total))
577
+ : 0;
578
+
579
+ return (
580
+ <View style={photoPickerStyles.root}>
581
+ {/* Photo grid (renders behind translucent header) */}
582
+ {isEmpty ? (
583
+ <View style={[photoPickerStyles.empty, { paddingTop: contentPaddingTop }]}>
584
+ <View style={photoPickerStyles.emptyIconWrap}>
585
+ <MaterialCommunityIcons name="image-outline" size={64} color="#FFFFFF" />
586
+ </View>
587
+ <Text style={[photoPickerStyles.emptyTitle, { color: '#FFFFFF' }]}>
588
+ {t('fileManagement.photoPicker.emptyTitle')}
589
+ </Text>
590
+ <Text style={[photoPickerStyles.emptySubtitle, { color: '#FFFFFF' }]}>
591
+ {t('fileManagement.photoPicker.emptySubtitle')}
592
+ </Text>
593
+ {isOwner && allowUpload && (
594
+ <TouchableOpacity
595
+ style={[photoPickerStyles.emptyCta, { backgroundColor: primaryColor }]}
596
+ onPress={onUpload}
597
+ disabled={uploading || isPickingDocument}
598
+ accessibilityRole="button"
599
+ accessibilityLabel={t('fileManagement.uploadPhoto')}
600
+ accessibilityState={{ busy: uploading || isPickingDocument }}
601
+ >
602
+ {(uploading || isPickingDocument) ? (
603
+ <ActivityIndicator size="small" color="#FFFFFF" />
604
+ ) : (
605
+ <>
606
+ <Ionicons name="cloud-upload" size={18} color="#FFFFFF" />
607
+ <Text style={photoPickerStyles.emptyCtaText}>
608
+ {t('fileManagement.uploadPhoto')}
609
+ </Text>
610
+ </>
611
+ )}
612
+ </TouchableOpacity>
613
+ )}
614
+ </View>
615
+ ) : (
616
+ <FlatList
617
+ key={`cols-${columns}`}
618
+ data={photos}
619
+ renderItem={renderItem}
620
+ keyExtractor={keyExtractor}
621
+ numColumns={columns}
622
+ contentContainerStyle={[
623
+ photoPickerStyles.gridContent,
624
+ { paddingTop: contentPaddingTop },
625
+ ]}
626
+ style={photoPickerStyles.grid}
627
+ showsVerticalScrollIndicator={false}
628
+ refreshControl={
629
+ <RefreshControl
630
+ refreshing={refreshing}
631
+ onRefresh={onRefresh}
632
+ tintColor="#FFFFFF"
633
+ colors={[primaryColor]}
634
+ progressViewOffset={contentPaddingTop}
635
+ />
636
+ }
637
+ onEndReached={handleEndReached}
638
+ onEndReachedThreshold={0.4}
639
+ ListFooterComponent={listFooter}
640
+ removeClippedSubviews
641
+ initialNumToRender={Math.max(12, columns * 6)}
642
+ windowSize={9}
643
+ />
644
+ )}
645
+
646
+ {/* Translucent black header. The bottom sheet already sits below
647
+ the status bar, so we do NOT add `insets.top` here — that would
648
+ double-pad. `paddingTop: HANDLE_ZONE` clears the 28dp drag
649
+ handle floating at the top of the sheet. */}
650
+ <View
651
+ style={[
652
+ photoPickerStyles.header,
653
+ { paddingTop: HANDLE_ZONE, minHeight: headerHeight },
654
+ ]}
655
+ >
656
+ <View style={photoPickerStyles.headerRow}>
657
+ <View style={[photoPickerStyles.headerSide, photoPickerStyles.headerSideLeft]}>
658
+ <TouchableOpacity
659
+ onPress={onCancel}
660
+ style={photoPickerStyles.headerCancel}
661
+ accessibilityRole="button"
662
+ accessibilityLabel={t('fileManagement.a11y.cancelPicker')}
663
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
664
+ >
665
+ <Text style={photoPickerStyles.headerCancelText}>
666
+ {t('fileManagement.cancel')}
667
+ </Text>
668
+ </TouchableOpacity>
669
+ </View>
670
+ <View pointerEvents="none">
671
+ <Text style={photoPickerStyles.headerTitle} numberOfLines={1}>
672
+ {t('fileManagement.choosePhoto')}
673
+ </Text>
674
+ </View>
675
+ <View style={[photoPickerStyles.headerSide, photoPickerStyles.headerSideRight]}>
676
+ {multiSelect ? (
677
+ <TouchableOpacity
678
+ onPress={handleConfirm}
679
+ disabled={confirmDisabled}
680
+ style={[
681
+ photoPickerStyles.headerPrimaryPill,
682
+ {
683
+ backgroundColor: confirmDisabled
684
+ ? 'rgba(255,255,255,0.18)'
685
+ : primaryColor,
686
+ opacity: confirmDisabled ? 0.6 : 1,
687
+ },
688
+ ]}
689
+ accessibilityRole="button"
690
+ accessibilityLabel={t('fileManagement.a11y.confirmSelection')}
691
+ accessibilityState={{ disabled: confirmDisabled }}
692
+ >
693
+ <Text style={photoPickerStyles.headerPrimaryText}>
694
+ {confirmLabel}
695
+ </Text>
696
+ </TouchableOpacity>
697
+ ) : (
698
+ isOwner && allowUpload && (
699
+ <TouchableOpacity
700
+ onPress={onUpload}
701
+ disabled={uploading || isPickingDocument}
702
+ style={[
703
+ photoPickerStyles.headerPrimaryPill,
704
+ !showUploadLabel && photoPickerStyles.headerPrimaryPillIconOnly,
705
+ { backgroundColor: primaryColor },
706
+ ]}
707
+ accessibilityRole="button"
708
+ accessibilityLabel={t('fileManagement.a11y.uploadFromDevice')}
709
+ accessibilityState={{ busy: uploading || isPickingDocument }}
710
+ >
711
+ {(uploading || isPickingDocument) ? (
712
+ <ActivityIndicator size="small" color="#FFFFFF" />
713
+ ) : (
714
+ <>
715
+ <Ionicons name="cloud-upload" size={16} color="#FFFFFF" />
716
+ {showUploadLabel && (
717
+ <Text style={photoPickerStyles.headerPrimaryText}>
718
+ {t('fileManagement.upload')}
719
+ </Text>
720
+ )}
721
+ </>
722
+ )}
723
+ </TouchableOpacity>
724
+ )
725
+ )}
726
+ </View>
727
+ </View>
728
+ {/* Subtle top progress bar during upload (non-blocking). */}
729
+ {uploading && (
730
+ <View style={photoPickerStyles.headerProgressBarTrack}>
731
+ <View
732
+ style={[
733
+ photoPickerStyles.headerProgressBarFill,
734
+ {
735
+ width: `${Math.round(progressFraction * 100)}%`,
736
+ backgroundColor: primaryColor,
737
+ },
738
+ ]}
739
+ />
740
+ </View>
741
+ )}
742
+ </View>
743
+ </View>
744
+ );
745
+ };
746
+
114
747
  const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
115
748
  onClose,
116
749
  theme,
@@ -135,9 +768,9 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
135
768
  const { t } = useI18n();
136
769
  const uploadFileMutation = useUploadFile();
137
770
  // Prompt controls
138
- const fileDeletePrompt = usePromptControl();
139
- const bulkDeletePrompt = usePromptControl();
140
- const visibilityChangePrompt = usePromptControl();
771
+ const fileDeleteDialog = useDialogControl();
772
+ const bulkDeleteDialog = useDialogControl();
773
+ const visibilityChangeDialog = useDialogControl();
141
774
  const [pendingDeleteFile, setPendingDeleteFile] = useState<{ id: string; name: string } | null>(null);
142
775
  const files = useFiles();
143
776
  // Ensure containerWidth is a number (TypeScript guard)
@@ -156,11 +789,50 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
156
789
  const [loadingFileContent, setLoadingFileContent] = useState(false);
157
790
  const [showFileDetailsInViewer, setShowFileDetailsInViewer] = useState(false);
158
791
  const [isPickingDocument, setIsPickingDocument] = useState(false);
159
- const [viewMode, setViewMode] = useState<'all' | 'photos' | 'videos' | 'documents' | 'audio'>('all');
792
+ const [reduceMotion, setReduceMotion] = useState(false);
793
+
794
+ // Detect reduce-motion preference once on mount + subscribe to changes.
795
+ // Used by `PhotoPickerView` to skip cell stagger animations.
796
+ useEffect(() => {
797
+ let cancelled = false;
798
+ AccessibilityInfo.isReduceMotionEnabled()
799
+ .then((enabled) => {
800
+ if (!cancelled) setReduceMotion(enabled);
801
+ })
802
+ .catch(() => {
803
+ // Defaults to false; no action needed.
804
+ });
805
+ const sub = AccessibilityInfo.addEventListener('reduceMotionChanged', (enabled) => {
806
+ setReduceMotion(enabled);
807
+ });
808
+ return () => {
809
+ cancelled = true;
810
+ sub.remove();
811
+ };
812
+ }, []);
813
+
814
+ // Image-only picker mode: when the consumer restricts to image MIME types
815
+ // (e.g. avatar picker), photos grid is the more useful default view.
816
+ const isImageOnlyPicker = useMemo(() => {
817
+ if (!selectMode) return false;
818
+ if (disabledMimeTypes.length === 0) return false;
819
+ const blocksVideos = disabledMimeTypes.some(mt => mt === 'video/' || mt.startsWith('video/'));
820
+ const blocksAudio = disabledMimeTypes.some(mt => mt === 'audio/' || mt.startsWith('audio/'));
821
+ const blocksDocs = disabledMimeTypes.some(mt =>
822
+ mt === 'application/pdf' ||
823
+ mt === 'application/' ||
824
+ mt.startsWith('application/')
825
+ );
826
+ return blocksVideos && blocksAudio && blocksDocs;
827
+ }, [disabledMimeTypes, selectMode]);
828
+
829
+ const [viewMode, setViewMode] = useState<'all' | 'photos' | 'videos' | 'documents' | 'audio'>(
830
+ isImageOnlyPicker ? 'photos' : 'all',
831
+ );
160
832
  const [searchQuery, setSearchQuery] = useState('');
161
833
  const [sortBy, setSortBy] = useState<'date' | 'size' | 'name' | 'type'>('date');
162
834
  const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
163
- const [pendingFiles, setPendingFiles] = useState<Array<{ file: File | Blob; preview?: string; size: number; name: string; type: string }>>([]);
835
+ const [pendingFiles, setPendingFiles] = useState<Array<{ file: UploadCandidate; preview?: string; size: number; name: string; type: string }>>([]);
164
836
  const [showUploadPreview, setShowUploadPreview] = useState(false);
165
837
  // Derived filtered and sorted files (avoid setState loops)
166
838
  const filteredFiles = useMemo(() => {
@@ -263,7 +935,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
263
935
  linkContext.entityType,
264
936
  linkContext.entityId,
265
937
  defaultVisibility,
266
- (linkContext as Record<string, unknown>).webhookUrl
938
+ linkContext.webhookUrl
267
939
  );
268
940
  } catch (error) {
269
941
  // Continue anyway - selection shouldn't fail if linking fails
@@ -322,7 +994,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
322
994
  linkContext.entityType,
323
995
  linkContext.entityId,
324
996
  defaultVisibility,
325
- (linkContext as Record<string, unknown>).webhookUrl
997
+ linkContext.webhookUrl
326
998
  );
327
999
  } catch (error) {
328
1000
  // File linking failed, continue with selection
@@ -383,15 +1055,15 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
383
1055
  const currentPaging = mode === 'more' ? (prevPagingRef.current ?? paging) : paging;
384
1056
  const effectiveOffset = mode === 'more' ? currentPaging.offset + currentPaging.limit : 0;
385
1057
  const response = await oxyServices.listUserFiles(currentPaging.limit, effectiveOffset);
386
- const assets: FileMetadata[] = (response.files || []).map((f: Record<string, unknown>) => ({
1058
+ const assets: FileMetadata[] = (response.files || []).map((f: { id: string; originalName?: string; sha256?: string; mime?: string; size?: number; createdAt?: string; metadata?: Record<string, unknown>; variants?: unknown[] }) => ({
387
1059
  id: f.id,
388
- filename: f.originalName || f.sha256,
389
- contentType: f.mime,
390
- length: f.size,
1060
+ filename: f.originalName ?? f.sha256 ?? '',
1061
+ contentType: f.mime ?? '',
1062
+ length: f.size ?? 0,
391
1063
  chunkSize: 0,
392
- uploadDate: f.createdAt,
393
- metadata: f.metadata || {},
394
- variants: f.variants || [],
1064
+ uploadDate: f.createdAt ?? '',
1065
+ metadata: f.metadata ?? {},
1066
+ variants: (f.variants ?? []) as FileMetadata['variants'],
395
1067
  }));
396
1068
  if (mode === 'more') {
397
1069
  // append
@@ -500,16 +1172,16 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
500
1172
  return rows;
501
1173
  }, []);
502
1174
 
503
- const processFileUploads = async (selectedFiles: File[]): Promise<FileMetadata[]> => {
1175
+ const processFileUploads = async (selectedFiles: UploadCandidate[]): Promise<FileMetadata[]> => {
504
1176
  if (selectedFiles.length === 0) return [];
505
1177
  if (!targetUserId) return []; // Guard clause to ensure userId is defined
506
1178
  const uploadedFiles: FileMetadata[] = [];
507
1179
  try {
508
1180
  storeSetUploadProgress({ current: 0, total: selectedFiles.length });
509
1181
  const maxSize = 50 * 1024 * 1024; // 50MB
510
- const oversizedFiles = selectedFiles.filter(file => file.size > maxSize);
1182
+ const oversizedFiles = selectedFiles.filter(file => candidateSize(file) > maxSize);
511
1183
  if (oversizedFiles.length > 0) {
512
- const fileList = oversizedFiles.map(f => f.name).join(', ');
1184
+ const fileList = oversizedFiles.map(f => candidateName(f, 'file')).join(', ');
513
1185
  toast.error(t('fileManagement.toasts.filesTooLarge', { files: fileList }));
514
1186
  return [];
515
1187
  }
@@ -519,12 +1191,14 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
519
1191
  for (let i = 0; i < selectedFiles.length; i++) {
520
1192
  storeSetUploadProgress({ current: i + 1, total: selectedFiles.length });
521
1193
  const raw = selectedFiles[i];
522
- const fileName = raw.name || `file-${i + 1}`;
1194
+ const fileName = candidateName(raw, `file-${i + 1}`);
1195
+ const fileSize = candidateSize(raw);
1196
+ const fileType = candidateType(raw);
523
1197
  const optimisticId = `temp-${Date.now()}-${i}-${Math.random().toString(36).substr(2, 9)}`; // Unique ID per file
524
1198
 
525
1199
  try {
526
1200
  // Validate file before upload
527
- if (!raw || !raw.name || raw.size === undefined || raw.size <= 0) {
1201
+ if (!raw || !fileName || fileSize <= 0) {
528
1202
  const errorMsg = `Invalid file: ${fileName}`;
529
1203
  if (__DEV__) {
530
1204
  console.error('Upload validation failed:', { file: raw, error: errorMsg });
@@ -536,9 +1210,9 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
536
1210
 
537
1211
  const optimisticFile: FileMetadata = {
538
1212
  id: optimisticId,
539
- filename: raw.name,
540
- contentType: raw.type || 'application/octet-stream',
541
- length: raw.size,
1213
+ filename: fileName,
1214
+ contentType: fileType,
1215
+ length: fileSize,
542
1216
  chunkSize: 0,
543
1217
  uploadDate: new Date().toISOString(),
544
1218
  metadata: { uploading: true },
@@ -548,7 +1222,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
548
1222
 
549
1223
  // Use the mutation hook with authentication handling
550
1224
  const result = await uploadFileMutation.mutateAsync({
551
- file: raw,
1225
+ file: raw as AssetUploadInput,
552
1226
  visibility: defaultVisibility,
553
1227
  });
554
1228
 
@@ -557,9 +1231,9 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
557
1231
  if (f) {
558
1232
  const merged: FileMetadata = {
559
1233
  id: f.id,
560
- filename: f.originalName || f.sha256 || raw.name,
561
- contentType: f.mime || raw.type || 'application/octet-stream',
562
- length: f.size || raw.size,
1234
+ filename: f.originalName || f.sha256 || fileName,
1235
+ contentType: f.mime || fileType,
1236
+ length: f.size || fileSize,
563
1237
  chunkSize: 0,
564
1238
  uploadDate: f.createdAt || new Date().toISOString(),
565
1239
  metadata: f.metadata || {},
@@ -581,14 +1255,14 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
581
1255
  }
582
1256
  } catch (error: unknown) {
583
1257
  failureCount++;
584
- const errorMessage = getErrorMessage(error) || String(error) || 'Upload failed';
1258
+ const errorMessage = getErrorMessage(error) || 'Upload failed';
585
1259
  const fullError = `${fileName}: ${errorMessage}`;
586
1260
  errors.push(fullError);
587
1261
  if (__DEV__) {
588
1262
  console.error('File upload failed:', {
589
1263
  fileName,
590
- fileSize: raw.size,
591
- fileType: raw.type,
1264
+ fileSize,
1265
+ fileType,
592
1266
  error: errorMessage,
593
1267
  stack: (error instanceof Error) ? error.stack : undefined
594
1268
  });
@@ -620,10 +1294,9 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
620
1294
  return uploadedFiles;
621
1295
  };
622
1296
 
623
- // biome-ignore lint/suspicious/noExplicitAny: Files from document picker may have extra properties like uri
624
- const handleFileSelection = useCallback(async (selectedFiles: Array<File | any>) => {
1297
+ const handleFileSelection = useCallback(async (selectedFiles: UploadCandidate[]) => {
625
1298
  const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
626
- const processedFiles: Array<{ file: File | Blob; preview?: string; size: number; name: string; type: string }> = [];
1299
+ const processedFiles: Array<{ file: UploadCandidate; preview?: string; size: number; name: string; type: string }> = [];
627
1300
 
628
1301
  for (const file of selectedFiles) {
629
1302
  // Validate file has required properties
@@ -635,7 +1308,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
635
1308
  continue;
636
1309
  }
637
1310
 
638
- if (!file.name || typeof file.name !== 'string') {
1311
+ const name = candidateName(file, '');
1312
+ if (!name) {
639
1313
  if (__DEV__) {
640
1314
  console.error('Invalid file: missing or invalid name property', file);
641
1315
  }
@@ -643,46 +1317,47 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
643
1317
  continue;
644
1318
  }
645
1319
 
646
- if (file.size === undefined || file.size === null || Number.isNaN(file.size)) {
1320
+ const size = (file as { size?: number }).size;
1321
+ if (size === undefined || size === null || Number.isNaN(size)) {
647
1322
  if (__DEV__) {
648
1323
  console.error('Invalid file: missing or invalid size property', file);
649
1324
  }
650
- toast.error(t('fileManagement.toasts.invalidFileSize', { name: file.name || 'unknown' }));
1325
+ toast.error(t('fileManagement.toasts.invalidFileSize', { name }));
651
1326
  continue;
652
1327
  }
653
1328
 
654
- if (file.size <= 0) {
1329
+ if (size <= 0) {
655
1330
  if (__DEV__) {
656
1331
  console.error('Invalid file: file size is zero or negative', file);
657
1332
  }
658
- toast.error(t('fileManagement.toasts.fileEmpty', { name: file.name }));
1333
+ toast.error(t('fileManagement.toasts.fileEmpty', { name }));
659
1334
  continue;
660
1335
  }
661
1336
 
662
1337
  // Validate file size
663
- if (file.size > MAX_FILE_SIZE) {
664
- toast.error(t('fileManagement.toasts.fileTooLarge', { name: file.name, maxSize: formatFileSize(MAX_FILE_SIZE) }));
1338
+ if (size > MAX_FILE_SIZE) {
1339
+ toast.error(t('fileManagement.toasts.fileTooLarge', { name, maxSize: formatFileSize(MAX_FILE_SIZE) }));
665
1340
  continue;
666
1341
  }
667
1342
 
668
- // Ensure file has a type property
669
- const fileType = file.type || 'application/octet-stream';
1343
+ const fileType = candidateType(file);
670
1344
 
671
1345
  // Generate preview for images - unified approach
672
1346
  let preview: string | undefined;
673
1347
  if (fileType.startsWith('image/')) {
674
1348
  // Try to use file URI from expo-document-picker if available (works on all platforms)
675
- const fileUri = (file as File & { uri?: string }).uri;
676
- if (fileUri && typeof fileUri === 'string' &&
1349
+ const fileUri = candidateUri(file);
1350
+ if (fileUri &&
677
1351
  (fileUri.startsWith('file://') || fileUri.startsWith('content://') ||
678
1352
  fileUri.startsWith('http://') || fileUri.startsWith('https://') ||
679
1353
  fileUri.startsWith('blob:'))) {
680
1354
  preview = fileUri;
681
1355
  } else {
682
- // Fallback: create blob URL if possible (works on web)
1356
+ // Fallback: create blob URL if possible (works on web only)
683
1357
  try {
684
- if ((file as object) instanceof File || (file as object) instanceof Blob) {
685
- preview = URL.createObjectURL(file);
1358
+ if ((typeof File !== 'undefined' && file instanceof File) ||
1359
+ (typeof Blob !== 'undefined' && file instanceof Blob)) {
1360
+ preview = URL.createObjectURL(file as Blob);
686
1361
  }
687
1362
  } catch (error: unknown) {
688
1363
  if (__DEV__) {
@@ -696,8 +1371,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
696
1371
  processedFiles.push({
697
1372
  file,
698
1373
  preview,
699
- size: file.size,
700
- name: file.name,
1374
+ size,
1375
+ name,
701
1376
  type: fileType
702
1377
  });
703
1378
  }
@@ -710,7 +1385,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
710
1385
  // Show preview modal for user to review files before upload
711
1386
  setPendingFiles(processedFiles);
712
1387
  setShowUploadPreview(true);
713
- }, []);
1388
+ }, [t]);
714
1389
 
715
1390
  const handleConfirmUpload = async () => {
716
1391
  if (pendingFiles.length === 0) return;
@@ -721,7 +1396,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
721
1396
  storeSetUploadProgress(null);
722
1397
 
723
1398
  try {
724
- const filesToUpload = pendingFiles.map(pf => pf.file as File);
1399
+ const filesToUpload = pendingFiles.map(pf => pf.file);
725
1400
  storeSetUploadProgress({ current: 0, total: filesToUpload.length });
726
1401
  const uploadedFiles = await processFileUploads(filesToUpload);
727
1402
 
@@ -830,17 +1505,17 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
830
1505
  // - size: file size in bytes
831
1506
  // - mimeType: MIME type of the file
832
1507
  // - file: (optional) native File object (usually only on web)
833
- const files: File[] = [];
1508
+ const files: UploadCandidate[] = [];
834
1509
  const errors: string[] = [];
835
1510
 
836
1511
  // Process files in parallel for better performance
837
1512
  // This allows multiple files to be converted simultaneously
838
1513
  const conversionPromises = result.assets.map((doc, index) =>
839
1514
  convertDocumentPickerAssetToFile(doc, index)
840
- .then((file) => {
1515
+ .then((file): UploadCandidate | null => {
841
1516
  if (file) {
842
1517
  // Validate file has required properties before adding
843
- if (!file.name || file.size === undefined) {
1518
+ if (!file.name || (file as { size?: number }).size === undefined) {
844
1519
  errors.push(`File "${doc.name || 'file'}" is invalid: missing required properties`);
845
1520
  return null;
846
1521
  }
@@ -897,8 +1572,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
897
1572
 
898
1573
  const confirmFileDelete = useCallback((fileId: string, filename: string) => {
899
1574
  setPendingDeleteFile({ id: fileId, name: filename });
900
- fileDeletePrompt.open();
901
- }, [fileDeletePrompt]);
1575
+ fileDeleteDialog.open();
1576
+ }, [fileDeleteDialog]);
902
1577
 
903
1578
  const handleFileDelete = useCallback(async () => {
904
1579
  if (!pendingDeleteFile) return;
@@ -935,8 +1610,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
935
1610
 
936
1611
  const confirmBulkDelete = useCallback(() => {
937
1612
  if (selectedIds.size === 0) return;
938
- bulkDeletePrompt.open();
939
- }, [selectedIds.size, bulkDeletePrompt]);
1613
+ bulkDeleteDialog.open();
1614
+ }, [selectedIds.size, bulkDeleteDialog]);
940
1615
 
941
1616
  const handleBulkDelete = useCallback(async () => {
942
1617
  if (selectedIds.size === 0) return;
@@ -1913,6 +2588,59 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
1913
2588
  return <SkeletonLoader />;
1914
2589
  }
1915
2590
 
2591
+ // Dedicated flagship-style photo picker view used in the avatar-picker
2592
+ // context (selectMode + image-only filter). The picker is intentionally
2593
+ // minimal: black backdrop, edge-to-edge grid, translucent header. The
2594
+ // standalone file manager (non-picker browse) keeps the existing UI.
2595
+ if (isImageOnlyPicker && !showUploadPreview) {
2596
+ const photosOnly = filteredFiles.filter(
2597
+ (file) => file.contentType.startsWith('image/'),
2598
+ );
2599
+ const isOwner = user?.id === targetUserId;
2600
+ const allowUpload = isOwner && allowUploadInSelectMode;
2601
+
2602
+ return (
2603
+ <>
2604
+ <PhotoPickerView
2605
+ photos={photosOnly}
2606
+ selectedIds={selectedIds}
2607
+ multiSelect={multiSelect}
2608
+ maxSelection={maxSelection}
2609
+ allowUpload={allowUpload}
2610
+ refreshing={refreshing}
2611
+ uploading={uploading}
2612
+ isPickingDocument={isPickingDocument}
2613
+ uploadProgress={uploadProgress}
2614
+ hasMore={paging.hasMore}
2615
+ loadingMore={paging.loadingMore}
2616
+ reduceMotion={reduceMotion}
2617
+ getThumbUrl={getSafeDownloadUrlCallback}
2618
+ primaryColor={colors.primary}
2619
+ isOwner={isOwner}
2620
+ onTogglePhoto={toggleSelect}
2621
+ onPreviewPhoto={(file) => showFileDetailsModal(file)}
2622
+ onUpload={handleFileUpload}
2623
+ onRefresh={() => loadFiles('refresh')}
2624
+ onLoadMore={() => loadFiles('more')}
2625
+ onCancel={() => {
2626
+ if (onClose) onClose();
2627
+ else goBack?.();
2628
+ }}
2629
+ onConfirm={confirmMultiSelection}
2630
+ t={t}
2631
+ />
2632
+ {/* Long-press preview surfaces the existing details modal. */}
2633
+ <FileDetailsModal
2634
+ control={fileDetailsControl}
2635
+ file={selectedFile}
2636
+ onDownload={handleFileDownload}
2637
+ onDelete={confirmFileDelete}
2638
+ isOwner={isOwner}
2639
+ />
2640
+ </>
2641
+ );
2642
+ }
2643
+
1916
2644
  // If a file is opened, show the file viewer
1917
2645
  if (!selectMode && openedFile) {
1918
2646
  return (
@@ -1997,7 +2725,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
1997
2725
  key: 'visibility',
1998
2726
  text: t('fileManagement.visibility'),
1999
2727
  onPress: () => {
2000
- visibilityChangePrompt.open();
2728
+ visibilityChangeDialog.open();
2001
2729
  },
2002
2730
  icon: 'eye',
2003
2731
  }
@@ -2029,6 +2757,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
2029
2757
  primaryColor={colors.primary}
2030
2758
  textColor={colors.text}
2031
2759
  style={fileManagementStyles.viewModeButton}
2760
+ accessibilityLabel={t('fileManagement.a11y.viewAll') || 'Show all files'}
2032
2761
  />
2033
2762
  <AnimatedButton
2034
2763
  isSelected={viewMode === 'photos'}
@@ -2037,37 +2766,50 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
2037
2766
  primaryColor={colors.primary}
2038
2767
  textColor={colors.text}
2039
2768
  style={fileManagementStyles.viewModeButton}
2769
+ accessibilityLabel={t('fileManagement.a11y.viewPhotos') || 'Show photos only'}
2040
2770
  />
2041
- <AnimatedButton
2042
- isSelected={viewMode === 'videos'}
2043
- onPress={() => setViewMode('videos')}
2044
- icon={viewMode === 'videos' ? 'video' : 'video-outline'}
2045
- primaryColor={colors.primary}
2046
- textColor={colors.text}
2047
- style={fileManagementStyles.viewModeButton}
2048
- />
2049
- <AnimatedButton
2050
- isSelected={viewMode === 'documents'}
2051
- onPress={() => setViewMode('documents')}
2052
- icon={viewMode === 'documents' ? 'file-document' : 'file-document-outline'}
2053
- primaryColor={colors.primary}
2054
- textColor={colors.text}
2055
- style={fileManagementStyles.viewModeButton}
2056
- />
2057
- <AnimatedButton
2058
- isSelected={viewMode === 'audio'}
2059
- onPress={() => setViewMode('audio')}
2060
- icon={viewMode === 'audio' ? 'music-note' : 'music-note-outline'}
2061
- primaryColor={colors.primary}
2062
- textColor={colors.text}
2063
- style={fileManagementStyles.viewModeButton}
2064
- />
2771
+ {!isImageOnlyPicker && (
2772
+ <>
2773
+ <AnimatedButton
2774
+ isSelected={viewMode === 'videos'}
2775
+ onPress={() => setViewMode('videos')}
2776
+ icon={viewMode === 'videos' ? 'video' : 'video-outline'}
2777
+ primaryColor={colors.primary}
2778
+ textColor={colors.text}
2779
+ style={fileManagementStyles.viewModeButton}
2780
+ accessibilityLabel={t('fileManagement.a11y.viewVideos') || 'Show videos only'}
2781
+ />
2782
+ <AnimatedButton
2783
+ isSelected={viewMode === 'documents'}
2784
+ onPress={() => setViewMode('documents')}
2785
+ icon={viewMode === 'documents' ? 'file-document' : 'file-document-outline'}
2786
+ primaryColor={colors.primary}
2787
+ textColor={colors.text}
2788
+ style={fileManagementStyles.viewModeButton}
2789
+ accessibilityLabel={t('fileManagement.a11y.viewDocuments') || 'Show documents only'}
2790
+ />
2791
+ <AnimatedButton
2792
+ isSelected={viewMode === 'audio'}
2793
+ onPress={() => setViewMode('audio')}
2794
+ icon={viewMode === 'audio' ? 'music-note' : 'music-note-outline'}
2795
+ primaryColor={colors.primary}
2796
+ textColor={colors.text}
2797
+ style={fileManagementStyles.viewModeButton}
2798
+ accessibilityLabel={t('fileManagement.a11y.viewAudio') || 'Show audio only'}
2799
+ />
2800
+ </>
2801
+ )}
2065
2802
  </View>
2066
2803
  </ScrollView>
2067
2804
  <TouchableOpacity
2068
2805
  style={[fileManagementStyles.sortButton, {
2069
2806
  backgroundColor: colors.card,
2070
2807
  }]}
2808
+ accessibilityRole="button"
2809
+ accessibilityLabel={t('fileManagement.a11y.sortBy', {
2810
+ field: sortBy,
2811
+ order: sortOrder === 'asc' ? 'ascending' : 'descending',
2812
+ }) || `Sort by ${sortBy}, ${sortOrder === 'asc' ? 'ascending' : 'descending'}`}
2071
2813
  onPress={() => {
2072
2814
  // Cycle through sort options: date -> size -> name -> type -> date
2073
2815
  const sortOrder: Array<'date' | 'size' | 'name' | 'type'> = ['date', 'size', 'name', 'type'];
@@ -2097,9 +2839,20 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
2097
2839
  </TouchableOpacity>
2098
2840
  {user?.id === targetUserId && (!selectMode || (selectMode && allowUploadInSelectMode)) && (
2099
2841
  <TouchableOpacity
2100
- style={[fileManagementStyles.uploadButton, { backgroundColor: colors.primary }]}
2842
+ style={[
2843
+ fileManagementStyles.uploadButton,
2844
+ isImageOnlyPicker && fileManagementStyles.uploadButtonExtended,
2845
+ { backgroundColor: colors.primary },
2846
+ ]}
2101
2847
  onPress={handleFileUpload}
2102
2848
  disabled={uploading || isPickingDocument}
2849
+ accessibilityRole="button"
2850
+ accessibilityLabel={
2851
+ isImageOnlyPicker
2852
+ ? (t('fileManagement.a11y.uploadFromDevice') || 'Upload photo from device')
2853
+ : (t('fileManagement.a11y.uploadFile') || 'Upload file')
2854
+ }
2855
+ accessibilityState={{ busy: uploading || isPickingDocument }}
2103
2856
  >
2104
2857
  {uploading ? (
2105
2858
  <View style={fileManagementStyles.uploadProgress}>
@@ -2112,6 +2865,13 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
2112
2865
  </View>
2113
2866
  ) : isPickingDocument ? (
2114
2867
  <ActivityIndicator size="small" color="#FFFFFF" />
2868
+ ) : isImageOnlyPicker ? (
2869
+ <View style={fileManagementStyles.uploadButtonContent}>
2870
+ <Ionicons name="cloud-upload" size={18} color="#FFFFFF" />
2871
+ <Text style={fileManagementStyles.uploadButtonLabel} numberOfLines={1}>
2872
+ {t('fileManagement.upload') || 'Upload'}
2873
+ </Text>
2874
+ </View>
2115
2875
  ) : (
2116
2876
  <Ionicons name="add" size={22} color="#FFFFFF" />
2117
2877
  )}
@@ -2284,34 +3044,35 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
2284
3044
 
2285
3045
  {/* Selection bar removed; actions are now in header */}
2286
3046
  {/* Global loadingMore bar removed; now inline in scroll areas */}
2287
- <Prompt.Basic
2288
- control={fileDeletePrompt}
3047
+ <Dialog
3048
+ control={fileDeleteDialog}
2289
3049
  title={t('fileManagement.deleteFile') || 'Delete File'}
2290
3050
  description={pendingDeleteFile ? t('fileManagement.confirms.deleteFile', { filename: pendingDeleteFile.name }) : ''}
2291
- onConfirm={handleFileDelete}
2292
- confirmButtonCta={t('fileManagement.confirm') || 'Delete'}
2293
- confirmButtonColor='negative'
3051
+ actions={[
3052
+ { label: t('fileManagement.confirm') || 'Delete', color: 'destructive', onPress: handleFileDelete },
3053
+ { label: t('common.cancel') || 'Cancel', color: 'cancel' },
3054
+ ]}
2294
3055
  />
2295
- <Prompt.Basic
2296
- control={bulkDeletePrompt}
3056
+ <Dialog
3057
+ control={bulkDeleteDialog}
2297
3058
  title={t('fileManagement.deleteFiles') || 'Delete Files'}
2298
3059
  description={t('fileManagement.confirms.deleteFiles', { count: selectedIds.size })}
2299
- onConfirm={handleBulkDelete}
2300
- confirmButtonCta={t('fileManagement.confirm') || 'Delete'}
2301
- confirmButtonColor='negative'
3060
+ actions={[
3061
+ { label: t('fileManagement.confirm') || 'Delete', color: 'destructive', onPress: handleBulkDelete },
3062
+ { label: t('common.cancel') || 'Cancel', color: 'cancel' },
3063
+ ]}
3064
+ />
3065
+ <Dialog
3066
+ control={visibilityChangeDialog}
3067
+ title={t('fileManagement.changeVisibility') || 'Change Visibility'}
3068
+ description={t('fileManagement.changeVisibilityConfirm', { count: selectedIds.size })}
3069
+ actions={[
3070
+ { label: t('fileManagement.private') || 'Private', onPress: () => handleBulkVisibilityChange('private') },
3071
+ { label: t('fileManagement.public') || 'Public', onPress: () => handleBulkVisibilityChange('public') },
3072
+ { label: t('fileManagement.unlisted') || 'Unlisted', onPress: () => handleBulkVisibilityChange('unlisted') },
3073
+ { label: t('common.cancel') || 'Cancel', color: 'cancel' },
3074
+ ]}
2302
3075
  />
2303
- <Prompt.Outer control={visibilityChangePrompt}>
2304
- <Prompt.Content>
2305
- <Prompt.TitleText>{t('fileManagement.changeVisibility') || 'Change Visibility'}</Prompt.TitleText>
2306
- <Prompt.DescriptionText>{t('fileManagement.changeVisibilityConfirm', { count: selectedIds.size })}</Prompt.DescriptionText>
2307
- </Prompt.Content>
2308
- <Prompt.Actions>
2309
- <Prompt.Action cta={t('fileManagement.private') || 'Private'} onPress={() => handleBulkVisibilityChange('private')} color='primary' />
2310
- <Prompt.Action cta={t('fileManagement.public') || 'Public'} onPress={() => handleBulkVisibilityChange('public')} color='primary_subtle' />
2311
- <Prompt.Action cta={t('fileManagement.unlisted') || 'Unlisted'} onPress={() => handleBulkVisibilityChange('unlisted')} color='primary_subtle' />
2312
- <Prompt.Cancel cta={t('common.cancel') || 'Cancel'} />
2313
- </Prompt.Actions>
2314
- </Prompt.Outer>
2315
3076
  </View>
2316
3077
  );
2317
3078
  };