@technotoil/image-video-editor 0.1.1 → 0.1.3

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 (47) hide show
  1. package/README.md +17 -3
  2. package/android/src/main/java/com/technotoil/image_videoeditor/FrameGrabberModule.kt +2 -6
  3. package/android/src/main/java/com/technotoil/image_videoeditor/MediaEditorModule.kt +103 -37
  4. package/android/src/main/java/com/technotoil/image_videoeditor/MediaLibraryModule.kt +51 -35
  5. package/android/src/main/java/com/technotoil/image_videoeditor/RNVideoPreviewManager.kt +98 -117
  6. package/ios/RNMediaEditor.m +38 -7
  7. package/ios/RNMediaLibrary.m +19 -15
  8. package/ios/RNVideoPreviewManager.m +2 -0
  9. package/lib/commonjs/components/Icon.js +31 -0
  10. package/lib/commonjs/components/Icon.js.map +1 -0
  11. package/lib/commonjs/components/VideoEditor.js +97 -32
  12. package/lib/commonjs/components/VideoEditor.js.map +1 -1
  13. package/lib/commonjs/icons.js +35 -0
  14. package/lib/commonjs/icons.js.map +1 -0
  15. package/lib/commonjs/screens/CropScreen.js +5 -3
  16. package/lib/commonjs/screens/CropScreen.js.map +1 -1
  17. package/lib/commonjs/screens/EditorScreen.js +269 -84
  18. package/lib/commonjs/screens/EditorScreen.js.map +1 -1
  19. package/lib/commonjs/screens/PickScreen.js +221 -129
  20. package/lib/commonjs/screens/PickScreen.js.map +1 -1
  21. package/lib/module/components/Icon.js +25 -0
  22. package/lib/module/components/Icon.js.map +1 -0
  23. package/lib/module/components/VideoEditor.js +98 -33
  24. package/lib/module/components/VideoEditor.js.map +1 -1
  25. package/lib/module/icons.js +31 -0
  26. package/lib/module/icons.js.map +1 -0
  27. package/lib/module/screens/CropScreen.js +5 -3
  28. package/lib/module/screens/CropScreen.js.map +1 -1
  29. package/lib/module/screens/EditorScreen.js +230 -45
  30. package/lib/module/screens/EditorScreen.js.map +1 -1
  31. package/lib/module/screens/PickScreen.js +216 -124
  32. package/lib/module/screens/PickScreen.js.map +1 -1
  33. package/lib/typescript/src/components/Icon.d.ts +11 -0
  34. package/lib/typescript/src/components/VideoEditor.d.ts +10 -2
  35. package/lib/typescript/src/icons.d.ts +28 -0
  36. package/lib/typescript/src/screens/CropScreen.d.ts +2 -1
  37. package/lib/typescript/src/screens/EditorScreen.d.ts +2 -1
  38. package/lib/typescript/src/screens/PickScreen.d.ts +4 -1
  39. package/lib/typescript/src/types.d.ts +1 -0
  40. package/package.json +4 -4
  41. package/src/components/Icon.tsx +19 -0
  42. package/src/components/VideoEditor.tsx +67 -11
  43. package/src/icons.ts +28 -0
  44. package/src/screens/CropScreen.tsx +8 -3
  45. package/src/screens/EditorScreen.tsx +228 -62
  46. package/src/screens/PickScreen.tsx +198 -120
  47. package/src/types.ts +1 -0
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.PickScreen = PickScreen;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
- var _Ionicons = _interopRequireDefault(require("react-native-vector-icons/Ionicons"));
9
+ var _Icon = require("../components/Icon");
10
10
  var _reactNativeImageCropPicker = _interopRequireDefault(require("react-native-image-crop-picker"));
11
11
  var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
12
12
  var _CameraView = require("../native/CameraView");
@@ -56,6 +56,7 @@ function formatDuration(ms) {
56
56
  return `${m}:${s.toString().padStart(2, '0')}`;
57
57
  }
