react-native-video-trim 6.0.3 → 6.0.5

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 CHANGED
@@ -254,7 +254,7 @@ All configuration options are optional. Here are the most commonly used ones:
254
254
  |--------|------|---------|-------------|
255
255
  | `type` | `'video' \| 'audio'` | `'video'` | Media type to trim |
256
256
  | `outputExt` | `string` | `'mp4'` | Output file extension |
257
- | `maxDuration` | `number` | - | Maximum duration in milliseconds |
257
+ | `maxDuration` | `number` | `video duration` | Maximum duration in milliseconds |
258
258
  | `minDuration` | `number` | `1000` | Minimum duration in milliseconds |
259
259
  | `autoplay` | `boolean` | `false` | Auto-play media on load |
260
260
  | `jumpToPositionOnLoad` | `number` | - | Initial position in milliseconds |
@@ -267,7 +267,11 @@ All configuration options are optional. Here are the most commonly used ones:
267
267
  | `openDocumentsOnFinish` | `boolean` | `false` | Open document picker when done |
268
268
  | `openShareSheetOnFinish` | `boolean` | `false` | Open share sheet when done |
269
269
  | `removeAfterSavedToPhoto` | `boolean` | `false` | Delete file after saving to photos |
270
+ | `removeAfterFailedToSavePhoto` | `boolean` | `false` | Delete file if saving to photos fails |
271
+ | `removeAfterSavedToDocuments` | `boolean` | `false` | Delete file after saving to documents |
272
+ | `removeAfterFailedToSaveDocuments` | `boolean` | `false` | Delete file if saving to documents fails |
270
273
  | `removeAfterShared` | `boolean` | `false` | Delete file after sharing (iOS only) |
274
+ | `removeAfterFailedToShare` | `boolean` | `false` | Delete file if sharing fails (iOS only) |
271
275
 
272
276
  ### UI Customization
273
277
 
@@ -278,11 +282,62 @@ All configuration options are optional. Here are the most commonly used ones:
278
282
  | `trimmingText` | `string` | `"Trimming video..."` | Progress dialog text |
279
283
  | `headerText` | `string` | - | Header text |
280
284
  | `headerTextSize` | `number` | `16` | Header text size |
281
- | `headerTextColor` | `string` | `"white"` | Header text color |
285
+ | `headerTextColor` | `string` | - | Header text color |
282
286
  | `trimmerColor` | `string` | - | Trimmer bar color |
283
- | `handleIconColor` | `string` | - | Trimmer handle color |
287
+ | `handleIconColor` | `string` | - | Trimmer left/right handles color |
284
288
  | `fullScreenModalIOS` | `boolean` | `false` | Use fullscreen modal on iOS |
285
289
 
290
+ ### Dialog Options
291
+
292
+ <details>
293
+ <summary><strong>Cancel Dialog</strong></summary>
294
+
295
+ | Option | Type | Default | Description |
296
+ |--------|------|---------|-------------|
297
+ | `enableCancelDialog` | `boolean` | `true` | Show confirmation dialog on cancel |
298
+ | `cancelDialogTitle` | `string` | `"Warning!"` | Cancel dialog title |
299
+ | `cancelDialogMessage` | `string` | `"Are you sure want to cancel?"` | Cancel dialog message |
300
+ | `cancelDialogCancelText` | `string` | `"Close"` | Cancel dialog cancel button text |
301
+ | `cancelDialogConfirmText` | `string` | `"Proceed"` | Cancel dialog confirm button text |
302
+ </details>
303
+
304
+ <details>
305
+ <summary><strong>Save Dialog</strong></summary>
306
+
307
+ | Option | Type | Default | Description |
308
+ |--------|------|---------|-------------|
309
+ | `enableSaveDialog` | `boolean` | `true` | Show confirmation dialog on save |
310
+ | `saveDialogTitle` | `string` | `"Confirmation!"` | Save dialog title |
311
+ | `saveDialogMessage` | `string` | `"Are you sure want to save?"` | Save dialog message |
312
+ | `saveDialogCancelText` | `string` | `"Close"` | Save dialog cancel button text |
313
+ | `saveDialogConfirmText` | `string` | `"Proceed"` | Save dialog confirm button text |
314
+ </details>
315
+
316
+ <details>
317
+ <summary><strong>Trimming Cancel Dialog</strong></summary>
318
+
319
+ | Option | Type | Default | Description |
320
+ |--------|------|---------|-------------|
321
+ | `enableCancelTrimming` | `boolean` | `true` | Enable cancel during trimming |
322
+ | `cancelTrimmingButtonText` | `string` | `"Cancel"` | Cancel trimming button text |
323
+ | `enableCancelTrimmingDialog` | `boolean` | `true` | Show cancel trimming confirmation |
324
+ | `cancelTrimmingDialogTitle` | `string` | `"Warning!"` | Cancel trimming dialog title |
325
+ | `cancelTrimmingDialogMessage` | `string` | `"Are you sure want to cancel trimming?"` | Cancel trimming dialog message |
326
+ | `cancelTrimmingDialogCancelText` | `string` | `"Close"` | Cancel trimming dialog cancel button |
327
+ | `cancelTrimmingDialogConfirmText` | `string` | `"Proceed"` | Cancel trimming dialog confirm button |
328
+ </details>
329
+
330
+ <details>
331
+ <summary><strong>Error Dialog</strong></summary>
332
+
333
+ | Option | Type | Default | Description |
334
+ |--------|------|---------|-------------|
335
+ | `alertOnFailToLoad` | `boolean` | `true` | Show alert dialog on load failure |
336
+ | `alertOnFailTitle` | `string` | `"Error"` | Error dialog title |
337
+ | `alertOnFailMessage` | `string` | `"Fail to load media..."` | Error dialog message |
338
+ | `alertOnFailCloseText` | `string` | `"Close"` | Error dialog close button text |
339
+ </details>
340
+
286
341
  ### Advanced Options
287
342
 
288
343
  | Option | Type | Default | Description |
@@ -291,8 +346,7 @@ All configuration options are optional. Here are the most commonly used ones:
291
346
  | `closeWhenFinish` | `boolean` | `true` | Close editor when done |
292
347
  | `enableRotation` | `boolean` | `false` | Enable video rotation |
293
348
  | `rotationAngle` | `number` | `0` | Rotation angle in degrees |
294
- | `changeStatusBarColorOnOpen` | `boolean` | `false` | Change status bar color (Android) |
295
- | `alertOnFailToLoad` | `boolean` | `true` | Show alert on load failure |
349
+ | `changeStatusBarColorOnOpen` | `boolean` | `false` | Change status bar color (Android only) |
296
350
 
297
351
  ### Example Configuration
298
352
 
