@amityco/react-native-social-uikit 4.1.1-b58e7e9.0 → 4.1.1-bcb7944e.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/README.md +7 -0
  2. package/lib/commonjs/core/assets/icons/post.js +1 -1
  3. package/lib/commonjs/core/assets/icons/post.js.map +1 -1
  4. package/lib/commonjs/core/assets/icons/story.js +1 -1
  5. package/lib/commonjs/core/assets/icons/story.js.map +1 -1
  6. package/lib/commonjs/core/assets/icons/xml.js +69 -1
  7. package/lib/commonjs/core/assets/icons/xml.js.map +1 -1
  8. package/lib/commonjs/core/hooks/usePostByIds.js +38 -0
  9. package/lib/commonjs/core/hooks/usePostByIds.js.map +1 -0
  10. package/lib/commonjs/core/legacy/file.js +145 -62
  11. package/lib/commonjs/core/legacy/file.js.map +1 -1
  12. package/lib/commonjs/core/stores/slices/feedSlice.js +3 -0
  13. package/lib/commonjs/core/stores/slices/feedSlice.js.map +1 -1
  14. package/lib/commonjs/core/stores/slices/globalfeedSlice.js +5 -0
  15. package/lib/commonjs/core/stores/slices/globalfeedSlice.js.map +1 -1
  16. package/lib/commonjs/core/stores/slices/localVideoThumbnailSlice.js +46 -0
  17. package/lib/commonjs/core/stores/slices/localVideoThumbnailSlice.js.map +1 -0
  18. package/lib/commonjs/core/stores/slices/uiSlice.js +5 -1
  19. package/lib/commonjs/core/stores/slices/uiSlice.js.map +1 -1
  20. package/lib/commonjs/core/stores/store/index.js +3 -1
  21. package/lib/commonjs/core/stores/store/index.js.map +1 -1
  22. package/lib/commonjs/social/components/LoadingImage/index.js +76 -14
  23. package/lib/commonjs/social/components/LoadingImage/index.js.map +1 -1
  24. package/lib/commonjs/social/components/LoadingImage/styles.js +12 -3
  25. package/lib/commonjs/social/components/LoadingImage/styles.js.map +1 -1
  26. package/lib/commonjs/social/components/LoadingVideo/index.js +98 -18
  27. package/lib/commonjs/social/components/LoadingVideo/index.js.map +1 -1
  28. package/lib/commonjs/social/components/LoadingVideo/styles.js +18 -5
  29. package/lib/commonjs/social/components/LoadingVideo/styles.js.map +1 -1
  30. package/lib/commonjs/social/components/MediaViewer/MediaViewer.js +266 -0
  31. package/lib/commonjs/social/components/MediaViewer/MediaViewer.js.map +1 -0
  32. package/lib/commonjs/social/components/MediaViewer/index.js +13 -0
  33. package/lib/commonjs/social/components/MediaViewer/index.js.map +1 -0
  34. package/lib/commonjs/social/components/MediaViewer/styles.js +126 -0
  35. package/lib/commonjs/social/components/MediaViewer/styles.js.map +1 -0
  36. package/lib/commonjs/social/components/PostContent/index.js +80 -146
  37. package/lib/commonjs/social/components/PostContent/index.js.map +1 -1
  38. package/lib/commonjs/social/components/SelectedMediaComponent/SelectedMediaComponent.js +239 -0
  39. package/lib/commonjs/social/components/SelectedMediaComponent/SelectedMediaComponent.js.map +1 -0
  40. package/lib/commonjs/social/components/SelectedMediaComponent/index.js +13 -0
  41. package/lib/commonjs/social/components/SelectedMediaComponent/index.js.map +1 -0
  42. package/lib/commonjs/social/components/SelectedMediaComponent/styles.js +43 -0
  43. package/lib/commonjs/social/components/SelectedMediaComponent/styles.js.map +1 -0
  44. package/lib/commonjs/social/components/legacy/LoadingVideo/index.js +17 -6
  45. package/lib/commonjs/social/components/legacy/LoadingVideo/index.js.map +1 -1
  46. package/lib/commonjs/social/constants/index.js +11 -0
  47. package/lib/commonjs/social/constants/index.js.map +1 -0
  48. package/lib/commonjs/social/elements/PostMediaElement/PostMediaElement.js +342 -0
  49. package/lib/commonjs/social/elements/PostMediaElement/PostMediaElement.js.map +1 -0
  50. package/lib/commonjs/social/elements/PostMediaElement/index.js +13 -0
  51. package/lib/commonjs/social/elements/PostMediaElement/index.js.map +1 -0
  52. package/lib/commonjs/social/elements/PostMediaElement/styles.js +124 -0
  53. package/lib/commonjs/social/elements/PostMediaElement/styles.js.map +1 -0
  54. package/lib/commonjs/social/features/community/PendingRequest/components/PendingPostList/PendingPostList.js +11 -5
  55. package/lib/commonjs/social/features/community/PendingRequest/components/PendingPostList/PendingPostList.js.map +1 -1
  56. package/lib/commonjs/social/features/feed/components/NewsFeed/NewsFeed.js +14 -0
  57. package/lib/commonjs/social/features/feed/components/NewsFeed/NewsFeed.js.map +1 -1
  58. package/lib/commonjs/social/features/post/Composer/PostComposer.js +273 -154
  59. package/lib/commonjs/social/features/post/Composer/PostComposer.js.map +1 -1
  60. package/lib/commonjs/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js +17 -7
  61. package/lib/commonjs/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js.map +1 -1
  62. package/lib/commonjs/social/features/post/components/MediaAttachment/MediaAttachment.js +17 -7
  63. package/lib/commonjs/social/features/post/components/MediaAttachment/MediaAttachment.js.map +1 -1
  64. package/lib/commonjs/social/hooks/index.js +11 -0
  65. package/lib/commonjs/social/hooks/index.js.map +1 -1
  66. package/lib/commonjs/social/hooks/useCommunities.js +5 -3
  67. package/lib/commonjs/social/hooks/useCommunities.js.map +1 -1
  68. package/lib/commonjs/social/hooks/useCommunityPermission.js +43 -0
  69. package/lib/commonjs/social/hooks/useCommunityPermission.js.map +1 -0
  70. package/lib/commonjs/social/hooks/useCustomRankingGlobalFeed.js +10 -1
  71. package/lib/commonjs/social/hooks/useCustomRankingGlobalFeed.js.map +1 -1
  72. package/lib/commonjs/social/hooks/useFile.js +11 -0
  73. package/lib/commonjs/social/hooks/useFile.js.map +1 -1
  74. package/lib/commonjs/social/screens/CommunityProfile/components/Header/Header.js +18 -7
  75. package/lib/commonjs/social/screens/CommunityProfile/components/Header/Header.js.map +1 -1
  76. package/lib/commonjs/social/utils/getFrameRatio.js +52 -0
  77. package/lib/commonjs/social/utils/getFrameRatio.js.map +1 -0
  78. package/lib/commonjs/social/utils/getIndicatorConfig.js +59 -0
  79. package/lib/commonjs/social/utils/getIndicatorConfig.js.map +1 -0
  80. package/lib/commonjs/social/utils/mediaAttachments.js +150 -0
  81. package/lib/commonjs/social/utils/mediaAttachments.js.map +1 -0
  82. package/lib/commonjs/social/utils/postChildren.js +72 -0
  83. package/lib/commonjs/social/utils/postChildren.js.map +1 -0
  84. package/lib/module/core/assets/icons/post.js +1 -1
  85. package/lib/module/core/assets/icons/post.js.map +1 -1
  86. package/lib/module/core/assets/icons/story.js +1 -1
  87. package/lib/module/core/assets/icons/story.js.map +1 -1
  88. package/lib/module/core/assets/icons/xml.js +61 -0
  89. package/lib/module/core/assets/icons/xml.js.map +1 -1
  90. package/lib/module/core/hooks/usePostByIds.js +32 -0
  91. package/lib/module/core/hooks/usePostByIds.js.map +1 -0
  92. package/lib/module/core/legacy/file.js +145 -62
  93. package/lib/module/core/legacy/file.js.map +1 -1
  94. package/lib/module/core/stores/slices/feedSlice.js +3 -0
  95. package/lib/module/core/stores/slices/feedSlice.js.map +1 -1
  96. package/lib/module/core/stores/slices/globalfeedSlice.js +5 -0
  97. package/lib/module/core/stores/slices/globalfeedSlice.js.map +1 -1
  98. package/lib/module/core/stores/slices/localVideoThumbnailSlice.js +41 -0
  99. package/lib/module/core/stores/slices/localVideoThumbnailSlice.js.map +1 -0
  100. package/lib/module/core/stores/slices/uiSlice.js +5 -1
  101. package/lib/module/core/stores/slices/uiSlice.js.map +1 -1
  102. package/lib/module/core/stores/store/index.js +3 -1
  103. package/lib/module/core/stores/store/index.js.map +1 -1
  104. package/lib/module/social/components/LoadingImage/index.js +77 -16
  105. package/lib/module/social/components/LoadingImage/index.js.map +1 -1
  106. package/lib/module/social/components/LoadingImage/styles.js +12 -3
  107. package/lib/module/social/components/LoadingImage/styles.js.map +1 -1
  108. package/lib/module/social/components/LoadingVideo/index.js +99 -19
  109. package/lib/module/social/components/LoadingVideo/index.js.map +1 -1
  110. package/lib/module/social/components/LoadingVideo/styles.js +18 -5
  111. package/lib/module/social/components/LoadingVideo/styles.js.map +1 -1
  112. package/lib/module/social/components/MediaViewer/MediaViewer.js +259 -0
  113. package/lib/module/social/components/MediaViewer/MediaViewer.js.map +1 -0
  114. package/lib/module/social/components/MediaViewer/index.js +2 -0
  115. package/lib/module/social/components/MediaViewer/index.js.map +1 -0
  116. package/lib/module/social/components/MediaViewer/styles.js +119 -0
  117. package/lib/module/social/components/MediaViewer/styles.js.map +1 -0
  118. package/lib/module/social/components/PostContent/index.js +82 -148
  119. package/lib/module/social/components/PostContent/index.js.map +1 -1
  120. package/lib/module/social/components/SelectedMediaComponent/SelectedMediaComponent.js +233 -0
  121. package/lib/module/social/components/SelectedMediaComponent/SelectedMediaComponent.js.map +1 -0
  122. package/lib/module/social/components/SelectedMediaComponent/index.js +2 -0
  123. package/lib/module/social/components/SelectedMediaComponent/index.js.map +1 -0
  124. package/lib/module/social/components/SelectedMediaComponent/styles.js +36 -0
  125. package/lib/module/social/components/SelectedMediaComponent/styles.js.map +1 -0
  126. package/lib/module/social/components/legacy/LoadingVideo/index.js +17 -6
  127. package/lib/module/social/components/legacy/LoadingVideo/index.js.map +1 -1
  128. package/lib/module/social/constants/index.js +5 -0
  129. package/lib/module/social/constants/index.js.map +1 -0
  130. package/lib/module/social/elements/PostMediaElement/PostMediaElement.js +335 -0
  131. package/lib/module/social/elements/PostMediaElement/PostMediaElement.js.map +1 -0
  132. package/lib/module/social/elements/PostMediaElement/index.js +2 -0
  133. package/lib/module/social/elements/PostMediaElement/index.js.map +1 -0
  134. package/lib/module/social/elements/PostMediaElement/styles.js +117 -0
  135. package/lib/module/social/elements/PostMediaElement/styles.js.map +1 -0
  136. package/lib/module/social/features/community/PendingRequest/components/PendingPostList/PendingPostList.js +12 -6
  137. package/lib/module/social/features/community/PendingRequest/components/PendingPostList/PendingPostList.js.map +1 -1
  138. package/lib/module/social/features/feed/components/NewsFeed/NewsFeed.js +15 -1
  139. package/lib/module/social/features/feed/components/NewsFeed/NewsFeed.js.map +1 -1
  140. package/lib/module/social/features/post/Composer/PostComposer.js +278 -160
  141. package/lib/module/social/features/post/Composer/PostComposer.js.map +1 -1
  142. package/lib/module/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js +17 -7
  143. package/lib/module/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js.map +1 -1
  144. package/lib/module/social/features/post/components/MediaAttachment/MediaAttachment.js +17 -7
  145. package/lib/module/social/features/post/components/MediaAttachment/MediaAttachment.js.map +1 -1
  146. package/lib/module/social/hooks/index.js +1 -0
  147. package/lib/module/social/hooks/index.js.map +1 -1
  148. package/lib/module/social/hooks/useCommunities.js +5 -3
  149. package/lib/module/social/hooks/useCommunities.js.map +1 -1
  150. package/lib/module/social/hooks/useCommunityPermission.js +37 -0
  151. package/lib/module/social/hooks/useCommunityPermission.js.map +1 -0
  152. package/lib/module/social/hooks/useCustomRankingGlobalFeed.js +10 -1
  153. package/lib/module/social/hooks/useCustomRankingGlobalFeed.js.map +1 -1
  154. package/lib/module/social/hooks/useFile.js +11 -0
  155. package/lib/module/social/hooks/useFile.js.map +1 -1
  156. package/lib/module/social/screens/CommunityProfile/components/Header/Header.js +19 -8
  157. package/lib/module/social/screens/CommunityProfile/components/Header/Header.js.map +1 -1
  158. package/lib/module/social/utils/getFrameRatio.js +44 -0
  159. package/lib/module/social/utils/getFrameRatio.js.map +1 -0
  160. package/lib/module/social/utils/getIndicatorConfig.js +53 -0
  161. package/lib/module/social/utils/getIndicatorConfig.js.map +1 -0
  162. package/lib/module/social/utils/mediaAttachments.js +139 -0
  163. package/lib/module/social/utils/mediaAttachments.js.map +1 -0
  164. package/lib/module/social/utils/postChildren.js +66 -0
  165. package/lib/module/social/utils/postChildren.js.map +1 -0
  166. package/lib/typescript/core/assets/icons/xml.d.ts +8 -0
  167. package/lib/typescript/core/assets/icons/xml.d.ts.map +1 -1
  168. package/lib/typescript/core/hooks/usePostByIds.d.ts +8 -0
  169. package/lib/typescript/core/hooks/usePostByIds.d.ts.map +1 -0
  170. package/lib/typescript/core/legacy/file.d.ts +32 -0
  171. package/lib/typescript/core/legacy/file.d.ts.map +1 -1
  172. package/lib/typescript/core/stores/slices/feedSlice.d.ts.map +1 -1
  173. package/lib/typescript/core/stores/slices/globalfeedSlice.d.ts.map +1 -1
  174. package/lib/typescript/core/stores/slices/localVideoThumbnailSlice.d.ts +35 -0
  175. package/lib/typescript/core/stores/slices/localVideoThumbnailSlice.d.ts.map +1 -0
  176. package/lib/typescript/core/stores/slices/uiSlice.d.ts +5 -0
  177. package/lib/typescript/core/stores/slices/uiSlice.d.ts.map +1 -1
  178. package/lib/typescript/core/stores/store/index.d.ts.map +1 -1
  179. package/lib/typescript/core/types/mention.d.ts +34 -0
  180. package/lib/typescript/core/types/mention.d.ts.map +1 -1
  181. package/lib/typescript/social/components/LoadingImage/index.d.ts +9 -2
  182. package/lib/typescript/social/components/LoadingImage/index.d.ts.map +1 -1
  183. package/lib/typescript/social/components/LoadingImage/styles.d.ts +4 -0
  184. package/lib/typescript/social/components/LoadingImage/styles.d.ts.map +1 -1
  185. package/lib/typescript/social/components/LoadingVideo/index.d.ts +10 -2
  186. package/lib/typescript/social/components/LoadingVideo/index.d.ts.map +1 -1
  187. package/lib/typescript/social/components/LoadingVideo/styles.d.ts +5 -0
  188. package/lib/typescript/social/components/LoadingVideo/styles.d.ts.map +1 -1
  189. package/lib/typescript/social/components/MediaViewer/MediaViewer.d.ts +17 -0
  190. package/lib/typescript/social/components/MediaViewer/MediaViewer.d.ts.map +1 -0
  191. package/lib/typescript/social/components/MediaViewer/index.d.ts +3 -0
  192. package/lib/typescript/social/components/MediaViewer/index.d.ts.map +1 -0
  193. package/lib/typescript/social/components/MediaViewer/styles.d.ts +100 -0
  194. package/lib/typescript/social/components/MediaViewer/styles.d.ts.map +1 -0
  195. package/lib/typescript/social/components/PostContent/index.d.ts.map +1 -1
  196. package/lib/typescript/social/components/SelectedMediaComponent/SelectedMediaComponent.d.ts +12 -0
  197. package/lib/typescript/social/components/SelectedMediaComponent/SelectedMediaComponent.d.ts.map +1 -0
  198. package/lib/typescript/social/components/SelectedMediaComponent/index.d.ts +3 -0
  199. package/lib/typescript/social/components/SelectedMediaComponent/index.d.ts.map +1 -0
  200. package/lib/typescript/social/components/SelectedMediaComponent/styles.d.ts +25 -0
  201. package/lib/typescript/social/components/SelectedMediaComponent/styles.d.ts.map +1 -0
  202. package/lib/typescript/social/components/legacy/LoadingVideo/index.d.ts.map +1 -1
  203. package/lib/typescript/social/constants/index.d.ts +4 -0
  204. package/lib/typescript/social/constants/index.d.ts.map +1 -0
  205. package/lib/typescript/social/elements/PostMediaElement/PostMediaElement.d.ts +15 -0
  206. package/lib/typescript/social/elements/PostMediaElement/PostMediaElement.d.ts.map +1 -0
  207. package/lib/typescript/social/elements/PostMediaElement/index.d.ts +3 -0
  208. package/lib/typescript/social/elements/PostMediaElement/index.d.ts.map +1 -0
  209. package/lib/typescript/social/elements/PostMediaElement/styles.d.ts +92 -0
  210. package/lib/typescript/social/elements/PostMediaElement/styles.d.ts.map +1 -0
  211. package/lib/typescript/social/features/community/PendingRequest/components/PendingPostList/PendingPostList.d.ts.map +1 -1
  212. package/lib/typescript/social/features/feed/components/NewsFeed/NewsFeed.d.ts.map +1 -1
  213. package/lib/typescript/social/features/post/Composer/PostComposer.d.ts.map +1 -1
  214. package/lib/typescript/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.d.ts +3 -0
  215. package/lib/typescript/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.d.ts.map +1 -1
  216. package/lib/typescript/social/features/post/components/MediaAttachment/MediaAttachment.d.ts +3 -0
  217. package/lib/typescript/social/features/post/components/MediaAttachment/MediaAttachment.d.ts.map +1 -1
  218. package/lib/typescript/social/hooks/index.d.ts +1 -0
  219. package/lib/typescript/social/hooks/index.d.ts.map +1 -1
  220. package/lib/typescript/social/hooks/useCommunities.d.ts +2 -1
  221. package/lib/typescript/social/hooks/useCommunities.d.ts.map +1 -1
  222. package/lib/typescript/social/hooks/useCommunityPermission.d.ts +14 -0
  223. package/lib/typescript/social/hooks/useCommunityPermission.d.ts.map +1 -0
  224. package/lib/typescript/social/hooks/useCustomRankingGlobalFeed.d.ts.map +1 -1
  225. package/lib/typescript/social/hooks/useFile.d.ts +11 -0
  226. package/lib/typescript/social/hooks/useFile.d.ts.map +1 -1
  227. package/lib/typescript/social/screens/CommunityProfile/components/Header/Header.d.ts.map +1 -1
  228. package/lib/typescript/social/utils/getFrameRatio.d.ts +21 -0
  229. package/lib/typescript/social/utils/getFrameRatio.d.ts.map +1 -0
  230. package/lib/typescript/social/utils/getIndicatorConfig.d.ts +11 -0
  231. package/lib/typescript/social/utils/getIndicatorConfig.d.ts.map +1 -0
  232. package/lib/typescript/social/utils/mediaAttachments.d.ts +91 -0
  233. package/lib/typescript/social/utils/mediaAttachments.d.ts.map +1 -0
  234. package/lib/typescript/social/utils/postChildren.d.ts +38 -0
  235. package/lib/typescript/social/utils/postChildren.d.ts.map +1 -0
  236. package/package.json +3 -3
  237. package/src/core/assets/icons/post.tsx +1 -1
  238. package/src/core/assets/icons/story.tsx +1 -1
  239. package/src/core/assets/icons/xml.ts +75 -0
  240. package/src/core/hooks/usePostByIds.ts +33 -0
  241. package/src/core/legacy/file.tsx +169 -84
  242. package/src/core/stores/slices/feedSlice.ts +3 -0
  243. package/src/core/stores/slices/globalfeedSlice.ts +5 -0
  244. package/src/core/stores/slices/localVideoThumbnailSlice.ts +58 -0
  245. package/src/core/stores/slices/uiSlice.ts +8 -0
  246. package/src/core/stores/store/index.ts +2 -0
  247. package/src/core/types/mention.ts +34 -0
  248. package/src/social/components/LoadingImage/index.tsx +93 -14
  249. package/src/social/components/LoadingImage/styles.ts +12 -3
  250. package/src/social/components/LoadingVideo/index.tsx +135 -21
  251. package/src/social/components/LoadingVideo/styles.ts +17 -4
  252. package/src/social/components/MediaViewer/MediaViewer.tsx +383 -0
  253. package/src/social/components/MediaViewer/index.tsx +2 -0
  254. package/src/social/components/MediaViewer/styles.ts +117 -0
  255. package/src/social/components/PostContent/index.tsx +86 -191
  256. package/src/social/components/SelectedMediaComponent/SelectedMediaComponent.tsx +292 -0
  257. package/src/social/components/SelectedMediaComponent/index.ts +2 -0
  258. package/src/social/components/SelectedMediaComponent/styles.ts +38 -0
  259. package/src/social/components/legacy/LoadingVideo/index.tsx +26 -15
  260. package/src/social/constants/index.ts +4 -0
  261. package/src/social/elements/PostMediaElement/PostMediaElement.tsx +428 -0
  262. package/src/social/elements/PostMediaElement/index.tsx +5 -0
  263. package/src/social/elements/PostMediaElement/styles.ts +106 -0
  264. package/src/social/features/community/PendingRequest/components/PendingPostList/PendingPostList.tsx +11 -6
  265. package/src/social/features/feed/components/NewsFeed/NewsFeed.tsx +16 -1
  266. package/src/social/features/post/Composer/PostComposer.tsx +366 -183
  267. package/src/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.tsx +10 -3
  268. package/src/social/features/post/components/MediaAttachment/MediaAttachment.tsx +14 -3
  269. package/src/social/hooks/index.ts +1 -0
  270. package/src/social/hooks/useCommunities.ts +4 -2
  271. package/src/social/hooks/useCommunityPermission.ts +40 -0
  272. package/src/social/hooks/useCustomRankingGlobalFeed.ts +8 -1
  273. package/src/social/hooks/useFile.ts +11 -0
  274. package/src/social/screens/CommunityProfile/components/Header/Header.tsx +19 -10
  275. package/src/social/utils/getFrameRatio.ts +42 -0
  276. package/src/social/utils/getIndicatorConfig.ts +62 -0
  277. package/src/social/utils/mediaAttachments.ts +158 -0
  278. package/src/social/utils/postChildren.ts +85 -0