58
58
  function PickScreen({
59
+ isActive = true,
59
60
  items,
60
61
  onPicked,
61
62
  onNext,
@@ -66,10 +67,12 @@ function PickScreen({
66
67
  onCameraModeChange,
67
68
  defaultCameraMode,
68
69
  maxSelection = 1,
69
- aspectRatio = 'free'
70
+ aspectRatio = 'free',
71
+ mediaType = 'any',
72
+ mediaTabs = ['GALLERY', 'PHOTO', 'VIDEO']
70
73
  }) {
71
74
  const insets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
72
- const [tab, setTab] = (0, _react.useState)('GALLERY');
75
+ const [tab, setTab] = (0, _react.useState)(mediaTabs[0] || 'GALLERY');
73
76
  const [activeAlbum, setActiveAlbum] = (0, _react.useState)({
74
77
  id: 'all',
75
78
  title: 'Recents'
@@ -173,27 +176,32 @@ function PickScreen({
173
176
  };
174
177
  const loadMedia = async albumId => {
175
178
  try {
179
+ console.log('loadMedia called with albumId:', albumId);
176
180
  setLoading(true);
177
181
  const assets = await (0, _MediaLibrary.listMedia)({
178
182
  limit: 200,
179
183
  offset: 0,
180
- type: 'all',
184
+ type: mediaType === 'photo' ? 'image' : mediaType === 'video' ? 'video' : 'all',
181
185
  albumId: albumId === 'all' ? undefined : albumId
182
186
  });
187
+ console.log('loadMedia got assets:', assets.length);
183
188
  setLibrary(assets);
184
189
  if (assets[0] && !multiSelect) {
185
190
  setSelectedMedia(assets[0]);
186
191
  }
187
192
  } catch (err) {
193
+ console.error('loadMedia error:', err);
188
194
  _reactNative.Alert.alert('Library error', err?.message ?? 'Failed to load library.');
189
195
  } finally {
190
196
  setLoading(false);
191
197
  }
192
198
  };
193
199
  (0, _react.useEffect)(() => {
200
+ console.log('PickScreen mounted!');
194
201
  (async () => {
195
202
  try {
196
203
  const ok = await (0, _MediaLibrary.requestMediaAccess)();
204
+ console.log('requestMediaAccess ok?', ok);
197
205
  if (!ok) {
198
206
  _reactNative.Alert.alert('Permission needed', 'Allow photo access to continue.');
199
207
  return;
@@ -219,6 +227,22 @@ function PickScreen({
219
227
  };
220
228
  return [cameraItem, ...list];
221
229
  }, [library, tab]);
230
+ const listData = (0, _react.useMemo)(() => {
231
+ const rows = Array.from({
232
+ length: Math.ceil(filtered.length / 4)
233
+ }).map((_, i) => ({
234
+ id: `row_${i}`,
235
+ type: 'row',
236
+ items: filtered.slice(i * 4, i * 4 + 4)
237
+ }));
238
+ return [{
239
+ id: 'header_preview',
240
+ type: 'preview'
241
+ }, {
242
+ id: 'header_albumRow',
243
+ type: 'albumRow'
244
+ }, ...rows];
245
+ }, [filtered]);
222
246
  (0, _react.useEffect)(() => {
223
247
  let cancelled = false;
224
248
  setVideoPaused(false);
@@ -231,6 +255,7 @@ function PickScreen({
231
255
  setPreviewUri(selectedMedia.uri);
232
256
  return;
233
257
  }
258
+ setPreviewUri(null);
234
259
  try {
235
260
  const fileUri = await (0, _MediaLibrary.exportAsset)(selectedMedia.id);
236
261
  if (!cancelled) setPreviewUri(fileUri);
@@ -244,23 +269,34 @@ function PickScreen({
244
269
  }, [selectedMedia]);
245
270
  const playableUri = (0, _react.useMemo)(() => {
246
271
  if (!selectedMedia) return null;
247
- if (previewUri && !previewUri.startsWith('ph://') && !previewUri.startsWith('content://')) return previewUri;
248
- if (selectedMedia.uri && !selectedMedia.uri.startsWith('ph://') && !selectedMedia.uri.startsWith('content://')) return selectedMedia.uri;
249
- return null;
272
+ if (previewUri) return previewUri;
273
+ return selectedMedia.uri;
250
274
  }, [previewUri, selectedMedia]);
251
275
  const toggleMultiSelect = () => {
252
- setMultiSelect(v => !v);
253
- setSelectedItems([]);
276
+ setMultiSelect(v => {
277
+ if (!v && selectedMedia) {
278
+ setSelectedItems([selectedMedia]);
279
+ } else {
280
+ setSelectedItems([]);
281
+ }
282
+ return !v;
283
+ });
254
284
  };
255
285
  const handleSelectItem = item => {
256
- setSelectedMedia(item);
257
286
  if (multiSelect) {
258
287
  setSelectedItems(prev => {
259
288
  const exists = prev.find(i => i.id === item.id);
260
- if (exists) return prev.filter(i => i.id !== item.id);
289
+ if (exists) {
290
+ const newItems = prev.filter(i => i.id !== item.id);
291
+ setSelectedMedia(newItems.length > 0 ? newItems[newItems.length - 1] : null);
292
+ return newItems;
293
+ }
261
294
  if (prev.length >= maxSelection) return prev;
295
+ setSelectedMedia(item);
262
296
  return [...prev, item];
263
297
  });
298
+ } else {
299
+ setSelectedMedia(item);
264
300
  }
265
301
  _reactNative.Animated.sequence([_reactNative.Animated.timing(scaleAnim, {
266
302
  toValue: 0.97,
@@ -400,7 +436,7 @@ function PickScreen({
400
436
  }), item.type === 'video' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
401
437
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
402
438
  style: styles.videoPlayBadge,
403
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
439
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
404
440
  name: "play",
405
441
  size: 10,
406
442
  color: "#fff"
@@ -427,7 +463,7 @@ function PickScreen({
427
463
  onNext([]);
428
464
  }
429
465
  },
430
- children: customCancelIcon ? customCancelIcon : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
466
+ children: customCancelIcon ? customCancelIcon : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
431
467
  name: "close",
432
468
  size: 22,
433
469
  color: "#fff"
@@ -470,7 +506,7 @@ function PickScreen({
470
506
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
471
507
  style: [styles.albumSheetOptionText, activeAlbum.id === album.id && styles.albumSheetOptionActive],
472
508
  children: album.title
473
- }), activeAlbum.id === album.id && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
509
+ }), activeAlbum.id === album.id && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
474
510
  name: "checkmark",
475
511
  size: 20,
476
512
  color: "#3b82f6"
@@ -478,129 +514,185 @@ function PickScreen({
478
514
  }, album.id))
479
515
  })]
480
516
  })]
481
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
482
- style: [styles.preview, {
483
- transform: [{
484
- scale: scaleAnim
485
- }]
486
- }, isRatioLocked && previewAspectRatio ? {
487
- height: undefined,
488
- aspectRatio: previewAspectRatio
489
- } : {}],
490
- children: [selectedMedia?.type === 'video' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
491
- style: styles.previewImage,
492
- onPress: () => setVideoPaused(v => !v),
493
- children: [playableUri ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_VideoPreview.VideoPreview, {
494
- uri: playableUri,
495
- paused: videoPaused,
496
- muted: false,
497
- style: styles.previewImage,
498
- resizeMode: "cover"
499
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
500
- source: {
501
- uri: selectedMedia.thumbnailUri || selectedMedia.uri
502
- },
503
- style: styles.previewImage,
504
- resizeMode: "cover"
505
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
506
- style: styles.previewOverlay,
507
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
508
- style: styles.playPauseCircle,
509
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
510
- name: videoPaused ? 'play' : 'pause',
511
- size: 24,
512
- color: "#fff"
513
- })
514
- })
515
- })]
516
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
517
- source: {
518
- uri: previewUri ?? selectedMedia?.uri
519
- },
520
- style: [styles.previewImage, cropMode === '1:1' ? styles.squareCrop : styles.originalCrop],
521
- resizeMode: isRatioLocked ? 'cover' : cropMode === '1:1' ? 'cover' : 'contain'
522
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
523
- style: styles.previewControls,
524
- children: [isRatioLocked && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
525
- style: styles.ratioBadge,
526
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
527
- style: styles.ratioBadgeText,
528
- children: aspectRatio
529
- })
530
- }), !isRatioLocked && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
531
- style: styles.cropToggle,
532
- onPress: () => setCropMode(v => v === '1:1' ? 'original' : '1:1'),
533
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
534
- name: cropMode === '1:1' ? 'square-outline' : 'expand-outline',
535
- size: 20,
536
- color: "#fff"
537
- })
538
- })]
539
- })]
540
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
541
- style: styles.albumRow,
542
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
543
- style: styles.albumSelector,
544
- onPress: () => setShowAlbumPicker(v => !v),
545
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
546
- style: styles.albumTitle,
547
- children: activeAlbum.title
548
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
549
- name: "chevron-down",
550
- size: 16,
551
- color: "#fff",
552
- style: {
553
- marginLeft: 6
554
- }
555
- })]
556
- }), maxSelection > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
557
- style: {
558
- flexDirection: 'row',
559
- alignItems: 'center',
560
- gap: 8
561
- },
562
- children: [multiSelect && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
563
- style: {
564
- color: '#3b82f6',
565
- fontSize: 12,
566
- fontWeight: '700'
567
- },
568
- children: [selectedItems.length, "/", maxSelection]
569
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
570
- style: [styles.multiSelectBtn, multiSelect && styles.multiSelectBtnActive, multiSelect && selectedItems.length === 0 && {
571
- opacity: 0.35
572
- }],
573
- onPress: () => {
574
- if (multiSelect) {
575
- handleNext();
576
- } else {
577
- toggleMultiSelect();
578
- }
579
- },
580
- disabled: multiSelect && selectedItems.length === 0,
581
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
582
- style: [styles.multiSelectText, multiSelect && styles.multiSelectTextActive],
583
- children: multiSelect ? 'Done' : 'Select'
584
- })
585
- })]
586
- })]
587
517
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
588
- data: filtered,
518
+ data: listData,
519
+ extraData: {
520
+ selectedMedia,
521
+ previewUri,
522
+ playableUri,
523
+ videoPaused,
524
+ cropMode,
525
+ isRatioLocked,
526
+ activeAlbum,
527
+ multiSelect,
528
+ selectedItems,
529
+ showAlbumPicker,
530
+ loading
531
+ },
589
532
  keyExtractor: item => item.id,
