react-native-video-trim 6.0.4 → 6.0.6
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 +60 -6
- package/android/src/main/java/com/videotrim/BaseVideoTrimModule.kt +7 -19
- package/android/src/main/java/com/videotrim/widgets/VideoTrimmerView.java +16 -2
- package/ios/VideoTrim.mm +12 -10
- package/ios/VideoTrim.swift +33 -6
- package/ios/VideoTrimmer.swift +19 -4
- package/ios/VideoTrimmerViewController.swift +3 -0
- package/lib/module/NativeVideoTrim.js.map +1 -1
- package/lib/module/index.js +7 -6
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeVideoTrim.d.ts +12 -6
- package/lib/typescript/src/NativeVideoTrim.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativeVideoTrim.ts +12 -6
- package/src/index.tsx +7 -6
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` |
|
|
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` |
|
|
285
|
+
| `headerTextColor` | `string` | - | Header text color |
|
|
282
286
|
| `trimmerColor` | `string` | - | Trimmer bar color |
|
|
283
|
-
| `handleIconColor` | `string` | - | Trimmer
|
|
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,8 @@ 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
|
-
| `
|
|
349
|
+
| `changeStatusBarColorOnOpen` | `boolean` | `false` | Change status bar color (Android only) |
|
|
350
|
+
| `zoomOnWaitingDuration` | `number` | `5000` | Duration for zoom-on-waiting feature in milliseconds (default: 5000) |
|
|
296
351
|
|
|
297
352
|
### Example Configuration
|
|
298
353
|
|
|
@@ -567,7 +622,6 @@ export default function VideoTrimmer() {
|
|
|
567
622
|
- Use `trim()` for batch processing without UI
|
|
568
623
|
- Clean up generated files regularly with `cleanFiles()`
|
|
569
624
|
- Consider file compression for large videos
|
|
570
|
-
- Use appropriate `maxDuration` limits
|
|
571
625
|
|
|
572
626
|
## Credits
|
|
573
627
|
|
|
@@ -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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
669
|
+
shareIntent.type = "*/*"
|
|
682
670
|
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
|
|
683
671
|
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
684
672
|
|
|
@@ -91,6 +91,7 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
91
91
|
private long startTime = 0, endTime = 0;
|
|
92
92
|
private boolean enableRotation = false;
|
|
93
93
|
private double rotationAngle = 0.0;
|
|
94
|
+
private long zoomOnWaitingDuration = 5000; // Default: 5 seconds (in milliseconds)
|
|
94
95
|
|
|
95
96
|
private Vibrator vibrator;
|
|
96
97
|
private boolean didClampWhilePanning = false;
|
|
@@ -524,6 +525,12 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
524
525
|
alertOnFailCloseText = config.hasKey("alertOnFailCloseText") ? config.getString("alertOnFailCloseText") : "Close";
|
|
525
526
|
enableRotation = config.hasKey("enableRotation") && config.getBoolean("enableRotation");
|
|
526
527
|
rotationAngle = config.hasKey("rotationAngle") ? config.getDouble("rotationAngle") : 0.0;
|
|
528
|
+
|
|
529
|
+
// Configure zoom on waiting duration (in seconds, converted to milliseconds)
|
|
530
|
+
if (config.hasKey("zoomOnWaitingDuration") && config.getDouble("zoomOnWaitingDuration") > 0) {
|
|
531
|
+
zoomOnWaitingDuration = (long) (config.getDouble("zoomOnWaitingDuration"));
|
|
532
|
+
Log.d(TAG, "Configured zoom on waiting duration: " + (zoomOnWaitingDuration / 1000.0) + " seconds");
|
|
533
|
+
}
|
|
527
534
|
|
|
528
535
|
trimmerColor = config.hasKey("trimmerColor") ? config.getInt("trimmerColor") : Color.parseColor(getContext().getString(R.string.trim_color));
|
|
529
536
|
handleIconColor = config.hasKey("handleIconColor") ? config.getInt("handleIconColor") : Color.BLACK;
|
|
@@ -971,8 +978,15 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
971
978
|
float currentLeadingX = leadingHandle.getX();
|
|
972
979
|
float currentTrailingX = trailingHandle.getX();
|
|
973
980
|
|
|
974
|
-
//
|
|
975
|
-
long newDuration =
|
|
981
|
+
// Use configurable zoom duration, but ensure it's reasonable for the video
|
|
982
|
+
long newDuration = Math.min(zoomOnWaitingDuration, mDuration);
|
|
983
|
+
|
|
984
|
+
// For very short videos, use a smaller zoom range
|
|
985
|
+
if (mDuration < 2000) {
|
|
986
|
+
newDuration = Math.max(500, mDuration / 2); // At least 0.5 seconds for very short videos
|
|
987
|
+
} else if (mDuration < zoomOnWaitingDuration) {
|
|
988
|
+
newDuration = Math.max(1000, mDuration / 2); // Use half duration for short videos
|
|
989
|
+
}
|
|
976
990
|
|
|
977
991
|
// Ensure zoom duration doesn't exceed video duration
|
|
978
992
|
newDuration = Math.min(newDuration, mDuration);
|
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> *
|
|
78
|
-
|
|
79
|
-
|
|
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
|
}
|
|
@@ -153,6 +150,11 @@ RCT_EXPORT_MODULE()
|
|
|
153
150
|
dict[@"handleIconColor"] = @(handleIconColorOpt.value());
|
|
154
151
|
}
|
|
155
152
|
|
|
153
|
+
auto zoomOnWaitingDurationOpt = config.zoomOnWaitingDuration();
|
|
154
|
+
if (zoomOnWaitingDurationOpt.has_value()) {
|
|
155
|
+
dict[@"zoomOnWaitingDuration"] = @(zoomOnWaitingDurationOpt.value());
|
|
156
|
+
}
|
|
157
|
+
|
|
156
158
|
[self->videoTrim showEditor:filePath withConfig:dict];
|
|
157
159
|
}
|
|
158
160
|
|
package/ios/VideoTrim.swift
CHANGED
|
@@ -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]
|
|
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
|
-
|
|
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 = [
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
package/ios/VideoTrimmer.swift
CHANGED
|
@@ -153,6 +153,7 @@ import AVFoundation
|
|
|
153
153
|
var minimumDuration: CMTime = CMTime(seconds: 1, preferredTimescale: 600)
|
|
154
154
|
var maximumDuration: CMTime = .positiveInfinity
|
|
155
155
|
var enableHapticFeedback = true
|
|
156
|
+
var zoomOnWaitingDuration: Double = 5.0 // Default: 5 seconds
|
|
156
157
|
|
|
157
158
|
// the available range of the asset.
|
|
158
159
|
// Will be set to the full duration of the asset when assigning a new asset
|
|
@@ -499,18 +500,32 @@ import AVFoundation
|
|
|
499
500
|
let size = bounds.size
|
|
500
501
|
let inset = thumbView.chevronWidth + horizontalInset
|
|
501
502
|
let availableWidth = size.width - inset * 2
|
|
502
|
-
let newDuration = CGFloat(range.duration.seconds > 4 ? 2.0 : range.duration.seconds * 0.5)
|
|
503
503
|
|
|
504
|
-
|
|
504
|
+
// Use configurable zoom duration, but ensure it's reasonable for the video
|
|
505
|
+
var newDuration = zoomOnWaitingDuration
|
|
506
|
+
|
|
507
|
+
// For very short videos, use a smaller zoom range
|
|
508
|
+
if range.duration.seconds < 2.0 {
|
|
509
|
+
newDuration = max(0.5, range.duration.seconds * 0.5) // At least 0.5 seconds for very short videos
|
|
510
|
+
} else if range.duration.seconds < zoomOnWaitingDuration {
|
|
511
|
+
newDuration = max(1.0, range.duration.seconds * 0.5) // Use half duration for short videos
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Ensure zoom duration doesn't exceed video duration
|
|
515
|
+
newDuration = min(newDuration, range.duration.seconds)
|
|
516
|
+
|
|
517
|
+
print("Zoom activated - Video duration: \(range.duration.seconds)s, Configured zoom: \(zoomOnWaitingDuration)s, Actual zoom: \(newDuration)s")
|
|
518
|
+
|
|
519
|
+
let durationTime = CMTime(seconds: newDuration, preferredTimescale: 600)
|
|
505
520
|
|
|
506
521
|
if trimmingState == .leading {
|
|
507
522
|
let position = locationForTime(selectedRange.start) - inset
|
|
508
|
-
let start = position / availableWidth * newDuration
|
|
523
|
+
let start = position / availableWidth * CGFloat(newDuration)
|
|
509
524
|
zoomedInRange = CMTimeRange(start: CMTimeSubtract(selectedRange.start, CMTime(seconds: Double(start), preferredTimescale: 600)), duration: durationTime)
|
|
510
525
|
} else {
|
|
511
526
|
let position = locationForTime(selectedRange.end) - inset
|
|
512
527
|
|
|
513
|
-
let durationToStart = position / availableWidth * newDuration
|
|
528
|
+
let durationToStart = position / availableWidth * CGFloat(newDuration)
|
|
514
529
|
let newStart = CMTimeSubtract(selectedRange.end, CMTime(seconds: Double(durationToStart), preferredTimescale: 600))
|
|
515
530
|
zoomedInRange = CMTimeRange(start: newStart, duration: durationTime)
|
|
516
531
|
}
|
|
@@ -47,6 +47,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
47
47
|
var cancelBtnClicked: (() -> Void)?
|
|
48
48
|
var saveBtnClicked: ((CMTimeRange) -> Void)?
|
|
49
49
|
private var enableHapticFeedback = true
|
|
50
|
+
private var zoomOnWaitingDuration: Double = 5.0 // Default: 5 seconds
|
|
50
51
|
|
|
51
52
|
// New color properties
|
|
52
53
|
private var trimmerColor: UIColor = UIColor.systemYellow
|
|
@@ -328,6 +329,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
328
329
|
trimmer.asset = asset
|
|
329
330
|
trimmer.minimumDuration = CMTime(seconds: 1, preferredTimescale: 600)
|
|
330
331
|
trimmer.enableHapticFeedback = enableHapticFeedback
|
|
332
|
+
trimmer.zoomOnWaitingDuration = zoomOnWaitingDuration
|
|
331
333
|
|
|
332
334
|
if let maxDuration = maximumDuration {
|
|
333
335
|
trimmer.maximumDuration = CMTime(seconds: max(1, Double(maxDuration)), preferredTimescale: 600)
|
|
@@ -477,6 +479,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
477
479
|
saveButtonText = config["saveButtonText"] as? String ?? "Save"
|
|
478
480
|
jumpToPositionOnLoad = config["jumpToPositionOnLoad"] as? Double ?? 0
|
|
479
481
|
enableHapticFeedback = config["enableHapticFeedback"] as? Bool ?? true
|
|
482
|
+
zoomOnWaitingDuration = (config["zoomOnWaitingDuration"] as? Double ?? 5.0) / 1000.0 // convert ms to s
|
|
480
483
|
autoplay = config["autoplay"] as? Bool ?? false
|
|
481
484
|
headerText = config["headerText"] as? String
|
|
482
485
|
headerTextSize = config["headerTextSize"] as? Int ?? 16
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeVideoTrim.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeVideoTrim.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAkIlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,WAAW,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -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,
|
|
@@ -59,6 +59,7 @@ function createEditorConfig(overrides = {}) {
|
|
|
59
59
|
headerTextColor: processColor('white'),
|
|
60
60
|
trimmerColor: processColor('#f1d247'),
|
|
61
61
|
handleIconColor: processColor('black'),
|
|
62
|
+
zoomOnWaitingDuration: 5000,
|
|
62
63
|
alertOnFailToLoad: true,
|
|
63
64
|
alertOnFailTitle: 'Error',
|
|
64
65
|
alertOnFailMessage: 'Fail to load media. Possibly invalid file or no network connection',
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["VideoTrimNewArch","VideoTrimOldArch","processColor","isFabric","global","nativeFabricUIManager","VideoTrim","createBaseOptions","overrides","saveToPhoto","type","outputExt","
|
|
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","zoomOnWaitingDuration","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":";;AAAA,OAAOA,gBAAgB,MAAM,sBAAmB;AAChD,OAAOC,gBAAgB,MAAM,cAAW;AAOxC,SAASC,YAAY,QAAQ,cAAc;;AAE3C;AACA,MAAMC,QAAQ,GAAG,CAAC,CAAEC,MAAM,CAASC,qBAAqB;AACxD,MAAMC,SAAS,GAAGH,QAAQ,GAAGH,gBAAgB,GAAGC,gBAAgB;AAEhE,SAASM,iBAAiBA,CAACC,SAA+B,GAAG,CAAC,CAAC,EAAe;EAC5E,OAAO;IACLC,WAAW,EAAE,KAAK;IAClBC,IAAI,EAAE,OAAO;IACbC,SAAS,EAAE,KAAK;IAChBC,uBAAuB,EAAE,KAAK;IAC9BC,4BAA4B,EAAE,KAAK;IACnCC,cAAc,EAAE,KAAK;IACrBC,aAAa,EAAE,CAAC;IAChB,GAAGP;EACL,CAAC;AACH;AAEA,SAASQ,kBAAkBA,CACzBR,SAAgC,GAAG,CAAC,CAAC,EACvB;EACd,OAAO;IACLS,oBAAoB,EAAE,IAAI;IAC1BC,WAAW,EAAE,CAAC,CAAC;IACfC,WAAW,EAAE,CAAC,CAAC;IACfC,qBAAqB,EAAE,KAAK;IAC5BC,sBAAsB,EAAE,KAAK;IAC7BC,2BAA2B,EAAE,KAAK;IAClCC,gCAAgC,EAAE,KAAK;IACvCC,iBAAiB,EAAE,KAAK;IACxBC,wBAAwB,EAAE,KAAK;IAC/BC,gBAAgB,EAAE,QAAQ;IAC1BC,cAAc,EAAE,MAAM;IACtBC,kBAAkB,EAAE,IAAI;IACxBC,iBAAiB,EAAE,UAAU;IAC7BC,mBAAmB,EAAE,8BAA8B;IACnDC,sBAAsB,EAAE,OAAO;IAC/BC,uBAAuB,EAAE,SAAS;IAClCC,gBAAgB,EAAE,IAAI;IACtBC,eAAe,EAAE,eAAe;IAChCC,iBAAiB,EAAE,4BAA4B;IAC/CC,oBAAoB,EAAE,OAAO;IAC7BC,qBAAqB,EAAE,SAAS;IAChCC,YAAY,EAAE,mBAAmB;IACjCC,kBAAkB,EAAE,KAAK;IACzBC,QAAQ,EAAE,KAAK;IACfC,oBAAoB,EAAE,CAAC,CAAC;IACxBC,eAAe,EAAE,IAAI;IACrBC,oBAAoB,EAAE,IAAI;IAC1BC,wBAAwB,EAAE,QAAQ;IAClCC,0BAA0B,EAAE,IAAI;IAChCC,yBAAyB,EAAE,UAAU;IACrCC,2BAA2B,EAAE,uCAAuC;IACpEC,8BAA8B,EAAE,OAAO;IACvCC,+BAA+B,EAAE,SAAS;IAC1CC,UAAU,EAAE,EAAE;IACdC,cAAc,EAAE,EAAE;IAClBC,eAAe,EAAElD,YAAY,CAAC,OAAO,CAAW;IAChDmD,YAAY,EAAEnD,YAAY,CAAC,SAAS,CAAW;IAC/CoD,eAAe,EAAEpD,YAAY,CAAC,OAAO,CAAW;IAChDqD,qBAAqB,EAAE,IAAI;IAC3BC,iBAAiB,EAAE,IAAI;IACvBC,gBAAgB,EAAE,OAAO;IACzBC,kBAAkB,EAChB,oEAAoE;IACtEC,oBAAoB,EAAE,OAAO;IAC7B,GAAGpD,iBAAiB,CAACC,SAAS,CAAC;IAC/B,GAAGA;EACL,CAAC;AACH;AAEA,SAASoD,iBAAiBA,CAACpD,SAA+B,GAAG,CAAC,CAAC,EAAe;EAC5E,OAAO;IACLqD,SAAS,EAAE,CAAC;IACZC,OAAO,EAAE,IAAI;IACb,GAAGvD,iBAAiB,CAACC,SAAS,CAAC;IAC/B,GAAGA;EACL,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASuD,UAAUA,CACxBC,QAAgB,EAChBC,MAMC,EACK;EACN,MAAM;IAAEb,eAAe;IAAEC,YAAY;IAAEC;EAAgB,CAAC,GAAGW,MAAM;EACjE,MAAMC,gBAAgB,GAAGhE,YAAY,CAACkD,eAAe,IAAI,OAAO,CAAC;EACjE,MAAMe,aAAa,GAAGjE,YAAY,CAACmD,YAAY,IAAI,SAAS,CAAC;EAC7D,MAAMe,gBAAgB,GAAGlE,YAAY,CAACoD,eAAe,IAAI,OAAO,CAAC;EAEjEhD,SAAS,CAACyD,UAAU,CAClBC,QAAQ,EACRhD,kBAAkB,CAAC;IACjB,GAAGiD,MAAM;IACTb,eAAe,EAAEc,gBAAuB;IACxCb,YAAY,EAAEc,aAAoB;IAClCb,eAAe,EAAEc;EACnB,CAAC,CACH,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,SAASA,CAAA,EAAsB;EAC7C,OAAO/D,SAAS,CAAC+D,SAAS,CAAC,CAAC;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAAA,EAAoB;EAC5C,OAAOhE,SAAS,CAACgE,UAAU,CAAC,CAAC;AAC/B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAACP,QAAgB,EAAoB;EAC7D,IAAI,CAACA,QAAQ,EAAEQ,IAAI,CAAC,CAAC,CAACC,MAAM,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,4BAA4B,CAAC;EAC/C;EACA,OAAOpE,SAAS,CAACiE,UAAU,CAACP,QAAQ,CAAC;AACvC;;AAEA;AACA;AACA;AACA,OAAO,SAASW,WAAWA,CAAA,EAAS;EAClC,OAAOrE,SAAS,CAACqE,WAAW,CAAC,CAAC;AAChC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CAACC,GAAW,EAAiC;EACtE,OAAOvE,SAAS,CAACsE,WAAW,CAACC,GAAG,CAAC;AACnC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASL,IAAIA,CAClBK,GAAW,EACXC,OAA6B,EACZ;EACjB,OAAOxE,SAAS,CAACkE,IAAI,CAACK,GAAG,EAAEjB,iBAAiB,CAACkB,OAAO,CAAC,CAAC;AACxD;AAEA,cAAc,sBAAmB;AACjC,eAAexE,SAAS","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;
|
|
@@ -63,6 +63,12 @@ export interface EditorConfig extends BaseOptions {
|
|
|
63
63
|
* Color of the trimmer left/right handle icons
|
|
64
64
|
*/
|
|
65
65
|
handleIconColor?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Duration for zoom-on-waiting feature in milliseconds (default: 5000)
|
|
68
|
+
* When user pauses while dragging trim handles, the view will zoom to show
|
|
69
|
+
* this duration around the current trim position for more precise editing
|
|
70
|
+
*/
|
|
71
|
+
zoomOnWaitingDuration?: number;
|
|
66
72
|
}
|
|
67
73
|
export interface TrimOptions extends BaseOptions {
|
|
68
74
|
startTime: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeVideoTrim.d.ts","sourceRoot":"","sources":["../../../src/NativeVideoTrim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"NativeVideoTrim.d.ts","sourceRoot":"","sources":["../../../src/NativeVideoTrim.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAK3B,QAAA,MAAM,SAAS,KAAiD,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAK3B,QAAA,MAAM,SAAS,KAAiD,CAAC;AA6EjE;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CACb,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,cAAc,GAAG,iBAAiB,CAAC,CAC3E,GAAG;IACF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,IAAI,CAeN;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK7D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED,cAAc,mBAAmB,CAAC;AAClC,eAAe,SAAS,CAAC"}
|
package/package.json
CHANGED
package/src/NativeVideoTrim.ts
CHANGED
|
@@ -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;
|
|
@@ -66,6 +66,12 @@ export interface EditorConfig extends BaseOptions {
|
|
|
66
66
|
* Color of the trimmer left/right handle icons
|
|
67
67
|
*/
|
|
68
68
|
handleIconColor?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Duration for zoom-on-waiting feature in milliseconds (default: 5000)
|
|
71
|
+
* When user pauses while dragging trim handles, the view will zoom to show
|
|
72
|
+
* this duration around the current trim position for more precise editing
|
|
73
|
+
*/
|
|
74
|
+
zoomOnWaitingDuration?: number;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
export interface TrimOptions extends BaseOptions {
|
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,
|
|
@@ -67,6 +67,7 @@ function createEditorConfig(
|
|
|
67
67
|
headerTextColor: processColor('white') as number,
|
|
68
68
|
trimmerColor: processColor('#f1d247') as number,
|
|
69
69
|
handleIconColor: processColor('black') as number,
|
|
70
|
+
zoomOnWaitingDuration: 5000,
|
|
70
71
|
alertOnFailToLoad: true,
|
|
71
72
|
alertOnFailTitle: 'Error',
|
|
72
73
|
alertOnFailMessage:
|