@technotoil/image-video-editor 0.1.1 → 0.1.2
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/README.md +17 -3
- package/android/src/main/java/com/technotoil/image_videoeditor/FrameGrabberModule.kt +2 -6
- package/android/src/main/java/com/technotoil/image_videoeditor/MediaEditorModule.kt +75 -35
- package/android/src/main/java/com/technotoil/image_videoeditor/MediaLibraryModule.kt +51 -35
- package/android/src/main/java/com/technotoil/image_videoeditor/RNVideoPreviewManager.kt +98 -117
- package/ios/RNMediaEditor.m +38 -7
- package/ios/RNMediaLibrary.m +19 -15
- package/ios/RNVideoPreviewManager.m +2 -0
- package/lib/commonjs/components/VideoEditor.js +100 -32
- package/lib/commonjs/components/VideoEditor.js.map +1 -1
- package/lib/commonjs/screens/CropScreen.js +5 -3
- package/lib/commonjs/screens/CropScreen.js.map +1 -1
- package/lib/commonjs/screens/EditorScreen.js +229 -44
- package/lib/commonjs/screens/EditorScreen.js.map +1 -1
- package/lib/commonjs/screens/PickScreen.js +214 -122
- package/lib/commonjs/screens/PickScreen.js.map +1 -1
- package/lib/module/components/VideoEditor.js +100 -33
- package/lib/module/components/VideoEditor.js.map +1 -1
- package/lib/module/screens/CropScreen.js +5 -3
- package/lib/module/screens/CropScreen.js.map +1 -1
- package/lib/module/screens/EditorScreen.js +229 -44
- package/lib/module/screens/EditorScreen.js.map +1 -1
- package/lib/module/screens/PickScreen.js +215 -123
- package/lib/module/screens/PickScreen.js.map +1 -1
- package/lib/typescript/src/components/VideoEditor.d.ts +10 -2
- package/lib/typescript/src/screens/CropScreen.d.ts +2 -1
- package/lib/typescript/src/screens/EditorScreen.d.ts +2 -1
- package/lib/typescript/src/screens/PickScreen.d.ts +4 -1
- package/lib/typescript/src/types.d.ts +1 -0
- package/package.json +4 -1
- package/src/components/VideoEditor.tsx +68 -11
- package/src/screens/CropScreen.tsx +8 -3
- package/src/screens/EditorScreen.tsx +227 -61
- package/src/screens/PickScreen.tsx +197 -119
- package/src/types.ts +1 -0
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
StyleSheet,
|
|
13
13
|
Text,
|
|
14
14
|
View,
|
|
15
|
+
Dimensions,
|
|
15
16
|
} from 'react-native';
|
|
16
17
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
|
17
18
|
import ImagePicker from 'react-native-image-crop-picker';
|
|
@@ -41,6 +42,7 @@ function formatDuration(ms?: number) {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export function PickScreen({
|
|
45
|
+
isActive = true,
|
|
44
46
|
items,
|
|
45
47
|
onPicked,
|
|
46
48
|
onNext,
|
|
@@ -52,6 +54,8 @@ export function PickScreen({
|
|
|
52
54
|
defaultCameraMode,
|
|
53
55
|
maxSelection = 1,
|
|
54
56
|
aspectRatio = 'free',
|
|
57
|
+
mediaType = 'any',
|
|
58
|
+
mediaTabs = ['GALLERY', 'PHOTO', 'VIDEO'],
|
|
55
59
|
}: {
|
|
56
60
|
items: MediaItem[];
|
|
57
61
|
onPicked: (items: MediaItem[]) => void;
|
|
@@ -64,9 +68,12 @@ export function PickScreen({
|
|
|
64
68
|
defaultCameraMode?: string;
|
|
65
69
|
maxSelection?: number;
|
|
66
70
|
aspectRatio?: '1:1' | '4:3' | '4:5' | '16:9' | '9:16' | 'free';
|
|
71
|
+
mediaType?: 'photo' | 'video' | 'any';
|
|
72
|
+
mediaTabs?: ('GALLERY' | 'PHOTO' | 'VIDEO')[];
|
|
73
|
+
isActive?: boolean;
|
|
67
74
|
}) {
|
|
68
75
|
const insets = useSafeAreaInsets();
|
|
69
|
-
const [tab, setTab] = useState<'GALLERY' | 'PHOTO' | 'VIDEO'>('GALLERY');
|
|
76
|
+
const [tab, setTab] = useState<'GALLERY' | 'PHOTO' | 'VIDEO'>(mediaTabs[0] || 'GALLERY');
|
|
70
77
|
const [activeAlbum, setActiveAlbum] = useState<Album>({ id: 'all', title: 'Recents' });
|
|
71
78
|
const [showAlbumPicker, setShowAlbumPicker] = useState(false);
|
|
72
79
|
const [postType, setPostType] = useState<'POST' | 'STORY' | 'REEL'>('POST');
|
|
@@ -176,18 +183,21 @@ export function PickScreen({
|
|
|
176
183
|
|
|
177
184
|
const loadMedia = async (albumId?: string) => {
|
|
178
185
|
try {
|
|
186
|
+
console.log('loadMedia called with albumId:', albumId);
|
|
179
187
|
setLoading(true);
|
|
180
188
|
const assets = await listMedia({
|
|
181
189
|
limit: 200,
|
|
182
190
|
offset: 0,
|
|
183
|
-
type: 'all',
|
|
191
|
+
type: mediaType === 'photo' ? 'image' : mediaType === 'video' ? 'video' : 'all',
|
|
184
192
|
albumId: albumId === 'all' ? undefined : albumId,
|
|
185
193
|
});
|
|
194
|
+
console.log('loadMedia got assets:', assets.length);
|
|
186
195
|
setLibrary(assets);
|
|
187
196
|
if (assets[0] && !multiSelect) {
|
|
188
197
|
setSelectedMedia(assets[0]);
|
|
189
198
|
}
|
|
190
199
|
} catch (err: any) {
|
|
200
|
+
console.error('loadMedia error:', err);
|
|
191
201
|
Alert.alert('Library error', err?.message ?? 'Failed to load library.');
|
|
192
202
|
} finally {
|
|
193
203
|
setLoading(false);
|
|
@@ -195,9 +205,11 @@ export function PickScreen({
|
|
|
195
205
|
};
|
|
196
206
|
|
|
197
207
|
useEffect(() => {
|
|
208
|
+
console.log('PickScreen mounted!');
|
|
198
209
|
(async () => {
|
|
199
210
|
try {
|
|
200
211
|
const ok = await requestMediaAccess();
|
|
212
|
+
console.log('requestMediaAccess ok?', ok);
|
|
201
213
|
if (!ok) {
|
|
202
214
|
Alert.alert('Permission needed', 'Allow photo access to continue.');
|
|
203
215
|
return;
|
|
@@ -224,6 +236,20 @@ export function PickScreen({
|
|
|
224
236
|
return [cameraItem, ...list];
|
|
225
237
|
}, [library, tab]);
|
|
226
238
|
|
|
239
|
+
const listData = useMemo(() => {
|
|
240
|
+
const rows = Array.from({ length: Math.ceil(filtered.length / 4) }).map((_, i) => ({
|
|
241
|
+
id: `row_${i}`,
|
|
242
|
+
type: 'row',
|
|
243
|
+
items: filtered.slice(i * 4, i * 4 + 4),
|
|
244
|
+
}));
|
|
245
|
+
|
|
246
|
+
return [
|
|
247
|
+
{ id: 'header_preview', type: 'preview' },
|
|
248
|
+
{ id: 'header_albumRow', type: 'albumRow' },
|
|
249
|
+
...rows
|
|
250
|
+
];
|
|
251
|
+
}, [filtered]);
|
|
252
|
+
|
|
227
253
|
useEffect(() => {
|
|
228
254
|
let cancelled = false;
|
|
229
255
|
setVideoPaused(false);
|
|
@@ -236,6 +262,7 @@ export function PickScreen({
|
|
|
236
262
|
setPreviewUri(selectedMedia.uri);
|
|
237
263
|
return;
|
|
238
264
|
}
|
|
265
|
+
setPreviewUri(null);
|
|
239
266
|
try {
|
|
240
267
|
const fileUri = await exportAsset(selectedMedia.id);
|
|
241
268
|
if (!cancelled) setPreviewUri(fileUri);
|
|
@@ -250,25 +277,36 @@ export function PickScreen({
|
|
|
250
277
|
|
|
251
278
|
const playableUri = useMemo(() => {
|
|
252
279
|
if (!selectedMedia) return null;
|
|
253
|
-
if (previewUri
|
|
254
|
-
|
|
255
|
-
return null;
|
|
280
|
+
if (previewUri) return previewUri;
|
|
281
|
+
return selectedMedia.uri;
|
|
256
282
|
}, [previewUri, selectedMedia]);
|
|
257
283
|
|
|
258
284
|
const toggleMultiSelect = () => {
|
|
259
|
-
setMultiSelect((v) =>
|
|
260
|
-
|
|
285
|
+
setMultiSelect((v) => {
|
|
286
|
+
if (!v && selectedMedia) {
|
|
287
|
+
setSelectedItems([selectedMedia]);
|
|
288
|
+
} else {
|
|
289
|
+
setSelectedItems([]);
|
|
290
|
+
}
|
|
291
|
+
return !v;
|
|
292
|
+
});
|
|
261
293
|
};
|
|
262
294
|
|
|
263
295
|
const handleSelectItem = (item: MediaItem) => {
|
|
264
|
-
setSelectedMedia(item);
|
|
265
296
|
if (multiSelect) {
|
|
266
297
|
setSelectedItems((prev) => {
|
|
267
298
|
const exists = prev.find((i) => i.id === item.id);
|
|
268
|
-
if (exists)
|
|
299
|
+
if (exists) {
|
|
300
|
+
const newItems = prev.filter((i) => i.id !== item.id);
|
|
301
|
+
setSelectedMedia(newItems.length > 0 ? newItems[newItems.length - 1] : null);
|
|
302
|
+
return newItems;
|
|
303
|
+
}
|
|
269
304
|
if (prev.length >= maxSelection) return prev;
|
|
305
|
+
setSelectedMedia(item);
|
|
270
306
|
return [...prev, item];
|
|
271
307
|
});
|
|
308
|
+
} else {
|
|
309
|
+
setSelectedMedia(item);
|
|
272
310
|
}
|
|
273
311
|
|
|
274
312
|
Animated.sequence([
|
|
@@ -497,127 +535,167 @@ export function PickScreen({
|
|
|
497
535
|
</View>
|
|
498
536
|
</Modal>
|
|
499
537
|
|
|
500
|
-
<Animated.View
|
|
501
|
-
style={[
|
|
502
|
-
styles.preview,
|
|
503
|
-
{ transform: [{ scale: scaleAnim }] },
|
|
504
|
-
isRatioLocked && previewAspectRatio
|
|
505
|
-
? { height: undefined, aspectRatio: previewAspectRatio }
|
|
506
|
-
: {},
|
|
507
|
-
]}
|
|
508
|
-
>
|
|
509
|
-
{selectedMedia?.type === 'video' ? (
|
|
510
|
-
<Pressable style={styles.previewImage} onPress={() => setVideoPaused((v) => !v)}>
|
|
511
|
-
{playableUri ? (
|
|
512
|
-
<VideoPreview
|
|
513
|
-
uri={playableUri}
|
|
514
|
-
paused={videoPaused}
|
|
515
|
-
muted={false}
|
|
516
|
-
style={styles.previewImage}
|
|
517
|
-
resizeMode="cover"
|
|
518
|
-
/>
|
|
519
|
-
) : (
|
|
520
|
-
<Image
|
|
521
|
-
source={{ uri: selectedMedia.thumbnailUri || selectedMedia.uri }}
|
|
522
|
-
style={styles.previewImage}
|
|
523
|
-
resizeMode="cover"
|
|
524
|
-
/>
|
|
525
|
-
)}
|
|
526
|
-
<View style={styles.previewOverlay}>
|
|
527
|
-
<View style={styles.playPauseCircle}>
|
|
528
|
-
<Ionicons name={videoPaused ? 'play' : 'pause'} size={24} color="#fff" />
|
|
529
|
-
</View>
|
|
530
|
-
</View>
|
|
531
|
-
</Pressable>
|
|
532
|
-
) : (
|
|
533
|
-
<Image
|
|
534
|
-
source={{ uri: previewUri ?? selectedMedia?.uri }}
|
|
535
|
-
style={[styles.previewImage, cropMode === '1:1' ? styles.squareCrop : styles.originalCrop]}
|
|
536
|
-
resizeMode={isRatioLocked ? 'cover' : (cropMode === '1:1' ? 'cover' : 'contain')}
|
|
537
|
-
/>
|
|
538
|
-
)}
|
|
539
|
-
|
|
540
|
-
<View style={styles.previewControls}>
|
|
541
|
-
{/* Ratio lock badge */}
|
|
542
|
-
{isRatioLocked && (
|
|
543
|
-
<View style={styles.ratioBadge}>
|
|
544
|
-
<Text style={styles.ratioBadgeText}>{aspectRatio}</Text>
|
|
545
|
-
</View>
|
|
546
|
-
)}
|
|
547
|
-
|
|
548
|
-
{/* Crop toggle — hidden when ratio is locked */}
|
|
549
|
-
{!isRatioLocked && (
|
|
550
|
-
<Pressable
|
|
551
|
-
style={styles.cropToggle}
|
|
552
|
-
onPress={() => setCropMode((v) => (v === '1:1' ? 'original' : '1:1'))}
|
|
553
|
-
>
|
|
554
|
-
<Ionicons
|
|
555
|
-
name={cropMode === '1:1' ? 'square-outline' : 'expand-outline'}
|
|
556
|
-
size={20}
|
|
557
|
-
color="#fff"
|
|
558
|
-
/>
|
|
559
|
-
</Pressable>
|
|
560
|
-
)}
|
|
561
|
-
</View>
|
|
562
|
-
</Animated.View>
|
|
563
|
-
|
|
564
|
-
<View style={styles.albumRow}>
|
|
565
|
-
<Pressable
|
|
566
|
-
style={styles.albumSelector}
|
|
567
|
-
onPress={() => setShowAlbumPicker((v) => !v)}
|
|
568
|
-
>
|
|
569
|
-
<Text style={styles.albumTitle}>{activeAlbum.title}</Text>
|
|
570
|
-
<Ionicons name="chevron-down" size={16} color="#fff" style={{ marginLeft: 6 }} />
|
|
571
|
-
</Pressable>
|
|
572
|
-
|
|
573
|
-
{/* Only show Select/Done button when maxSelection > 1 */}
|
|
574
|
-
{maxSelection > 1 && (
|
|
575
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
576
|
-
{multiSelect && (
|
|
577
|
-
<Text style={{ color: '#3b82f6', fontSize: 12, fontWeight: '700' }}>
|
|
578
|
-
{selectedItems.length}/{maxSelection}
|
|
579
|
-
</Text>
|
|
580
|
-
)}
|
|
581
|
-
<Pressable
|
|
582
|
-
style={[
|
|
583
|
-
styles.multiSelectBtn,
|
|
584
|
-
multiSelect && styles.multiSelectBtnActive,
|
|
585
|
-
multiSelect && selectedItems.length === 0 && { opacity: 0.35 },
|
|
586
|
-
]}
|
|
587
|
-
onPress={() => {
|
|
588
|
-
if (multiSelect) {
|
|
589
|
-
handleNext();
|
|
590
|
-
} else {
|
|
591
|
-
toggleMultiSelect();
|
|
592
|
-
}
|
|
593
|
-
}}
|
|
594
|
-
disabled={multiSelect && selectedItems.length === 0}
|
|
595
|
-
>
|
|
596
|
-
<Text style={[
|
|
597
|
-
styles.multiSelectText,
|
|
598
|
-
multiSelect && styles.multiSelectTextActive,
|
|
599
|
-
]}>{multiSelect ? 'Done' : 'Select'}</Text>
|
|
600
|
-
</Pressable>
|
|
601
|
-
</View>
|
|
602
|
-
)}
|
|
603
|
-
</View>
|
|
604
|
-
|
|
605
538
|
<FlatList
|
|
606
|
-
data={
|
|
539
|
+
data={listData}
|
|
540
|
+
extraData={{
|
|
541
|
+
selectedMedia,
|
|
542
|
+
previewUri,
|
|
543
|
+
playableUri,
|
|
544
|
+
videoPaused,
|
|
545
|
+
cropMode,
|
|
546
|
+
isRatioLocked,
|
|
547
|
+
activeAlbum,
|
|
548
|
+
multiSelect,
|
|
549
|
+
selectedItems,
|
|
550
|
+
showAlbumPicker,
|
|
551
|
+
loading
|
|
552
|
+
}}
|
|
607
553
|
keyExtractor={(item) => item.id}
|
|
608
|
-
|
|
554
|
+
stickyHeaderIndices={[1]}
|
|
609
555
|
style={styles.libraryList}
|
|
610
|
-
renderItem={renderThumb}
|
|
611
556
|
contentContainerStyle={styles.grid}
|
|
557
|
+
getItemLayout={(data, index) => {
|
|
558
|
+
const previewHeight = isRatioLocked && previewAspectRatio
|
|
559
|
+
? Dimensions.get('window').width / previewAspectRatio
|
|
560
|
+
: 420;
|
|
561
|
+
const albumRowHeight = 48;
|
|
562
|
+
const rowHeight = Dimensions.get('window').width / 4;
|
|
563
|
+
|
|
564
|
+
if (index === 0) return { length: previewHeight, offset: 0, index };
|
|
565
|
+
if (index === 1) return { length: albumRowHeight, offset: previewHeight, index };
|
|
566
|
+
|
|
567
|
+
const offset = previewHeight + albumRowHeight + (index - 2) * rowHeight;
|
|
568
|
+
return { length: rowHeight, offset, index };
|
|
569
|
+
}}
|
|
570
|
+
removeClippedSubviews={false}
|
|
571
|
+
windowSize={11}
|
|
612
572
|
ListEmptyComponent={
|
|
613
573
|
<View style={styles.empty}>
|
|
614
574
|
<Text style={styles.emptyText}>{loading ? 'Loading…' : 'No media found'}</Text>
|
|
615
575
|
</View>
|
|
616
576
|
}
|
|
577
|
+
renderItem={({ item }) => {
|
|
578
|
+
if (item.type === 'preview') {
|
|
579
|
+
const previewStyleHeight = isRatioLocked && previewAspectRatio
|
|
580
|
+
? Dimensions.get('window').width / previewAspectRatio
|
|
581
|
+
: 420;
|
|
582
|
+
|
|
583
|
+
return (
|
|
584
|
+
<Animated.View
|
|
585
|
+
style={[
|
|
586
|
+
styles.preview,
|
|
587
|
+
{ transform: [{ scale: scaleAnim }], height: previewStyleHeight },
|
|
588
|
+
]}
|
|
589
|
+
>
|
|
590
|
+
{selectedMedia?.type === 'video' ? (
|
|
591
|
+
<Pressable style={styles.previewImage} onPress={() => setVideoPaused((v) => !v)}>
|
|
592
|
+
{playableUri && isActive ? (
|
|
593
|
+
<VideoPreview
|
|
594
|
+
uri={playableUri}
|
|
595
|
+
paused={videoPaused || !isActive}
|
|
596
|
+
muted={false}
|
|
597
|
+
style={styles.previewImage}
|
|
598
|
+
resizeMode="cover"
|
|
599
|
+
/>
|
|
600
|
+
) : (
|
|
601
|
+
<Image
|
|
602
|
+
source={{ uri: selectedMedia.thumbnailUri || selectedMedia.uri }}
|
|
603
|
+
style={styles.previewImage}
|
|
604
|
+
resizeMode="cover"
|
|
605
|
+
/>
|
|
606
|
+
)}
|
|
607
|
+
<View style={styles.previewOverlay}>
|
|
608
|
+
<View style={styles.playPauseCircle}>
|
|
609
|
+
<Ionicons name={videoPaused ? 'play' : 'pause'} size={24} color="#fff" />
|
|
610
|
+
</View>
|
|
611
|
+
</View>
|
|
612
|
+
</Pressable>
|
|
613
|
+
) : (
|
|
614
|
+
<Image
|
|
615
|
+
source={{ uri: previewUri ?? selectedMedia?.uri }}
|
|
616
|
+
style={[styles.previewImage, cropMode === '1:1' ? styles.squareCrop : styles.originalCrop]}
|
|
617
|
+
resizeMode={isRatioLocked ? 'cover' : (cropMode === '1:1' ? 'cover' : 'contain')}
|
|
618
|
+
/>
|
|
619
|
+
)}
|
|
620
|
+
|
|
621
|
+
<View style={styles.previewControls}>
|
|
622
|
+
{isRatioLocked && (
|
|
623
|
+
<View style={styles.ratioBadge}>
|
|
624
|
+
<Text style={styles.ratioBadgeText}>{aspectRatio}</Text>
|
|
625
|
+
</View>
|
|
626
|
+
)}
|
|
627
|
+
|
|
628
|
+
{!isRatioLocked && (
|
|
629
|
+
<Pressable
|
|
630
|
+
style={styles.cropToggle}
|
|
631
|
+
onPress={() => setCropMode((v) => (v === '1:1' ? 'original' : '1:1'))}
|
|
632
|
+
>
|
|
633
|
+
<Ionicons
|
|
634
|
+
name={cropMode === '1:1' ? 'square-outline' : 'expand-outline'}
|
|
635
|
+
size={20}
|
|
636
|
+
color="#fff"
|
|
637
|
+
/>
|
|
638
|
+
</Pressable>
|
|
639
|
+
)}
|
|
640
|
+
</View>
|
|
641
|
+
</Animated.View>
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (item.type === 'albumRow') {
|
|
646
|
+
return (
|
|
647
|
+
<View style={[styles.albumRow, { backgroundColor: '#0b0f1a', zIndex: 999, elevation: 5 }]}>
|
|
648
|
+
<Pressable
|
|
649
|
+
style={styles.albumSelector}
|
|
650
|
+
onPress={() => setShowAlbumPicker((v) => !v)}
|
|
651
|
+
>
|
|
652
|
+
<Text style={styles.albumTitle}>{activeAlbum.title}</Text>
|
|
653
|
+
<Ionicons name="chevron-down" size={16} color="#fff" style={{ marginLeft: 6 }} />
|
|
654
|
+
</Pressable>
|
|
655
|
+
|
|
656
|
+
{maxSelection > 1 && (
|
|
657
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
658
|
+
{multiSelect && (
|
|
659
|
+
<Text style={{ color: '#3b82f6', fontSize: 12, fontWeight: '700' }}>
|
|
660
|
+
{selectedItems.length}/{maxSelection}
|
|
661
|
+
</Text>
|
|
662
|
+
)}
|
|
663
|
+
<Pressable
|
|
664
|
+
style={[
|
|
665
|
+
styles.multiSelectBtn,
|
|
666
|
+
multiSelect && styles.multiSelectBtnActive,
|
|
667
|
+
multiSelect && selectedItems.length === 0 && { opacity: 0.35 },
|
|
668
|
+
]}
|
|
669
|
+
onPress={() => {
|
|
670
|
+
if (multiSelect) {
|
|
671
|
+
handleNext();
|
|
672
|
+
} else {
|
|
673
|
+
toggleMultiSelect();
|
|
674
|
+
}
|
|
675
|
+
}}
|
|
676
|
+
disabled={multiSelect && selectedItems.length === 0}
|
|
677
|
+
>
|
|
678
|
+
<Text style={[
|
|
679
|
+
styles.multiSelectText,
|
|
680
|
+
multiSelect && styles.multiSelectTextActive,
|
|
681
|
+
]}>{multiSelect ? 'Done' : 'Select multiple'}</Text>
|
|
682
|
+
</Pressable>
|
|
683
|
+
</View>
|
|
684
|
+
)}
|
|
685
|
+
</View>
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
return (
|
|
690
|
+
<View style={{ flexDirection: 'row' }}>
|
|
691
|
+
{(item as any).items.map((mediaItem: any) => renderThumb({ item: mediaItem }))}
|
|
692
|
+
</View>
|
|
693
|
+
);
|
|
694
|
+
}}
|
|
617
695
|
/>
|
|
618
696
|
|
|
619
697
|
<View style={styles.tabBar}>
|
|
620
|
-
{
|
|
698
|
+
{mediaTabs.filter(t => mediaType === 'any' || (mediaType === 'photo' && t !== 'VIDEO') || (mediaType === 'video' && t !== 'PHOTO')).map((t) => (
|
|
621
699
|
<Pressable key={t} onPress={() => setTab(t)}>
|
|
622
700
|
<Text style={[styles.tab, tab === t && styles.tabActive]}>{t}</Text>
|
|
623
701
|
</Pressable>
|
|
@@ -876,7 +954,7 @@ const styles = StyleSheet.create({
|
|
|
876
954
|
justifyContent: 'space-between',
|
|
877
955
|
alignItems: 'center',
|
|
878
956
|
paddingHorizontal: 16,
|
|
879
|
-
|
|
957
|
+
height: 48,
|
|
880
958
|
},
|
|
881
959
|
albumSelector: { flexDirection: 'row', alignItems: 'center' },
|
|
882
960
|
albumTitle: { fontSize: 16, fontWeight: '700', color: '#fff' },
|