@amityco/react-native-social-uikit 4.1.0 → 4.1.1-11cdc854.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.
- package/lib/commonjs/core/assets/icons/xml.js +55 -1
- package/lib/commonjs/core/assets/icons/xml.js.map +1 -1
- package/lib/commonjs/core/hooks/usePostByIds.js +38 -0
- package/lib/commonjs/core/hooks/usePostByIds.js.map +1 -0
- package/lib/commonjs/social/components/LoadingImage/index.js +4 -3
- package/lib/commonjs/social/components/LoadingImage/index.js.map +1 -1
- package/lib/commonjs/social/components/LoadingImage/styles.js +4 -0
- package/lib/commonjs/social/components/LoadingImage/styles.js.map +1 -1
- package/lib/commonjs/social/components/LoadingVideo/index.js +12 -6
- package/lib/commonjs/social/components/LoadingVideo/index.js.map +1 -1
- package/lib/commonjs/social/components/LoadingVideo/styles.js +4 -0
- package/lib/commonjs/social/components/LoadingVideo/styles.js.map +1 -1
- package/lib/commonjs/social/components/MediaViewer/MediaViewer.js +266 -0
- package/lib/commonjs/social/components/MediaViewer/MediaViewer.js.map +1 -0
- package/lib/commonjs/social/components/MediaViewer/index.js +13 -0
- package/lib/commonjs/social/components/MediaViewer/index.js.map +1 -0
- package/lib/commonjs/social/components/MediaViewer/styles.js +116 -0
- package/lib/commonjs/social/components/MediaViewer/styles.js.map +1 -0
- package/lib/commonjs/social/components/PostContent/index.js +75 -120
- package/lib/commonjs/social/components/PostContent/index.js.map +1 -1
- package/lib/commonjs/social/components/SelectedMediaComponent/SelectedMediaComponent.js +180 -0
- package/lib/commonjs/social/components/SelectedMediaComponent/SelectedMediaComponent.js.map +1 -0
- package/lib/commonjs/social/components/SelectedMediaComponent/index.js +13 -0
- package/lib/commonjs/social/components/SelectedMediaComponent/index.js.map +1 -0
- package/lib/commonjs/social/components/SelectedMediaComponent/styles.js +43 -0
- package/lib/commonjs/social/components/SelectedMediaComponent/styles.js.map +1 -0
- package/lib/commonjs/social/constants/index.js +11 -0
- package/lib/commonjs/social/constants/index.js.map +1 -0
- package/lib/commonjs/social/elements/PostMediaElement/PostMediaElement.js +280 -0
- package/lib/commonjs/social/elements/PostMediaElement/PostMediaElement.js.map +1 -0
- package/lib/commonjs/social/elements/PostMediaElement/index.js +13 -0
- package/lib/commonjs/social/elements/PostMediaElement/index.js.map +1 -0
- package/lib/commonjs/social/elements/PostMediaElement/styles.js +117 -0
- package/lib/commonjs/social/elements/PostMediaElement/styles.js.map +1 -0
- package/lib/commonjs/social/features/post/Composer/PostComposer.js +91 -106
- package/lib/commonjs/social/features/post/Composer/PostComposer.js.map +1 -1
- package/lib/commonjs/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js +17 -7
- package/lib/commonjs/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js.map +1 -1
- package/lib/commonjs/social/features/post/components/MediaAttachment/MediaAttachment.js +17 -7
- package/lib/commonjs/social/features/post/components/MediaAttachment/MediaAttachment.js.map +1 -1
- package/lib/commonjs/social/utils/getFrameRatio.js +52 -0
- package/lib/commonjs/social/utils/getFrameRatio.js.map +1 -0
- package/lib/commonjs/social/utils/getIndicatorConfig.js +59 -0
- package/lib/commonjs/social/utils/getIndicatorConfig.js.map +1 -0
- package/lib/module/core/assets/icons/xml.js +48 -0
- package/lib/module/core/assets/icons/xml.js.map +1 -1
- package/lib/module/core/hooks/usePostByIds.js +32 -0
- package/lib/module/core/hooks/usePostByIds.js.map +1 -0
- package/lib/module/social/components/LoadingImage/index.js +4 -3
- package/lib/module/social/components/LoadingImage/index.js.map +1 -1
- package/lib/module/social/components/LoadingImage/styles.js +4 -0
- package/lib/module/social/components/LoadingImage/styles.js.map +1 -1
- package/lib/module/social/components/LoadingVideo/index.js +13 -7
- package/lib/module/social/components/LoadingVideo/index.js.map +1 -1
- package/lib/module/social/components/LoadingVideo/styles.js +4 -0
- package/lib/module/social/components/LoadingVideo/styles.js.map +1 -1
- package/lib/module/social/components/MediaViewer/MediaViewer.js +259 -0
- package/lib/module/social/components/MediaViewer/MediaViewer.js.map +1 -0
- package/lib/module/social/components/MediaViewer/index.js +2 -0
- package/lib/module/social/components/MediaViewer/index.js.map +1 -0
- package/lib/module/social/components/MediaViewer/styles.js +109 -0
- package/lib/module/social/components/MediaViewer/styles.js.map +1 -0
- package/lib/module/social/components/PostContent/index.js +77 -122
- package/lib/module/social/components/PostContent/index.js.map +1 -1
- package/lib/module/social/components/SelectedMediaComponent/SelectedMediaComponent.js +174 -0
- package/lib/module/social/components/SelectedMediaComponent/SelectedMediaComponent.js.map +1 -0
- package/lib/module/social/components/SelectedMediaComponent/index.js +2 -0
- package/lib/module/social/components/SelectedMediaComponent/index.js.map +1 -0
- package/lib/module/social/components/SelectedMediaComponent/styles.js +36 -0
- package/lib/module/social/components/SelectedMediaComponent/styles.js.map +1 -0
- package/lib/module/social/constants/index.js +5 -0
- package/lib/module/social/constants/index.js.map +1 -0
- package/lib/module/social/elements/PostMediaElement/PostMediaElement.js +273 -0
- package/lib/module/social/elements/PostMediaElement/PostMediaElement.js.map +1 -0
- package/lib/module/social/elements/PostMediaElement/index.js +2 -0
- package/lib/module/social/elements/PostMediaElement/index.js.map +1 -0
- package/lib/module/social/elements/PostMediaElement/styles.js +110 -0
- package/lib/module/social/elements/PostMediaElement/styles.js.map +1 -0
- package/lib/module/social/features/post/Composer/PostComposer.js +94 -109
- package/lib/module/social/features/post/Composer/PostComposer.js.map +1 -1
- package/lib/module/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js +17 -7
- package/lib/module/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.js.map +1 -1
- package/lib/module/social/features/post/components/MediaAttachment/MediaAttachment.js +17 -7
- package/lib/module/social/features/post/components/MediaAttachment/MediaAttachment.js.map +1 -1
- package/lib/module/social/utils/getFrameRatio.js +44 -0
- package/lib/module/social/utils/getFrameRatio.js.map +1 -0
- package/lib/module/social/utils/getIndicatorConfig.js +53 -0
- package/lib/module/social/utils/getIndicatorConfig.js.map +1 -0
- package/lib/typescript/core/assets/icons/xml.d.ts +7 -0
- package/lib/typescript/core/assets/icons/xml.d.ts.map +1 -1
- package/lib/typescript/core/hooks/usePostByIds.d.ts +8 -0
- package/lib/typescript/core/hooks/usePostByIds.d.ts.map +1 -0
- package/lib/typescript/core/types/mention.d.ts +6 -0
- package/lib/typescript/core/types/mention.d.ts.map +1 -1
- package/lib/typescript/social/components/LoadingImage/index.d.ts +2 -1
- package/lib/typescript/social/components/LoadingImage/index.d.ts.map +1 -1
- package/lib/typescript/social/components/LoadingImage/styles.d.ts +4 -0
- package/lib/typescript/social/components/LoadingImage/styles.d.ts.map +1 -1
- package/lib/typescript/social/components/LoadingVideo/index.d.ts +2 -1
- package/lib/typescript/social/components/LoadingVideo/index.d.ts.map +1 -1
- package/lib/typescript/social/components/LoadingVideo/styles.d.ts +4 -0
- package/lib/typescript/social/components/LoadingVideo/styles.d.ts.map +1 -1
- package/lib/typescript/social/components/MediaViewer/MediaViewer.d.ts +17 -0
- package/lib/typescript/social/components/MediaViewer/MediaViewer.d.ts.map +1 -0
- package/lib/typescript/social/components/MediaViewer/index.d.ts +3 -0
- package/lib/typescript/social/components/MediaViewer/index.d.ts.map +1 -0
- package/lib/typescript/social/components/MediaViewer/styles.d.ts +99 -0
- package/lib/typescript/social/components/MediaViewer/styles.d.ts.map +1 -0
- package/lib/typescript/social/components/PostContent/index.d.ts.map +1 -1
- package/lib/typescript/social/components/SelectedMediaComponent/SelectedMediaComponent.d.ts +12 -0
- package/lib/typescript/social/components/SelectedMediaComponent/SelectedMediaComponent.d.ts.map +1 -0
- package/lib/typescript/social/components/SelectedMediaComponent/index.d.ts +3 -0
- package/lib/typescript/social/components/SelectedMediaComponent/index.d.ts.map +1 -0
- package/lib/typescript/social/components/SelectedMediaComponent/styles.d.ts +25 -0
- package/lib/typescript/social/components/SelectedMediaComponent/styles.d.ts.map +1 -0
- package/lib/typescript/social/constants/index.d.ts +4 -0
- package/lib/typescript/social/constants/index.d.ts.map +1 -0
- package/lib/typescript/social/elements/PostMediaElement/PostMediaElement.d.ts +15 -0
- package/lib/typescript/social/elements/PostMediaElement/PostMediaElement.d.ts.map +1 -0
- package/lib/typescript/social/elements/PostMediaElement/index.d.ts +3 -0
- package/lib/typescript/social/elements/PostMediaElement/index.d.ts.map +1 -0
- package/lib/typescript/social/elements/PostMediaElement/styles.d.ts +88 -0
- package/lib/typescript/social/elements/PostMediaElement/styles.d.ts.map +1 -0
- package/lib/typescript/social/features/post/Composer/PostComposer.d.ts.map +1 -1
- package/lib/typescript/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.d.ts +3 -0
- package/lib/typescript/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.d.ts.map +1 -1
- package/lib/typescript/social/features/post/components/MediaAttachment/MediaAttachment.d.ts +3 -0
- package/lib/typescript/social/features/post/components/MediaAttachment/MediaAttachment.d.ts.map +1 -1
- package/lib/typescript/social/utils/getFrameRatio.d.ts +21 -0
- package/lib/typescript/social/utils/getFrameRatio.d.ts.map +1 -0
- package/lib/typescript/social/utils/getIndicatorConfig.d.ts +11 -0
- package/lib/typescript/social/utils/getIndicatorConfig.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/core/assets/icons/xml.ts +60 -0
- package/src/core/hooks/usePostByIds.ts +33 -0
- package/src/core/types/mention.ts +6 -0
- package/src/social/components/LoadingImage/index.tsx +12 -2
- package/src/social/components/LoadingImage/styles.ts +4 -0
- package/src/social/components/LoadingVideo/index.tsx +28 -4
- package/src/social/components/LoadingVideo/styles.ts +4 -0
- package/src/social/components/MediaViewer/MediaViewer.tsx +384 -0
- package/src/social/components/MediaViewer/index.tsx +2 -0
- package/src/social/components/MediaViewer/styles.ts +109 -0
- package/src/social/components/PostContent/index.tsx +86 -159
- package/src/social/components/SelectedMediaComponent/SelectedMediaComponent.tsx +236 -0
- package/src/social/components/SelectedMediaComponent/index.ts +2 -0
- package/src/social/components/SelectedMediaComponent/styles.ts +38 -0
- package/src/social/constants/index.ts +4 -0
- package/src/social/elements/PostMediaElement/PostMediaElement.tsx +362 -0
- package/src/social/elements/PostMediaElement/index.tsx +5 -0
- package/src/social/elements/PostMediaElement/styles.ts +99 -0
- package/src/social/features/post/Composer/PostComposer.tsx +107 -123
- package/src/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.tsx +10 -3
- package/src/social/features/post/components/MediaAttachment/MediaAttachment.tsx +14 -3
- package/src/social/utils/getFrameRatio.ts +42 -0
- package/src/social/utils/getIndicatorConfig.ts +62 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Alert,
|
|
3
|
-
FlatList,
|
|
4
3
|
Keyboard,
|
|
5
4
|
KeyboardAvoidingView,
|
|
6
5
|
Platform,
|
|
@@ -38,22 +37,18 @@ import uiSlice from '../../../../core/stores/slices/uiSlice';
|
|
|
38
37
|
import { amityPostsFormatter } from '../../../../core/utils/post';
|
|
39
38
|
import useAuth from '../../../../core/hooks/useAuth';
|
|
40
39
|
import globalfeedSlice from '../../../../core/stores/slices/globalfeedSlice';
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
editPost,
|
|
44
|
-
getPostById,
|
|
45
|
-
} from '../../../../core/legacy/feed';
|
|
40
|
+
import { createPostToFeed, editPost } from '../../../../core/legacy/feed';
|
|
41
|
+
import { usePostByIds } from '../../../../core/hooks/usePostByIds';
|
|
46
42
|
import TextKeyElement from '../../../elements/TextKeyElement/TextKeyElement';
|
|
47
43
|
import AmityMediaAttachmentComponent from '../components/MediaAttachment';
|
|
48
44
|
import AmityDetailedMediaAttachmentComponent from '../components/DetailedMediaAttachment';
|
|
49
45
|
import { useKeyboardStatus } from '../../../hooks';
|
|
50
46
|
import ImagePicker, {
|
|
51
|
-
launchImageLibrary,
|
|
52
47
|
type Asset,
|
|
53
48
|
launchCamera,
|
|
49
|
+
launchImageLibrary,
|
|
54
50
|
} from 'react-native-image-picker';
|
|
55
|
-
import
|
|
56
|
-
import LoadingVideo from '../../../components/LoadingVideo';
|
|
51
|
+
import { SelectedMediaComponent } from '../../../components/SelectedMediaComponent';
|
|
57
52
|
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
58
53
|
import { RootStackParamList } from '../../../../core/routes/RouteParamList';
|
|
59
54
|
import {
|
|
@@ -197,36 +192,38 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
197
192
|
[]
|
|
198
193
|
);
|
|
199
194
|
|
|
195
|
+
// Load the edited post's child media the same way the web UIKit does
|
|
196
|
+
// (usePostByIds → batch getPostByIds), instead of the racy per-id fetch.
|
|
197
|
+
const childrenPosts = usePostByIds(post?.children ?? []);
|
|
198
|
+
|
|
200
199
|
const getPostInfo = useCallback(
|
|
201
|
-
async (
|
|
200
|
+
async (response: Amity.Post[]) => {
|
|
202
201
|
try {
|
|
203
|
-
const response = await Promise.all(
|
|
204
|
-
postArray.map(async (id: string) => {
|
|
205
|
-
const { data } = await getPostById(id);
|
|
206
|
-
return data;
|
|
207
|
-
})
|
|
208
|
-
);
|
|
209
|
-
|
|
210
202
|
const images: IDisplayImage[] = [];
|
|
211
203
|
const videos: IDisplayImage[] = [];
|
|
212
204
|
|
|
213
205
|
for (const item of response) {
|
|
214
206
|
if (item?.dataType === 'image') {
|
|
215
|
-
const fileId = item?.data?.fileId;
|
|
207
|
+
const fileId = (item as Amity.Post<'image'>)?.data?.fileId;
|
|
216
208
|
const url = await getImage({
|
|
217
209
|
fileId: fileId,
|
|
218
210
|
imageSize: ImageSizeState.full,
|
|
219
211
|
});
|
|
212
|
+
// Dimensions for composer frame-ratio classification (REQ-003d).
|
|
213
|
+
const imageInfo = (item as any)?.getImageInfo?.();
|
|
220
214
|
images.push({
|
|
221
215
|
url,
|
|
222
216
|
fileId,
|
|
223
217
|
fileName: fileId,
|
|
224
218
|
isUploaded: true,
|
|
225
219
|
postId: item.postId,
|
|
220
|
+
width: imageInfo?.getWidth?.(),
|
|
221
|
+
height: imageInfo?.getHeight?.(),
|
|
226
222
|
});
|
|
227
223
|
} else if (item?.dataType === 'video') {
|
|
228
|
-
const
|
|
229
|
-
const
|
|
224
|
+
const videoData = (item as Amity.Post<'video'>)?.data;
|
|
225
|
+
const fileId = videoData?.videoFileId?.original;
|
|
226
|
+
const thumbnailFileId = videoData?.thumbnailFileId;
|
|
230
227
|
const fileUrls = await Promise.allSettled(
|
|
231
228
|
[fileId, thumbnailFileId].map(async (id) => {
|
|
232
229
|
return await getImage({
|
|
@@ -235,6 +232,9 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
235
232
|
});
|
|
236
233
|
})
|
|
237
234
|
);
|
|
235
|
+
// STORED dims + rotation; rotation is applied at classify time
|
|
236
|
+
// (SelectedMediaComponent REQ-003d1 / AmityVideo REQ-SDK-002).
|
|
237
|
+
const videoInfo = (item as any)?.getVideoInfo?.();
|
|
238
238
|
videos.push({
|
|
239
239
|
//@ts-ignore
|
|
240
240
|
url: fileUrls[0]?.value,
|
|
@@ -244,6 +244,9 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
244
244
|
//@ts-ignore
|
|
245
245
|
thumbNail: fileUrls[1]?.value,
|
|
246
246
|
postId: item.postId,
|
|
247
|
+
width: videoInfo?.getWidth?.(),
|
|
248
|
+
height: videoInfo?.getHeight?.(),
|
|
249
|
+
rotation: videoInfo?.getRotation?.(),
|
|
247
250
|
});
|
|
248
251
|
}
|
|
249
252
|
}
|
|
@@ -267,8 +270,8 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
267
270
|
}, []);
|
|
268
271
|
|
|
269
272
|
useEffect(() => {
|
|
270
|
-
|
|
271
|
-
}, [getPostInfo,
|
|
273
|
+
if (childrenPosts.length > 0) getPostInfo(childrenPosts);
|
|
274
|
+
}, [getPostInfo, childrenPosts]);
|
|
272
275
|
|
|
273
276
|
const getMentionPositions = useCallback(
|
|
274
277
|
(text: string, mentioneeIds: string[]) => {
|
|
@@ -583,65 +586,67 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
583
586
|
]);
|
|
584
587
|
}, [displayImages.length, displayVideos.length, pickCamera]);
|
|
585
588
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
const updatedArray = [...prev, ...mediaOj];
|
|
604
|
-
if (updatedArray.length > 10) {
|
|
605
|
-
Alert.alert(
|
|
606
|
-
'Maximum number of images exceeded',
|
|
607
|
-
'Maximum number of images that can be uploaded is 10. The rest images will be discarded'
|
|
608
|
-
);
|
|
609
|
-
return updatedArray.slice(0, 10);
|
|
610
|
-
}
|
|
611
|
-
return updatedArray;
|
|
589
|
+
// Open the native OS camera roll (matches the web UIKit's native file
|
|
590
|
+
// picker). Appends the picked media, de-duplicating by uri and capping at 10.
|
|
591
|
+
const pickFromLibrary = useCallback(
|
|
592
|
+
async (mediaType: 'photo' | 'video') => {
|
|
593
|
+
const isPhoto = mediaType === 'photo';
|
|
594
|
+
const current = isPhoto ? displayImages.length : displayVideos.length;
|
|
595
|
+
if (current >= 10)
|
|
596
|
+
return Alert.alert(
|
|
597
|
+
'Maximum upload limit reached',
|
|
598
|
+
`You've reached the upload limit of 10 ${
|
|
599
|
+
isPhoto ? 'images' : 'videos'
|
|
600
|
+
}. Any additional ${isPhoto ? 'images' : 'videos'} will not be saved.`
|
|
601
|
+
);
|
|
602
|
+
const result: ImagePicker.ImagePickerResponse = await launchImageLibrary({
|
|
603
|
+
mediaType,
|
|
604
|
+
quality: 1,
|
|
605
|
+
selectionLimit: 10 - current,
|
|
612
606
|
});
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
);
|
|
639
|
-
return updatedArray.slice(0, 10);
|
|
607
|
+
if (result.didCancel || !result.assets?.length) return;
|
|
608
|
+
|
|
609
|
+
const setter = isPhoto ? setDisplayImages : setDisplayVideos;
|
|
610
|
+
setter((prev) => {
|
|
611
|
+
// Silently drop duplicates, matching the web UIKit (which dedups by
|
|
612
|
+
// file name). The picker copies each pick to a fresh temp uri, so uri
|
|
613
|
+
// is not stable across picks — the original `fileName` is.
|
|
614
|
+
const seen = new Set(prev.map((m) => m.fileName));
|
|
615
|
+
const additions: IDisplayImage[] = [];
|
|
616
|
+
for (const asset of result.assets ?? []) {
|
|
617
|
+
if (!asset.uri) continue;
|
|
618
|
+
const fileName =
|
|
619
|
+
asset.fileName ??
|
|
620
|
+
asset.uri.substring(asset.uri.lastIndexOf('/') + 1);
|
|
621
|
+
if (seen.has(fileName)) continue; // duplicate → silently drop
|
|
622
|
+
seen.add(fileName);
|
|
623
|
+
additions.push({
|
|
624
|
+
url: asset.uri,
|
|
625
|
+
fileName,
|
|
626
|
+
fileId: '',
|
|
627
|
+
isUploaded: false,
|
|
628
|
+
// Locally-picked dimensions are already display-oriented (the
|
|
629
|
+
// picker's extractor applied any rotation) — no rotation to carry.
|
|
630
|
+
width: asset.width,
|
|
631
|
+
height: asset.height,
|
|
632
|
+
});
|
|
640
633
|
}
|
|
641
|
-
|
|
634
|
+
const updated = [...prev, ...additions];
|
|
635
|
+
return updated.length > 10 ? updated.slice(0, 10) : updated;
|
|
642
636
|
});
|
|
643
|
-
}
|
|
644
|
-
|
|
637
|
+
},
|
|
638
|
+
[displayImages.length, displayVideos.length]
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
const onPressImage = useCallback(
|
|
642
|
+
() => pickFromLibrary('photo'),
|
|
643
|
+
[pickFromLibrary]
|
|
644
|
+
);
|
|
645
|
+
|
|
646
|
+
const onPressVideo = useCallback(
|
|
647
|
+
() => pickFromLibrary('video'),
|
|
648
|
+
[pickFromLibrary]
|
|
649
|
+
);
|
|
645
650
|
|
|
646
651
|
const handleImageUploadError = useCallback(
|
|
647
652
|
(hasError: boolean, source: string) => {
|
|
@@ -752,6 +757,11 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
752
757
|
[]
|
|
753
758
|
);
|
|
754
759
|
|
|
760
|
+
// PDT-4310 / PDT-4312: at the 10-attachment cap the camera + gallery icons
|
|
761
|
+
// are disabled until the user removes a frame.
|
|
762
|
+
const isMediaCapReached =
|
|
763
|
+
displayImages.length >= 10 || displayVideos.length >= 10;
|
|
764
|
+
|
|
755
765
|
const renderDetailedAttachment = useCallback(() => {
|
|
756
766
|
if (isEditMode) return null;
|
|
757
767
|
if (shouldShowDetailAttachment) {
|
|
@@ -762,6 +772,7 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
762
772
|
onPressVideo={onPressVideo}
|
|
763
773
|
chosenMediaType={chosenMediaType}
|
|
764
774
|
onHeightChange={setAttachmentBarHeight}
|
|
775
|
+
disabled={isMediaCapReached}
|
|
765
776
|
/>
|
|
766
777
|
);
|
|
767
778
|
}
|
|
@@ -772,11 +783,13 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
772
783
|
onPressVideo={onPressVideo}
|
|
773
784
|
chosenMediaType={chosenMediaType}
|
|
774
785
|
onHeightChange={setAttachmentBarHeight}
|
|
786
|
+
disabled={isMediaCapReached}
|
|
775
787
|
/>
|
|
776
788
|
);
|
|
777
789
|
}, [
|
|
778
790
|
chosenMediaType,
|
|
779
791
|
isEditMode,
|
|
792
|
+
isMediaCapReached,
|
|
780
793
|
onPressCamera,
|
|
781
794
|
onPressImage,
|
|
782
795
|
onPressVideo,
|
|
@@ -835,54 +848,25 @@ const AmityPostComposerPage: FC<AmityPostComposerPageType> = ({
|
|
|
835
848
|
})}
|
|
836
849
|
<View style={styles.imageContainer}>
|
|
837
850
|
{displayImages.length > 0 && (
|
|
838
|
-
<
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
source={item.url}
|
|
847
|
-
onClose={handleOnCloseImage}
|
|
848
|
-
index={index} //TODO: Fix this without index
|
|
849
|
-
onLoadFinish={handleOnFinishImage}
|
|
850
|
-
onUploadError={handleImageUploadError}
|
|
851
|
-
isUploaded={item.isUploaded}
|
|
852
|
-
fileId={item.fileId}
|
|
853
|
-
fileCount={displayImages.length}
|
|
854
|
-
isEditMode={isEditMode}
|
|
855
|
-
postId={item.postId}
|
|
856
|
-
setIsUploading={setIsUploading}
|
|
857
|
-
/>
|
|
858
|
-
);
|
|
859
|
-
}}
|
|
860
|
-
numColumns={3}
|
|
851
|
+
<SelectedMediaComponent
|
|
852
|
+
mediaType="image"
|
|
853
|
+
media={displayImages}
|
|
854
|
+
onClose={handleOnCloseImage}
|
|
855
|
+
onLoadFinish={handleOnFinishImage}
|
|
856
|
+
onUploadError={handleImageUploadError}
|
|
857
|
+
isEditMode={isEditMode}
|
|
858
|
+
setIsUploading={setIsUploading}
|
|
861
859
|
/>
|
|
862
860
|
)}
|
|
863
861
|
{displayVideos.length > 0 && (
|
|
864
|
-
<
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
index={index} //TODO: Fix this without index
|
|
873
|
-
onLoadFinish={handleOnFinishVideo}
|
|
874
|
-
onUploadError={handleVideoUploadError}
|
|
875
|
-
isUploaded={item.isUploaded}
|
|
876
|
-
fileId={item.fileId}
|
|
877
|
-
thumbNail={item.thumbNail as string}
|
|
878
|
-
fileCount={displayVideos.length}
|
|
879
|
-
isEditMode={isEditMode}
|
|
880
|
-
postId={item.postId}
|
|
881
|
-
setIsUploading={setIsUploading}
|
|
882
|
-
/>
|
|
883
|
-
);
|
|
884
|
-
}}
|
|
885
|
-
numColumns={3}
|
|
862
|
+
<SelectedMediaComponent
|
|
863
|
+
mediaType="video"
|
|
864
|
+
media={displayVideos}
|
|
865
|
+
onClose={handleOnCloseVideo}
|
|
866
|
+
onLoadFinish={handleOnFinishVideo}
|
|
867
|
+
onUploadError={handleVideoUploadError}
|
|
868
|
+
isEditMode={isEditMode}
|
|
869
|
+
setIsUploading={setIsUploading}
|
|
886
870
|
/>
|
|
887
871
|
)}
|
|
888
872
|
</View>
|
package/src/social/features/post/components/DetailedMediaAttachment/DetailedMediaAttachment.tsx
CHANGED
|
@@ -18,6 +18,9 @@ type AmityDetailedMediaAttachmentComponentType = {
|
|
|
18
18
|
onPressVideo: () => void;
|
|
19
19
|
chosenMediaType?: mediaAttachment;
|
|
20
20
|
onHeightChange?: (height: number) => void;
|
|
21
|
+
/** When the 10-attachment cap is reached, the camera + gallery icons are
|
|
22
|
+
* disabled and untappable (PDT-4310 / PDT-4312). */
|
|
23
|
+
disabled?: boolean;
|
|
21
24
|
};
|
|
22
25
|
|
|
23
26
|
const AmityDetailedMediaAttachmentComponent: FC<
|
|
@@ -28,6 +31,7 @@ const AmityDetailedMediaAttachmentComponent: FC<
|
|
|
28
31
|
onPressVideo,
|
|
29
32
|
chosenMediaType,
|
|
30
33
|
onHeightChange,
|
|
34
|
+
disabled = false,
|
|
31
35
|
}) => {
|
|
32
36
|
const pageId = PageID.post_composer_page;
|
|
33
37
|
const componentId = ComponentID.detailed_media_attachment;
|
|
@@ -91,8 +95,9 @@ const AmityDetailedMediaAttachmentComponent: FC<
|
|
|
91
95
|
<Pressable
|
|
92
96
|
testID={cameraElement.accessibilityId}
|
|
93
97
|
accessibilityLabel={cameraElement.accessibilityId}
|
|
94
|
-
style={styles.mediaAttachmentBtn}
|
|
98
|
+
style={[styles.mediaAttachmentBtn, disabled && { opacity: 0.4 }]}
|
|
95
99
|
onPress={onPressCamera}
|
|
100
|
+
disabled={disabled}
|
|
96
101
|
>
|
|
97
102
|
<View style={styles.iconContainer}>
|
|
98
103
|
<SvgXml
|
|
@@ -115,8 +120,9 @@ const AmityDetailedMediaAttachmentComponent: FC<
|
|
|
115
120
|
<Pressable
|
|
116
121
|
testID={imageElement.accessibilityId}
|
|
117
122
|
accessibilityLabel={imageElement.accessibilityId}
|
|
118
|
-
style={styles.mediaAttachmentBtn}
|
|
123
|
+
style={[styles.mediaAttachmentBtn, disabled && { opacity: 0.4 }]}
|
|
119
124
|
onPress={onPressImage}
|
|
125
|
+
disabled={disabled}
|
|
120
126
|
>
|
|
121
127
|
<View style={styles.iconContainer}>
|
|
122
128
|
<SvgXml
|
|
@@ -139,8 +145,9 @@ const AmityDetailedMediaAttachmentComponent: FC<
|
|
|
139
145
|
<Pressable
|
|
140
146
|
testID={videoElement.accessibilityId}
|
|
141
147
|
accessibilityLabel={videoElement.accessibilityId}
|
|
142
|
-
style={styles.mediaAttachmentBtn}
|
|
148
|
+
style={[styles.mediaAttachmentBtn, disabled && { opacity: 0.4 }]}
|
|
143
149
|
onPress={onPressVideo}
|
|
150
|
+
disabled={disabled}
|
|
144
151
|
>
|
|
145
152
|
<View style={styles.iconContainer}>
|
|
146
153
|
<SvgXml
|
|
@@ -17,6 +17,9 @@ type AmityMediaAttachmentComponentType = {
|
|
|
17
17
|
onPressVideo: () => void;
|
|
18
18
|
chosenMediaType?: mediaAttachment;
|
|
19
19
|
onHeightChange?: (height: number) => void;
|
|
20
|
+
/** When the 10-attachment cap is reached, the camera + gallery icons are
|
|
21
|
+
* disabled and untappable (PDT-4310 / PDT-4312). */
|
|
22
|
+
disabled?: boolean;
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
const AmityMediaAttachmentComponent: FC<AmityMediaAttachmentComponentType> = ({
|
|
@@ -25,6 +28,7 @@ const AmityMediaAttachmentComponent: FC<AmityMediaAttachmentComponentType> = ({
|
|
|
25
28
|
onPressVideo,
|
|
26
29
|
chosenMediaType,
|
|
27
30
|
onHeightChange,
|
|
31
|
+
disabled = false,
|
|
28
32
|
}) => {
|
|
29
33
|
const pageId = PageID.post_composer_page;
|
|
30
34
|
const componentId = ComponentID.media_attachment;
|
|
@@ -89,8 +93,9 @@ const AmityMediaAttachmentComponent: FC<AmityMediaAttachmentComponentType> = ({
|
|
|
89
93
|
testID={cameraElement.accessibilityId}
|
|
90
94
|
accessibilityLabel={cameraElement.accessibilityId}
|
|
91
95
|
onPress={onPressCamera}
|
|
96
|
+
disabled={disabled}
|
|
92
97
|
>
|
|
93
|
-
<View style={styles.iconContainer}>
|
|
98
|
+
<View style={[styles.iconContainer, disabled && { opacity: 0.4 }]}>
|
|
94
99
|
<SvgXml
|
|
95
100
|
xml={camera()}
|
|
96
101
|
width={24}
|
|
@@ -107,8 +112,11 @@ const AmityMediaAttachmentComponent: FC<AmityMediaAttachmentComponentType> = ({
|
|
|
107
112
|
testID={imageElement.accessibilityId}
|
|
108
113
|
accessibilityLabel={imageElement.accessibilityId}
|
|
109
114
|
onPress={onPressImage}
|
|
115
|
+
disabled={disabled}
|
|
110
116
|
>
|
|
111
|
-
<View
|
|
117
|
+
<View
|
|
118
|
+
style={[styles.iconContainer, disabled && { opacity: 0.4 }]}
|
|
119
|
+
>
|
|
112
120
|
<SvgXml
|
|
113
121
|
xml={photo()}
|
|
114
122
|
width={24}
|
|
@@ -124,8 +132,11 @@ const AmityMediaAttachmentComponent: FC<AmityMediaAttachmentComponentType> = ({
|
|
|
124
132
|
testID={videoElement.accessibilityId}
|
|
125
133
|
accessibilityLabel={videoElement.accessibilityId}
|
|
126
134
|
onPress={onPressVideo}
|
|
135
|
+
disabled={disabled}
|
|
127
136
|
>
|
|
128
|
-
<View
|
|
137
|
+
<View
|
|
138
|
+
style={[styles.iconContainer, disabled && { opacity: 0.4 }]}
|
|
139
|
+
>
|
|
129
140
|
<SvgXml
|
|
130
141
|
xml={video()}
|
|
131
142
|
width={24}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type FrameRatio = '16:9' | '1:1' | '4:5';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Numeric aspect ratio (width / height) for each frame ratio.
|
|
5
|
+
* React Native's `aspectRatio` style takes a number, unlike web's CSS string.
|
|
6
|
+
*/
|
|
7
|
+
export const FRAME_RATIO_VALUE: Record<FrameRatio, number> = {
|
|
8
|
+
'16:9': 16 / 9,
|
|
9
|
+
'1:1': 1,
|
|
10
|
+
'4:5': 4 / 5,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const LANDSCAPE_THRESHOLD = 1.25;
|
|
14
|
+
const PORTRAIT_THRESHOLD = 0.8;
|
|
15
|
+
|
|
16
|
+
export const DEFAULT_FRAME_RATIO: FrameRatio = '1:1';
|
|
17
|
+
|
|
18
|
+
export function getFrameRatio(width?: number, height?: number): FrameRatio {
|
|
19
|
+
if (!width || !height || height <= 0) return DEFAULT_FRAME_RATIO;
|
|
20
|
+
|
|
21
|
+
const ratio = width / height;
|
|
22
|
+
|
|
23
|
+
if (ratio >= LANDSCAPE_THRESHOLD) return '16:9';
|
|
24
|
+
if (ratio <= PORTRAIT_THRESHOLD) return '4:5';
|
|
25
|
+
return '1:1';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Swap width/height when a video is rotated 90/270 degrees so the frame ratio
|
|
30
|
+
* reflects how the video is actually displayed. Mirrors web getVideoDisplayDims.
|
|
31
|
+
*/
|
|
32
|
+
export function getVideoDisplayDims(video?: {
|
|
33
|
+
width?: number;
|
|
34
|
+
height?: number;
|
|
35
|
+
rotation?: number;
|
|
36
|
+
}): { width?: number; height?: number } {
|
|
37
|
+
const { width, height, rotation } = video ?? {};
|
|
38
|
+
if (width == null || height == null) return { width, height };
|
|
39
|
+
if (Math.abs(rotation ?? 0) % 180 === 90)
|
|
40
|
+
return { width: height, height: width };
|
|
41
|
+
return { width, height };
|
|
42
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { MAX_INDICATOR_DOTS } from '../constants';
|
|
2
|
+
|
|
3
|
+
export type IndicatorDotState = 'active' | 'inactive' | 'edge';
|
|
4
|
+
|
|
5
|
+
export type IndicatorDot = {
|
|
6
|
+
key: string;
|
|
7
|
+
state: IndicatorDotState;
|
|
8
|
+
side?: 'left' | 'right';
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type IndicatorConfig = {
|
|
12
|
+
dots: IndicatorDot[];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function getIndicatorConfig(
|
|
16
|
+
current: number,
|
|
17
|
+
total: number
|
|
18
|
+
): IndicatorConfig {
|
|
19
|
+
if (total <= MAX_INDICATOR_DOTS) {
|
|
20
|
+
const dots = Array.from({ length: total }, (_, page) => ({
|
|
21
|
+
key: `page-${page}`,
|
|
22
|
+
state: page === current ? ('active' as const) : ('inactive' as const),
|
|
23
|
+
}));
|
|
24
|
+
return { dots };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let windowStart: number;
|
|
28
|
+
let windowEnd: number;
|
|
29
|
+
|
|
30
|
+
if (current <= 1) {
|
|
31
|
+
windowStart = 0;
|
|
32
|
+
windowEnd = 4;
|
|
33
|
+
} else if (current >= total - 3) {
|
|
34
|
+
windowStart = total - 5;
|
|
35
|
+
windowEnd = total - 1;
|
|
36
|
+
} else {
|
|
37
|
+
windowStart = current - 1;
|
|
38
|
+
windowEnd = current + 2;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const showLeft = windowStart > 0;
|
|
42
|
+
const showRight = windowEnd < total - 1;
|
|
43
|
+
|
|
44
|
+
const dots: IndicatorDot[] = [];
|
|
45
|
+
|
|
46
|
+
if (showLeft) {
|
|
47
|
+
dots.push({ key: 'edge-left', state: 'edge', side: 'left' });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
for (let page = windowStart; page <= windowEnd; page += 1) {
|
|
51
|
+
dots.push({
|
|
52
|
+
key: `page-${page}`,
|
|
53
|
+
state: page === current ? 'active' : 'inactive',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (showRight) {
|
|
58
|
+
dots.push({ key: 'edge-right', state: 'edge', side: 'right' });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { dots };
|
|
62
|
+
}
|