react-native-video-trim 7.1.1 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +257 -1
- package/android/src/main/java/com/videotrim/BaseVideoTrimModule.kt +488 -34
- package/android/src/main/java/com/videotrim/utils/StorageUtil.kt +95 -36
- package/android/src/main/java/com/videotrim/utils/VideoTrimmerUtil.kt +38 -16
- package/android/src/main/java/com/videotrim/widgets/VideoTrimmerView.kt +92 -5
- package/android/src/main/res/drawable/speaker_slash_fill.xml +19 -0
- package/android/src/main/res/drawable/speaker_wave_2_fill.xml +23 -0
- package/android/src/main/res/layout/video_trimmer_view.xml +25 -3
- package/android/src/newarch/VideoTrimModule.kt +33 -0
- package/android/src/oldarch/VideoTrimModule.kt +41 -0
- package/android/src/oldarch/VideoTrimSpec.kt +17 -0
- package/ios/VideoTrim.mm +160 -1
- package/ios/VideoTrim.swift +632 -39
- package/ios/VideoTrimmerViewController.swift +129 -28
- package/lib/module/NativeVideoTrim.js +52 -0
- package/lib/module/NativeVideoTrim.js.map +1 -1
- package/lib/module/index.js +143 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeVideoTrim.d.ts +161 -0
- package/lib/typescript/src/NativeVideoTrim.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +62 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativeVideoTrim.ts +183 -0
- package/src/index.tsx +186 -0
|
@@ -10,22 +10,26 @@ import AVKit
|
|
|
10
10
|
import React
|
|
11
11
|
|
|
12
12
|
extension CMTime {
|
|
13
|
-
|
|
14
|
-
let
|
|
15
|
-
let
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
let
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
13
|
+
func displayString(format: String) -> String {
|
|
14
|
+
let totalSeconds = max(0, seconds.isFinite ? seconds : 0)
|
|
15
|
+
let totalMs = Int((totalSeconds * 1000).rounded())
|
|
16
|
+
let h = totalMs / 3_600_000
|
|
17
|
+
let m = (totalMs / 60_000) % 60
|
|
18
|
+
let s = (totalMs / 1000) % 60
|
|
19
|
+
let ms = totalMs % 1000
|
|
20
|
+
switch format {
|
|
21
|
+
case "mm:ss":
|
|
22
|
+
return String(format: "%02d:%02d", m + h * 60, s)
|
|
23
|
+
case "mm:ss.SS":
|
|
24
|
+
return String(format: "%02d:%02d.%02d", m + h * 60, s, ms / 10)
|
|
25
|
+
case "hh:mm:ss":
|
|
26
|
+
return String(format: "%02d:%02d:%02d", h, m, s)
|
|
27
|
+
case "hh:mm:ss.SSS":
|
|
28
|
+
return String(format: "%02d:%02d:%02d.%03d", h, m, s, ms)
|
|
29
|
+
default:
|
|
30
|
+
return String(format: "%02d:%02d.%03d", m + h * 60, s, ms)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
@available(iOS 13.0, *)
|
|
@@ -52,6 +56,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
52
56
|
private var trimmerColor: UIColor = UIColor.systemYellow
|
|
53
57
|
private var handleIconColor: UIColor = UIColor.black
|
|
54
58
|
private var isLightTheme = false
|
|
59
|
+
private var durationFormat: String = "mm:ss.SSS"
|
|
55
60
|
private var waveformBarColor: UIColor = .white
|
|
56
61
|
private var waveformBgColor: UIColor = UIColor(red: 0.204, green: 0.471, blue: 0.965, alpha: 1)
|
|
57
62
|
private var waveformBarWidth: CGFloat = 3
|
|
@@ -59,6 +64,8 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
59
64
|
private var waveformBarCornerRadius: CGFloat = 1.5
|
|
60
65
|
private var iconColor: UIColor { isLightTheme ? .black : .white }
|
|
61
66
|
private var dimmedIconColor: UIColor { iconColor.withAlphaComponent(0.5) }
|
|
67
|
+
private let symbolConfig = UIImage.SymbolConfiguration(pointSize: 14, weight: .medium)
|
|
68
|
+
private let speedOptions: [Double] = [0.25, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0]
|
|
62
69
|
|
|
63
70
|
private let playerController = AVPlayerViewController()
|
|
64
71
|
private var trimmer: VideoTrimmer!
|
|
@@ -86,6 +93,10 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
86
93
|
|
|
87
94
|
private(set) var rotationCount = 0
|
|
88
95
|
private(set) var isFlipped = false
|
|
96
|
+
private(set) var isMuted = false
|
|
97
|
+
private var muteBtn: UIButton?
|
|
98
|
+
private(set) var speed: Double = 1.0
|
|
99
|
+
private var speedBtn: UIButton?
|
|
89
100
|
private var isVideoType = true
|
|
90
101
|
private var playerContainerView: UIView!
|
|
91
102
|
private var transformStackView: UIStackView?
|
|
@@ -190,9 +201,9 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
190
201
|
|
|
191
202
|
// MARK: - Private
|
|
192
203
|
private func updateLabels() {
|
|
193
|
-
leadingTrimLabel.text = trimmer.selectedRange.start.displayString
|
|
194
|
-
currentTimeLabel.text = trimmer.progress.displayString
|
|
195
|
-
trailingTrimLabel.text = trimmer.selectedRange.end.displayString
|
|
204
|
+
leadingTrimLabel.text = trimmer.selectedRange.start.displayString(format: durationFormat)
|
|
205
|
+
currentTimeLabel.text = trimmer.progress.displayString(format: durationFormat)
|
|
206
|
+
trailingTrimLabel.text = trimmer.selectedRange.end.displayString(format: durationFormat)
|
|
196
207
|
}
|
|
197
208
|
|
|
198
209
|
private func handleBeforeProgressChange() {
|
|
@@ -270,6 +281,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
270
281
|
}
|
|
271
282
|
|
|
272
283
|
player.play()
|
|
284
|
+
player.rate = Float(speed)
|
|
273
285
|
}
|
|
274
286
|
|
|
275
287
|
setPlayBtnIcon()
|
|
@@ -375,12 +387,13 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
375
387
|
|
|
376
388
|
private func setupTimeLabels() {
|
|
377
389
|
let labelColor = isLightTheme ? UIColor.black : UIColor.white
|
|
390
|
+
let placeholder = CMTime.zero.displayString(format: durationFormat)
|
|
378
391
|
leadingTrimLabel = UILabel.createLabel(textAlignment: .left, textColor: labelColor)
|
|
379
|
-
leadingTrimLabel.text =
|
|
392
|
+
leadingTrimLabel.text = placeholder
|
|
380
393
|
currentTimeLabel = UILabel.createLabel(textAlignment: .center, textColor: labelColor)
|
|
381
|
-
currentTimeLabel.text =
|
|
394
|
+
currentTimeLabel.text = placeholder
|
|
382
395
|
trailingTrimLabel = UILabel.createLabel(textAlignment: .right, textColor: labelColor)
|
|
383
|
-
trailingTrimLabel.text =
|
|
396
|
+
trailingTrimLabel.text = placeholder
|
|
384
397
|
|
|
385
398
|
timingStackView = UIStackView(arrangedSubviews: [leadingTrimLabel, currentTimeLabel, trailingTrimLabel])
|
|
386
399
|
timingStackView.axis = .horizontal
|
|
@@ -463,6 +476,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
463
476
|
}
|
|
464
477
|
playerController.player = AVPlayer()
|
|
465
478
|
player.replaceCurrentItem(with: AVPlayerItem(asset: asset))
|
|
479
|
+
player.isMuted = isMuted
|
|
466
480
|
|
|
467
481
|
statusObservation = player.observe(\.status, options: [.new, .initial]) { [weak self] player, _ in
|
|
468
482
|
DispatchQueue.main.async {
|
|
@@ -521,8 +535,6 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
521
535
|
private func setupTransformButtons() {
|
|
522
536
|
guard isVideoType else { return }
|
|
523
537
|
|
|
524
|
-
let symbolConfig = UIImage.SymbolConfiguration(pointSize: 14, weight: .medium)
|
|
525
|
-
|
|
526
538
|
let flipBtn = UIButton(type: .system)
|
|
527
539
|
flipBtn.setImage(UIImage(systemName: "arrow.trianglehead.left.and.right.righttriangle.left.righttriangle.right", withConfiguration: symbolConfig), for: .normal)
|
|
528
540
|
flipBtn.tintColor = iconColor
|
|
@@ -539,6 +551,25 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
539
551
|
cropButton.addTarget(self, action: #selector(onCropTapped), for: .touchUpInside)
|
|
540
552
|
self.cropBtn = cropButton
|
|
541
553
|
|
|
554
|
+
let muteButton = UIButton(type: .system)
|
|
555
|
+
muteButton.setImage(UIImage(systemName: isMuted ? "speaker.slash.fill" : "speaker.wave.2.fill", withConfiguration: symbolConfig), for: .normal)
|
|
556
|
+
muteButton.tintColor = iconColor
|
|
557
|
+
muteButton.addTarget(self, action: #selector(onMuteTapped), for: .touchUpInside)
|
|
558
|
+
self.muteBtn = muteButton
|
|
559
|
+
|
|
560
|
+
let speedButton = UIButton(type: .system)
|
|
561
|
+
let speedLabel = speed == 1.0 ? "1x" : "\(speed)x"
|
|
562
|
+
speedButton.setTitle(speedLabel, for: .normal)
|
|
563
|
+
speedButton.titleLabel?.font = .systemFont(ofSize: 13, weight: .semibold)
|
|
564
|
+
speedButton.tintColor = iconColor
|
|
565
|
+
if #available(iOS 14.0, *) {
|
|
566
|
+
speedButton.showsMenuAsPrimaryAction = true
|
|
567
|
+
speedButton.menu = buildSpeedMenu()
|
|
568
|
+
} else {
|
|
569
|
+
speedButton.addTarget(self, action: #selector(onSpeedTapped), for: .touchUpInside)
|
|
570
|
+
}
|
|
571
|
+
self.speedBtn = speedButton
|
|
572
|
+
|
|
542
573
|
let undoButton = UIButton(type: .system)
|
|
543
574
|
undoButton.setImage(UIImage(systemName: "arrow.uturn.backward", withConfiguration: symbolConfig), for: .normal)
|
|
544
575
|
undoButton.tintColor = dimmedIconColor
|
|
@@ -553,7 +584,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
553
584
|
redoButton.addTarget(self, action: #selector(onRedoTapped), for: .touchUpInside)
|
|
554
585
|
self.redoBtn = redoButton
|
|
555
586
|
|
|
556
|
-
let leftStack = UIStackView(arrangedSubviews: [flipBtn, rotateBtn, cropButton])
|
|
587
|
+
let leftStack = UIStackView(arrangedSubviews: [flipBtn, rotateBtn, cropButton, muteButton, speedButton])
|
|
557
588
|
leftStack.axis = .horizontal
|
|
558
589
|
leftStack.spacing = 12
|
|
559
590
|
|
|
@@ -578,6 +609,10 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
578
609
|
rotateBtn.heightAnchor.constraint(equalToConstant: btnSize),
|
|
579
610
|
cropButton.widthAnchor.constraint(equalToConstant: btnSize),
|
|
580
611
|
cropButton.heightAnchor.constraint(equalToConstant: btnSize),
|
|
612
|
+
muteButton.widthAnchor.constraint(equalToConstant: btnSize),
|
|
613
|
+
muteButton.heightAnchor.constraint(equalToConstant: btnSize),
|
|
614
|
+
speedButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 36),
|
|
615
|
+
speedButton.heightAnchor.constraint(equalToConstant: btnSize),
|
|
581
616
|
undoButton.widthAnchor.constraint(equalToConstant: btnSize),
|
|
582
617
|
undoButton.heightAnchor.constraint(equalToConstant: btnSize),
|
|
583
618
|
redoButton.widthAnchor.constraint(equalToConstant: btnSize),
|
|
@@ -590,6 +625,66 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
590
625
|
self.transformStackView = fullRow
|
|
591
626
|
}
|
|
592
627
|
|
|
628
|
+
@objc private func onMuteTapped() {
|
|
629
|
+
isMuted.toggle()
|
|
630
|
+
muteBtn?.setImage(UIImage(systemName: isMuted ? "speaker.slash.fill" : "speaker.wave.2.fill", withConfiguration: symbolConfig), for: .normal)
|
|
631
|
+
player.isMuted = isMuted
|
|
632
|
+
if enableHapticFeedback {
|
|
633
|
+
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Builds a native context menu for speed selection (iOS 14+). The menu is
|
|
638
|
+
// attached via showsMenuAsPrimaryAction so it opens on tap without an extra
|
|
639
|
+
// long-press gesture. Falls back to UIAlertController on older iOS versions.
|
|
640
|
+
@available(iOS 14.0, *)
|
|
641
|
+
private func buildSpeedMenu() -> UIMenu {
|
|
642
|
+
let actions = speedOptions.map { opt in
|
|
643
|
+
let title = opt == 1.0 ? "Normal (1x)" : "\(opt)x"
|
|
644
|
+
let isSelected = abs(opt - speed) < 0.0001
|
|
645
|
+
return UIAction(title: title, state: isSelected ? .on : .off) { [weak self] _ in
|
|
646
|
+
self?.setSpeed(opt)
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return UIMenu(title: "", children: actions)
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/// Fallback for iOS < 14 where UIMenu is unavailable.
|
|
653
|
+
@objc private func onSpeedTapped() {
|
|
654
|
+
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
|
655
|
+
alert.overrideUserInterfaceStyle = isLightTheme ? .light : .dark
|
|
656
|
+
for opt in speedOptions {
|
|
657
|
+
let title = opt == 1.0 ? "Normal (1x)" : "\(opt)x"
|
|
658
|
+
let isSelected = abs(opt - speed) < 0.0001
|
|
659
|
+
let action = UIAlertAction(title: title, style: isSelected ? .destructive : .default) { [weak self] _ in
|
|
660
|
+
self?.setSpeed(opt)
|
|
661
|
+
}
|
|
662
|
+
alert.addAction(action)
|
|
663
|
+
}
|
|
664
|
+
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
|
|
665
|
+
if let pop = alert.popoverPresentationController, let btn = speedBtn {
|
|
666
|
+
pop.sourceView = btn
|
|
667
|
+
pop.sourceRect = btn.bounds
|
|
668
|
+
}
|
|
669
|
+
present(alert, animated: true)
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
private func setSpeed(_ newSpeed: Double) {
|
|
673
|
+
speed = newSpeed
|
|
674
|
+
let label = newSpeed == 1.0 ? "1x" : "\(newSpeed)x"
|
|
675
|
+
speedBtn?.setTitle(label, for: .normal)
|
|
676
|
+
if #available(iOS 14.0, *) {
|
|
677
|
+
speedBtn?.menu = buildSpeedMenu()
|
|
678
|
+
}
|
|
679
|
+
player.rate = Float(newSpeed)
|
|
680
|
+
if player.timeControlStatus != .playing {
|
|
681
|
+
player.pause()
|
|
682
|
+
}
|
|
683
|
+
if enableHapticFeedback {
|
|
684
|
+
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
593
688
|
@objc private func onFlipTapped() {
|
|
594
689
|
pushUndo()
|
|
595
690
|
isFlipped.toggle()
|
|
@@ -915,7 +1010,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
915
1010
|
self.seek(to: trimmer.selectedRange.end)
|
|
916
1011
|
}
|
|
917
1012
|
|
|
918
|
-
currentTimeLabel.text = trimmer.progress.displayString
|
|
1013
|
+
currentTimeLabel.text = trimmer.progress.displayString(format: durationFormat)
|
|
919
1014
|
|
|
920
1015
|
self.setPlayBtnIcon()
|
|
921
1016
|
}
|
|
@@ -970,6 +1065,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
970
1065
|
}
|
|
971
1066
|
|
|
972
1067
|
isLightTheme = (config["theme"] as? String) == "light"
|
|
1068
|
+
durationFormat = (config["durationFormat"] as? String) ?? "mm:ss.SSS"
|
|
973
1069
|
|
|
974
1070
|
cancelButtonText = config["cancelButtonText"] as? String ?? "Cancel"
|
|
975
1071
|
saveButtonText = config["saveButtonText"] as? String ?? "Save"
|
|
@@ -978,6 +1074,10 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
978
1074
|
zoomOnWaitingDuration = (config["zoomOnWaitingDuration"] as? Double ?? 5.0) / 1000.0 // convert ms to s
|
|
979
1075
|
autoplay = config["autoplay"] as? Bool ?? false
|
|
980
1076
|
isVideoType = (config["type"] as? String ?? "video") == "video"
|
|
1077
|
+
isMuted = config["removeAudio"] as? Bool ?? false
|
|
1078
|
+
if let cfgSpeed = config["speed"] as? Double {
|
|
1079
|
+
speed = cfgSpeed
|
|
1080
|
+
}
|
|
981
1081
|
headerText = config["headerText"] as? String
|
|
982
1082
|
headerTextSize = config["headerTextSize"] as? Int ?? 16
|
|
983
1083
|
headerTextColor = config["headerTextColor"] as? Double
|
|
@@ -1029,7 +1129,7 @@ class VideoTrimmerViewController: UIViewController {
|
|
|
1029
1129
|
|
|
1030
1130
|
self.seek(to: cmtime)
|
|
1031
1131
|
self.trimmer.progress = cmtime
|
|
1032
|
-
self.currentTimeLabel.text = self.trimmer.progress.displayString
|
|
1132
|
+
self.currentTimeLabel.text = self.trimmer.progress.displayString(format: durationFormat)
|
|
1033
1133
|
}
|
|
1034
1134
|
|
|
1035
1135
|
if autoplay {
|
|
@@ -1064,7 +1164,8 @@ private extension UIButton {
|
|
|
1064
1164
|
private extension UILabel {
|
|
1065
1165
|
static func createLabel(textAlignment: NSTextAlignment, textColor: UIColor) -> UILabel {
|
|
1066
1166
|
let label = UILabel()
|
|
1067
|
-
|
|
1167
|
+
let baseFont = UIFont.preferredFont(forTextStyle: .caption1)
|
|
1168
|
+
label.font = UIFont.monospacedDigitSystemFont(ofSize: baseFont.pointSize, weight: .regular)
|
|
1068
1169
|
label.textAlignment = textAlignment
|
|
1069
1170
|
label.textColor = textColor
|
|
1070
1171
|
return label
|
|
@@ -22,6 +22,58 @@ import { TurboModuleRegistry } from 'react-native';
|
|
|
22
22
|
* Result returned by a trim operation (both editor and headless).
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Options for extracting a single frame from a video.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Result returned by {@link Spec.getFrameAt}.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Options for extracting the audio track from a video file.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Result returned by {@link Spec.extractAudio}.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Options for compressing a video file.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Result returned by {@link Spec.compress}.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Options for converting a video segment to an animated GIF.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Result returned by {@link Spec.toGif}.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Options for merging multiple media files into one.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Result returned by {@link Spec.merge}.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Result returned by {@link Spec.saveToPhoto}.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Result returned by {@link Spec.saveToDocuments}.
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Result returned by {@link Spec.share}.
|
|
75
|
+
*/
|
|
76
|
+
|
|
25
77
|
/**
|
|
26
78
|
* TurboModule spec for the native VideoTrim module.
|
|
27
79
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeVideoTrim.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAGlD;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeVideoTrim.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAGlD;AACA;AACA;;AAgCA;AACA;AACA;;AA4HA;AACA;AACA;;AAQA;AACA;AACA;;AAUA;AACA;AACA;;AAcA;AACA;AACA;;AAcA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AAQA;AACA;AACA;;AAqBA;AACA;AACA;;AAMA;AACA;AACA;;AAYA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AAQA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AA4FA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,WAAW,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -15,6 +15,51 @@ function createBaseOptions(overrides = {}) {
|
|
|
15
15
|
removeAfterSavedToPhoto: false,
|
|
16
16
|
removeAfterFailedToSavePhoto: false,
|
|
17
17
|
enablePreciseTrimming: false,
|
|
18
|
+
removeAudio: false,
|
|
19
|
+
speed: 1.0,
|
|
20
|
+
...overrides
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function createCompressOptions(overrides = {}) {
|
|
24
|
+
return {
|
|
25
|
+
quality: 'medium',
|
|
26
|
+
bitrate: -1,
|
|
27
|
+
width: -1,
|
|
28
|
+
height: -1,
|
|
29
|
+
frameRate: -1,
|
|
30
|
+
outputExt: 'mp4',
|
|
31
|
+
removeAudio: false,
|
|
32
|
+
...overrides
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function createFrameExtractionOptions(overrides = {}) {
|
|
36
|
+
return {
|
|
37
|
+
time: 0,
|
|
38
|
+
format: 'jpeg',
|
|
39
|
+
quality: 80,
|
|
40
|
+
maxWidth: -1,
|
|
41
|
+
maxHeight: -1,
|
|
42
|
+
...overrides
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function createExtractAudioOptions(overrides = {}) {
|
|
46
|
+
return {
|
|
47
|
+
outputExt: 'm4a',
|
|
48
|
+
...overrides
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function createGifOptions(overrides = {}) {
|
|
52
|
+
return {
|
|
53
|
+
startTime: 0,
|
|
54
|
+
endTime: -1,
|
|
55
|
+
fps: 10,
|
|
56
|
+
width: -1,
|
|
57
|
+
...overrides
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function createMergeOptions(overrides = {}) {
|
|
61
|
+
return {
|
|
62
|
+
outputExt: 'mp4',
|
|
18
63
|
...overrides
|
|
19
64
|
};
|
|
20
65
|
}
|
|
@@ -68,6 +113,7 @@ function createEditorConfig(overrides = {}) {
|
|
|
68
113
|
waveformBarWidth: 3,
|
|
69
114
|
waveformBarGap: 2,
|
|
70
115
|
waveformBarCornerRadius: 1.5,
|
|
116
|
+
durationFormat: 'mm:ss.SSS',
|
|
71
117
|
...createBaseOptions(overrides),
|
|
72
118
|
...overrides
|
|
73
119
|
};
|
|
@@ -171,6 +217,103 @@ export function isValidFile(url) {
|
|
|
171
217
|
export function trim(url, options) {
|
|
172
218
|
return VideoTrim.trim(url, createTrimOptions(options));
|
|
173
219
|
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Extract a single frame from a video at a given timestamp
|
|
223
|
+
*
|
|
224
|
+
* @param {string} url: absolute non-empty file path
|
|
225
|
+
* @param {Partial<FrameExtractionOptions>} options: extraction options
|
|
226
|
+
* @returns {Promise<FrameResult>} A **Promise** which resolves to the FrameResult
|
|
227
|
+
*/
|
|
228
|
+
export function getFrameAt(url, options = {}) {
|
|
229
|
+
return VideoTrim.getFrameAt(url, createFrameExtractionOptions(options));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Extract the audio track from a video file
|
|
234
|
+
*
|
|
235
|
+
* @param {string} url: absolute non-empty file path
|
|
236
|
+
* @param {Partial<ExtractAudioOptions>} options: extraction options
|
|
237
|
+
* @returns {Promise<ExtractAudioResult>} A **Promise** which resolves to the result
|
|
238
|
+
*/
|
|
239
|
+
export function extractAudio(url, options = {}) {
|
|
240
|
+
return VideoTrim.extractAudio(url, createExtractAudioOptions(options));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Compress a video file to reduce its size
|
|
245
|
+
*
|
|
246
|
+
* @param {string} url: absolute non-empty file path
|
|
247
|
+
* @param {Partial<CompressOptions>} options: compression options
|
|
248
|
+
* @returns {Promise<CompressResult>} A **Promise** which resolves to the result
|
|
249
|
+
*/
|
|
250
|
+
export function compress(url, options = {}) {
|
|
251
|
+
return VideoTrim.compress(url, createCompressOptions(options));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Convert a video segment to an animated GIF
|
|
256
|
+
*
|
|
257
|
+
* @param {string} url: absolute non-empty file path
|
|
258
|
+
* @param {Partial<GifOptions>} options: GIF conversion options
|
|
259
|
+
* @returns {Promise<GifResult>} A **Promise** which resolves to the result
|
|
260
|
+
*/
|
|
261
|
+
export function toGif(url, options = {}) {
|
|
262
|
+
return VideoTrim.toGif(url, createGifOptions(options));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Merge multiple media files into a single file (headless, no UI)
|
|
267
|
+
*
|
|
268
|
+
* @param {string[]} urls: array of file paths to merge in order
|
|
269
|
+
* @param {Partial<MergeOptions>} options: merge options
|
|
270
|
+
* @returns {Promise<MergeResult>} A **Promise** which resolves to the result
|
|
271
|
+
*/
|
|
272
|
+
export function merge(urls, options = {}) {
|
|
273
|
+
if (!urls?.length) {
|
|
274
|
+
throw new Error('URLs array cannot be empty!');
|
|
275
|
+
}
|
|
276
|
+
return VideoTrim.merge(urls, createMergeOptions(options));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Save a file to the device's photo library
|
|
281
|
+
*
|
|
282
|
+
* @param {string} filePath: absolute path to the file
|
|
283
|
+
* @returns {Promise<SaveToPhotoResult>} A **Promise** which resolves to the result
|
|
284
|
+
*/
|
|
285
|
+
export function saveToPhoto(filePath) {
|
|
286
|
+
if (!filePath?.trim().length) {
|
|
287
|
+
throw new Error('File path cannot be empty!');
|
|
288
|
+
}
|
|
289
|
+
return VideoTrim.saveToPhoto(filePath);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Present the system document picker to save a file
|
|
294
|
+
*
|
|
295
|
+
* @param {string} filePath: absolute path to the file
|
|
296
|
+
* @returns {Promise<SaveToDocumentsResult>} A **Promise** which resolves to the result
|
|
297
|
+
*/
|
|
298
|
+
export function saveToDocuments(filePath) {
|
|
299
|
+
if (!filePath?.trim().length) {
|
|
300
|
+
throw new Error('File path cannot be empty!');
|
|
301
|
+
}
|
|
302
|
+
return VideoTrim.saveToDocuments(filePath);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Open the system share sheet for a file
|
|
307
|
+
*
|
|
308
|
+
* @param {string} filePath: absolute path to the file
|
|
309
|
+
* @returns {Promise<ShareResult>} A **Promise** which resolves to the result
|
|
310
|
+
*/
|
|
311
|
+
export function share(filePath) {
|
|
312
|
+
if (!filePath?.trim().length) {
|
|
313
|
+
throw new Error('File path cannot be empty!');
|
|
314
|
+
}
|
|
315
|
+
return VideoTrim.share(filePath);
|
|
316
|
+
}
|
|
174
317
|
export * from "./NativeVideoTrim.js";
|
|
175
318
|
export default VideoTrim;
|
|
176
319
|
//# sourceMappingURL=index.js.map
|
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","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","enablePreciseTrimming","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","waveformColor","waveformBackgroundColor","waveformBarWidth","waveformBarGap","waveformBarCornerRadius","
|
|
1
|
+
{"version":3,"names":["VideoTrimNewArch","VideoTrimOldArch","processColor","isFabric","global","nativeFabricUIManager","VideoTrim","createBaseOptions","overrides","saveToPhoto","type","outputExt","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","enablePreciseTrimming","removeAudio","speed","createCompressOptions","quality","bitrate","width","height","frameRate","createFrameExtractionOptions","time","format","maxWidth","maxHeight","createExtractAudioOptions","createGifOptions","startTime","endTime","fps","createMergeOptions","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","waveformColor","waveformBackgroundColor","waveformBarWidth","waveformBarGap","waveformBarCornerRadius","durationFormat","createTrimOptions","showEditor","filePath","config","isLight","theme","_headerTextColor","_trimmerColor","_handleIconColor","_waveformColor","_waveformBackgroundColor","listFiles","cleanFiles","deleteFile","trim","length","Error","closeEditor","isValidFile","url","options","getFrameAt","extractAudio","compress","toGif","merge","urls","saveToDocuments","share"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,gBAAgB,MAAM,sBAAmB;AAChD,OAAOC,gBAAgB,MAAM,cAAW;AAqBxC,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,qBAAqB,EAAE,KAAK;IAC5BC,WAAW,EAAE,KAAK;IAClBC,KAAK,EAAE,GAAG;IACV,GAAGR;EACL,CAAC;AACH;AAEA,SAASS,qBAAqBA,CAC5BT,SAAmC,GAAG,CAAC,CAAC,EACvB;EACjB,OAAO;IACLU,OAAO,EAAE,QAAQ;IACjBC,OAAO,EAAE,CAAC,CAAC;IACXC,KAAK,EAAE,CAAC,CAAC;IACTC,MAAM,EAAE,CAAC,CAAC;IACVC,SAAS,EAAE,CAAC,CAAC;IACbX,SAAS,EAAE,KAAK;IAChBI,WAAW,EAAE,KAAK;IAClB,GAAGP;EACL,CAAC;AACH;AAEA,SAASe,4BAA4BA,CACnCf,SAA0C,GAAG,CAAC,CAAC,EACvB;EACxB,OAAO;IACLgB,IAAI,EAAE,CAAC;IACPC,MAAM,EAAE,MAAM;IACdP,OAAO,EAAE,EAAE;IACXQ,QAAQ,EAAE,CAAC,CAAC;IACZC,SAAS,EAAE,CAAC,CAAC;IACb,GAAGnB;EACL,CAAC;AACH;AAEA,SAASoB,yBAAyBA,CAChCpB,SAAuC,GAAG,CAAC,CAAC,EACvB;EACrB,OAAO;IACLG,SAAS,EAAE,KAAK;IAChB,GAAGH;EACL,CAAC;AACH;AAEA,SAASqB,gBAAgBA,CAACrB,SAA8B,GAAG,CAAC,CAAC,EAAc;EACzE,OAAO;IACLsB,SAAS,EAAE,CAAC;IACZC,OAAO,EAAE,CAAC,CAAC;IACXC,GAAG,EAAE,EAAE;IACPZ,KAAK,EAAE,CAAC,CAAC;IACT,GAAGZ;EACL,CAAC;AACH;AAEA,SAASyB,kBAAkBA,CACzBzB,SAAgC,GAAG,CAAC,CAAC,EACvB;EACd,OAAO;IACLG,SAAS,EAAE,KAAK;IAChB,GAAGH;EACL,CAAC;AACH;AAEA,SAAS0B,kBAAkBA,CACzB1B,SAAgC,GAAG,CAAC,CAAC,EACvB;EACd,OAAO;IACL2B,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,EAAEpE,YAAY,CAAC,OAAO,CAAW;IAChDqE,YAAY,EAAErE,YAAY,CAAC,SAAS,CAAW;IAC/CsE,eAAe,EAAEtE,YAAY,CAAC,OAAO,CAAW;IAChDuE,qBAAqB,EAAE,IAAI;IAC3BC,iBAAiB,EAAE,IAAI;IACvBC,gBAAgB,EAAE,OAAO;IACzBC,kBAAkB,EAChB,oEAAoE;IACtEC,oBAAoB,EAAE,OAAO;IAC7BC,aAAa,EAAE5E,YAAY,CAAC,OAAO,CAAW;IAC9C6E,uBAAuB,EAAE7E,YAAY,CAAC,SAAS,CAAW;IAC1D8E,gBAAgB,EAAE,CAAC;IACnBC,cAAc,EAAE,CAAC;IACjBC,uBAAuB,EAAE,GAAG;IAC5BC,cAAc,EAAE,WAAW;IAC3B,GAAG5E,iBAAiB,CAACC,SAAS,CAAC;IAC/B,GAAGA;EACL,CAAC;AACH;AAEA,SAAS4E,iBAAiBA,CAAC5E,SAA+B,GAAG,CAAC,CAAC,EAAe;EAC5E,OAAO;IACLsB,SAAS,EAAE,CAAC;IACZC,OAAO,EAAE,IAAI;IACb,GAAGxB,iBAAiB,CAACC,SAAS,CAAC;IAC/B,GAAGA;EACL,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAAS6E,UAAUA,CACxBC,QAAgB,EAChBC,MAeC,EACK;EACN,MAAM;IACJjB,eAAe;IACfC,YAAY;IACZC,eAAe;IACfM,aAAa;IACbC;EACF,CAAC,GAAGQ,MAAM;EACV,MAAMC,OAAO,GAAGD,MAAM,CAACE,KAAK,KAAK,OAAO;EACxC,MAAMC,gBAAgB,GAAGxF,YAAY,CACnCoE,eAAe,KAAKkB,OAAO,GAAG,OAAO,GAAG,OAAO,CACjD,CAAC;EACD,MAAMG,aAAa,GAAGzF,YAAY,CAACqE,YAAY,IAAI,SAAS,CAAC;EAC7D,MAAMqB,gBAAgB,GAAG1F,YAAY,CACnCsE,eAAe,KAAKgB,OAAO,GAAG,OAAO,GAAG,OAAO,CACjD,CAAC;EACD,MAAMK,cAAc,GAAG3F,YAAY,CAAC4E,aAAa,IAAI,OAAO,CAAC;EAC7D,MAAMgB,wBAAwB,GAAG5F,YAAY,CAC3C6E,uBAAuB,IAAI,SAC7B,CAAC;EAEDzE,SAAS,CAAC+E,UAAU,CAClBC,QAAQ,EACRpD,kBAAkB,CAAC;IACjB,GAAGqD,MAAM;IACTjB,eAAe,EAAEoB,gBAAuB;IACxCnB,YAAY,EAAEoB,aAAoB;IAClCnB,eAAe,EAAEoB,gBAAuB;IACxCd,aAAa,EAAEe,cAAqB;IACpCd,uBAAuB,EAAEe;EAC3B,CAAC,CACH,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,SAASA,CAAA,EAAsB;EAC7C,OAAOzF,SAAS,CAACyF,SAAS,CAAC,CAAC;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAAA,EAAoB;EAC5C,OAAO1F,SAAS,CAAC0F,UAAU,CAAC,CAAC;AAC/B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAACX,QAAgB,EAAoB;EAC7D,IAAI,CAACA,QAAQ,EAAEY,IAAI,CAAC,CAAC,CAACC,MAAM,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,4BAA4B,CAAC;EAC/C;EACA,OAAO9F,SAAS,CAAC2F,UAAU,CAACX,QAAQ,CAAC;AACvC;;AAEA;AACA;AACA;AACA,OAAO,SAASe,WAAWA,CAAA,EAAS;EAClC,OAAO/F,SAAS,CAAC+F,WAAW,CAAC,CAAC;AAChC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CAACC,GAAW,EAAiC;EACtE,OAAOjG,SAAS,CAACgG,WAAW,CAACC,GAAG,CAAC;AACnC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASL,IAAIA,CAClBK,GAAW,EACXC,OAA6B,EACR;EACrB,OAAOlG,SAAS,CAAC4F,IAAI,CAACK,GAAG,EAAEnB,iBAAiB,CAACoB,OAAO,CAAC,CAAC;AACxD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CACxBF,GAAW,EACXC,OAAwC,GAAG,CAAC,CAAC,EACvB;EACtB,OAAOlG,SAAS,CAACmG,UAAU,CAACF,GAAG,EAAEhF,4BAA4B,CAACiF,OAAO,CAAC,CAAC;AACzE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,YAAYA,CAC1BH,GAAW,EACXC,OAAqC,GAAG,CAAC,CAAC,EACb;EAC7B,OAAOlG,SAAS,CAACoG,YAAY,CAACH,GAAG,EAAE3E,yBAAyB,CAAC4E,OAAO,CAAC,CAAC;AACxE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,QAAQA,CACtBJ,GAAW,EACXC,OAAiC,GAAG,CAAC,CAAC,EACb;EACzB,OAAOlG,SAAS,CAACqG,QAAQ,CAACJ,GAAG,EAAEtF,qBAAqB,CAACuF,OAAO,CAAC,CAAC;AAChE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,KAAKA,CACnBL,GAAW,EACXC,OAA4B,GAAG,CAAC,CAAC,EACb;EACpB,OAAOlG,SAAS,CAACsG,KAAK,CAACL,GAAG,EAAE1E,gBAAgB,CAAC2E,OAAO,CAAC,CAAC;AACxD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,KAAKA,CACnBC,IAAc,EACdN,OAA8B,GAAG,CAAC,CAAC,EACb;EACtB,IAAI,CAACM,IAAI,EAAEX,MAAM,EAAE;IACjB,MAAM,IAAIC,KAAK,CAAC,6BAA6B,CAAC;EAChD;EACA,OAAO9F,SAAS,CAACuG,KAAK,CAACC,IAAI,EAAE7E,kBAAkB,CAACuE,OAAO,CAAC,CAAC;AAC3D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAAS/F,WAAWA,CAAC6E,QAAgB,EAA8B;EACxE,IAAI,CAACA,QAAQ,EAAEY,IAAI,CAAC,CAAC,CAACC,MAAM,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,4BAA4B,CAAC;EAC/C;EACA,OAAO9F,SAAS,CAACG,WAAW,CAAC6E,QAAQ,CAAC;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASyB,eAAeA,CAC7BzB,QAAgB,EACgB;EAChC,IAAI,CAACA,QAAQ,EAAEY,IAAI,CAAC,CAAC,CAACC,MAAM,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,4BAA4B,CAAC;EAC/C;EACA,OAAO9F,SAAS,CAACyG,eAAe,CAACzB,QAAQ,CAAC;AAC5C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAAS0B,KAAKA,CAAC1B,QAAgB,EAAwB;EAC5D,IAAI,CAACA,QAAQ,EAAEY,IAAI,CAAC,CAAC,CAACC,MAAM,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,4BAA4B,CAAC;EAC/C;EACA,OAAO9F,SAAS,CAAC0G,KAAK,CAAC1B,QAAQ,CAAC;AAClC;AAEA,cAAc,sBAAmB;AACjC,eAAehF,SAAS","ignoreList":[]}
|