@@ -567,7 +621,6 @@ export default function VideoTrimmer() {
567
621
  - Use `trim()` for batch processing without UI
568
622
  - Clean up generated files regularly with `cleanFiles()`
569
623
  - Consider file compression for large videos
570
- - Use appropriate `maxDuration` limits
571
624
 
572
625
  ## Credits
573
626
 
@@ -70,7 +70,6 @@ open class BaseVideoTrimModule internal constructor(
70
70
  private var outputFile: String? = null
71
71
  private var isVideoType = true
72
72
  private var editorConfig: ReadableMap? = null
73
- private var trimOptions: ReadableMap? = null
74
73
  private var originalStatusBarColor: Int = Color.TRANSPARENT
75
74
  private val shouldChangeStatusBarColorOnOpen: Boolean
76
75
  get() = editorConfig?.hasKey("changeStatusBarColorOnOpen") == true && editorConfig?.getBoolean("changeStatusBarColorOnOpen") == true
@@ -101,8 +100,7 @@ open class BaseVideoTrimModule internal constructor(
101
100
  Log.d(TAG, "File saved successfully to $uri")
102
101
 
103
102
  if (
104
- editorConfig?.getBoolean("removeAfterSavedToDocuments") == true ||
105
- trimOptions?.getBoolean("removeAfterFailedToSaveDocuments") == true
103
+ editorConfig?.getBoolean("removeAfterSavedToDocuments") == true
106
104
  ) {
107
105
  StorageUtil.deleteFile(outputFile)
108
106
  }
@@ -114,7 +112,7 @@ open class BaseVideoTrimModule internal constructor(
114
112
  "Failed to save edited video to Documents: ${e.localizedMessage}",
115
113
  ErrorCode.FAIL_TO_SAVE_TO_DOCUMENTS
116
114
  )
117
- if (editorConfig?.getBoolean("removeAfterFailedToSaveDocuments") == true || trimOptions?.getBoolean("removeAfterFailedToSaveDocuments") == true) {
115
+ if (editorConfig?.getBoolean("removeAfterFailedToSaveDocuments") == true) {
118
116
  StorageUtil.deleteFile(outputFile)
119
117
  }
120
118
  } finally {
@@ -574,8 +572,6 @@ open class BaseVideoTrimModule internal constructor(
574
572
  }
575
573
 
576
574
  fun trim(url: String, options: ReadableMap?, promise: Promise) {
577
- trimOptions = options
578
-
579
575
  val currentDate = Date()
580
576
  val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
581
577
 
@@ -593,7 +589,7 @@ open class BaseVideoTrimModule internal constructor(
593
589
  cmds += arrayOf("-display_rotation", "${options.getDouble("rotationAngle")}")
594
590
  }
595
591
 
596
- outputFile = StorageUtil.getOutputPath(reactApplicationContext, options?.getString("outputExt") ?: "mp4")
592
+ val outputFile = StorageUtil.getOutputPath(reactApplicationContext, options?.getString("outputExt") ?: "mp4")
597
593
 
598
594
  cmds += arrayOf(
599
595
  "-i",
@@ -633,27 +629,19 @@ open class BaseVideoTrimModule internal constructor(
633
629
  Exception("Failed to save edited video to Photo Library: " + e.localizedMessage)
634
630
  )
635
631
  }
636
- } else {
637
- if (options?.getBoolean("openDocumentsOnFinish") == true) {
638
- saveFileToExternalStorage(File(outputFile!!))
639
- } else if (options?.getBoolean("openShareSheetOnFinish") == true) {
640
- shareFile(reactApplicationContext, File(outputFile!!))
641
- }
642
-
643
- promise.resolve(outputFile)
644
632
  }
645
633
  }
646
634
  ReturnCode.isCancel(returnCode) -> {
647
635
  // CANCEL
648
636
  println("FFmpeg command was cancelled")
649
637
  promise.reject(
650
- Exception("FFmpeg command was cancelled")
638
+ Exception("FFmpeg command was cancelled with code $returnCode")
651
639
  )
652
640
  }
653
641
  else -> {
654
642
  // FAILURE
655
643
  val errorMessage = String.format("Command failed with state %s and rc %s.%s", state, returnCode, session.getFailStackTrace());
656
- println(errorMessage)
644
+ Log.d(TAG, errorMessage)
657
645
  promise.reject(
658
646
  Exception(errorMessage)
659
647
  )
@@ -669,7 +657,7 @@ open class BaseVideoTrimModule internal constructor(
669
657
  private fun saveFileToExternalStorage(file: File) {
670
658
  val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
671
659
  intent.addCategory(Intent.CATEGORY_OPENABLE)
672
- intent.setType("*/*") // Change MIME type as needed
660
+ intent.type = "*/*" // Change MIME type as needed
673
661
  intent.putExtra(Intent.EXTRA_TITLE, file.name)
674
662
  reactApplicationContext.currentActivity?.startActivityForResult(intent, REQUEST_CODE_SAVE_FILE)
675
663
  }
@@ -678,7 +666,7 @@ open class BaseVideoTrimModule internal constructor(
678
666
  val fileUri = FileProvider.getUriForFile(context, context.packageName + ".provider", file)
679
667
 
680
668
  val shareIntent = Intent(Intent.ACTION_SEND)
681
- shareIntent.setType("*/*")
669
+ shareIntent.type = "*/*"
682
670
  shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
683
671
  shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
684
672
 
@@ -99,6 +99,13 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
99
99
  private boolean isZoomedIn = false;
100
100
  private final Handler zoomWaitTimer = new Handler();
101
101
  private Runnable zoomRunnable;
102
+ private long zoomedInRangeStart = 0;
103
+ private long zoomedInRangeDuration = 0;
104
+ private boolean isTrimmingLeading = false;
105
+
106
+ // thumbnail caching for zoom functionality
107
+ private final java.util.List<ImageView> cachedFullViewThumbnails = new java.util.ArrayList<>();
108
+ private volatile boolean isGeneratingThumbnails = false;
102
109
 
103
110
  private MediaMetadataRetriever mediaMetadataRetriever;
104
111
  private ProgressBar loadingIndicator;
@@ -244,6 +251,8 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
244
251
 
245
252
  private void startShootVideoThumbs(final Context context, int totalThumbsCount, long startPosition, long endPosition) {
246
253
  mThumbnailContainer.removeAllViews();
254
+ cachedFullViewThumbnails.clear(); // Clear previous cache
255
+
247
256
  VideoTrimmerUtil.shootVideoThumbInBackground(mediaMetadataRetriever, totalThumbsCount, startPosition, endPosition,
248
257
  (bitmap, interval) -> {
249
258
  if (bitmap != null) {
@@ -255,6 +264,13 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
255
264
  layoutParams.width = VideoTrimmerUtil.VIDEO_FRAMES_WIDTH / VideoTrimmerUtil.MAX_COUNT_RANGE;
256
265
  thumbImageView.setLayoutParams(layoutParams);
257
266
  mThumbnailContainer.addView(thumbImageView);
267
+
268
+ // Cache the thumbnail for zoom functionality
269
+ ImageView cachedView = new ImageView(context);
270
+ cachedView.setImageBitmap(bitmap);
271
+ cachedView.setScaleType(ImageView.ScaleType.CENTER_CROP);
272
+ cachedView.setLayoutParams(layoutParams);
273
+ cachedFullViewThumbnails.add(cachedView);
258
274
  });
259
275
  }
260
276
  });
@@ -327,12 +343,9 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
327
343
  }
328
344
 
329
345
  private void updateHandlePositions() {
330
- float startPercent = (float) startTime / mDuration;
331
- float endPercent = (float) endTime / mDuration;
332
-
333
- float containerWidth = trimmerContainerBg.getWidth();
334
- float leadingHandleX = startPercent * containerWidth;
335
- float trailingHandleX = endPercent * containerWidth;
346
+ // Use zoom-aware position calculation
347
+ float leadingHandleX = positionForTime(startTime);
348
+ float trailingHandleX = positionForTime(endTime);
336
349
 
337
350
  leadingHandle.setX(leadingHandleX);
338
351
  trailingHandle.setX(trailingHandleX + trailingHandle.getWidth());
@@ -429,12 +442,17 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
429
442
 
430
443
  @Override
431
444
  public void onDestroy() {
445
+ // Stop any ongoing operations
446
+ isGeneratingThumbnails = false;
432
447
  BackgroundExecutor.cancelAll("", true);
433
448
  UiThreadExecutor.cancelAll("");
434
449
  mContext.getCurrentActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
435
450
  mTimingHandler.removeCallbacks(mTimingRunnable);
436
451
  zoomWaitTimer.removeCallbacks(zoomRunnable);
437
452
 
453
+ // Clear cached thumbnails to prevent memory leaks
454
+ cachedFullViewThumbnails.clear();
455
+
438
456
  try {
439
457
  if (mediaMetadataRetriever != null) {
440
458
  mediaMetadataRetriever.release();
@@ -590,15 +608,41 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
590
608
  endTimeText.setText(endTime);
591
609
 
592
610
  if (needUpdateProgress) {
593
- // Update progressIndicator position
594
- float indicatorPosition = (float) currentPosition / duration * (trimmerContainerBg.getWidth() - progressIndicator.getWidth()) + leadingHandle.getWidth();
611
+ // Update progressIndicator position using zoom-aware calculation
612
+ float indicatorPosition;
613
+
614
+ if (isZoomedIn) {
615
+ // Calculate position relative to zoomed range
616
+ long visibleRangeStart = getVisibleRangeStart();
617
+ long visibleRangeDuration = getVisibleRangeDuration();
618
+
619
+ // Ensure current position is within visible range for proper calculation
620
+ if (currentPosition < visibleRangeStart || currentPosition > visibleRangeStart + visibleRangeDuration) {
621
+ // If current position is outside visible range, clamp it
622
+ currentPosition = (int) Math.max(visibleRangeStart, Math.min(visibleRangeStart + visibleRangeDuration, currentPosition));
623
+ }
624
+
625
+ float ratio = visibleRangeDuration > 0 ? (float) (currentPosition - visibleRangeStart) / visibleRangeDuration : 0;
626
+ indicatorPosition = ratio * (trimmerContainerBg.getWidth() - progressIndicator.getWidth()) + leadingHandle.getWidth();
627
+ } else {
628
+ // Calculate position relative to full duration (original logic)
629
+ indicatorPosition = mDuration > 0 ? (float) currentPosition / mDuration * (trimmerContainerBg.getWidth() - progressIndicator.getWidth()) + leadingHandle.getWidth() : leadingHandle.getWidth();
630
+ }
631
+
632
+ // Ensure indicator stays within handle bounds using actual handle positions
633
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
634
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
635
+
636
+ // Apply bounds checking based on actual handle positions
637
+ indicatorPosition = Math.max(leftBoundary, Math.min(rightBoundary, indicatorPosition));
595
638
 
596
639
  if (currentSelectedhandle == leadingHandle) {
597
- float leftBoundary = trimmerContainer.getX();
598
640
  progressIndicator.setX(Math.max(leftBoundary, indicatorPosition));
599
- } else {
600
- float rightBoundary = trimmerContainer.getX() + trimmerContainer.getWidth() - progressIndicator.getWidth();
641
+ } else if (currentSelectedhandle == trailingHandle) {
601
642
  progressIndicator.setX(Math.min(rightBoundary, indicatorPosition));
643
+ } else {
644
+ // Normal playback - use calculated position with handle bounds
645
+ progressIndicator.setX(indicatorPosition);
602
646
  }
603
647
  }
604
648
  }
@@ -636,9 +680,11 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
636
680
  private void onTrimmerContainerPanned(MotionEvent event) {
637
681
  float newX = event.getRawX();
638
682
  boolean didClamp = false;
639
- // Ensure newX is within valid range
640
- float leftBoundary = trimmerContainer.getX();
641
- float rightBoundary = trimmerContainer.getX() + trimmerContainer.getWidth() - progressIndicator.getWidth();
683
+
684
+ // Use handle positions for boundaries instead of trimmer container
685
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
686
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
687
+
642
688
  newX = Math.max(leftBoundary, newX);
643
689
  newX = Math.min(rightBoundary, newX);
644
690
 
@@ -658,9 +704,21 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
658
704
 
659
705
  float indicatorPosition = newX - (trimmerContainerBg.getX());
660
706
 
661
- // TODO: check this
662
- float indicatorPositionPercent = indicatorPosition / (trimmerContainerBg.getWidth() - progressIndicator.getWidth());
663
- long newVideoPosition = (long) (indicatorPositionPercent * mDuration);
707
+ // Calculate video position based on zoom state
708
+ float indicatorPositionPercent;
709
+ long newVideoPosition;
710
+
711
+ if (isZoomedIn) {
712
+ // Calculate relative to zoomed range
713
+ indicatorPositionPercent = indicatorPosition / (trimmerContainerBg.getWidth() - progressIndicator.getWidth());
714
+ long visibleStart = getVisibleRangeStart();
715
+ long visibleDuration = getVisibleRangeDuration();
716
+ newVideoPosition = visibleStart + (long) (indicatorPositionPercent * visibleDuration);
717
+ } else {
718
+ // Calculate relative to full duration
719
+ indicatorPositionPercent = indicatorPosition / (trimmerContainerBg.getWidth() - progressIndicator.getWidth());
720
+ newVideoPosition = (long) (indicatorPositionPercent * mDuration);
721
+ }
664
722
 
665
723
  seekTo(newVideoPosition, false);
666
724
  }
@@ -676,6 +734,7 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
676
734
  fadeOutProgressIndicator();
677
735
  seekTo(isLeading ? startTime : endTime, true);
678
736
  playHapticFeedback(true);
737
+ isTrimmingLeading = isLeading;
679
738
  break;
680
739
  case MotionEvent.ACTION_MOVE:
681
740
  if (draggingDisabled) {
@@ -684,6 +743,8 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
684
743
 
685
744
  boolean didClamp = false;
686
745
  float newX = event.getRawX() - ((float) view.getWidth() / 2);
746
+
747
+ // Handle constraints need to consider zoom state
687
748
  if (isLeading) {
688
749
  newX = Math.max(0, Math.min(newX, trailingHandle.getX() - view.getWidth()));
689
750
  } else {
@@ -692,54 +753,114 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
692
753
 
693
754
  view.setX(newX);
694
755
 
695
- // Calculate new startTime or endTime
756
+ // Calculate new startTime or endTime based on zoom state
696
757
  if (isLeading) {
697
758
  // Calculate the new startTime based on the handle's new position
698
- long newStartTime = (long) ((newX / trimmerContainerBg.getWidth()) * mDuration);
759
+ long newStartTime = timeForPosition(newX);
699
760
  // Calculate the duration between the new startTime and the current endTime
700
761
  long duration = endTime - newStartTime;
701
762
  if (duration >= mMinDuration && duration <= mMaxDuration) {
702
763
  // If the duration is within the allowed range, update startTime and move the progress indicator
703
764
  startTime = newStartTime;
704
- progressIndicator.setX(newX + view.getWidth());
765
+ float indicatorX = newX + view.getWidth();
766
+ // Ensure progress indicator stays within handle bounds
767
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
768
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
769
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
705
770
  } else if (duration < mMinDuration) {
706
771
  didClamp = true;
707
- // If the duration is less than the minimum, set startTime to the maximum possible to maintain the minimum duration
772
+ // If the duration is less than the minimum, calculate maximum startTime to maintain minimum duration
708
773
  startTime = endTime - mMinDuration;
709
- // Adjust the handle position accordingly
710
- view.setX((float) startTime / mDuration * trimmerContainerBg.getWidth());
711
- progressIndicator.setX(view.getX() + view.getWidth());
774
+
775
+ // In zoom mode, don't recalculate position - keep handle where it is but update times
776
+ if (isZoomedIn) {
777
+ // Keep handle at current position but clamp times
778
+ float indicatorX = newX + view.getWidth();
779
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
780
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
781
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
782
+ } else {
783
+ // Normal mode - adjust handle position
784
+ view.setX(positionForTime(startTime));
785
+ float indicatorX = view.getX() + view.getWidth();
786
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
787
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
788
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
789
+ }
712
790
  } else {
713
791
  didClamp = true;
714
- // If the duration is greater than the maximum, set startTime to the minimum possible to maintain the maximum duration
792
+ // If the duration is greater than the maximum, calculate minimum startTime to maintain maximum duration
715
793
  startTime = endTime - mMaxDuration;
716
- // Adjust the handle position accordingly
717
- view.setX((float) startTime / mDuration * trimmerContainerBg.getWidth());
718
- progressIndicator.setX(view.getX() + view.getWidth());
794
+
795
+ // In zoom mode, don't recalculate position - keep handle where it is but update times
796
+ if (isZoomedIn) {
797
+ // Keep handle at current position but clamp times
798
+ float indicatorX = newX + view.getWidth();
799
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
800
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
801
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
802
+ } else {
803
+ // Normal mode - adjust handle position
804
+ view.setX(positionForTime(startTime));
805
+ float indicatorX = view.getX() + view.getWidth();
806
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
807
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
808
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
809
+ }
719
810
  }
720
811
  } else {
721
812
  // Calculate the new endTime based on the handle's new position
722
- long newEndTime = (long) (((newX - view.getWidth()) / trimmerContainerBg.getWidth()) * mDuration);
813
+ long newEndTime = timeForPosition(newX - view.getWidth());
723
814
  // Calculate the duration between the new endTime and the current startTime
724
815
  long duration = newEndTime - startTime;
725
816
  if (duration >= mMinDuration && duration <= mMaxDuration) {
726
817
  // If the duration is within the allowed range, update endTime and move the progress indicator
727
818
  endTime = newEndTime;
728
- progressIndicator.setX(newX - progressIndicator.getWidth());
819
+ float indicatorX = newX - progressIndicator.getWidth();
820
+ // Ensure progress indicator stays within handle bounds
821
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
822
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
823
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
729
824
  } else if (duration < mMinDuration) {
730
825
  didClamp = true;
731
- // If the duration is less than the minimum, set endTime to the minimum possible to maintain the minimum duration
826
+ // If the duration is less than the minimum, calculate minimum endTime to maintain minimum duration
732
827
  endTime = startTime + mMinDuration;
733
- // Adjust the handle position accordingly
734
- view.setX((float) endTime / mDuration * trimmerContainerBg.getWidth() + view.getWidth());
735
- progressIndicator.setX(view.getX() - progressIndicator.getWidth());
828
+
829
+ // In zoom mode, don't recalculate position - keep handle where it is but update times
830
+ if (isZoomedIn) {
831
+ // Keep handle at current position but clamp times
832
+ float indicatorX = newX - progressIndicator.getWidth();
833
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
834
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
835
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
836
+ } else {
837
+ // Normal mode - adjust handle position
838
+ view.setX(positionForTime(endTime) + view.getWidth());
839
+ float indicatorX = view.getX() - progressIndicator.getWidth();
840
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
841
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
842
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
843
+ }
736
844
  } else {
737
845
  didClamp = true;
738
- // If the duration is greater than the maximum, set endTime to the maximum possible to maintain the maximum duration
846
+ // If the duration is greater than the maximum, calculate maximum endTime to maintain maximum duration
739
847
  endTime = startTime + mMaxDuration;
740
- // Adjust the handle position accordingly
741
- view.setX((float) endTime / mDuration * trimmerContainerBg.getWidth() + view.getWidth());
742
- progressIndicator.setX(view.getX() - progressIndicator.getWidth());
848
+
849
+ // In zoom mode, don't recalculate position - keep handle where it is but update times
850
+ if (isZoomedIn) {
851
+ // Keep handle at current position but clamp times
852
+ float indicatorX = newX - progressIndicator.getWidth();
853
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
854
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
855
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
856
+ } else {
857
+ // Normal mode - adjust handle position
858
+ view.setX(positionForTime(endTime) + view.getWidth());
859
+ float indicatorX = view.getX() - progressIndicator.getWidth();
860
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
861
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
862
+ progressIndicator.setX(Math.max(leftBoundary, Math.min(rightBoundary, indicatorX)));
863
+ }
743
864
  }
744
865
  }
745
866
 
@@ -751,11 +872,11 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
751
872
  updateTrimmerContainerWidth();
752
873
  seekTo(isLeading ? startTime : endTime, false);
753
874
 
754
- // TODO: create zoom feature like iOS
755
- // startZoomWaitTimer();
875
+ // Start zoom wait timer when dragging handles
876
+ startZoomWaitTimer();
756
877
  break;
757
878
  case MotionEvent.ACTION_UP:
758
- // stopZoomIfNeeded();
879
+ stopZoomIfNeeded();
759
880
  fadeInProgressIndicator();
760
881
  view.performClick();
761
882
  break;
@@ -805,7 +926,6 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
805
926
  }
806
927
 
807
928
  zoomRunnable = () -> {
808
- Log.i("tag", "A Kiss after 500ms");
809
929
  stopZoomWaitTimer();
810
930
  zoomIfNeeded();
811
931
  };
@@ -814,12 +934,32 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
814
934
  }
815
935
 
816
936
  private void stopZoomWaitTimer() {
817
- zoomWaitTimer.removeCallbacks(zoomRunnable);
937
+ if (zoomRunnable != null) {
938
+ zoomWaitTimer.removeCallbacks(zoomRunnable);
939
+ }
818
940
  }
819
941
 
820
942
  private void stopZoomIfNeeded() {
821
943
  stopZoomWaitTimer();
822
- isZoomedIn = false;
944
+ if (isZoomedIn) {
945
+ // Stop any ongoing thumbnail generation immediately
946
+ isGeneratingThumbnails = false;
947
+
948
+ // Cancel any ongoing background tasks for thumbnail generation
949
+ BackgroundExecutor.cancelAll("progressive_thumbs", true);
950
+
951
+ isZoomedIn = false;
952
+
953
+ // Immediately restore cached thumbnails without waiting for animation
954
+ restoreCachedThumbnails();
955
+
956
+ // Then apply smooth transition animation
957
+ animateZoomTransition(() -> {
958
+ updateHandlePositions();
959
+ // Force update progress indicator position after exiting zoom
960
+ updateCurrentTime(true);
961
+ });
962
+ }
823
963
  }
824
964
 
825
965
  private void zoomIfNeeded() {
@@ -827,9 +967,200 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
827
967
  return;
828
968
  }
829
969
 
830
- startShootVideoThumbs(mContext, 10, 5000, 10000);
970
+ // Store current handle positions to maintain visual continuity
971
+ float currentLeadingX = leadingHandle.getX();
972
+ float currentTrailingX = trailingHandle.getX();
973
+
974
+ // Calculate zoom range similar to iOS implementation
975
+ long newDuration = mDuration > 4000 ? 2000 : Math.max(1000, mDuration / 2); // At least 1 second, max 2 seconds or half duration
976
+
977
+ // Ensure zoom duration doesn't exceed video duration
978
+ newDuration = Math.min(newDuration, mDuration);
979
+
980
+ long rangeStart;
981
+ if (isTrimmingLeading) {
982
+ // Zoom around the start time, but ensure we don't go before video start
983
+ rangeStart = Math.max(0, startTime - (newDuration / 2));
984
+ // If range would extend past video end, adjust start
985
+ if (rangeStart + newDuration > mDuration) {
986
+ rangeStart = Math.max(0, mDuration - newDuration);
987
+ }
988
+ } else {
989
+ // Zoom around the end time
990
+ rangeStart = Math.max(0, endTime - (newDuration / 2));
991
+ // If range would extend past video end, adjust start
992
+ if (rangeStart + newDuration > mDuration) {
993
+ rangeStart = Math.max(0, mDuration - newDuration);
994
+ }
995
+ }
996
+
997
+ // Final bounds check
998
+ zoomedInRangeStart = Math.max(0, rangeStart);
999
+ zoomedInRangeDuration = Math.min(newDuration, mDuration - zoomedInRangeStart);
831
1000
 
832
1001
  isZoomedIn = true;
1002
+
1003
+ // Start progressive thumbnail generation immediately
1004
+ startProgressiveThumbnailGeneration();
1005
+
1006
+ // Update handle positions immediately without delay
1007
+ updateHandlePositionsForZoom(currentLeadingX, currentTrailingX);
1008
+
1009
+ // Provide haptic feedback
1010
+ playHapticFeedback(true);
1011
+ }
1012
+
1013
+ private void updateHandlePositionsForZoom(float previousLeadingX, float previousTrailingX) {
1014
+ // During zoom, we want to keep handles at their current visual positions
1015
+ // Don't recalculate based on zoom range - this causes jumping
1016
+
1017
+ Log.d(TAG, "Maintaining handle positions during zoom - Leading: " + previousLeadingX + ", Trailing: " + previousTrailingX);
1018
+
1019
+ // Keep handles exactly where they were visually
1020
+ leadingHandle.setX(previousLeadingX);
1021
+ trailingHandle.setX(previousTrailingX);
1022
+
1023
+ // Don't update times here - let the individual handle drag logic handle that
1024
+ // This prevents unwanted changes to startTime/endTime during zoom transition
1025
+
1026
+ // Update trimmer container width based on current handle positions
1027
+ updateTrimmerContainerWidth();
1028
+
1029
+ // Ensure progress indicator is positioned correctly within the handle bounds
1030
+ float leftBoundary = leadingHandle.getX() + leadingHandle.getWidth();
1031
+ float rightBoundary = trailingHandle.getX() - progressIndicator.getWidth();
1032
+ float currentX = progressIndicator.getX();
1033
+
1034
+ // If progress indicator is out of bounds, position it properly
1035
+ if (currentX < leftBoundary || currentX > rightBoundary) {
1036
+ // Position it based on the current media position
1037
+ updateCurrentTime(true);
1038
+ } else {
1039
+ updateCurrentTime(false);
1040
+ }
1041
+
1042
+ trimmerContainerWrapper.setVisibility(View.VISIBLE);
1043
+ if (trimmerContainerWrapper.getAlpha() == 0f) {
1044
+ trimmerContainerWrapper.animate().alpha(1f).setDuration(250).start();
1045
+ }
1046
+ }
1047
+
1048
+ private void startProgressiveThumbnailGeneration() {
1049
+ if (isGeneratingThumbnails || mediaMetadataRetriever == null) {
1050
+ return;
1051
+ }
1052
+
1053
+ isGeneratingThumbnails = true;
1054
+
1055
+ // Immediately create placeholder thumbnails with subtle animation
1056
+ UiThreadExecutor.runTask("", () -> {
1057
+ mThumbnailContainer.removeAllViews();
1058
+
1059
+ // Calculate proper number of thumbnails based on container width
1060
+ final int thumbnailWidth = VideoTrimmerUtil.VIDEO_FRAMES_WIDTH / VideoTrimmerUtil.MAX_COUNT_RANGE;
1061
+ final int numberOfThumbnails = Math.max(8, mThumbnailContainer.getWidth() / thumbnailWidth);
1062
+
1063
+ // Create placeholder thumbnails first
1064
+ for (int i = 0; i < numberOfThumbnails; i++) {
1065
+ ImageView placeholder = new ImageView(getContext());
1066
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(thumbnailWidth, LinearLayout.LayoutParams.MATCH_PARENT);
1067
+ placeholder.setLayoutParams(layoutParams);
1068
+ placeholder.setBackgroundColor(Color.parseColor("#F0F0F0")); // Light gray placeholder
1069
+ placeholder.setAlpha(0.2f);
1070
+ mThumbnailContainer.addView(placeholder);
1071
+ }
1072
+ }, 0);
1073
+
1074
+ // Start background thumbnail generation
1075
+ BackgroundExecutor.execute(new BackgroundExecutor.Task("progressive_thumbs", 0L, "") {
1076
+ @Override
1077
+ public void execute() {
1078
+ try {
1079
+ final int thumbnailWidth = VideoTrimmerUtil.VIDEO_FRAMES_WIDTH / VideoTrimmerUtil.MAX_COUNT_RANGE;
1080
+ final int numberOfThumbnails = Math.max(8, mThumbnailContainer.getWidth() / thumbnailWidth);
1081
+ final long visibleDuration = isZoomedIn ? zoomedInRangeDuration : mDuration;
1082
+ final long visibleStart = isZoomedIn ? zoomedInRangeStart : 0;
1083
+ final long interval = visibleDuration > 0 ? visibleDuration / numberOfThumbnails : 0;
1084
+
1085
+ // Generate thumbnails progressively
1086
+ for (int i = 0; i < numberOfThumbnails && isGeneratingThumbnails && isZoomedIn; i++) {
1087
+ // Check if we should continue generating
1088
+ if (!isGeneratingThumbnails || !isZoomedIn) {
1089
+ Log.d(TAG, "Thumbnail generation cancelled at index " + i);
1090
+ return;
1091
+ }
1092
+
1093
+ final int index = i;
1094
+ final long timeUs = (visibleStart + (i * interval)) * 1000; // Convert to microseconds
1095
+ final long clampedTimeUs = Math.max(0, Math.min(timeUs, mDuration * 1000L));
1096
+
1097
+ try {
1098
+ Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(clampedTimeUs, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
1099
+ if (bitmap != null && isGeneratingThumbnails && isZoomedIn) {
1100
+ // Update UI immediately for each thumbnail
1101
+ UiThreadExecutor.runTask("", () -> {
1102
+ // Double-check zoom state before updating UI
1103
+ if (isZoomedIn && index < mThumbnailContainer.getChildCount()) {
1104
+ ImageView thumbnailView = (ImageView) mThumbnailContainer.getChildAt(index);
1105
+ if (thumbnailView != null) {
1106
+ thumbnailView.setImageBitmap(bitmap);
1107
+ thumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP);
1108
+ thumbnailView.setBackground(null); // Remove placeholder background
1109
+
1110
+ // Smooth fade-in animation for each thumbnail
1111
+ thumbnailView.animate()
1112
+ .alpha(1.0f)
1113
+ .setDuration(150)
1114
+ .setStartDelay(index * 50L) // Stagger animations
1115
+ .start();
1116
+ }
1117
+ }
1118
+ }, 0);
1119
+
1120
+ // Small delay between generations to avoid blocking
1121
+ Thread.sleep(10);
1122
+ }
1123
+ } catch (Exception e) {
1124
+ Log.w(TAG, "Error generating progressive thumbnail at " + clampedTimeUs, e);
1125
+ }
1126
+ }
1127
+
1128
+ // Only finalize if we're still in zoom mode
1129
+ if (isGeneratingThumbnails && isZoomedIn) {
1130
+ isGeneratingThumbnails = false;
1131
+ } else {
1132
+ isGeneratingThumbnails = false;
1133
+ }
1134
+
1135
+ } catch (Exception e) {
1136
+ Log.e(TAG, "Error in progressive thumbnail generation", e);
1137
+ isGeneratingThumbnails = false;
1138
+ }
1139
+ }
1140
+ });
1141
+ }
1142
+
1143
+ private void animateZoomTransition(Runnable onComplete) {
1144
+ // Only animate if we're still transitioning
1145
+ if (mThumbnailContainer != null) {
1146
+ mThumbnailContainer.animate()
1147
+ .alpha(0.7f)
1148
+ .setDuration(200) // Shorter duration for better responsiveness
1149
+ .withEndAction(() -> {
1150
+ if (onComplete != null) {
1151
+ onComplete.run();
1152
+ }
1153
+ if (mThumbnailContainer != null) {
1154
+ mThumbnailContainer.animate()
1155
+ .alpha(1.0f)
1156
+ .setDuration(200)
1157
+ .start();
1158
+ }
1159
+ })
1160
+ .start();
1161
+ } else if (onComplete != null) {
1162
+ onComplete.run();
1163
+ }
833
1164
  }
834
1165
 
835
1166
  private void ignoreSystemGestureForView(View v) {
@@ -850,4 +1181,54 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
850
1181
  );
851
1182
  }
852
1183
  }
1184
+
1185
+ // Helper methods for position/time conversion considering zoom state
1186
+ private long timeForPosition(float position) {
1187
+ if (trimmerContainerBg.getWidth() <= 0) return 0;
1188
+
1189
+ if (isZoomedIn) {
1190
+ // Convert position to time within zoomed range
1191
+ float ratio = position / trimmerContainerBg.getWidth();
1192
+ return zoomedInRangeStart + (long) (ratio * zoomedInRangeDuration);
1193
+ } else {
1194
+ // Convert position to time within full duration
1195
+ return (long) ((position / trimmerContainerBg.getWidth()) * mDuration);
1196
+ }
1197
+ }
1198
+
1199
+ private float positionForTime(long time) {
1200
+ if (isZoomedIn) {
1201
+ // Convert time to position within zoomed range
1202
+ if (zoomedInRangeDuration <= 0) return 0;
1203
+ float ratio = (float) (time - zoomedInRangeStart) / zoomedInRangeDuration;
1204
+ return Math.max(0, Math.min(trimmerContainerBg.getWidth(), ratio * trimmerContainerBg.getWidth()));
1205
+ } else {
1206
+ // Convert time to position within full duration
1207
+ if (mDuration <= 0) return 0;
1208
+ return Math.max(0, Math.min(trimmerContainerBg.getWidth(), ((float) time / mDuration) * trimmerContainerBg.getWidth()));
1209
+ }
1210
+ }
1211
+
1212
+ private long getVisibleRangeStart() {
1213
+ return isZoomedIn ? zoomedInRangeStart : 0;
1214
+ }
1215
+
1216
+ private long getVisibleRangeDuration() {
1217
+ return isZoomedIn ? zoomedInRangeDuration : mDuration;
1218
+ }
1219
+
1220
+ private void restoreCachedThumbnails() {
1221
+ // Clear current thumbnails
1222
+ mThumbnailContainer.removeAllViews();
1223
+
1224
+ // Restore cached thumbnails efficiently
1225
+ for (ImageView cachedThumbnail : cachedFullViewThumbnails) {
1226
+ // Create a new ImageView with the same bitmap to avoid view reuse issues
1227
+ ImageView restoredView = new ImageView(getContext());
1228
+ restoredView.setImageBitmap(((android.graphics.drawable.BitmapDrawable) cachedThumbnail.getDrawable()).getBitmap());
1229
+ restoredView.setScaleType(ImageView.ScaleType.CENTER_CROP);
1230
+ restoredView.setLayoutParams(cachedThumbnail.getLayoutParams());
1231
+ mThumbnailContainer.addView(restoredView);
1232
+ }
1233
+ }
853
1234
  }
package/ios/VideoTrim.mm CHANGED
@@ -61,24 +61,21 @@ RCT_EXPORT_MODULE()
61
61
  dict[@"saveToPhoto"] = @(options.saveToPhoto());
62
62
  dict[@"type"] = options.type();
63
63
  dict[@"outputExt"] = options.outputExt();
64
- dict[@"openDocumentsOnFinish"] = @(options.openDocumentsOnFinish());
65
- dict[@"openShareSheetOnFinish"] = @(options.openShareSheetOnFinish());
66
64
  dict[@"removeAfterSavedToPhoto"] = @(options.removeAfterSavedToPhoto());
67
65
  dict[@"removeAfterFailedToSavePhoto"] = @(options.removeAfterFailedToSavePhoto());
68
- dict[@"removeAfterSavedToDocuments"] = @(options.removeAfterSavedToDocuments());
69
- dict[@"removeAfterFailedToSaveDocuments"] = @(options.removeAfterFailedToSaveDocuments());
70
- dict[@"removeAfterShared"] = @(options.removeAfterShared());
71
- dict[@"removeAfterFailedToShare"] = @(options.removeAfterFailedToShare());
72
66
  dict[@"enableRotation"] = @(options.enableRotation());
73
67
  dict[@"rotationAngle"] = @(options.rotationAngle());
74
68
  dict[@"startTime"] = @(options.startTime());
75
69
  dict[@"endTime"] = @(options.endTime());
76
70
 
77
- [self->videoTrim trim:url url:dict config:^(NSDictionary<NSString *,id> * _Nullable result) {
78
- if (!result) {
79
- reject(@"ERR_TRIM_FAILED", @"Trim failed", nil);
80
- } else {
71
+ [self->videoTrim trim:url url:dict config:^(NSDictionary<NSString *,id> * _Nonnull result) {
72
+ BOOL success = [result[@"success"] boolValue];
73
+ if (success) {
81
74
  resolve(result);
75
+ } else {
76
+ NSString *message = result[@"message"];
77
+ NSError *error = [NSError errorWithDomain:@"" code:200 userInfo:nil];
78
+ reject(@"ERR_TRIM_FAILED", message, error);
82
79
  }
83
80
  }];
84
81
  }
@@ -466,7 +466,7 @@ public class VideoTrim: RCTEventEmitter, AssetLoaderDelegate, UIDocumentPickerDe
466
466
 
467
467
  // New Arch
468
468
  @objc(trim:url:config:)
469
- public func _trim(inputFile: String, config: NSDictionary, completion: @escaping ([String: Any]?) -> Void) {
469
+ public func _trim(inputFile: String, config: NSDictionary, completion: @escaping ([String: Any]) -> Void) {
470
470
  var destPath: URL?
471
471
 
472
472
  if inputFile.hasPrefix("http://") || inputFile.hasPrefix("https://") {
@@ -476,7 +476,13 @@ public class VideoTrim: RCTEventEmitter, AssetLoaderDelegate, UIDocumentPickerDe
476
476
  }
477
477
 
478
478
  guard let destPath = destPath else {
479
- completion(nil)
479
+ let result = [
480
+ "success": false,
481
+ "message": "Invalid input file path",
482
+ ] as [String : Any]
483
+
484
+ completion(result)
485
+
480
486
  return
481
487
  }
482
488
 
@@ -521,15 +527,30 @@ public class VideoTrim: RCTEventEmitter, AssetLoaderDelegate, UIDocumentPickerDe
521
527
  let returnCode = session?.getReturnCode()
522
528
 
523
529
  if ReturnCode.isSuccess(returnCode) {
524
- let result = ["outputPath": outputFile.absoluteString, "startTime": startTime, "endTime": endTime] as [String : Any]
530
+ let result = [
531
+ "success": true,
532
+ "outputPath": outputFile.absoluteString,
533
+ "startTime": startTime,
534
+ "endTime": endTime
535
+ ] as [String : Any]
525
536
 
526
537
  completion(result)
527
538
  } else if ReturnCode.isCancel(returnCode) {
528
539
  // CANCEL
529
- completion(nil)
540
+ let result = [
541
+ "success": false,
542
+ "message": "FFmpeg command was cancelled with code \(returnCode?.getValue() ?? -1)",
543
+ ] as [String : Any]
544
+
545
+ completion(result)
530
546
  } else {
531
547
  // FAILURE
532
- completion(nil)
548
+ let result = [
549
+ "success": false,
550
+ "message": "Command failed with rc \(String(describing: returnCode)).\(String(describing: session?.getFailStackTrace()))",
551
+ ] as [String : Any]
552
+
553
+ completion(result)
533
554
  }
534
555
  }, withLogCallback: nil, withStatisticsCallback: nil)
535
556
  }
@@ -538,7 +559,13 @@ public class VideoTrim: RCTEventEmitter, AssetLoaderDelegate, UIDocumentPickerDe
538
559
  @objc(trim:withConfig:withResolver:withRejecter:)
539
560
  func _trim(inputFile: String, config: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
540
561
  _trim(inputFile: inputFile, config: config, completion: { payload in
541
- resolve(payload)
562
+ if let success = payload["success"] as? Bool, success {
563
+ resolve(payload)
564
+ } else {
565
+ let message = payload["message"] as? String ?? "Unknown error"
566
+ let error = NSError(domain: "", code: 200, userInfo: nil)
567
+ reject("ERR_TRIM_FAILED", message, error)
568
+ }
542
569
  })
543
570
  }
544
571
 
@@ -12,14 +12,8 @@ function createBaseOptions(overrides = {}) {
12
12
  saveToPhoto: false,
13
13
  type: 'video',
14
14
  outputExt: 'mp4',
15
- openDocumentsOnFinish: false,
16
- openShareSheetOnFinish: false,
17
15
  removeAfterSavedToPhoto: false,
18
16
  removeAfterFailedToSavePhoto: false,
19
- removeAfterSavedToDocuments: false,
20
- removeAfterFailedToSaveDocuments: false,
21
- removeAfterShared: false,
22
- removeAfterFailedToShare: false,
23
17
  enableRotation: false,
24
18
  rotationAngle: 0,
25
19
  ...overrides
@@ -30,6 +24,12 @@ function createEditorConfig(overrides = {}) {
30
24
  enableHapticFeedback: true,
31
25
  maxDuration: -1,
32
26
  minDuration: -1,
27
+ openDocumentsOnFinish: false,
28
+ openShareSheetOnFinish: false,
29
+ removeAfterSavedToDocuments: false,
30
+ removeAfterFailedToSaveDocuments: false,
31
+ removeAfterShared: false,
32
+ removeAfterFailedToShare: false,
33
33
  cancelButtonText: 'Cancel',
34
34
  saveButtonText: 'Save',
35
35
  enableCancelDialog: true,
@@ -1 +1 @@
1
- {"version":3,"names":["VideoTrimNewArch","VideoTrimOldArch","processColor","isFabric","global","nativeFabricUIManager","VideoTrim","createBaseOptions","overrides","saveToPhoto","type","outputExt","openDocumentsOnFinish","openShareSheetOnFinish","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","removeAfterSavedToDocuments","removeAfterFailedToSaveDocuments","removeAfterShared","removeAfterFailedToShare","enableRotation","rotationAngle","createEditorConfig","enableHapticFeedback","maxDuration","minDuration","cancelButtonText","saveButtonText","enableCancelDialog","cancelDialogTitle","cancelDialogMessage","cancelDialogCancelText","cancelDialogConfirmText","enableSaveDialog","saveDialogTitle","saveDialogMessage","saveDialogCancelText","saveDialogConfirmText","trimmingText","fullScreenModalIOS","autoplay","jumpToPositionOnLoad","closeWhenFinish","enableCancelTrimming","cancelTrimmingButtonText","enableCancelTrimmingDialog","cancelTrimmingDialogTitle","cancelTrimmingDialogMessage","cancelTrimmingDialogCancelText","cancelTrimmingDialogConfirmText","headerText","headerTextSize","headerTextColor","trimmerColor","handleIconColor","alertOnFailToLoad","alertOnFailTitle","alertOnFailMessage","alertOnFailCloseText","createTrimOptions","startTime","endTime","showEditor","filePath","config","_headerTextColor","_trimmerColor","_handleIconColor","listFiles","cleanFiles","deleteFile","trim","length","Error","closeEditor","isValidFile","url","options"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["VideoTrimNewArch","VideoTrimOldArch","processColor","isFabric","global","nativeFabricUIManager","VideoTrim","createBaseOptions","overrides","saveToPhoto","type","outputExt","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","enableRotation","rotationAngle","createEditorConfig","enableHapticFeedback","maxDuration","minDuration","openDocumentsOnFinish","openShareSheetOnFinish","removeAfterSavedToDocuments","removeAfterFailedToSaveDocuments","removeAfterShared","removeAfterFailedToShare","cancelButtonText","saveButtonText","enableCancelDialog","cancelDialogTitle","cancelDialogMessage","cancelDialogCancelText","cancelDialogConfirmText","enableSaveDialog","saveDialogTitle","saveDialogMessage","saveDialogCancelText","saveDialogConfirmText","trimmingText","fullScreenModalIOS","autoplay","jumpToPositionOnLoad","closeWhenFinish","enableCancelTrimming","cancelTrimmingButtonText","enableCancelTrimmingDialog","cancelTrimmingDialogTitle","cancelTrimmingDialogMessage","cancelTrimmingDialogCancelText","cancelTrimmingDialogConfirmText","headerText","headerTextSize","headerTextColor","trimmerColor","handleIconColor","alertOnFailToLoad","alertOnFailTitle","alertOnFailMessage","alertOnFailCloseText","createTrimOptions","startTime","endTime","showEditor","filePath","config","_headerTextColor","_trimmerColor","_handleIconColor","listFiles","cleanFiles","deleteFile","trim","length","Error","closeEditor","isValidFile","url","options"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -4,14 +4,8 @@ export interface BaseOptions {
4
4
  saveToPhoto: boolean;
5
5
  type: string;
6
6
  outputExt: string;
7
- openDocumentsOnFinish: boolean;
8
- openShareSheetOnFinish: boolean;
9
7
  removeAfterSavedToPhoto: boolean;
10
8
  removeAfterFailedToSavePhoto: boolean;
11
- removeAfterSavedToDocuments: boolean;
12
- removeAfterFailedToSaveDocuments: boolean;
13
- removeAfterShared: boolean;
14
- removeAfterFailedToShare: boolean;
15
9
  enableRotation: boolean;
16
10
  rotationAngle: number;
17
11
  }
@@ -19,6 +13,12 @@ export interface EditorConfig extends BaseOptions {
19
13
  enableHapticFeedback: boolean;
20
14
  maxDuration: number;
21
15
  minDuration: number;
16
+ openDocumentsOnFinish: boolean;
17
+ openShareSheetOnFinish: boolean;
18
+ removeAfterSavedToDocuments: boolean;
19
+ removeAfterFailedToSaveDocuments: boolean;
20
+ removeAfterShared: boolean;
21
+ removeAfterFailedToShare: boolean;
22
22
  cancelButtonText: string;
23
23
  saveButtonText: string;
24
24
  enableCancelDialog: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeVideoTrim.d.ts","sourceRoot":"","sources":["../../../src/NativeVideoTrim.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NativeVideoTrim.d.ts","sourceRoot":"","sources":["../../../src/NativeVideoTrim.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-video-trim",
3
- "version": "6.0.3",
3
+ "version": "6.0.5",
4
4
  "description": "Video trimmer for your React Native app",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -6,14 +6,8 @@ export interface BaseOptions {
6
6
  saveToPhoto: boolean;
7
7
  type: string;
8
8
  outputExt: string;
9
- openDocumentsOnFinish: boolean;
10
- openShareSheetOnFinish: boolean;
11
9
  removeAfterSavedToPhoto: boolean;
12
10
  removeAfterFailedToSavePhoto: boolean;
13
- removeAfterSavedToDocuments: boolean;
14
- removeAfterFailedToSaveDocuments: boolean;
15
- removeAfterShared: boolean;
16
- removeAfterFailedToShare: boolean;
17
11
  enableRotation: boolean;
18
12
  rotationAngle: number;
19
13
  }
@@ -22,6 +16,12 @@ export interface EditorConfig extends BaseOptions {
22
16
  enableHapticFeedback: boolean;
23
17
  maxDuration: number;
24
18
  minDuration: number;
19
+ openDocumentsOnFinish: boolean;
20
+ openShareSheetOnFinish: boolean;
21
+ removeAfterSavedToDocuments: boolean;
22
+ removeAfterFailedToSaveDocuments: boolean;
23
+ removeAfterShared: boolean;
24
+ removeAfterFailedToShare: boolean;
25
25
  cancelButtonText: string;
26
26
  saveButtonText: string;
27
27
  enableCancelDialog: boolean;
package/src/index.tsx CHANGED
@@ -17,14 +17,8 @@ function createBaseOptions(overrides: Partial<BaseOptions> = {}): BaseOptions {
17
17
  saveToPhoto: false,
18
18
  type: 'video',
19
19
  outputExt: 'mp4',
20
- openDocumentsOnFinish: false,
21
- openShareSheetOnFinish: false,
22
20
  removeAfterSavedToPhoto: false,
23
21
  removeAfterFailedToSavePhoto: false,
24
- removeAfterSavedToDocuments: false,
25
- removeAfterFailedToSaveDocuments: false,
26
- removeAfterShared: false,
27
- removeAfterFailedToShare: false,
28
22
  enableRotation: false,
29
23
  rotationAngle: 0,
30
24
  ...overrides,
@@ -38,6 +32,12 @@ function createEditorConfig(
38
32
  enableHapticFeedback: true,
39
33
  maxDuration: -1,
40
34
  minDuration: -1,
35
+ openDocumentsOnFinish: false,
36
+ openShareSheetOnFinish: false,
37
+ removeAfterSavedToDocuments: false,
38
+ removeAfterFailedToSaveDocuments: false,
39
+ removeAfterShared: false,
40
+ removeAfterFailedToShare: false,
41
41
  cancelButtonText: 'Cancel',
42
42
  saveButtonText: 'Save',
43
43
  enableCancelDialog: true,