diff --git a/RCTVideo.m b/RCTVideo.m index b68130ff..db991abf 100644 --- a/RCTVideo.m +++ b/RCTVideo.m @@ -10,17 +10,47 @@ AVPlayer *_player; AVPlayerLayer *_playerLayer; NSURL *_videoURL; + + /* Required to publish events */ RCTEventDispatcher *_eventDispatcher; + + /* For sending videoProgress events */ + id _progressUpdateTimer; + int _progressUpdateInterval; + NSDate *_prevProgressUpdateTime; } - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { if ((self = [super init])) { _eventDispatcher = eventDispatcher; + + /* Initialize videoProgress status publisher */ + _progressUpdateInterval = 1; + _prevProgressUpdateTime = nil; + _progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(sendProgressUpdate)]; + [_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } return self; } +- (void)sendProgressUpdate +{ + AVPlayerItem *video = [_player currentItem]; + if (video == nil) { + return; + } + + if (_prevProgressUpdateTime == nil || + ((int) [[NSDate date] timeIntervalSinceDate: _prevProgressUpdateTime]) >= _progressUpdateInterval) { + [_eventDispatcher sendInputEventWithName:@"videoProgress" body:@{ + @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)], + @"target": self.reactTag + }]; + _prevProgressUpdateTime = [NSDate date]; + } +} + - (void)setSrc:(NSString *)source { _videoURL = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:source ofType:@"mp4"]]; @@ -110,6 +140,7 @@ - (void)dealloc { + [_progressUpdateTimer invalidate]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } diff --git a/RCTVideoManager.m b/RCTVideoManager.m index 5514a747..6570c3da 100644 --- a/RCTVideoManager.m +++ b/RCTVideoManager.m @@ -12,7 +12,7 @@ return [[RCTVideo alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; } -/* onLoadStart, onLoad, and onError to stay consistent with Image */ +/* Should support: onLoadStart, onLoad, and onError to stay consistent with Image */ - (NSDictionary *)customDirectEventTypes { @@ -20,6 +20,9 @@ @"videoLoaded": @{ @"registrationName": @"onLoad" }, + @"videoProgress": @{ + @"registrationName": @"onProgress" + }, }; } diff --git a/Video.ios.js b/Video.ios.js index 18ca81fa..8cd3eedf 100644 --- a/Video.ios.js +++ b/Video.ios.js @@ -19,6 +19,7 @@ var Video = React.createClass({ repeat: PropTypes.bool, pause: PropTypes.bool, onLoad: PropTypes.func, + onProgress: PropTypes.func, }, mixins: [NativeMethodsMixin], @@ -32,6 +33,10 @@ var Video = React.createClass({ this.props.onLoad && this.props.onLoad(event.nativeEvent); }, + _onProgress(event) { + this.props.onProgress && this.props.onProgress(event.nativeEvent); + }, + render() { var style = flattenStyle([styles.base, this.props.style]); var source = this.props.source; @@ -52,6 +57,7 @@ var Video = React.createClass({ resizeMode: resizeMode, src: source, onLoad: this._onLoad, + onProgress: this._onProgress, }); return