@@ -13,6 +13,7 @@ var _types = require("../../../types");
13
13
  var _CloseButtonIconElement = _interopRequireDefault(require("../../../elements/CloseButtonIconElement/CloseButtonIconElement"));
14
14
  var _native = require("@react-navigation/native");
15
15
  var _uiSlice = _interopRequireDefault(require("../../../../core/stores/slices/uiSlice"));
16
+ var _localVideoThumbnailSlice = _interopRequireDefault(require("../../../../core/stores/slices/localVideoThumbnailSlice"));
16
17
  var _post = require("../../../../core/utils/post");
17
18
  var _useAuth = _interopRequireDefault(require("../../../../core/hooks/useAuth"));
18
19
  var _globalfeedSlice = _interopRequireDefault(require("../../../../core/stores/slices/globalfeedSlice"));
@@ -21,11 +22,11 @@ var _TextKeyElement = _interopRequireDefault(require("../../../elements/TextKeyE
21
22
  var _MediaAttachment = _interopRequireDefault(require("../components/MediaAttachment"));
22
23
  var _DetailedMediaAttachment = _interopRequireDefault(require("../components/DetailedMediaAttachment"));
23
24
  var _reactNativeImagePicker = require("react-native-image-picker");
24
- var _LoadingImage = _interopRequireDefault(require("../../../components/LoadingImage"));
25
- var _LoadingVideo = _interopRequireDefault(require("../../../components/LoadingVideo"));
25
+ var _SelectedMediaComponent = require("../../../components/SelectedMediaComponent");
26
26
  var _tsSdkReactNative = require("@amityco/ts-sdk-react-native");
27
27
  var _useMention = _interopRequireDefault(require("../../../hooks/useMention"));
28
28
  var _errors = require("../../../utils/errors");
29
+ var _mediaAttachments = require("../../../utils/mediaAttachments");
29
30
  var _constants = require("../../../../core/constants");
30
31
  var _reactNativeControlledMentions = require("react-native-controlled-mentions");
31
32
  var _store = require("../../../../core/stores/store");
@@ -39,7 +40,7 @@ const AmityPostComposerPage = ({
39
40
  community,
40
41
  post
41
42
  }) => {
42
- var _post$data;
43
+ var _post$data, _post$children;
43
44
  (0, _hooks.useRequestPermission)({
44
45
  onRequestPermissionFailed: () => {
45
46
  _reactNative.Linking.openSettings();
@@ -58,9 +59,6 @@ const AmityPostComposerPage = ({
58
59
  pageId
59
60
  });
60
61
  const styles = (0, _styles.useStyles)(themeStyles);
61
- const {
62
- getImage
63
- } = (0, _hooks.useFile)();
64
62
  const isEditMode = mode === _types.AmityPostComposerMode.EDIT;
65
63
  const navigation = (0, _native.useNavigation)();
66
64
  const {
@@ -81,6 +79,9 @@ const AmityPostComposerPage = ({
81
79
  showToastMessage,
82
80
  hideToastMessage
83
81
  } = _uiSlice.default.actions;
82
+ const {
83
+ setLocalVideoThumbnails
84
+ } = _localVideoThumbnailSlice.default.actions;
84
85
  const [inputMessage, setInputMessage] = (0, _react.useState)((post === null || post === void 0 || (_post$data = post.data) === null || _post$data === void 0 ? void 0 : _post$data.text) ?? '');
85
86
  const [mentionsPosition, setMentionsPosition] = (0, _react.useState)([]);
86
87
  const [chosenMediaType, setChosenMediaType] = (0, _react.useState)(null);
@@ -89,7 +90,14 @@ const AmityPostComposerPage = ({
89
90
  const [mentionUsers, setMentionUsers] = (0, _react.useState)([]);
90
91
  const [isSwipeup, setIsSwipeup] = (0, _react.useState)(true);
91
92
  const [deletedPostIds, setDeletedPostIds] = (0, _react.useState)([]);
92
- const [isUploading, setIsUploading] = (0, _react.useState)(false);
93
+ // Upload progress is tracked per media item, keyed by the item's `source`
94
+ // url — the same shape as `imageErrors`/`videoErrors` below. A
95
+ // single shared boolean was flipped back to false by whichever upload
96
+ // finished first, so Post/Save unlocked while the remaining frames were
97
+ // still in flight. Sources are unique across images and videos, so one set
98
+ // covers both attachment types.
99
+ const [uploadingSources, setUploadingSources] = (0, _react.useState)(new Set());
100
+ const isUploading = uploadingSources.size > 0;
93
101
  const [hasChangedAttachment, setHasChangedAttachment] = (0, _react.useState)(false);
94
102
  const [imageErrors, setImageErrors] = (0, _react.useState)(new Set());
95
103
  const [videoErrors, setVideoErrors] = (0, _react.useState)(new Set());
@@ -116,7 +124,7 @@ const AmityPostComposerPage = ({
116
124
  const effectiveCommunity = community ?? fetchedCommunity;
117
125
  const privateCommunityId = !(effectiveCommunity !== null && effectiveCommunity !== void 0 && effectiveCommunity.isPublic) && (effectiveCommunity === null || effectiveCommunity === void 0 ? void 0 : effectiveCommunity.communityId);
118
126
  const title = isEditMode ? 'Edit Post' : (effectiveCommunity === null || effectiveCommunity === void 0 ? void 0 : effectiveCommunity.displayName) ?? 'My Timeline';
119
- const isInputValid = !isUploading && imageErrors.size === 0 && videoErrors.size === 0 && inputMessage.trim().length <= _constants.MAXIMUM_POST_CHARACTERS && (inputMessage.trim().length > 0 || displayImages.length > 0 || displayVideos.length > 0) && (displayImages.length <= 10 || displayVideos.length <= 10);
127
+ const isInputValid = !isUploading && imageErrors.size === 0 && videoErrors.size === 0 && inputMessage.trim().length <= _constants.MAXIMUM_POST_CHARACTERS && (inputMessage.trim().length > 0 || displayImages.length > 0 || displayVideos.length > 0) && (displayImages.length <= _mediaAttachments.MAX_MEDIA_ATTACHMENTS || displayVideos.length <= _mediaAttachments.MAX_MEDIA_ATTACHMENTS);
120
128
  const {
121
129
  renderInput,
122
130
  renderSuggestions
@@ -137,8 +145,26 @@ const AmityPostComposerPage = ({
137
145
  }]);
138
146
  }
139
147
  });
148
+
149
+ // The edited post carries its own hydrated children: every post payload
150
+ // ingests `postChildren` into the `post` cache (PAYLOAD2MODEL maps it to
151
+ // 'post'), and postLinkedObject reads them straight back out. So the media is
152
+ // known on the first frame, with no fetch — no second source to reconcile.
153
+ const editChildren = (post === null || post === void 0 ? void 0 : post.childrenPosts) ?? [];
154
+
155
+ // `childrenPosts` drops cache misses silently (postLinkedObject filters with
156
+ // isNonNullable), so a short array means we cannot see every child. There is
157
+ // no fallback fetch behind it, so treat that state as read-only: no
158
+ // attachment bar, no Save.
159
+ const editChildrenIncomplete = isEditMode && editChildren.length !== ((post === null || post === void 0 || (_post$children = post.children) === null || _post$children === void 0 ? void 0 : _post$children.length) ?? 0);
140
160
  const checkIsEditValid = () => {
141
161
  var _post$data2;
162
+ // `type` in onPressPost is derived from displayImages/displayVideos, so
163
+ // saving while a child is missing submits it as removed — `attachments: []`
164
+ // and type 'text' strips the post's media outright. Nothing the user can do
165
+ // in the composer makes an unrendered child safe to save, so key this on
166
+ // completeness alone rather than on hasChangedAttachment.
167
+ if (editChildrenIncomplete) return false;
142
168
  return isInputValid && (inputMessage !== (post === null || post === void 0 || (_post$data2 = post.data) === null || _post$data2 === void 0 ? void 0 : _post$data2.text) || hasChangedAttachment);
143
169
  };
144
170
  const parsePostText = (0, _react.useCallback)((text, mentionUsersArr) => {
@@ -149,50 +175,82 @@ const AmityPostComposerPage = ({
149
175
  });
150
176
  return parsedText;
151
177
  }, []);
152
- const getPostInfo = (0, _react.useCallback)(async postArray => {
178
+
179
+ // A child post's file is usually already in the SDK cache, where the linked
180
+ // object exposes it synchronously (getImageInfo / getVideoInfo /
181
+ // getVideoThumbnailInfo are `pullFromCache(['file','get', …])` over the very
182
+ // ids we'd otherwise refetch). Use the cached `fileUrl` when it's there and
183
+ // fall back to the round trip on a cache miss. `fileUrlWithSize` is just
184
+ // `?size=`, so both branches produce the same url.
185
+ const resolveFileUrl = (0, _react.useCallback)(async (fileUrl, fileId) => {
186
+ var _file$data;
187
+ if (fileUrl) return _tsSdkReactNative.FileRepository.fileUrlWithSize(fileUrl, _enums.ImageSizeState.full);
188
+ if (!fileId) return undefined;
189
+
190
+ // Resolve the file directly rather than through useFile: that hook
191
+ // answers a miss with the default *avatar* image, which is right for a
192
+ // profile picture and wrong for post media. A video whose thumbnail the
193
+ // server has not produced yet has no file to resolve, and handing back an
194
+ // avatar made the carousel render a person icon behind the play button as
195
+ // though it were the real frame — and, because the url looked valid, it
196
+ // was also stored as the local thumbnail the feed falls back on.
197
+ const file = await _tsSdkReactNative.FileRepository.getFile(fileId);
198
+ const resolved = file === null || file === void 0 || (_file$data = file.data) === null || _file$data === void 0 ? void 0 : _file$data.fileUrl;
199
+ return resolved ? _tsSdkReactNative.FileRepository.fileUrlWithSize(resolved, _enums.ImageSizeState.full) : undefined;
200
+ }, []);
201
+ const getPostInfo = (0, _react.useCallback)(async response => {
153
202
  try {
154
- const response = await Promise.all(postArray.map(async id => {
155
- const {
156
- data
157
- } = await (0, _feed.getPostById)(id);
158
- return data;
159
- }));
160
203
  const images = [];
161
204
  const videos = [];
162
205
  for (const item of response) {
163
206
  if ((item === null || item === void 0 ? void 0 : item.dataType) === 'image') {
164
- var _item$data;
165
- const fileId = item === null || item === void 0 || (_item$data = item.data) === null || _item$data === void 0 ? void 0 : _item$data.fileId;
166
- const url = await getImage({
167
- fileId: fileId,
168
- imageSize: _enums.ImageSizeState.full
169
- });
207
+ var _data, _item$getImageInfo, _imageInfo$getWidth, _imageInfo$getHeight;
208
+ const fileId = item === null || item === void 0 || (_data = item.data) === null || _data === void 0 ? void 0 : _data.fileId;
209
+ // Dimensions for composer frame-ratio classification (REQ-003d).
210
+ const imageInfo = item === null || item === void 0 || (_item$getImageInfo = item.getImageInfo) === null || _item$getImageInfo === void 0 ? void 0 : _item$getImageInfo.call(item);
211
+ const url = await resolveFileUrl(imageInfo === null || imageInfo === void 0 ? void 0 : imageInfo.fileUrl, fileId);
170
212
  images.push({
171
213
  url,
172
214
  fileId,
173
215
  fileName: fileId,
216
+ // A hydrated child has no local pick behind it, so its identity
217
+ // is the file it already is. Unique per child, stable for the
218
+ // whole session, and never equal to a picker file name — so a
219
+ // later pick is de-duplicated against the other staged picks
220
+ // only, which is the most the picker can tell us.
221
+ localId: fileId ?? item.postId,
174
222
  isUploaded: true,
175
- postId: item.postId
223
+ postId: item.postId,
224
+ width: imageInfo === null || imageInfo === void 0 || (_imageInfo$getWidth = imageInfo.getWidth) === null || _imageInfo$getWidth === void 0 ? void 0 : _imageInfo$getWidth.call(imageInfo),
225
+ height: imageInfo === null || imageInfo === void 0 || (_imageInfo$getHeight = imageInfo.getHeight) === null || _imageInfo$getHeight === void 0 ? void 0 : _imageInfo$getHeight.call(imageInfo)
176
226
  });
177
227
  } else if ((item === null || item === void 0 ? void 0 : item.dataType) === 'video') {
178
- var _item$data2, _item$data3, _fileUrls$, _fileUrls$2;
179
- const fileId = item === null || item === void 0 || (_item$data2 = item.data) === null || _item$data2 === void 0 || (_item$data2 = _item$data2.videoFileId) === null || _item$data2 === void 0 ? void 0 : _item$data2.original;
180
- const thumbnailFileId = item === null || item === void 0 || (_item$data3 = item.data) === null || _item$data3 === void 0 ? void 0 : _item$data3.thumbnailFileId;
181
- const fileUrls = await Promise.allSettled([fileId, thumbnailFileId].map(async id => {
182
- return await getImage({
183
- fileId: id,
184
- imageSize: _enums.ImageSizeState.full
185
- });
186
- }));
228
+ var _videoData$videoFileI, _item$getVideoInfo, _item$getVideoThumbna, _videoInfo$getWidth, _videoInfo$getHeight, _videoInfo$getRotatio;
229
+ const videoData = item === null || item === void 0 ? void 0 : item.data;
230
+ const fileId = videoData === null || videoData === void 0 || (_videoData$videoFileI = videoData.videoFileId) === null || _videoData$videoFileI === void 0 ? void 0 : _videoData$videoFileI.original;
231
+ const thumbnailFileId = videoData === null || videoData === void 0 ? void 0 : videoData.thumbnailFileId;
232
+ // STORED dims + rotation; rotation is applied at classify time
233
+ // (SelectedMediaComponent REQ-003d1 / AmityVideo REQ-SDK-002).
234
+ const videoInfo = item === null || item === void 0 || (_item$getVideoInfo = item.getVideoInfo) === null || _item$getVideoInfo === void 0 ? void 0 : _item$getVideoInfo.call(item);
235
+ const thumbnailInfo = item === null || item === void 0 || (_item$getVideoThumbna = item.getVideoThumbnailInfo) === null || _item$getVideoThumbna === void 0 ? void 0 : _item$getVideoThumbna.call(item);
236
+ // Settle the two urls independently: a missing or unreachable
237
+ // thumbnail must not cost us the video itself. `Promise.all` would
238
+ // reject the pair, abort this loop, and leave displayVideos empty
239
+ // — which now also keeps Save disabled (see checkIsEditValid).
240
+ const [urlResult, thumbNailResult] = await Promise.allSettled([resolveFileUrl(videoInfo === null || videoInfo === void 0 ? void 0 : videoInfo.fileUrl, fileId), resolveFileUrl(thumbnailInfo === null || thumbnailInfo === void 0 ? void 0 : thumbnailInfo.fileUrl, thumbnailFileId)]);
241
+ const url = urlResult.status === 'fulfilled' ? urlResult.value : undefined;
242
+ const thumbNail = thumbNailResult.status === 'fulfilled' ? thumbNailResult.value : undefined;
187
243
  videos.push({
188
- //@ts-ignore
189
- url: (_fileUrls$ = fileUrls[0]) === null || _fileUrls$ === void 0 ? void 0 : _fileUrls$.value,
244
+ url,
190
245
  fileId: fileId,
191
246
  fileName: fileId,
247
+ localId: fileId ?? item.postId,
192
248
  isUploaded: true,
193
- //@ts-ignore
194
- thumbNail: (_fileUrls$2 = fileUrls[1]) === null || _fileUrls$2 === void 0 ? void 0 : _fileUrls$2.value,
195
- postId: item.postId
249
+ thumbNail,
250
+ postId: item.postId,
251
+ width: videoInfo === null || videoInfo === void 0 || (_videoInfo$getWidth = videoInfo.getWidth) === null || _videoInfo$getWidth === void 0 ? void 0 : _videoInfo$getWidth.call(videoInfo),
252
+ height: videoInfo === null || videoInfo === void 0 || (_videoInfo$getHeight = videoInfo.getHeight) === null || _videoInfo$getHeight === void 0 ? void 0 : _videoInfo$getHeight.call(videoInfo),
253
+ rotation: videoInfo === null || videoInfo === void 0 || (_videoInfo$getRotatio = videoInfo.getRotation) === null || _videoInfo$getRotatio === void 0 ? void 0 : _videoInfo$getRotatio.call(videoInfo)
196
254
  });
197
255
  }
198
256
  }
@@ -205,14 +263,36 @@ const AmityPostComposerPage = ({
205
263
  } catch (error) {
206
264
  console.log('error: ', error);
207
265
  }
208
- }, [getImage]);
266
+ }, [resolveFileUrl]);
209
267
  (0, _react.useEffect)(() => {
210
268
  setDeletedPostIds([]);
211
269
  return () => setDeletedPostIds([]);
212
270
  }, []);
271
+
272
+ // `post` comes from route params, so `editChildren` is reference-stable and
273
+ // this hydrates once. The hasChangedAttachment guard is belt-and-braces:
274
+ // getPostInfo assigns displayImages/displayVideos wholesale, so a re-run must
275
+ // never be able to wipe media the user added.
213
276
  (0, _react.useEffect)(() => {
214
- (post === null || post === void 0 ? void 0 : post.children) && getPostInfo(post === null || post === void 0 ? void 0 : post.children);
215
- }, [getPostInfo, post === null || post === void 0 ? void 0 : post.children]);
277
+ if (editChildren.length === 0 || hasChangedAttachment) return;
278
+ getPostInfo(editChildren);
279
+ }, [getPostInfo, post === null || post === void 0 ? void 0 : post.childrenPosts, hasChangedAttachment]);
280
+
281
+ // Media type of the post being edited, read off the children's dataType —
282
+ // the same signal the web UIKit feeds into useMediaAttachmentVisible.
283
+ const editMediaType = (0, _react.useMemo)(() => {
284
+ if (editChildren.some(item => (item === null || item === void 0 ? void 0 : item.dataType) === 'image')) return _enums.mediaAttachment.image;
285
+ if (editChildren.some(item => (item === null || item === void 0 ? void 0 : item.dataType) === 'video')) return _enums.mediaAttachment.video;
286
+ return null;
287
+ }, [post === null || post === void 0 ? void 0 : post.childrenPosts]);
288
+
289
+ // The post's single media type, as every media entry point must see it: the
290
+ // staged attachments when there are any, otherwise the type the edited post
291
+ // already has. Read the display arrays rather than `chosenMediaType`, which
292
+ // is assigned in an effect and so trails them by a render. Once the user has
293
+ // cleared the attachments itself the post has no type again and all three
294
+ // buttons come back, matching web.
295
+ const activeMediaType = displayImages.length > 0 ? _enums.mediaAttachment.image : displayVideos.length > 0 ? _enums.mediaAttachment.video : hasChangedAttachment ? null : editMediaType;
216
296
  const getMentionPositions = (0, _react.useCallback)((text, mentioneeIds) => {
217
297
  let index = 0;
218
298
  let mentions = [];
@@ -326,6 +406,21 @@ const AmityPostComposerPage = ({
326
406
  return;
327
407
  }
328
408
  dispatch(hideToastMessage());
409
+ // The server has no thumbnail for these videos until it finishes
410
+ // transcoding, so hand the feed the frames the composer already decoded
411
+ // to bridge that window (PDT-4904, web parity: LayoutProvider
412
+ // videoThumbnail). Keyed by the uploaded original video's fileId, which
413
+ // is what the created post exposes as `data.videoFileId.original`.
414
+ if (type === 'video' && displayVideos.length > 0) {
415
+ dispatch(setLocalVideoThumbnails({
416
+ postId: response.postId,
417
+ // Only frames that actually decoded: an entry with no thumbnail
418
+ // would still satisfy the feed's lookup and suppress its own
419
+ // pending state, leaving the frame blank instead of showing the
420
+ // play affordance over a plain background.
421
+ videos: (0, _mediaAttachments.toLocalVideoThumbnails)(displayVideos)
422
+ }));
423
+ }
329
424
  if (targetType === 'community' && ((effectiveCommunity === null || effectiveCommunity === void 0 ? void 0 : effectiveCommunity.postSetting) === 'ADMIN_REVIEW_POST_REQUIRED' || effectiveCommunity !== null && effectiveCommunity !== void 0 && effectiveCommunity.needApprovalOnPostCreation) && !isCommunityModerator) {
330
425
  onPressClose();
331
426
  return _reactNative.Alert.alert('Post submitted', 'Your post has been submitted to the pending list. It will be reviewed by community moderator', [{
@@ -356,7 +451,7 @@ const AmityPostComposerPage = ({
356
451
  toastMessage: errorMessage
357
452
  }));
358
453
  }
359
- }, [addPostToGlobalFeed, chosenMediaType, effectiveCommunity, deletedPostIds, dispatch, displayImages, displayVideos, hideToastMessage, inputMessage, isEditMode, isInputValid, isCommunityModerator, mentionUsers, mentionsPosition, onPressClose, post, showToastMessage, targetId, targetType, updateByPostId]);
454
+ }, [addPostToGlobalFeed, chosenMediaType, effectiveCommunity, deletedPostIds, dispatch, displayImages, displayVideos, hideToastMessage, inputMessage, isEditMode, isInputValid, isCommunityModerator, mentionUsers, mentionsPosition, onPressClose, setLocalVideoThumbnails, post, showToastMessage, targetId, targetType, updateByPostId]);
360
455
  let tEvents = [];
361
456
  const onSwipe = (0, _react.useCallback)(touchEvent => {
362
457
  const swipeUp = touchEvent[0] > touchEvent[touchEvent.length - 1];
@@ -378,6 +473,14 @@ const AmityPostComposerPage = ({
378
473
  return {
379
474
  url: url,
380
475
  fileName: fileName,
476
+ // Camera captures land on a freshly generated temp path, so the path
477
+ // itself is the identity: unique per shot, and stable once the upload
478
+ // rewrites `url` to the remote one. Deliberately no
479
+ // `localFileName` — two shots of the same scene are two distinct
480
+ // attachments and must never de-duplicate against each other, nor
481
+ // against a library pick that happens to share a basename.
482
+ localId: url,
483
+ localUrl: url,
381
484
  fileId: '',
382
485
  isUploaded: false
383
486
  };
@@ -390,8 +493,8 @@ const AmityPostComposerPage = ({
390
493
  return setChosenMediaType(null);
391
494
  }, [displayImages === null || displayImages === void 0 ? void 0 : displayImages.length, displayVideos === null || displayVideos === void 0 ? void 0 : displayVideos.length]);
392
495
  const pickCamera = (0, _react.useCallback)(async mediaType => {
393
- if (mediaType === 'photo' && displayImages.length === 10) return _reactNative.Alert.alert('Maximum upload limit reached', "You've reached the upload limit of 10 images. Any additional images will not be saved.");
394
- if (mediaType === 'video' && displayVideos.length === 10) return _reactNative.Alert.alert('Maximum upload limit reached', "You've reached the upload limit of 10 videos. Any additional videos will not be saved.");
496
+ if (mediaType === 'photo' && displayImages.length >= _mediaAttachments.MAX_MEDIA_ATTACHMENTS) return _reactNative.Alert.alert('Maximum upload limit reached', "You've reached the upload limit of 10 images. Any additional images will not be saved.");
497
+ if (mediaType === 'video' && displayVideos.length >= _mediaAttachments.MAX_MEDIA_ATTACHMENTS) return _reactNative.Alert.alert('Maximum upload limit reached', "You've reached the upload limit of 10 videos. Any additional videos will not be saved.");
395
498
  try {
396
499
  const result = await (0, _reactNativeImagePicker.launchCamera)({
397
500
  mediaType: mediaType,
@@ -420,8 +523,13 @@ const AmityPostComposerPage = ({
420
523
  }
421
524
  }, [displayImages.length, displayVideos.length, processMedia]);
422
525
  const onPressCamera = (0, _react.useCallback)(async () => {
423
- if (displayImages.length > 0) return pickCamera('photo');
424
- if (displayVideos.length > 0) return pickCamera('video');
526
+ // The camera button is always rendered — unlike photo/video, neither
527
+ // attachment bar hides it on `chosenMediaType` — so this is the one entry
528
+ // point that must decide the capture type itself. Keying it on the staged
529
+ // arrays alone offered both types while an edited post's media was still
530
+ // hydrating, which is how a video could be shot onto an image post.
531
+ if (activeMediaType === _enums.mediaAttachment.image) return pickCamera('photo');
532
+ if (activeMediaType === _enums.mediaAttachment.video) return pickCamera('video');
425
533
  if (_reactNative.Platform.OS === 'ios') return pickCamera('mixed');
426
534
  _reactNative.Alert.alert('Open Camera', null, [{
427
535
  text: 'Photo',
@@ -430,47 +538,95 @@ const AmityPostComposerPage = ({
430
538
  text: 'Video',
431
539
  onPress: async () => pickCamera('video')
432
540
  }]);
433
- }, [displayImages.length, displayVideos.length, pickCamera]);
434
- const onPressImage = (0, _react.useCallback)(async () => {
435
- if (displayImages.length === 10) return _reactNative.Alert.alert('Maximum upload limit reached', "You've reached the upload limit of 10 images. Any additional images will not be saved.");
541
+ }, [activeMediaType, pickCamera]);
542
+
543
+ // Open the native OS camera roll (matches the web UIKit's native file
544
+ // picker). Appends the picked media, de-duplicating by uri and capping at 10.
545
+ const pickFromLibrary = (0, _react.useCallback)(async mediaType => {
546
+ var _result$assets;
547
+ const isPhoto = mediaType === 'photo';
548
+ // A post holds one media type. The bar hides the mismatched button, but
549
+ // guard the entry point too so a tap landing before the button updates
550
+ // can't replace the existing attachments with the other type.
551
+ const pickedType = isPhoto ? _enums.mediaAttachment.image : _enums.mediaAttachment.video;
552
+ if (activeMediaType && activeMediaType !== pickedType) return;
553
+ const current = isPhoto ? displayImages.length : displayVideos.length;
554
+ if (current >= _mediaAttachments.MAX_MEDIA_ATTACHMENTS) return _reactNative.Alert.alert('Maximum upload limit reached', `You've reached the upload limit of 10 ${isPhoto ? 'images' : 'videos'}. Any additional ${isPhoto ? 'images' : 'videos'} will not be saved.`);
436
555
  const result = await (0, _reactNativeImagePicker.launchImageLibrary)({
437
- mediaType: 'photo',
556
+ mediaType,
438
557
  quality: 1,
439
- selectionLimit: 10 - displayImages.length
558
+ selectionLimit: _mediaAttachments.MAX_MEDIA_ATTACHMENTS - current,
559
+ // Required for `asset.id`, which is what recognises a re-pick of an
560
+ // asset already staged. Without it the iOS picker builds its
561
+ // PHPickerConfiguration without a photo library, so results carry no
562
+ // assetIdentifier and the native side never resolves a PHAsset —
563
+ // leaving `id` undefined and the fallback key, `fileName`, a fresh
564
+ // UUID per pick. Both dedupe keys were therefore unique every time
565
+ // and picking the same photo twice staged it twice. Android was
566
+ // unaffected: its filename is the MediaStore display name, stable
567
+ // across picks.
568
+ includeExtra: true
440
569
  });
441
- if (!result.didCancel && result.assets && result.assets.length > 0) {
442
- const imageUriArr = result.assets.map(item => item.uri);
443
- const mediaOj = processMedia(imageUriArr);
444
- setDisplayImages(prev => {
445
- const updatedArray = [...prev, ...mediaOj];
446
- if (updatedArray.length > 10) {
447
- _reactNative.Alert.alert('Maximum number of images exceeded', 'Maximum number of images that can be uploaded is 10. The rest images will be discarded');
448
- return updatedArray.slice(0, 10);
449
- }
450
- return updatedArray;
451
- });
452
- }
453
- }, [displayImages.length, processMedia]);
454
- const onPressVideo = (0, _react.useCallback)(async () => {
455
- if (displayVideos.length === 10) return _reactNative.Alert.alert('Maximum upload limit reached', "You've reached the upload limit of 10 videos. Any additional videos will not be saved.");
456
- const result = await (0, _reactNativeImagePicker.launchImageLibrary)({
457
- mediaType: 'video',
458
- quality: 1,
459
- selectionLimit: 10 - displayVideos.length
570
+ if (result.didCancel || !((_result$assets = result.assets) !== null && _result$assets !== void 0 && _result$assets.length)) return;
571
+
572
+ // iOS video is the one pick whose dims cannot be trusted: the picker
573
+ // reports the track's stored `naturalSize` with no rotation alongside
574
+ // it, so a portrait iPhone clip arrives as 1920×1080 and would
575
+ // classify the frame 16:9 (PDT-4904). Images on both platforms, and
576
+ // Android video (its extractor swaps w/h on 90°/270°), are already
577
+ // display-oriented and unaffected. With no rotation to correct the iOS
578
+ // value by, carry nothing and let SelectedMediaComponent measure the
579
+ // generated thumbnail, which is a rendered frame.
580
+ const isIosVideoDimsUnusable = !isPhoto && _reactNative.Platform.OS === 'ios';
581
+ const candidates = (result.assets ?? []).flatMap(asset => {
582
+ if (!asset.uri) return [];
583
+ const fileName = asset.fileName ?? asset.uri.substring(asset.uri.lastIndexOf('/') + 1);
584
+ return [{
585
+ url: asset.uri,
586
+ fileName,
587
+ // `asset.id` is the library's own identifier for the asset (PHAsset
588
+ // localIdentifier / MediaStore id) and is the one key that survives
589
+ // the picker copying the pick to a new temp uri every time. It is
590
+ // not populated by every picker configuration, so fall back to the
591
+ // file name and keep the name as a second key either way — that is
592
+ // what catches a re-pick when no id came back.
593
+ localId: asset.id ?? fileName,
594
+ localUrl: asset.uri,
595
+ localFileName: fileName,
596
+ fileId: '',
597
+ isUploaded: false,
598
+ width: isIosVideoDimsUnusable ? undefined : asset.width,
599
+ height: isIosVideoDimsUnusable ? undefined : asset.height
600
+ }];
460
601
  });
461
- if (!result.didCancel && result.assets && result.assets.length > 0) {
462
- const videoUriArr = result.assets.map(item => item.uri);
463
- const mediaOj = processMedia(videoUriArr);
464
- setDisplayVideos(prev => {
465
- const updatedArray = [...prev, ...mediaOj];
466
- if (updatedArray.length > 10) {
467
- _reactNative.Alert.alert('Maximum number of videos exceeded', 'Maximum number of videos that can be uploaded is 10. The rest videos will be discarded');
468
- return updatedArray.slice(0, 10);
469
- }
470
- return updatedArray;
471
- });
472
- }
473
- }, [displayVideos.length, processMedia]);
602
+
603
+ // Stage the picks and claim their upload slots in one go. Staging alone
604
+ // used to flip `isInputValid` true on the very next render — the frames
605
+ // exist, and `uploadingSources` is still empty because each child only
606
+ // registers from its own mount effect — so Post sat enabled for ~940 ms
607
+ // with nothing uploaded and a quick tap posted media that had no fileId
608
+ // yet. Seeding here makes "staged" and "gated" the same update; children
609
+ // still clear their own entry when they finish, and the unmount cleanup
610
+ // still covers a frame removed mid-flight.
611
+ const staged = isPhoto ? displayImages : displayVideos;
612
+ const accepted = (0, _mediaAttachments.appendWithinCap)(staged, (0, _mediaAttachments.dedupeMediaPicks)(staged, candidates));
613
+ // Only the entries that actually survived dedupe and the cap — seeding a
614
+ // key no child will ever mount for would leave Post disabled forever.
615
+ const newlyStaged = accepted.slice(staged.length);
616
+ const setter = isPhoto ? setDisplayImages : setDisplayVideos;
617
+ setter(accepted);
618
+ setUploadingSources(prev => newlyStaged.reduce((acc, item) => (0, _mediaAttachments.toggleUploadingSource)(acc, item.url, true), prev));
619
+ }, [activeMediaType, displayImages, displayVideos]);
620
+ const onPressImage = (0, _react.useCallback)(() => pickFromLibrary('photo'), [pickFromLibrary]);
621
+ const onPressVideo = (0, _react.useCallback)(() => pickFromLibrary('video'), [pickFromLibrary]);
622
+
623
+ // Children report their own upload start/end keyed by `source`, and a child
624
+ // that unmounts mid-upload (frame removed while still uploading) clears its
625
+ // own entry from its cleanup — otherwise the set would never empty and Post
626
+ // would stay disabled forever.
627
+ const handleUploadingChange = (0, _react.useCallback)((uploading, source) => {
628
+ setUploadingSources(prev => (0, _mediaAttachments.toggleUploadingSource)(prev, source, uploading));
629
+ }, []);
474
630
  const handleImageUploadError = (0, _react.useCallback)((hasError, source) => {
475
631
  setImageErrors(prev => {
476
632
  const newSet = new Set(prev);
@@ -495,7 +651,7 @@ const AmityPostComposerPage = ({
495
651
  }, []);
496
652
  const handleOnCloseImage = (0, _react.useCallback)((originalPath, _, postId) => {
497
653
  setHasChangedAttachment(true);
498
- setDeletedPostIds(prev => [...prev, postId]);
654
+ if (postId) setDeletedPostIds(prev => [...prev, postId]);
499
655
  setImageErrors(prev => {
500
656
  const newSet = new Set(prev);
501
657
  newSet.delete(originalPath);
@@ -508,7 +664,7 @@ const AmityPostComposerPage = ({
508
664
  }, []);
509
665
  const handleOnCloseVideo = (0, _react.useCallback)((originalPath, _, postId) => {
510
666
  setHasChangedAttachment(true);
511
- setDeletedPostIds(prev => [...prev, postId]);
667
+ if (postId) setDeletedPostIds(prev => [...prev, postId]);
512
668
  setVideoErrors(prev => {
513
669
  const newSet = new Set(prev);
514
670
  newSet.delete(originalPath);
@@ -519,54 +675,50 @@ const AmityPostComposerPage = ({
519
675
  return newData;
520
676
  });
521
677
  }, []);
522
- const handleOnFinishImage = (0, _react.useCallback)((fileId, fileUrl, fileName, index) => {
678
+ const handleOnFinishImage = (0, _react.useCallback)((fileId, fileUrl, fileName, _index, originalPath) => {
523
679
  setHasChangedAttachment(true);
524
- const imageObject = {
680
+ setDisplayImages(prevData => (0, _mediaAttachments.applyFinishedUpload)(prevData, originalPath, {
525
681
  url: fileUrl,
526
682
  fileId: fileId,
527
683
  fileName: fileName,
528
684
  isUploaded: true
529
- };
530
- setDisplayImages(prevData => {
531
- const newData = [...prevData];
532
- newData[index] = imageObject;
533
- return newData;
534
- });
685
+ }));
535
686
  }, []);
536
- const handleOnFinishVideo = (0, _react.useCallback)((fileId, fileUrl, fileName, index, _, thumbnail) => {
687
+ const handleOnFinishVideo = (0, _react.useCallback)((fileId, fileUrl, fileName, _index, originalPath, thumbnail) => {
537
688
  setHasChangedAttachment(true);
538
- const imageObject = {
689
+ setDisplayVideos(prevData => (0, _mediaAttachments.applyFinishedUpload)(prevData, originalPath, {
539
690
  url: fileUrl,
540
691
  fileId: fileId,
541
692
  fileName: fileName,
542
693
  isUploaded: true,
543
694
  thumbNail: thumbnail
544
- };
545
- setDisplayVideos(prevData => {
546
- const newData = [...prevData];
547
- newData[index] = imageObject;
548
- return newData;
549
- });
695
+ }));
550
696
  }, []);
697
+
698
+ // PDT-4310 / PDT-4312: at the 10-attachment cap the camera + gallery icons
699
+ // are disabled until the user removes a frame.
700
+ const isMediaCapReached = displayImages.length >= _mediaAttachments.MAX_MEDIA_ATTACHMENTS || displayVideos.length >= _mediaAttachments.MAX_MEDIA_ATTACHMENTS;
551
701
  const renderDetailedAttachment = (0, _react.useCallback)(() => {
552
- if (isEditMode) return null;
702
+ if (editChildrenIncomplete) return null;
553
703
  if (shouldShowDetailAttachment) {
554
704
  return /*#__PURE__*/React.createElement(_DetailedMediaAttachment.default, {
555
705
  onPressCamera: onPressCamera,
556
706
  onPressImage: onPressImage,
557
707
  onPressVideo: onPressVideo,
558
- chosenMediaType: chosenMediaType,
559
- onHeightChange: setAttachmentBarHeight
708
+ chosenMediaType: activeMediaType,
709
+ onHeightChange: setAttachmentBarHeight,
710
+ disabled: isMediaCapReached
560
711
  });
561
712
  }
562
713
  return /*#__PURE__*/React.createElement(_MediaAttachment.default, {
563
714
  onPressCamera: onPressCamera,
564
715
  onPressImage: onPressImage,
565
716
  onPressVideo: onPressVideo,
566
- chosenMediaType: chosenMediaType,
567
- onHeightChange: setAttachmentBarHeight
717
+ chosenMediaType: activeMediaType,
718
+ onHeightChange: setAttachmentBarHeight,
719
+ disabled: isMediaCapReached
568
720
  });
569
- }, [chosenMediaType, isEditMode, onPressCamera, onPressImage, onPressVideo, shouldShowDetailAttachment]);
721
+ }, [activeMediaType, editChildrenIncomplete, isMediaCapReached, onPressCamera, onPressImage, onPressVideo, shouldShowDetailAttachment]);
570
722
  if (isExcluded) return null;
571
723
  return /*#__PURE__*/React.createElement(_reactNativeSafeAreaContext.SafeAreaView, {
572
724
  testID: accessibilityId,
@@ -606,55 +758,22 @@ const AmityPostComposerPage = ({
606
758
  style: styles.input
607
759
  }), /*#__PURE__*/React.createElement(_reactNative.View, {
608
760
  style: styles.imageContainer
609
- }, displayImages.length > 0 && /*#__PURE__*/React.createElement(_reactNative.FlatList, {
610
- nestedScrollEnabled: true,
611
- scrollEnabled: false,
612
- data: displayImages,
613
- renderItem: ({
614
- item,
615
- index
616
- }) => {
617
- if (!item) return null;
618
- return /*#__PURE__*/React.createElement(_LoadingImage.default, {
619
- source: item.url,
620
- onClose: handleOnCloseImage,
621
- index: index //TODO: Fix this without index
622
- ,
623
- onLoadFinish: handleOnFinishImage,
624
- onUploadError: handleImageUploadError,
625
- isUploaded: item.isUploaded,
626
- fileId: item.fileId,
627
- fileCount: displayImages.length,
628
- isEditMode: isEditMode,
629
- postId: item.postId,
630
- setIsUploading: setIsUploading
631
- });
632
- },
633
- numColumns: 3
634
- }), displayVideos.length > 0 && /*#__PURE__*/React.createElement(_reactNative.FlatList, {
635
- data: displayVideos,
636
- renderItem: ({
637
- item,
638
- index
639
- }) => {
640
- if (!item) return null;
641
- return /*#__PURE__*/React.createElement(_LoadingVideo.default, {
642
- source: item.url,
643
- onClose: handleOnCloseVideo,
644
- index: index //TODO: Fix this without index
645
- ,
646
- onLoadFinish: handleOnFinishVideo,
647
- onUploadError: handleVideoUploadError,
648
- isUploaded: item.isUploaded,
649
- fileId: item.fileId,
650
- thumbNail: item.thumbNail,
651
- fileCount: displayVideos.length,
652
- isEditMode: isEditMode,
653
- postId: item.postId,
654
- setIsUploading: setIsUploading
655
- });
656
- },
657
- numColumns: 3
761
+ }, displayImages.length > 0 && /*#__PURE__*/React.createElement(_SelectedMediaComponent.SelectedMediaComponent, {
762
+ mediaType: "image",
763
+ media: displayImages,
764
+ onClose: handleOnCloseImage,
765
+ onLoadFinish: handleOnFinishImage,
766
+ onUploadError: handleImageUploadError,
767
+ isEditMode: isEditMode,
768
+ onUploadingChange: handleUploadingChange
769
+ }), displayVideos.length > 0 && /*#__PURE__*/React.createElement(_SelectedMediaComponent.SelectedMediaComponent, {
770
+ mediaType: "video",
771
+ media: displayVideos,
772
+ onClose: handleOnCloseVideo,
773
+ onLoadFinish: handleOnFinishVideo,
774
+ onUploadError: handleVideoUploadError,
775
+ isEditMode: isEditMode,
776
+ onUploadingChange: handleUploadingChange
658
777
  }))), renderSuggestions({
659
778
  type: 'post'
660
779
  }), /*#__PURE__*/React.createElement(_reactNative.View, {