590
- numColumns: 4,
533
+ stickyHeaderIndices: [1],
591
534
  style: styles.libraryList,
592
- renderItem: renderThumb,
593
535
  contentContainerStyle: styles.grid,
536
+ getItemLayout: (data, index) => {
537
+ const previewHeight = isRatioLocked && previewAspectRatio ? _reactNative.Dimensions.get('window').width / previewAspectRatio : 420;
538
+ const albumRowHeight = 48;
539
+ const rowHeight = _reactNative.Dimensions.get('window').width / 4;
540
+ if (index === 0) return {
541
+ length: previewHeight,
542
+ offset: 0,
543
+ index
544
+ };
545
+ if (index === 1) return {
546
+ length: albumRowHeight,
547
+ offset: previewHeight,
548
+ index
549
+ };
550
+ const offset = previewHeight + albumRowHeight + (index - 2) * rowHeight;
551
+ return {
552
+ length: rowHeight,
553
+ offset,
554
+ index
555
+ };
556
+ },
557
+ removeClippedSubviews: false,
558
+ windowSize: 11,
594
559
  ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
595
560
  style: styles.empty,
596
561
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
597
562
  style: styles.emptyText,
598
563
  children: loading ? 'Loading…' : 'No media found'
599
564
  })
600
- })
565
+ }),
566
+ renderItem: ({
567
+ item
568
+ }) => {
569
+ if (item.type === 'preview') {
570
+ const previewStyleHeight = isRatioLocked && previewAspectRatio ? _reactNative.Dimensions.get('window').width / previewAspectRatio : 420;
571
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
572
+ style: [styles.preview, {
573
+ transform: [{
574
+ scale: scaleAnim
575
+ }],
576
+ height: previewStyleHeight
577
+ }],
578
+ children: [selectedMedia?.type === 'video' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
579
+ style: styles.previewImage,
580
+ onPress: () => setVideoPaused(v => !v),
581
+ children: [playableUri && isActive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_VideoPreview.VideoPreview, {
582
+ uri: playableUri,
583
+ paused: videoPaused || !isActive,
584
+ muted: false,
585
+ style: styles.previewImage,
586
+ resizeMode: "cover"
587
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
588
+ source: {
589
+ uri: selectedMedia.thumbnailUri || selectedMedia.uri
590
+ },
591
+ style: styles.previewImage,
592
+ resizeMode: "cover"
593
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
594
+ style: styles.previewOverlay,
595
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
596
+ style: styles.playPauseCircle,
597
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
598
+ name: videoPaused ? 'play' : 'pause',
599
+ size: 24,
600
+ color: "#fff"
601
+ })
602
+ })
603
+ })]
604
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
605
+ source: {
606
+ uri: previewUri ?? selectedMedia?.uri
607
+ },
608
+ style: [styles.previewImage, cropMode === '1:1' ? styles.squareCrop : styles.originalCrop],
609
+ resizeMode: isRatioLocked ? 'cover' : cropMode === '1:1' ? 'cover' : 'contain'
610
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
611
+ style: styles.previewControls,
612
+ children: [isRatioLocked && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
613
+ style: styles.ratioBadge,
614
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
615
+ style: styles.ratioBadgeText,
616
+ children: aspectRatio
617
+ })
618
+ }), !isRatioLocked && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
619
+ style: styles.cropToggle,
620
+ onPress: () => setCropMode(v => v === '1:1' ? 'original' : '1:1'),
621
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
622
+ name: cropMode === '1:1' ? 'square-outline' : 'expand-outline',
623
+ size: 20,
624
+ color: "#fff"
625
+ })
626
+ })]
627
+ })]
628
+ });
629
+ }
630
+ if (item.type === 'albumRow') {
631
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
632
+ style: [styles.albumRow, {
633
+ backgroundColor: '#0b0f1a',
634
+ zIndex: 999,
635
+ elevation: 5
636
+ }],
637
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
638
+ style: styles.albumSelector,
639
+ onPress: () => setShowAlbumPicker(v => !v),
640
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
641
+ style: styles.albumTitle,
642
+ children: activeAlbum.title
643
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
644
+ name: "chevron-down",
645
+ size: 16,
646
+ color: "#fff",
647
+ style: {
648
+ marginLeft: 6
649
+ }
650
+ })]
651
+ }), maxSelection > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
652
+ style: {
653
+ flexDirection: 'row',
654
+ alignItems: 'center',
655
+ gap: 8
656
+ },
657
+ children: [multiSelect && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
658
+ style: {
659
+ color: '#3b82f6',
660
+ fontSize: 12,
661
+ fontWeight: '700'
662
+ },
663
+ children: [selectedItems.length, "/", maxSelection]
664
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
665
+ style: [styles.multiSelectBtn, multiSelect && styles.multiSelectBtnActive, multiSelect && selectedItems.length === 0 && {
666
+ opacity: 0.35
667
+ }],
668
+ onPress: () => {
669
+ if (multiSelect) {
670
+ handleNext();
671
+ } else {
672
+ toggleMultiSelect();
673
+ }
674
+ },
675
+ disabled: multiSelect && selectedItems.length === 0,
676
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
677
+ style: [styles.multiSelectText, multiSelect && styles.multiSelectTextActive],
678
+ children: multiSelect ? 'Done' : 'Select multiple'
679
+ })
680
+ })]
681
+ })]
682
+ });
683
+ }
684
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
685
+ style: {
686
+ flexDirection: 'row'
687
+ },
688
+ children: item.items.map(mediaItem => renderThumb({
689
+ item: mediaItem
690
+ }))
691
+ });
692
+ }
601
693
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
602
694
  style: styles.tabBar,
