react-native-video-trim 5.0.5 → 5.1.1

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.
@@ -1,533 +0,0 @@
1
- #import "VideoTrimmerViewController.h"
2
- #import "VideoTrimmer.h"
3
- #import <AVFoundation/AVFoundation.h>
4
-
5
-
6
- @implementation VideoTrimmerViewController
7
-
8
- - (instancetype)init {
9
- if (self = [super init]) {
10
- self.cancelButtonText = @"Cancel";
11
- self.saveButtonText = @"Save";
12
- self.headerTextSize = 16;
13
- self.headerTextColor = 0xFFFFFF;
14
- self.autoplay = NO;
15
- self.jumpToPositionOnLoad = 0;
16
- self.enableHapticFeedback = YES;
17
- self.chaseTime = kCMTimeZero;
18
- self.isSeekInProgress = NO;
19
- self.playerController = [[AVPlayerViewController alloc] init];
20
- self.loadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium];
21
- }
22
- return self;
23
- }
24
-
25
- - (void)setAsset:(AVAsset *)asset {
26
- NSLog(@"📱 VideoTrimmerViewController setAsset called with: %@", asset);
27
-
28
- _asset = asset;
29
- if (asset) {
30
- [self setupVideoTrimmer];
31
- [self setupPlayerController];
32
- [self setupTimeObserver];
33
- [self updateLabels];
34
- }
35
- }
36
-
37
- - (AVPlayer *)player {
38
- return self.playerController.player;
39
- }
40
-
41
- - (void)onAssetFailToLoad {
42
- [self.loadingIndicator stopAnimating];
43
- [self.btnStackView removeArrangedSubview:self.loadingIndicator];
44
- [self.loadingIndicator removeFromSuperview];
45
-
46
- UIView *imageViewContainer = [[UIView alloc] init];
47
- UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"exclamationmark.triangle.fill"]];
48
- imageView.tintColor = [UIColor systemYellowColor];
49
- imageView.translatesAutoresizingMaskIntoConstraints = NO;
50
-
51
- [imageViewContainer addSubview:imageView];
52
- [NSLayoutConstraint activateConstraints:@[
53
- [imageView.widthAnchor constraintEqualToConstant:36],
54
- [imageView.heightAnchor constraintEqualToConstant:36],
55
- [imageView.centerXAnchor constraintEqualToAnchor:imageViewContainer.centerXAnchor],
56
- [imageView.centerYAnchor constraintEqualToAnchor:imageViewContainer.centerYAnchor]
57
- ]];
58
- imageViewContainer.alpha = 0;
59
-
60
- [self.btnStackView insertArrangedSubview:imageViewContainer atIndex:1];
61
-
62
- [UIView animateWithDuration:0.25 animations:^{
63
- imageViewContainer.alpha = 1;
64
- }];
65
- }
66
-
67
- - (void)didBeginTrimmingFromStart:(VideoTrimmer *)sender {
68
- [self handleBeforeProgressChange];
69
- }
70
-
71
- - (void)leadingGrabberChanged:(VideoTrimmer *)sender {
72
- [self handleProgressChanged:self.trimmer.selectedRange.start];
73
- }
74
-
75
- - (void)didEndTrimmingFromStart:(VideoTrimmer *)sender {
76
- [self handleTrimmingEnd:YES];
77
- }
78
-
79
- - (void)didBeginTrimmingFromEnd:(VideoTrimmer *)sender {
80
- [self handleBeforeProgressChange];
81
- }
82
-
83
- - (void)trailingGrabberChanged:(VideoTrimmer *)sender {
84
- [self handleProgressChanged:CMTimeRangeGetEnd(self.trimmer.selectedRange)];
85
- }
86
-
87
- - (void)didEndTrimmingFromEnd:(VideoTrimmer *)sender {
88
- [self handleTrimmingEnd:NO];
89
- }
90
-
91
- - (void)didBeginScrubbing:(VideoTrimmer *)sender {
92
- [self handleBeforeProgressChange];
93
- }
94
-
95
- - (void)didEndScrubbing:(VideoTrimmer *)sender {
96
- [self updateLabels];
97
- }
98
-
99
- - (void)progressDidChanged:(VideoTrimmer *)sender {
100
- [self handleProgressChanged:self.trimmer.progress];
101
- }
102
-
103
- - (void)updateLabels {
104
- self.leadingTrimLabel.text = [self displayStringFromCMTime:self.trimmer.selectedRange.start];
105
- self.currentTimeLabel.text = [self displayStringFromCMTime:self.trimmer.progress];
106
- self.trailingTrimLabel.text = [self displayStringFromCMTime:CMTimeRangeGetEnd(self.trimmer.selectedRange)];
107
- }
108
-
109
- - (NSString *)displayStringFromCMTime:(CMTime)time {
110
- NSTimeInterval offset = CMTimeGetSeconds(time);
111
- double numberOfNanosecondsFloat = (offset - (NSTimeInterval)((int)offset)) * 100.0;
112
- int nanoseconds = (int)numberOfNanosecondsFloat;
113
-
114
- NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
115
- formatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
116
- formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
117
- formatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond;
118
-
119
- NSString *timeString = [formatter stringFromTimeInterval:offset] ?: @"00:00";
120
- return [NSString stringWithFormat:@"%@.%02d", timeString, nanoseconds];
121
- }
122
-
123
- - (void)handleBeforeProgressChange {
124
- [self updateLabels];
125
- [self.player pause];
126
- [self setPlayBtnIcon];
127
- }
128
-
129
- - (void)handleProgressChanged:(CMTime)time {
130
- [self updateLabels];
131
- [self seek:time];
132
- }
133
-
134
- - (void)handleTrimmingEnd:(BOOL)start {
135
- self.trimmer.progress = start ? self.trimmer.selectedRange.start : CMTimeRangeGetEnd(self.trimmer.selectedRange);
136
- [self updateLabels];
137
- [self seek:self.trimmer.progress];
138
- }
139
-
140
- - (void)viewDidLoad {
141
- [super viewDidLoad];
142
- [self setupView];
143
- [self setupButtons];
144
- [self setupTimeLabels];
145
- }
146
-
147
- - (void)viewWillDisappear:(BOOL)animated {
148
- [super viewWillDisappear:animated];
149
-
150
- if (!self.asset) return;
151
- [self.player pause];
152
-
153
- [self.player removeObserver:self forKeyPath:@"status"];
154
-
155
- if (self.timeObserverToken) {
156
- [self.player removeTimeObserver:self.timeObserverToken];
157
- self.timeObserverToken = nil;
158
- }
159
-
160
- [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
161
-
162
- self.playerController.player = nil;
163
- [self.playerController dismissViewControllerAnimated:NO completion:nil];
164
- }
165
-
166
- - (void)pausePlayer {
167
- [self.player pause];
168
- [self setPlayBtnIcon];
169
- }
170
-
171
- - (void)togglePlay:(UIButton *)sender {
172
- if (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
173
- [self.player pause];
174
- } else {
175
- if (CMTimeCompare(self.trimmer.progress, CMTimeRangeGetEnd(self.trimmer.selectedRange)) != -1) {
176
- self.trimmer.progress = self.trimmer.selectedRange.start;
177
- [self seek:self.trimmer.progress];
178
- }
179
- [self.player play];
180
- }
181
- [self setPlayBtnIcon];
182
- }
183
-
184
- - (void)onSaveBtnClicked {
185
- if (self.saveBtnClicked) {
186
- self.saveBtnClicked(self.trimmer.selectedRange);
187
- }
188
- }
189
-
190
- - (void)onCancelBtnClicked {
191
- if (self.cancelBtnClicked) {
192
- self.cancelBtnClicked();
193
- }
194
- }
195
-
196
- - (UIColor *)colorFromHex:(double)hex defaultColor:(UIColor *)defaultColor {
197
- int32_t hexValue = (int32_t)hex;
198
- CGFloat red = ((hexValue >> 16) & 0xFF) / 255.0;
199
- CGFloat green = ((hexValue >> 8) & 0xFF) / 255.0;
200
- CGFloat blue = (hexValue & 0xFF) / 255.0;
201
- CGFloat alpha = (hexValue > 0xFFFFFF) ? ((hexValue >> 24) & 0xFF) / 255.0 : 1.0;
202
- return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
203
- }
204
-
205
- - (UIButton *)createButtonWithTitle:(NSString *)title
206
- font:(UIFont *)font
207
- titleColor:(UIColor *)titleColor
208
- image:(UIImage *)image
209
- tintColor:(UIColor *)tintColor
210
- target:(id)target
211
- action:(SEL)action {
212
- UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
213
- if (title) [button setTitle:title forState:UIControlStateNormal];
214
- if (image) [button setImage:image forState:UIControlStateNormal];
215
- if (font) button.titleLabel.font = font;
216
- if (titleColor) [button setTitleColor:titleColor forState:UIControlStateNormal];
217
- if (tintColor) button.tintColor = tintColor;
218
- [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
219
- return button;
220
- }
221
-
222
- - (UILabel *)createLabelWithAlignment:(NSTextAlignment)alignment textColor:(UIColor *)color {
223
- UILabel *label = [[UILabel alloc] init];
224
- label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1];
225
- label.textAlignment = alignment;
226
- label.textColor = color;
227
- return label;
228
- }
229
-
230
- - (void)setupView {
231
- self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
232
- self.view.backgroundColor = [UIColor blackColor];
233
-
234
- if (self.headerText) {
235
- self.headerView = [[UIView alloc] init];
236
- self.headerView.translatesAutoresizingMaskIntoConstraints = NO;
237
- [self.view addSubview:self.headerView];
238
-
239
- UITextView *headerTextView = [[UITextView alloc] init];
240
- headerTextView.text = self.headerText;
241
- headerTextView.textAlignment = NSTextAlignmentCenter;
242
- headerTextView.textColor = [self colorFromHex:self.headerTextColor defaultColor:[UIColor whiteColor]];
243
- headerTextView.font = [UIFont systemFontOfSize:self.headerTextSize];
244
- headerTextView.translatesAutoresizingMaskIntoConstraints = NO;
245
- [self.headerView addSubview:headerTextView];
246
-
247
- [NSLayoutConstraint activateConstraints:@[
248
- [self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
249
- [self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
250
- [self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
251
- [self.headerView.heightAnchor constraintGreaterThanOrEqualToConstant:50],
252
-
253
- [headerTextView.topAnchor constraintEqualToAnchor:self.headerView.topAnchor],
254
- [headerTextView.bottomAnchor constraintEqualToAnchor:self.headerView.bottomAnchor],
255
- [headerTextView.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor],
256
- [headerTextView.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor],
257
- ]];
258
-
259
- [self.view layoutIfNeeded];
260
- }
261
- }
262
-
263
- - (void)setupButtons {
264
- self.cancelBtn = [self createButtonWithTitle:self.cancelButtonText
265
- font:[UIFont systemFontOfSize:18]
266
- titleColor:[UIColor whiteColor]
267
- image:nil
268
- tintColor:nil
269
- target:self
270
- action:@selector(onCancelBtnClicked)];
271
-
272
- self.playBtn = [self createButtonWithTitle:nil
273
- font:nil
274
- titleColor:nil
275
- image:[UIImage systemImageNamed:@"play.fill"]
276
- tintColor:[UIColor whiteColor]
277
- target:self
278
- action:@selector(togglePlay:)];
279
- self.playBtn.alpha = 0;
280
- self.playBtn.enabled = NO;
281
-
282
- self.saveBtn = [self createButtonWithTitle:self.saveButtonText
283
- font:[UIFont systemFontOfSize:18]
284
- titleColor:[UIColor systemBlueColor]
285
- image:nil
286
- tintColor:nil
287
- target:self
288
- action:@selector(onSaveBtnClicked)];
289
- self.saveBtn.alpha = 0;
290
- self.saveBtn.enabled = NO;
291
-
292
- [self.loadingIndicator startAnimating];
293
-
294
- self.btnStackView = [[UIStackView alloc] initWithArrangedSubviews:@[self.cancelBtn, self.loadingIndicator, self.saveBtn]];
295
- self.btnStackView.axis = UILayoutConstraintAxisHorizontal;
296
- self.btnStackView.alignment = UIStackViewAlignmentCenter;
297
- self.btnStackView.distribution = UIStackViewDistributionFillEqually;
298
- self.btnStackView.spacing = UIStackViewSpacingUseSystem;
299
- self.btnStackView.translatesAutoresizingMaskIntoConstraints = NO;
300
-
301
- [self.view addSubview:self.btnStackView];
302
-
303
- [NSLayoutConstraint activateConstraints:@[
304
- [self.btnStackView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:16],
305
- [self.btnStackView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-16],
306
- [self.btnStackView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:-16]
307
- ]];
308
- }
309
-
310
- - (void)setupTimeLabels {
311
- self.leadingTrimLabel = [self createLabelWithAlignment:NSTextAlignmentLeft textColor:[UIColor whiteColor]];
312
- self.leadingTrimLabel.text = @"00:00.000";
313
-
314
- self.currentTimeLabel = [self createLabelWithAlignment:NSTextAlignmentCenter textColor:[UIColor whiteColor]];
315
- self.currentTimeLabel.text = @"00:00.000";
316
-
317
- self.trailingTrimLabel = [self createLabelWithAlignment:NSTextAlignmentRight textColor:[UIColor whiteColor]];
318
- self.trailingTrimLabel.text = @"00:00.000";
319
-
320
- self.timingStackView = [[UIStackView alloc] initWithArrangedSubviews:@[self.leadingTrimLabel, self.currentTimeLabel, self.trailingTrimLabel]];
321
- self.timingStackView.axis = UILayoutConstraintAxisHorizontal;
322
- self.timingStackView.alignment = UIStackViewAlignmentFill;
323
- self.timingStackView.distribution = UIStackViewDistributionFillEqually;
324
- self.timingStackView.spacing = UIStackViewSpacingUseSystem;
325
- self.timingStackView.translatesAutoresizingMaskIntoConstraints = NO;
326
-
327
- [self.view addSubview:self.timingStackView];
328
-
329
- [NSLayoutConstraint activateConstraints:@[
330
- [self.timingStackView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:16],
331
- [self.timingStackView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-16],
332
- [self.timingStackView.bottomAnchor constraintEqualToAnchor:self.btnStackView.topAnchor constant:-8]
333
- ]];
334
- }
335
-
336
- - (void)setupVideoTrimmer {
337
- self.trimmer = [[VideoTrimmer alloc] init];
338
- self.trimmer.asset = self.asset;
339
- self.trimmer.minimumDuration = CMTimeMake(1 * 600, 600); // 1 second
340
- self.trimmer.enableHapticFeedback = self.enableHapticFeedback;
341
-
342
- if (self.maximumDuration > 0) {
343
- CMTime maxDuration = CMTimeMake(MAX(1, self.maximumDuration) * 600, 600);
344
- if (CMTimeCompare(maxDuration, self.asset.duration) > 0) {
345
- maxDuration = self.asset.duration;
346
- }
347
- self.trimmer.maximumDuration = maxDuration;
348
- self.trimmer.selectedRange = CMTimeRangeMake(kCMTimeZero, maxDuration);
349
- }
350
-
351
- if (self.minimumDuration > 0) {
352
- self.trimmer.minimumDuration = CMTimeMake(MAX(1, self.minimumDuration) * 600, 600);
353
- }
354
-
355
- // Add target-action for all VideoTrimmer custom events
356
- [self.trimmer addTarget:self action:@selector(didBeginScrubbing:) forControlEvents:[VideoTrimmer didBeginScrubbing]];
357
- [self.trimmer addTarget:self action:@selector(didEndScrubbing:) forControlEvents:[VideoTrimmer didEndScrubbing]];
358
- [self.trimmer addTarget:self action:@selector(progressDidChanged:) forControlEvents:[VideoTrimmer progressChanged]];
359
-
360
- [self.trimmer addTarget:self action:@selector(didBeginTrimmingFromStart:) forControlEvents:[VideoTrimmer didBeginTrimmingFromStart]];
361
- [self.trimmer addTarget:self action:@selector(leadingGrabberChanged:) forControlEvents:[VideoTrimmer leadingGrabberChanged]];
362
- [self.trimmer addTarget:self action:@selector(didEndTrimmingFromStart:) forControlEvents:[VideoTrimmer didEndTrimmingFromStart]];
363
-
364
- [self.trimmer addTarget:self action:@selector(didBeginTrimmingFromEnd:) forControlEvents:[VideoTrimmer didBeginTrimmingFromEnd]];
365
- [self.trimmer addTarget:self action:@selector(trailingGrabberChanged:) forControlEvents:[VideoTrimmer trailingGrabberChanged]];
366
- [self.trimmer addTarget:self action:@selector(didEndTrimmingFromEnd:) forControlEvents:[VideoTrimmer didEndTrimmingFromEnd]];
367
-
368
- self.trimmer.alpha = 0;
369
- self.trimmer.translatesAutoresizingMaskIntoConstraints = NO;
370
- [self.view addSubview:self.trimmer];
371
-
372
- [NSLayoutConstraint activateConstraints:@[
373
- [self.trimmer.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor],
374
- [self.trimmer.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor],
375
- [self.trimmer.bottomAnchor constraintEqualToAnchor:self.timingStackView.topAnchor constant:-16],
376
- [self.trimmer.heightAnchor constraintEqualToConstant:50]
377
- ]];
378
-
379
- [UIView animateWithDuration:0.25 animations:^{
380
- self.trimmer.alpha = 1;
381
- }];
382
- }
383
-
384
- - (void)setupPlayerController {
385
- self.playerController.showsPlaybackControls = NO;
386
- if (@available(iOS 16.0, *)) {
387
- self.playerController.allowsVideoFrameAnalysis = NO;
388
- }
389
- self.playerController.player = [[AVPlayer alloc] init];
390
- [self.player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithAsset:self.asset]];
391
-
392
- [self.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:nil];
393
-
394
- NSError *error = nil;
395
- [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeDefault options:0 error:&error];
396
- if (error) {
397
- NSLog(@"AVAudioSession error: %@", error);
398
- }
399
-
400
- [self addChildViewController:self.playerController];
401
- [self.view addSubview:self.playerController.view];
402
- self.playerController.view.translatesAutoresizingMaskIntoConstraints = NO;
403
-
404
- [NSLayoutConstraint activateConstraints:@[
405
- [self.playerController.view.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
406
- [self.playerController.view.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
407
- [self.playerController.view.topAnchor constraintEqualToAnchor:self.headerView ? self.headerView.bottomAnchor : self.view.safeAreaLayoutGuide.topAnchor],
408
- [self.playerController.view.bottomAnchor constraintEqualToAnchor:self.trimmer.topAnchor constant:-16]
409
- ]];
410
-
411
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
412
- }
413
-
414
- - (void)playerDidFinishPlaying:(NSNotification *)notification {
415
- [self.playBtn setImage:[UIImage systemImageNamed:@"play.fill"] forState:UIControlStateNormal];
416
- }
417
-
418
- - (void)setupTimeObserver {
419
- __weak __typeof__(self) weakSelf = self;
420
- self.timeObserverToken = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 30) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
421
- if (weakSelf.player.timeControlStatus != AVPlayerTimeControlStatusPlaying) {
422
- return;
423
- }
424
-
425
- weakSelf.trimmer.progress = time;
426
-
427
- if (CMTimeCompare(weakSelf.trimmer.progress, CMTimeRangeGetEnd(weakSelf.trimmer.selectedRange)) == 1) {
428
- [weakSelf.player pause];
429
- weakSelf.trimmer.progress = CMTimeRangeGetEnd(weakSelf.trimmer.selectedRange);
430
- [weakSelf seek:CMTimeRangeGetEnd(weakSelf.trimmer.selectedRange)];
431
- }
432
-
433
- weakSelf.currentTimeLabel.text = [weakSelf displayStringFromCMTime:weakSelf.trimmer.progress];
434
- [weakSelf setPlayBtnIcon];
435
- }];
436
- }
437
-
438
- - (void)setPlayBtnIcon {
439
- UIImage *icon = (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) ?
440
- [UIImage systemImageNamed:@"pause.fill"] :
441
- [UIImage systemImageNamed:@"play.fill"];
442
- [self.playBtn setImage:icon forState:UIControlStateNormal];
443
- }
444
-
445
- - (void)seek:(CMTime)time {
446
- [self seekSmoothlyToTime:time];
447
- }
448
-
449
- - (void)seekSmoothlyToTime:(CMTime)newChaseTime {
450
- if (CMTimeCompare(newChaseTime, self.chaseTime) != 0) {
451
- self.chaseTime = newChaseTime;
452
-
453
- if (!self.isSeekInProgress) {
454
- [self trySeekToChaseTime];
455
- }
456
- }
457
- }
458
-
459
- - (void)trySeekToChaseTime {
460
- if (self.player.status != AVPlayerStatusReadyToPlay) return;
461
- [self actuallySeekToTime];
462
- }
463
-
464
- - (void)actuallySeekToTime {
465
- self.isSeekInProgress = YES;
466
- CMTime seekTimeInProgress = self.chaseTime;
467
-
468
- [self.player seekToTime:seekTimeInProgress toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
469
- if (CMTimeCompare(seekTimeInProgress, self.chaseTime) == 0) {
470
- self.isSeekInProgress = NO;
471
- } else {
472
- [self trySeekToChaseTime];
473
- }
474
- }];
475
- }
476
-
477
- - (void)configureWithConfig:(JS::NativeVideoTrim::EditorConfig)config {
478
- if (config.maxDuration() > 0) {
479
- self.maximumDuration = (NSInteger)config.maxDuration();
480
- }
481
-
482
- if (config.minDuration() > 0) {
483
- self.minimumDuration = (NSInteger)config.minDuration();
484
- }
485
-
486
- self.cancelButtonText = config.cancelButtonText();
487
- self.saveButtonText = config.saveButtonText();
488
- self.jumpToPositionOnLoad = config.jumpToPositionOnLoad();
489
-
490
- self.enableHapticFeedback = config.enableHapticFeedback();
491
- self.autoplay = config.autoplay();
492
-
493
- NSString *headerText = config.headerText();
494
- if (headerText && headerText.length > 0) {
495
- self.headerText = headerText;
496
- self.headerTextSize = (NSInteger)config.headerTextSize();
497
- self.headerTextColor = config.headerTextColor();
498
- }
499
- }
500
-
501
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
502
- if ([keyPath isEqualToString:@"status"]) {
503
- if (self.player.status == AVPlayerStatusReadyToPlay) {
504
- [self.loadingIndicator stopAnimating];
505
- [self.btnStackView removeArrangedSubview:self.loadingIndicator];
506
- [self.loadingIndicator removeFromSuperview];
507
- [self.btnStackView insertArrangedSubview:self.playBtn atIndex:1];
508
-
509
- [UIView animateWithDuration:0.25 animations:^{
510
- self.playBtn.alpha = 1;
511
- self.playBtn.enabled = YES;
512
- self.saveBtn.alpha = 1;
513
- self.saveBtn.enabled = YES;
514
- }];
515
-
516
- if (self.jumpToPositionOnLoad > 0) {
517
- double duration = CMTimeGetSeconds(self.asset.duration) * 1000;
518
- double time = (self.jumpToPositionOnLoad > duration) ? duration : self.jumpToPositionOnLoad;
519
- CMTime cmtime = CMTimeMake((CMTimeValue)time, 1000);
520
-
521
- [self seek:cmtime];
522
- self.trimmer.progress = cmtime;
523
- self.currentTimeLabel.text = [self displayStringFromCMTime:self.trimmer.progress];
524
- }
525
-
526
- if (self.autoplay) {
527
- [self togglePlay:self.playBtn];
528
- }
529
- }
530
- }
531
- }
532
-
533
- @end