Merge branch 'master' into fix-memleak
This commit is contained in:
commit
236d17e8b5
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -10,37 +10,24 @@ assignees: ''
|
||||
# Bug
|
||||
|
||||
<!--
|
||||
Before opening a ticket
|
||||
* Ensure the issue has not been already reported
|
||||
* Please test using the latest release of the library, as maybe said bug has been already fixed.
|
||||
* Provide a clear and concise description of what the bug is.
|
||||
* If the library has multiple install methods, describe installation method (e.g., pod, not pod, with jetifier etc)
|
||||
* Include screenshots if needed.
|
||||
Very important, before opening a ticket:
|
||||
1) Ensure the issue has not been already reported
|
||||
2) lease test using the latest release (including 6.0.0 preRelease) of the library, as maybe the bug has been already fixed.
|
||||
3) please don't use emulator to reproduce issues. if you have strange or sporadic error check if this is not devices specific (understand that this library is just a binding to player).
|
||||
4) ensure you cannot solve the issue by yourself using following guide: https://github.com/react-native-video/react-native-video/blob/master/docs/DEBUGGING.md
|
||||
-->
|
||||
|
||||
## Platform
|
||||
<!--
|
||||
Platform where your bug is happening.
|
||||
-->
|
||||
Which player are you experiencing the problem on:
|
||||
* iOS
|
||||
* Android
|
||||
* Windows UWP
|
||||
* Windows WPF
|
||||
* Windows
|
||||
|
||||
## Environment info
|
||||
|
||||
<!--
|
||||
Run `react-native info` in your terminal and copy the results here. Also, include the *precise* version number of this library that you are using in the project
|
||||
-->
|
||||
|
||||
React native info output:
|
||||
|
||||
```bash
|
||||
// paste it here
|
||||
```
|
||||
|
||||
<!-- This fields are mandatory -->
|
||||
Library version: x.x.x
|
||||
Device:
|
||||
|
||||
## Steps To Reproduce
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
### Version 6.0.0-alpha.7
|
||||
- Android: Fix memory leaks from AudioManager [#3123](https://github.com/react-native-video/react-native-video/pull/3123)
|
||||
- Android: Fixed syntax error [#3182](https://github.com/react-native-video/react-native-video/issues/3182)
|
||||
|
||||
### Version 6.0.0-alpha.6
|
||||
- Feature: Video range support [#3030](https://github.com/react-native-video/react-native-video/pull/3030)
|
||||
|
17
Video.js
17
Video.js
@ -77,7 +77,7 @@ export default class Video extends Component {
|
||||
this.setNativeProps({ fullscreen: false });
|
||||
};
|
||||
|
||||
save = async (options?) => {
|
||||
save = async (options) => {
|
||||
return await NativeModules.VideoManager.save(options, findNodeHandle(this._root));
|
||||
}
|
||||
|
||||
@ -416,13 +416,6 @@ Video.propTypes = {
|
||||
FilterType.SEPIA,
|
||||
]),
|
||||
filterEnabled: PropTypes.bool,
|
||||
/* Native only */
|
||||
src: PropTypes.object,
|
||||
seek: PropTypes.oneOfType([
|
||||
PropTypes.number,
|
||||
PropTypes.object,
|
||||
]),
|
||||
fullscreen: PropTypes.bool,
|
||||
onVideoLoadStart: PropTypes.func,
|
||||
onVideoLoad: PropTypes.func,
|
||||
onVideoBuffer: PropTypes.func,
|
||||
@ -566,10 +559,4 @@ Video.propTypes = {
|
||||
...ViewPropTypes,
|
||||
};
|
||||
|
||||
const RCTVideo = requireNativeComponent('RCTVideo', Video, {
|
||||
nativeOnly: {
|
||||
src: true,
|
||||
seek: true,
|
||||
fullscreen: true,
|
||||
},
|
||||
});
|
||||
const RCTVideo = requireNativeComponent('RCTVideo');
|
||||
|
@ -17,6 +17,7 @@ def configStringPath = (
|
||||
).md5()
|
||||
|
||||
android {
|
||||
namespace 'com.brentvatne.react'
|
||||
compileSdkVersion safeExtGet('compileSdkVersion', 31)
|
||||
buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2')
|
||||
|
||||
|
@ -14,27 +14,27 @@
|
||||
android:paddingTop="4dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton android:id="@id/exo_prev"
|
||||
<ImageButton android:id="@+id/exo_prev"
|
||||
style="@style/ExoMediaButton.Previous"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_rew"
|
||||
<ImageButton android:id="@+id/exo_rew"
|
||||
style="@style/ExoMediaButton.Rewind"/>
|
||||
<FrameLayout
|
||||
android:id="@+id/exo_play_pause_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center">
|
||||
<ImageButton android:id="@id/exo_play"
|
||||
<ImageButton android:id="@+id/exo_play"
|
||||
style="@style/ExoMediaButton.Play"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_pause"
|
||||
<ImageButton android:id="@+id/exo_pause"
|
||||
style="@style/ExoMediaButton.Pause"/>
|
||||
</FrameLayout>
|
||||
|
||||
<ImageButton android:id="@id/exo_ffwd"
|
||||
<ImageButton android:id="@+id/exo_ffwd"
|
||||
style="@style/ExoMediaButton.FastForward"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_next"
|
||||
<ImageButton android:id="@+id/exo_next"
|
||||
style="@style/ExoMediaButton.Next"/>
|
||||
|
||||
</LinearLayout>
|
||||
@ -46,7 +46,7 @@
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView android:id="@id/exo_position"
|
||||
<TextView android:id="@+id/exo_position"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
@ -57,12 +57,12 @@
|
||||
android:textColor="#FFBEBEBE"/>
|
||||
|
||||
<com.google.android.exoplayer2.ui.DefaultTimeBar
|
||||
android:id="@id/exo_progress"
|
||||
android:id="@+id/exo_progress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="26dp"/>
|
||||
|
||||
<TextView android:id="@id/exo_duration"
|
||||
<TextView android:id="@+id/exo_duration"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
@ -73,7 +73,7 @@
|
||||
android:textColor="#FFBEBEBE"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@id/exo_fullscreen"
|
||||
android:id="@+id/exo_fullscreen"
|
||||
style="@style/ExoMediaButton.FullScreen"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
|
@ -4,7 +4,7 @@ import GoogleInteractiveMediaAds
|
||||
|
||||
class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
||||
|
||||
private var _video:RCTVideo
|
||||
private weak var _video: RCTVideo?
|
||||
|
||||
/* Entry point for the SDK. Used to make ad requests. */
|
||||
private var adsLoader: IMAAdsLoader!
|
||||
@ -23,6 +23,7 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
||||
}
|
||||
|
||||
func requestAds() {
|
||||
guard let _video = _video else {return}
|
||||
// Create ad display container for ad rendering.
|
||||
let adDisplayContainer = IMAAdDisplayContainer(adContainer: _video, viewController: _video.reactViewController())
|
||||
|
||||
@ -54,6 +55,7 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
||||
// MARK: - IMAAdsLoaderDelegate
|
||||
|
||||
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
|
||||
guard let _video = _video else {return}
|
||||
// Grab the instance of the IMAAdsManager and set yourself as the delegate.
|
||||
adsManager = adsLoadedData.adsManager
|
||||
adsManager?.delegate = self
|
||||
@ -71,12 +73,13 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
||||
print("Error loading ads: " + adErrorData.adError.message!)
|
||||
}
|
||||
|
||||
_video.setPaused(false)
|
||||
_video?.setPaused(false)
|
||||
}
|
||||
|
||||
// MARK: - IMAAdsManagerDelegate
|
||||
|
||||
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
|
||||
guard let _video = _video else {return}
|
||||
// Mute ad if the main player is muted
|
||||
if (_video.isMuted()) {
|
||||
adsManager.volume = 0;
|
||||
@ -102,19 +105,19 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
||||
}
|
||||
|
||||
// Fall back to playing content
|
||||
_video.setPaused(false)
|
||||
_video?.setPaused(false)
|
||||
}
|
||||
|
||||
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
|
||||
// Pause the content for the SDK to play ads.
|
||||
_video.setPaused(true)
|
||||
_video.setAdPlaying(true)
|
||||
_video?.setPaused(true)
|
||||
_video?.setAdPlaying(true)
|
||||
}
|
||||
|
||||
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
|
||||
// Resume the content since the SDK is done playing ads (at least for now).
|
||||
_video.setAdPlaying(false)
|
||||
_video.setPaused(false)
|
||||
_video?.setAdPlaying(false)
|
||||
_video?.setPaused(false)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
@ -25,7 +25,7 @@ protocol RCTPlayerObserverHandler: RCTPlayerObserverHandlerObjc {
|
||||
|
||||
class RCTPlayerObserver: NSObject {
|
||||
|
||||
var _handlers: RCTPlayerObserverHandler!
|
||||
weak var _handlers: RCTPlayerObserverHandler?
|
||||
|
||||
var player:AVPlayer? {
|
||||
willSet {
|
||||
@ -84,11 +84,13 @@ class RCTPlayerObserver: NSObject {
|
||||
private var _playerViewControllerOverlayFrameObserver:NSKeyValueObservation?
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(_handlers)
|
||||
if let _handlers = _handlers {
|
||||
NotificationCenter.default.removeObserver(_handlers)
|
||||
}
|
||||
}
|
||||
|
||||
func addPlayerObservers() {
|
||||
guard let player = player else {
|
||||
guard let player = player, let _handlers = _handlers else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -102,7 +104,7 @@ class RCTPlayerObserver: NSObject {
|
||||
}
|
||||
|
||||
func addPlayerItemObservers() {
|
||||
guard let playerItem = playerItem else { return }
|
||||
guard let playerItem = playerItem, let _handlers = _handlers else { return }
|
||||
|
||||
_playerItemStatusObserver = playerItem.observe(\.status, options: [.new, .old], changeHandler: _handlers.handlePlayerItemStatusChange)
|
||||
_playerPlaybackBufferEmptyObserver = playerItem.observe(\.isPlaybackBufferEmpty, options: [.new, .old], changeHandler: _handlers.handlePlaybackBufferKeyEmpty)
|
||||
@ -118,7 +120,7 @@ class RCTPlayerObserver: NSObject {
|
||||
}
|
||||
|
||||
func addPlayerViewControllerObservers() {
|
||||
guard let playerViewController = playerViewController else { return }
|
||||
guard let playerViewController = playerViewController, let _handlers = _handlers else { return }
|
||||
|
||||
_playerViewControllerReadyForDisplayObserver = playerViewController.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
|
||||
|
||||
@ -131,6 +133,7 @@ class RCTPlayerObserver: NSObject {
|
||||
}
|
||||
|
||||
func addPlayerLayerObserver() {
|
||||
guard let _handlers = _handlers else {return}
|
||||
_playerLayerReadyForDisplayObserver = playerLayer?.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
|
||||
}
|
||||
|
||||
@ -139,6 +142,7 @@ class RCTPlayerObserver: NSObject {
|
||||
}
|
||||
|
||||
func addPlayerTimeObserver() {
|
||||
guard let _handlers = _handlers else {return}
|
||||
removePlayerTimeObserver()
|
||||
let progressUpdateIntervalMS:Float64 = _progressUpdateInterval / 1000
|
||||
// @see endScrubbing in AVPlayerDemoPlaybackViewController.m
|
||||
@ -174,6 +178,7 @@ class RCTPlayerObserver: NSObject {
|
||||
}
|
||||
|
||||
func attachPlayerEventListeners() {
|
||||
guard let _handlers = _handlers else {return}
|
||||
|
||||
NotificationCenter.default.removeObserver(_handlers,
|
||||
name:NSNotification.Name.AVPlayerItemDidPlayToEndTime,
|
||||
@ -202,6 +207,8 @@ class RCTPlayerObserver: NSObject {
|
||||
func clearPlayer() {
|
||||
player = nil
|
||||
playerItem = nil
|
||||
NotificationCenter.default.removeObserver(_handlers)
|
||||
if let _handlers = _handlers {
|
||||
NotificationCenter.default.removeObserver(_handlers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import <React/RCTViewManager.h>
|
||||
#import "RCTVideoSwiftLog.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
|
||||
#if __has_include(<react-native-video/RCTVideoCache.h>)
|
||||
#import "RCTVideoCache.h"
|
||||
|
@ -59,6 +59,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
private var _fullscreenAutorotate:Bool = true
|
||||
private var _fullscreenOrientation:String! = "all"
|
||||
private var _fullscreenPlayerPresented:Bool = false
|
||||
private var _fullscreenUncontrolPlayerPresented:Bool = false // to call events switching full screen mode from player controls
|
||||
private var _filterName:String!
|
||||
private var _filterEnabled:Bool = false
|
||||
private var _presentingViewController:UIViewController?
|
||||
@ -246,7 +247,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
// MARK: - Player and source
|
||||
@objc
|
||||
func setSrc(_ source:NSDictionary!) {
|
||||
DispatchQueue.global(qos: .default).async {
|
||||
DispatchQueue.global(qos: .default).async { [weak self] in
|
||||
guard let self = self else {return}
|
||||
self._source = VideoSource(source)
|
||||
if (self._source?.uri == nil || self._source?.uri == "") {
|
||||
self._player?.replaceCurrentItem(with: nil)
|
||||
@ -662,7 +664,13 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
self.onVideoFullscreenPlayerWillPresent?(["target": reactTag as Any])
|
||||
|
||||
if let playerViewController = _playerViewController {
|
||||
viewController.present(playerViewController, animated:true, completion:{
|
||||
if(_controls) {
|
||||
// prevents crash https://github.com/react-native-video/react-native-video/issues/3040
|
||||
self._playerViewController?.removeFromParent()
|
||||
}
|
||||
|
||||
viewController.present(playerViewController, animated:true, completion:{ [weak self] in
|
||||
guard let self = self else {return}
|
||||
self._playerViewController?.showsPlaybackControls = self._controls
|
||||
self._fullscreenPlayerPresented = fullscreen
|
||||
self._playerViewController?.autorotate = self._fullscreenAutorotate
|
||||
@ -674,8 +682,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
}
|
||||
} else if !fullscreen && _fullscreenPlayerPresented, let _playerViewController = _playerViewController {
|
||||
self.videoPlayerViewControllerWillDismiss(playerViewController: _playerViewController)
|
||||
_presentingViewController?.dismiss(animated: true, completion:{
|
||||
self.videoPlayerViewControllerDidDismiss(playerViewController: _playerViewController)
|
||||
_presentingViewController?.dismiss(animated: true, completion:{[weak self] in
|
||||
self?.videoPlayerViewControllerDidDismiss(playerViewController: _playerViewController)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1103,12 +1111,27 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
let oldRect = change.oldValue
|
||||
let newRect = change.newValue
|
||||
if !oldRect!.equalTo(newRect!) {
|
||||
// https://github.com/react-native-video/react-native-video/issues/3085#issuecomment-1557293391
|
||||
if newRect!.equalTo(UIScreen.main.bounds) {
|
||||
RCTLog("in fullscreen")
|
||||
if (!_fullscreenUncontrolPlayerPresented) {
|
||||
_fullscreenUncontrolPlayerPresented = true;
|
||||
|
||||
self.reactViewController().view.frame = UIScreen.main.bounds
|
||||
self.reactViewController().view.setNeedsLayout()
|
||||
} else {NSLog("not fullscreen")}
|
||||
self.onVideoFullscreenPlayerWillPresent?(["target": self.reactTag as Any])
|
||||
self.onVideoFullscreenPlayerDidPresent?(["target": self.reactTag as Any])
|
||||
}
|
||||
} else {
|
||||
NSLog("not fullscreen")
|
||||
if (_fullscreenUncontrolPlayerPresented) {
|
||||
_fullscreenUncontrolPlayerPresented = false;
|
||||
|
||||
self.onVideoFullscreenPlayerWillDismiss?(["target": self.reactTag as Any])
|
||||
self.onVideoFullscreenPlayerDidDismiss?(["target": self.reactTag as Any])
|
||||
}
|
||||
}
|
||||
|
||||
self.reactViewController().view.frame = UIScreen.main.bounds
|
||||
self.reactViewController().view.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import AVKit
|
||||
|
||||
class RCTVideoPlayerViewController: AVPlayerViewController {
|
||||
|
||||
var rctDelegate:RCTVideoPlayerViewControllerDelegate!
|
||||
weak var rctDelegate: RCTVideoPlayerViewControllerDelegate?
|
||||
|
||||
// Optional paramters
|
||||
var preferredOrientation:String?
|
||||
@ -20,10 +20,8 @@ class RCTVideoPlayerViewController: AVPlayerViewController {
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
if rctDelegate != nil {
|
||||
rctDelegate.videoPlayerViewControllerWillDismiss(playerViewController: self)
|
||||
rctDelegate.videoPlayerViewControllerDidDismiss(playerViewController: self)
|
||||
}
|
||||
rctDelegate?.videoPlayerViewControllerWillDismiss(playerViewController: self)
|
||||
rctDelegate?.videoPlayerViewControllerDidDismiss(playerViewController: self)
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
Loading…
Reference in New Issue
Block a user