603
- children: TABS.map(t => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
695
+ children: mediaTabs.filter(t => mediaType === 'any' || mediaType === 'photo' && t !== 'VIDEO' || mediaType === 'video' && t !== 'PHOTO').map(t => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
604
696
  onPress: () => setTab(t),
605
697
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
606
698
  style: [styles.tab, tab === t && styles.tabActive],
@@ -657,7 +749,7 @@ function PickScreen({
657
749
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
658
750
  style: styles.cameraCloseBtn,
659
751
  onPress: () => setShowCustomCamera(false),
660
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
752
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
661
753
  name: "close",
662
754
  size: 22,
663
755
  color: "#fff"
@@ -668,7 +760,7 @@ function PickScreen({
668
760
  }],
669
761
  onPress: () => setFlashMode(f => f === 'on' ? 'off' : 'on'),
670
762
  disabled: facing === 'front',
671
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
763
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
672
764
  name: flashMode === 'on' && facing === 'back' ? 'flash' : 'flash-off',
673
765
  size: 22,
674
766
  color: flashMode === 'on' && facing === 'back' ? '#FFD700' : 'rgba(255,255,255,0.4)'
@@ -700,7 +792,7 @@ function PickScreen({
700
792
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
701
793
  style: styles.flipCameraBtn,
702
794
  onPress: () => setFacing(f => f === 'front' ? 'back' : 'front'),
703
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Ionicons.default, {
795
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
704
796
  name: "camera-reverse-outline",
705
797
  size: 26,
706
798
  color: "#fff"
@@ -900,7 +992,7 @@ const styles = _reactNative.StyleSheet.create({
900
992
  justifyContent: 'space-between',
901
993
  alignItems: 'center',
902
994
  paddingHorizontal: 16,
903
- paddingVertical: 10
995
+ height: 48
904
996
  },
905
997
  albumSelector: {
906
998
  flexDirection: 'row',