Skip to content

Commit

Permalink
replace react-native-video with expo-av (#18812)
Browse files Browse the repository at this point in the history
* replace react-native-video with expo-av

* story

* 😢

* remove rnvideo pod

* use 5.0.1

* review feedback from jzila

* fix android

* postinstall patch

* remove rnvideo

* just copy file instead of patch

* story
  • Loading branch information
songgao committed Aug 9, 2019
1 parent 43b3207 commit 25cae7c
Show file tree
Hide file tree
Showing 67 changed files with 5,004 additions and 4,877 deletions.
1 change: 0 additions & 1 deletion shared/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ dependencies {
implementation project(':react-native-webview')
implementation project(':react-native-community-netinfo')
implementation project(':react-native-reanimated')
implementation project(':react-native-video')

addUnimodulesDependencies([modulesPaths: ['../../node_modules']])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import com.swmansion.reanimated.ReanimatedPackage;
import com.swmansion.rnscreens.RNScreensPackage;
import com.brentvatne.react.ReactVideoPackage;


import java.io.File;
Expand Down Expand Up @@ -112,7 +111,6 @@ public List<NativeModule> createNativeModules(ReactApplicationContext reactAppli
new RNScreensPackage(),
new NetInfoPackage(),
new RNCWebViewPackage(),
new ReactVideoPackage(),
new ReanimatedPackage(),
new ModuleRegistryAdapter(mModuleRegistryProvider)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
public class BasePackageList {
public List<Package> getPackageList() {
return Arrays.<Package>asList(
new expo.modules.av.AVPackage(),
new expo.modules.barcodescanner.BarCodeScannerPackage(),
new expo.modules.constants.ConstantsPackage(),
new expo.modules.contacts.ContactsPackage(),
Expand Down
83 changes: 83 additions & 0 deletions shared/android/patched-expo-av-build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
buildscript {
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
}
}

apply plugin: 'com.android.library'
apply plugin: 'maven'

group = 'host.exp.exponent'
version = '5.0.2'

def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

// Upload android library to maven with javadoc and android sources
configurations {
deployerJars
}

// Creating sources with comments
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}

// Put the androidSources and javadoc to the artifacts
artifacts {
archives androidSourcesJar
}

uploadArchives {
repositories {
mavenDeployer {
configuration = configurations.deployerJars
repository(url: mavenLocal().url)
}
}
}

android {
compileSdkVersion safeExtGet("compileSdkVersion", 28)

defaultConfig {
minSdkVersion safeExtGet("minSdkVersion", 21)
targetSdkVersion safeExtGet("targetSdkVersion", 28)
versionCode 9
versionName "5.0.2"
}
lintOptions {
abortOnError false
}
}

if (new File(rootProject.projectDir.parentFile, 'package.json').exists()) {
apply from: project(":unimodules-core").file("../unimodules-core.gradle")
} else {
throw new GradleException(
"'unimodules-core.gradle' was not found in the usual Flutter or React Native dependency locations. " +
"This package can only be used in such projects. Are you sure you've installed the dependencies properly?")
}

dependencies {
unimodule "unimodules-core"
unimodule "unimodules-permissions-interface"
implementation 'com.android.support:support-annotations:28.0.0'
// Newer version introduces dependency versions conflict
// on 'com.android.support:support-annotations'
api 'com.google.android.exoplayer:exoplayer:2.9.2'

api 'com.google.android.exoplayer:extension-okhttp:2.9.2'

api 'com.yqritc:android-scalablevideoview:1.0.1'

api "com.squareup.okhttp3:okhttp:3.10.0"
api "com.squareup.okhttp3:okhttp-urlconnection:3.10.0"
}
2 changes: 0 additions & 2 deletions shared/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ includeUnimodulesProjects()

include ':app', ':keybaselib'

include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')
include ':react-native-push-notification', ':app'
project(':react-native-push-notification').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-push-notification/android')
include ':react-native-fetch-blob'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as Kb from '../../../common-adapters/mobile.native'
import * as Styles from '../../../styles'
import MessagePopup from '../messages/message-popup/'
import {Props} from './index.types'
import RNVideo from 'react-native-video'
import {Video as ExpoVideo} from 'expo-av'
import logger from '../../../logger'

const {width: screenWidth, height: screenHeight} = Kb.NativeDimensions.get('window')
Expand Down Expand Up @@ -93,14 +93,14 @@ class _Fullscreen extends React.Component<Props & Kb.OverlayParentProps, {loaded
centerChildren={true}
style={{position: 'relative'}}
>
<RNVideo
<ExpoVideo
source={{uri: `${this.props.path}&contentforce=true`}}
onError={e => {
logger.error(`Error loading vid: ${JSON.stringify(e)}`)
}}
onLoad={this._setLoaded}
paused={true}
controls={true}
shouldPlay={false}
useNativeControls={true}
style={{
height: this.props.previewHeight,
width: this.props.previewWidth,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as Kb from '../../../../../common-adapters/mobile.native'
import * as Styles from '../../../../../styles'
import logger from '../../../../../logger'
import {Props} from './image-render.types'
import Video from 'react-native-video'
import {Video} from 'expo-av'

type State = {
paused: boolean
Expand All @@ -15,8 +15,10 @@ export class ImageRender extends React.Component<Props, State> {
paused: false,
showVideo: false,
}
private videoRef: any = React.createRef()

onVideoClick = () => {
this.videoRef.current && this.videoRef.current.playAsync()
this.setState({showVideo: true})
}

Expand All @@ -40,14 +42,15 @@ export class ImageRender extends React.Component<Props, State> {
{this.state.showVideo ? (
<Video
source={source}
controls={!this.state.paused}
paused={this.state.paused}
useNativeControls={!this.state.paused}
onLoad={() => this._allLoads()}
onError={e => {
logger.error(`Error loading vid: ${JSON.stringify(e)}`)
}}
resizeMode={Video.RESIZE_MODE_COVER}
style={Styles.collapseStyles([styles.video, {height, width}])}
resizeMode="cover"
shouldPlay={true}
ref={this.videoRef}
/>
) : (
<Kb.NativeFastImage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react'
import * as Kb from '../../../../../../common-adapters/index'
import * as Styles from '../../../../../../styles'
import logger from '../../../../../../logger'
import RNVideo from 'react-native-video'
import {Video as ExpoVideo} from 'expo-av'
import {Props} from './video.types'

type State = {
Expand All @@ -11,13 +11,20 @@ type State = {

export class Video extends React.Component<Props, State> {
state = {playingVideo: this.props.autoPlay}
private videoRef: any = React.createRef()

_onClick = () => {
if (this.props.onClick) {
this.props.onClick()
return
}
this.setState({playingVideo: !this.state.playingVideo})
this.setState(({playingVideo}) => {
if (!this.videoRef.current) {
return
}
playingVideo ? this.videoRef.current.pauseAsync() : this.videoRef.current.playAsync()
return {playingVideo: !playingVideo}
})
}

render() {
Expand All @@ -36,15 +43,17 @@ export class Video extends React.Component<Props, State> {
onClick={this._onClick}
style={Styles.collapseStyles([this.props.style, styles.container])}
>
<RNVideo
<ExpoVideo
source={source}
onError={e => {
logger.error(`Error loading vid: ${JSON.stringify(e)}`)
}}
resizeMode="cover"
resizeMode={ExpoVideo.RESIZE_MODE_COVER}
style={Styles.collapseStyles([styles.player, this.props.style])}
repeat={true}
paused={!this.state.playingVideo}
isLooping={true}
isMuted={true}
shouldPlay={this.props.autoPlay}
ref={this.videoRef}
/>
<Kb.Box
style={Styles.collapseStyles([
Expand Down
22 changes: 22 additions & 0 deletions shared/common-adapters/av.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from 'react'
import * as Styles from '../styles'

export type Props = {
autoPlay?: boolean
controls?: boolean
loop?: boolean
muted?: boolean // note that we're keeping playsInSilentModeIOS default which is false
style?: Styles.StylesCrossPlatform | null
url: string
}

export type VideoState = {
containerHeight: number
containerWidth: number
loadedVideoSize: boolean
videoHeight: number
videoWidth: number
}

declare class Video extends React.Component<Props> {}
declare class Audio extends React.Component<Props> {}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react'
import Measure from 'react-measure'
import {Props, State} from './video'
import {Props, VideoState} from './av'
import * as Styles from '../styles'
import {getVideoSize, CheckURL} from './video.shared'
import {getVideoSize, CheckURL} from './av.shared'

export default class extends React.PureComponent<Props, State> {
export class Video extends React.PureComponent<Props, VideoState> {
state = {
containerHeight: 0,
containerWidth: 0,
Expand All @@ -18,9 +18,7 @@ export default class extends React.PureComponent<Props, State> {
_onContainerResize = ({bounds}) =>
this._mounted && this.setState({containerHeight: bounds.height, containerWidth: bounds.width})

_videoRef: {
current: HTMLVideoElement | null
} = React.createRef()
_videoRef: {current: HTMLVideoElement | null} = React.createRef()
_onVideoClick = () =>
this._videoRef.current &&
(this._videoRef.current.paused ? this._videoRef.current.play() : this._videoRef.current.pause())
Expand Down Expand Up @@ -52,11 +50,12 @@ export default class extends React.PureComponent<Props, State> {
controlsList="nodownload nofullscreen"
onClick={this._onVideoClick}
ref={this._videoRef}
controls={!this.props.hideControls}
controls={!!this.props.controls}
src={this.props.url}
style={Styles.collapseStyles([styles.container, getVideoSize(this.state)])}
muted={true}
autoPlay={true}
muted={!!this.props.muted}
autoPlay={!!this.props.autoPlay}
loop={!!this.props.loop}
preload="metadata"
onLoadedMetadata={this._onVideoLoadedmetadata}
/>
Expand All @@ -68,6 +67,8 @@ export default class extends React.PureComponent<Props, State> {
}
}

export const Audio = Video

const styles = Styles.styleSheetCreate({
container: {
...Styles.globalStyles.flexBoxColumn,
Expand Down
82 changes: 82 additions & 0 deletions shared/common-adapters/av.native.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as React from 'react'
import {Props} from './av'
import Box from './box'
import * as Styles from '../styles'
import {useVideoSizer, CheckURL} from './av.shared'
import {Video as ExpoVideo} from 'expo-av'
import {StatusBar} from 'react-native'
import logger from '../logger'

const Kb = {
Box,
}

export const Video = (props: Props) => {
const [videoSize, setContainerSize, setVideoNaturalSize] = useVideoSizer()
return (
<CheckURL url={props.url}>
<Kb.Box
style={styles.container}
onLayout={event =>
event &&
event.nativeEvent &&
event.nativeEvent.layout &&
setContainerSize(event.nativeEvent.layout.height, event.nativeEvent.layout.width)
}
>
<ExpoVideo
source={{uri: props.url}}
onError={e => {
logger.error(`Error loading vid: ${JSON.stringify(e)}`)
}}
useNativeControls={!!props.controls}
onFullscreenUpdate={update =>
update.fullscreenUpdate === ExpoVideo.FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS &&
StatusBar.setHidden(false)
}
onReadyForDisplay={ready =>
ready &&
ready.naturalSize &&
setVideoNaturalSize(ready.naturalSize.height, ready.naturalSize.width)
}
style={videoSize}
isMuted={!!props.muted}
resizeMode={ExpoVideo.RESIZE_MODE_CONTAIN}
shouldPlay={!!props.autoPlay}
isLooping={!!props.loop}
/>
</Kb.Box>
</CheckURL>
)
}

// TODO we should probalby have custom style here. The controls auto hides on
// Android.
export const Audio = (props: Props) => (
<ExpoVideo
source={{uri: props.url}}
onError={e => {
logger.error(`Error loading vid: ${JSON.stringify(e)}`)
}}
useNativeControls={!!props.controls}
isMuted={!!props.muted}
shouldPlay={!!props.autoPlay}
isLooping={!!props.loop}
style={styles.audio}
/>
)

const styles = Styles.styleSheetCreate({
audio: {
...Styles.globalStyles.fullWidth,
backgroundColor: Styles.globalColors.black,
height: Styles.isAndroid ? 96 : 48,
},
container: {
...Styles.globalStyles.flexBoxRow,
alignItems: 'center',
height: '100%',
justifyContent: 'center',
width: '100%',
},
})
Loading

0 comments on commit 25cae7c

Please sign in to comment.