diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 00000000..949fb3c7
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,4 @@
+{
+ "extends": "airbnb",
+ "parser": "babel-eslint"
+}
diff --git a/Examples/VideoPlayer/.flowconfig b/Examples/VideoPlayer/.flowconfig
index 8eadd339..66b57e09 100644
--- a/Examples/VideoPlayer/.flowconfig
+++ b/Examples/VideoPlayer/.flowconfig
@@ -14,17 +14,21 @@
# Ignore react and fbjs where there are overlaps, but don't ignore
# anything that react-native relies on
-.*/node_modules/fbjs-haste/.*/__tests__/.*
-.*/node_modules/fbjs-haste/__forks__/Map.js
-.*/node_modules/fbjs-haste/__forks__/Promise.js
-.*/node_modules/fbjs-haste/__forks__/fetch.js
-.*/node_modules/fbjs-haste/core/ExecutionEnvironment.js
-.*/node_modules/fbjs-haste/core/isEmpty.js
-.*/node_modules/fbjs-haste/crypto/crc32.js
-.*/node_modules/fbjs-haste/stubs/ErrorUtils.js
-.*/node_modules/react-haste/React.js
-.*/node_modules/react-haste/renderers/dom/ReactDOM.js
-.*/node_modules/react-haste/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
+.*/node_modules/fbjs/lib/Map.js
+.*/node_modules/fbjs/lib/fetch.js
+.*/node_modules/fbjs/lib/ExecutionEnvironment.js
+.*/node_modules/fbjs/lib/ErrorUtils.js
+
+# Flow has a built-in definition for the 'react' module which we prefer to use
+# over the currently-untyped source
+.*/node_modules/react/react.js
+.*/node_modules/react/lib/React.js
+.*/node_modules/react/lib/ReactDOM.js
+
+.*/__mocks__/.*
+.*/__tests__/.*
+
+.*/commoner/test/source/widget/share.js
# Ignore commoner tests
.*/node_modules/commoner/test/.*
@@ -38,26 +42,48 @@
# Ignore Website
.*/website/.*
+.*/node_modules/is-my-json-valid/test/.*\.json
+.*/node_modules/iconv-lite/encodings/tables/.*\.json
+.*/node_modules/y18n/test/.*\.json
+.*/node_modules/spdx-license-ids/spdx-license-ids.json
+.*/node_modules/spdx-exceptions/index.json
+.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json
+.*/node_modules/resolve/lib/core.json
+.*/node_modules/jsonparse/samplejson/.*\.json
+.*/node_modules/json5/test/.*\.json
+.*/node_modules/ua-parser-js/test/.*\.json
+.*/node_modules/builtin-modules/builtin-modules.json
+.*/node_modules/binary-extensions/binary-extensions.json
+.*/node_modules/url-regex/tlds.json
+.*/node_modules/joi/.*\.json
+.*/node_modules/isemail/.*\.json
+.*/node_modules/tr46/.*\.json
+
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
+node_modules/react-native/flow
+flow/
[options]
module.system=haste
+esproposal.class_static_fields=enable
+esproposal.class_instance_fields=enable
+
munge_underscores=true
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
-module.name_mapper='^[./a-zA-Z0-9$_-]+\.png$' -> 'RelativeImageStub'
+module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
-suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-8]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
-suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-8]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
+suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-2]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
+suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-2]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version]
-0.18.1
+0.22.0
diff --git a/Examples/VideoPlayer/.gitignore b/Examples/VideoPlayer/.gitignore
index 07e4fe72..54a65557 100644
--- a/Examples/VideoPlayer/.gitignore
+++ b/Examples/VideoPlayer/.gitignore
@@ -1 +1,37 @@
-node_modules/**/*
+VideoPlayer.xcodeproj/project.xcworkspace/**/*
+VideoPlayer.xcodeproj/xcuserdata/**/*
+
+# OSX
+#
+.DS_Store
+
+# Xcode
+#
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+*.xccheckout
+*.moved-aside
+DerivedData
+*.hmap
+*.ipa
+*.xcuserstate
+project.xcworkspace
+
+# Android/IJ
+#
+.idea
+.gradle
+local.properties
+
+# node.js
+#
+node_modules/
+npm-debug.log
diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.pbxproj b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.pbxproj
index 2a8de0fc..f40c2d81 100644
--- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.pbxproj
+++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.pbxproj
@@ -302,7 +302,7 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0610;
+ LastUpgradeCheck = 0720;
ORGANIZATIONNAME = Facebook;
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "VideoPlayer" */;
@@ -487,8 +487,10 @@
"$(SRCROOT)/node_modules/react-native/React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = VideoPlayer;
};
name = Debug;
@@ -503,8 +505,10 @@
"$(SRCROOT)/node_modules/react-native/React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = VideoPlayer;
};
name = Release;
@@ -529,6 +533,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 4ac4c91f..00000000
--- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout
deleted file mode 100644
index 6ce4fd2f..00000000
--- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcshareddata/VideoPlayer.xccheckout
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- IDESourceControlProjectFavoriteDictionaryKey
-
- IDESourceControlProjectIdentifier
- 9B1B824B-5918-47F5-B27A-FA559B781ACC
- IDESourceControlProjectName
- VideoPlayer
- IDESourceControlProjectOriginsDictionary
-
- D05F265D0E65FFE673B2E9F5A4680A7F46E27F31
- github.com:johanneslumpe/react-native-video.git
-
- IDESourceControlProjectPath
- Examples/VideoPlayer/VideoPlayer.xcodeproj
- IDESourceControlProjectRelativeInstallPathDictionary
-
- D05F265D0E65FFE673B2E9F5A4680A7F46E27F31
- ../../../..
-
- IDESourceControlProjectURL
- github.com:johanneslumpe/react-native-video.git
- IDESourceControlProjectVersion
- 111
- IDESourceControlProjectWCCIdentifier
- D05F265D0E65FFE673B2E9F5A4680A7F46E27F31
- IDESourceControlProjectWCConfigurations
-
-
- IDESourceControlRepositoryExtensionIdentifierKey
- public.vcs.git
- IDESourceControlWCCIdentifierKey
- D05F265D0E65FFE673B2E9F5A4680A7F46E27F31
- IDESourceControlWCCName
- react-native-video
-
-
-
-
diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate b/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index 01791fee..00000000
Binary files a/Examples/VideoPlayer/VideoPlayer.xcodeproj/project.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ
diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme
index b089e027..a328632b 100644
--- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme
+++ b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme
@@ -1,6 +1,6 @@
+ shouldUseLaunchSchemeArgsEnv = "YES">
@@ -38,15 +38,18 @@
ReferencedContainer = "container:VideoPlayer.xcodeproj">
+
+
@@ -62,10 +65,10 @@
diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
deleted file mode 100644
index b1a4c519..00000000
--- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist b/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist
deleted file mode 100644
index bc98ef59..00000000
--- a/Examples/VideoPlayer/VideoPlayer.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- SchemeUserState
-
- VideoPlayer.xcscheme_^#shared#^_
-
- orderHint
- 0
-
-
- SuppressBuildableAutocreation
-
- 13B07F861A680F5B00A75B9A
-
- primary
-
-
-
-
-
diff --git a/Examples/VideoPlayer/android/app/build.gradle b/Examples/VideoPlayer/android/app/build.gradle
index 1c09ff66..2afbba5c 100644
--- a/Examples/VideoPlayer/android/app/build.gradle
+++ b/Examples/VideoPlayer/android/app/build.gradle
@@ -1,5 +1,7 @@
apply plugin: "com.android.application"
+import com.android.build.OutputFile
+
/**
* The react.gradle file registers two tasks: bundleDebugJsAndAssets and bundleReleaseJsAndAssets.
* These basically call `react-native bundle` with the correct arguments during the Android build
@@ -49,6 +51,22 @@ apply plugin: "com.android.application"
apply from: "react.gradle"
+/**
+ * Set this to true to create three separate APKs instead of one:
+ * - A universal APK that works on all devices
+ * - An APK that only works on ARM devices
+ * - An APK that only works on x86 devices
+ * The advantage is the size of the APK is reduced by about 4MB.
+ * Upload all the APKs to the Play Store and people will download
+ * the correct one based on the CPU architecture of their device.
+ */
+def enableSeparateBuildPerCPUArchitecture = false
+
+/**
+ * Run Proguard to shrink the Java bytecode in release builds.
+ */
+def enableProguardInReleaseBuilds = false
+
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
@@ -63,17 +81,38 @@ android {
abiFilters "armeabi-v7a", "x86"
}
}
+ splits {
+ abi {
+ enable enableSeparateBuildPerCPUArchitecture
+ universalApk true
+ reset()
+ include "armeabi-v7a", "x86"
+ }
+ }
buildTypes {
release {
- minifyEnabled false // Set this to true to enable Proguard
+ minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
+ // applicationVariants are e.g. debug, release
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ // For each separate APK per architecture, set a unique version code as described here:
+ // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
+ def versionCodes = ["armeabi-v7a":1, "x86":2]
+ def abi = output.getFilter(OutputFile.ABI)
+ if (abi != null) { // null for the universal-debug, universal-release variants
+ output.versionCodeOverride =
+ versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
+ }
+ }
+ }
}
dependencies {
+ compile project(':react-native-video')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
- compile "com.facebook.react:react-native:0.16.+"
- compile project(':RCTVideo')
+ compile "com.facebook.react:react-native:0.19.+"
}
diff --git a/Examples/VideoPlayer/android/app/proguard-rules.pro b/Examples/VideoPlayer/android/app/proguard-rules.pro
index ffa8c9f6..35840261 100644
--- a/Examples/VideoPlayer/android/app/proguard-rules.pro
+++ b/Examples/VideoPlayer/android/app/proguard-rules.pro
@@ -40,10 +40,13 @@
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
-keep class * extends com.facebook.react.bridge.NativeModule { *; }
+-keepclassmembers,includedescriptorclasses class * { native ; }
-keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; }
-keepclassmembers class * { @com.facebook.react.uimanager.ReactProp ; }
-keepclassmembers class * { @com.facebook.react.uimanager.ReactPropGroup ; }
+-dontwarn com.facebook.react.**
+
# okhttp
-keepattributes Signature
@@ -58,3 +61,7 @@
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.**
+
+# stetho
+
+-dontwarn com.facebook.stetho.**
diff --git a/Examples/VideoPlayer/android/app/react.gradle b/Examples/VideoPlayer/android/app/react.gradle
index 1e08b00f..f2152d1f 100644
--- a/Examples/VideoPlayer/android/app/react.gradle
+++ b/Examples/VideoPlayer/android/app/react.gradle
@@ -74,14 +74,33 @@ task bundleReleaseJsAndAssets(type: Exec) {
enabled config.bundleInRelease ?: true
}
+void runBefore(String dependentTaskName, Task task) {
+ Task dependentTask = tasks.findByPath(dependentTaskName);
+ if (dependentTask != null) {
+ dependentTask.dependsOn task
+ }
+}
+
gradle.projectsEvaluated {
+
// hook bundleDebugJsAndAssets into the android build process
+
bundleDebugJsAndAssets.dependsOn mergeDebugResources
bundleDebugJsAndAssets.dependsOn mergeDebugAssets
- processDebugResources.dependsOn bundleDebugJsAndAssets
+
+ runBefore('processArmeabi-v7aDebugResources', bundleDebugJsAndAssets)
+ runBefore('processX86DebugResources', bundleDebugJsAndAssets)
+ runBefore('processUniversalDebugResources', bundleDebugJsAndAssets)
+ runBefore('processDebugResources', bundleDebugJsAndAssets)
// hook bundleReleaseJsAndAssets into the android build process
+
bundleReleaseJsAndAssets.dependsOn mergeReleaseResources
bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets
- processReleaseResources.dependsOn bundleReleaseJsAndAssets
+
+ runBefore('processArmeabi-v7aReleaseResources', bundleReleaseJsAndAssets)
+ runBefore('processX86ReleaseResources', bundleReleaseJsAndAssets)
+ runBefore('processUniversalReleaseResources', bundleReleaseJsAndAssets)
+ runBefore('processReleaseResources', bundleReleaseJsAndAssets)
+
}
diff --git a/Examples/VideoPlayer/android/app/src/main/java/com/videoplayer/MainActivity.java b/Examples/VideoPlayer/android/app/src/main/java/com/videoplayer/MainActivity.java
index bb84c0e5..ba386ade 100644
--- a/Examples/VideoPlayer/android/app/src/main/java/com/videoplayer/MainActivity.java
+++ b/Examples/VideoPlayer/android/app/src/main/java/com/videoplayer/MainActivity.java
@@ -1,80 +1,41 @@
package com.videoplayer;
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.KeyEvent;
-
+import com.facebook.react.ReactActivity;
import com.brentvatne.react.ReactVideoPackage;
-import com.facebook.react.LifecycleState;
-import com.facebook.react.ReactInstanceManager;
-import com.facebook.react.ReactRootView;
-import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
+import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
-import com.facebook.soloader.SoLoader;
-public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
+import java.util.Arrays;
+import java.util.List;
- private ReactInstanceManager mReactInstanceManager;
- private ReactRootView mReactRootView;
+public class MainActivity extends ReactActivity {
+ /**
+ * Returns the name of the main component registered from JavaScript.
+ * This is used to schedule rendering of the component.
+ */
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mReactRootView = new ReactRootView(this);
-
- mReactInstanceManager = ReactInstanceManager.builder()
- .setApplication(getApplication())
- .setBundleAssetName("index.android.bundle")
- .setJSMainModuleName("index.android")
- .addPackage(new MainReactPackage())
- .addPackage(new ReactVideoPackage())
- .setUseDeveloperSupport(BuildConfig.DEBUG)
- .setInitialLifecycleState(LifecycleState.RESUMED)
- .build();
-
- mReactRootView.startReactApplication(mReactInstanceManager, "VideoPlayer", null);
-
- setContentView(mReactRootView);
+ protected String getMainComponentName() {
+ return "VideoPlayer";
}
+ /**
+ * Returns whether dev mode should be enabled.
+ * This enables e.g. the dev menu.
+ */
@Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
- mReactInstanceManager.showDevOptionsDialog();
- return true;
- }
- return super.onKeyUp(keyCode, event);
+ protected boolean getUseDeveloperSupport() {
+ return BuildConfig.DEBUG;
}
+ /**
+ * A list of packages used by the app. If the app uses additional views
+ * or modules besides the default ones, add more packages here.
+ */
@Override
- public void onBackPressed() {
- if (mReactInstanceManager != null) {
- mReactInstanceManager.onBackPressed();
- } else {
- super.onBackPressed();
- }
- }
-
- @Override
- public void invokeDefaultOnBackPressed() {
- super.onBackPressed();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- if (mReactInstanceManager != null) {
- mReactInstanceManager.onPause();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- if (mReactInstanceManager != null) {
- mReactInstanceManager.onResume(this, this);
- }
+ protected List getPackages() {
+ return Arrays.asList(
+ new MainReactPackage(),
+ new ReactVideoPackage());
}
}
diff --git a/Examples/VideoPlayer/android/settings.gradle b/Examples/VideoPlayer/android/settings.gradle
index 4c6aa278..941ffdb9 100644
--- a/Examples/VideoPlayer/android/settings.gradle
+++ b/Examples/VideoPlayer/android/settings.gradle
@@ -1,5 +1,7 @@
rootProject.name = 'VideoPlayer'
include ':app'
+include ':react-native-video'
+project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')
include ':RCTVideo', ':app'
project(':RCTVideo').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')
diff --git a/Examples/VideoPlayer/iOS/Info.plist b/Examples/VideoPlayer/iOS/Info.plist
index e4b8e7c8..45532a3a 100644
--- a/Examples/VideoPlayer/iOS/Info.plist
+++ b/Examples/VideoPlayer/iOS/Info.plist
@@ -7,7 +7,7 @@
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
- org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
+ $(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
@@ -15,11 +15,11 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.0
+ 1.0.0
CFBundleSignature
????
CFBundleVersion
- 1
+ 2
LSApplicationCategoryType
LSRequiresIPhoneOS
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer.xcodeproj/project.pbxproj b/Examples/VideoPlayer/iOS/VideoPlayer.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..86221d3b
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer.xcodeproj/project.pbxproj
@@ -0,0 +1,779 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+/* Begin PBXBuildFile section */
+ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
+ 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
+ 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
+ 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
+ 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
+ 00E356F31AD99517003FC87E /* VideoPlayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* VideoPlayerTests.m */; };
+ 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
+ 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
+ 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
+ 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
+ 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+ 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+ 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
+ 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
+ F45119DCD4CB4566AA95CCBF /* libRCTVideo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E6D74A42E295462FBFFFB2F5 /* libRCTVideo.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 134814201AA4EA6300B7C361;
+ remoteInfo = RCTActionSheet;
+ };
+ 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 134814201AA4EA6300B7C361;
+ remoteInfo = RCTGeolocation;
+ };
+ 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
+ remoteInfo = RCTImage;
+ };
+ 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 58B511DB1A9E6C8500147676;
+ remoteInfo = RCTNetwork;
+ };
+ 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
+ remoteInfo = RCTVibration;
+ };
+ 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
+ remoteInfo = VideoPlayer;
+ };
+ 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 134814201AA4EA6300B7C361;
+ remoteInfo = RCTSettings;
+ };
+ 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
+ remoteInfo = RCTWebSocket;
+ };
+ 146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
+ remoteInfo = React;
+ };
+ 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 134814201AA4EA6300B7C361;
+ remoteInfo = RCTLinking;
+ };
+ 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 58B5119B1A9E6C1200147676;
+ remoteInfo = RCTText;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = main.jsbundle; sourceTree = ""; };
+ 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = ""; };
+ 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = ""; };
+ 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj; sourceTree = ""; };
+ 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj; sourceTree = ""; };
+ 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = ""; };
+ 00E356EE1AD99517003FC87E /* VideoPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VideoPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 00E356F21AD99517003FC87E /* VideoPlayerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VideoPlayerTests.m; sourceTree = ""; };
+ 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj; sourceTree = ""; };
+ 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = ""; };
+ 13B07F961A680F5B00A75B9A /* VideoPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VideoPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = VideoPlayer/AppDelegate.h; sourceTree = ""; };
+ 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = VideoPlayer/AppDelegate.m; sourceTree = ""; };
+ 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
+ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = VideoPlayer/Images.xcassets; sourceTree = ""; };
+ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = VideoPlayer/Info.plist; sourceTree = ""; };
+ 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = VideoPlayer/main.m; sourceTree = ""; };
+ 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../node_modules/react-native/React/React.xcodeproj; sourceTree = ""; };
+ 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = ""; };
+ 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../node_modules/react-native/Libraries/Text/RCTText.xcodeproj; sourceTree = ""; };
+ 1AAB246A2EAD48DC803233C0 /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; name = "RCTVideo.xcodeproj"; path = "../node_modules/react-native-video/RCTVideo.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
+ E6D74A42E295462FBFFFB2F5 /* libRCTVideo.a */ = {isa = PBXFileReference; name = "libRCTVideo.a"; path = "libRCTVideo.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 00E356EB1AD99517003FC87E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 146834051AC3E58100842450 /* libReact.a in Frameworks */,
+ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
+ 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
+ 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
+ 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
+ 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
+ 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
+ 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
+ 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
+ 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
+ F45119DCD4CB4566AA95CCBF /* libRCTVideo.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 00C302A81ABCB8CE00DB3ED1 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 00C302B61ABCB90400DB3ED1 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 00C302BC1ABCB91800DB3ED1 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 00C302D41ABCB9D200DB3ED1 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 00C302E01ABCB9EE00DB3ED1 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 00E356EF1AD99517003FC87E /* VideoPlayerTests */ = {
+ isa = PBXGroup;
+ children = (
+ 00E356F21AD99517003FC87E /* VideoPlayerTests.m */,
+ 00E356F01AD99517003FC87E /* Supporting Files */,
+ );
+ path = VideoPlayerTests;
+ sourceTree = "";
+ };
+ 00E356F01AD99517003FC87E /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 00E356F11AD99517003FC87E /* Info.plist */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+ 139105B71AF99BAD00B5F7CC /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 139FDEE71B06529A00C62182 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 13B07FAE1A68108700A75B9A /* VideoPlayer */ = {
+ isa = PBXGroup;
+ children = (
+ 008F07F21AC5B25A0029DE68 /* main.jsbundle */,
+ 13B07FAF1A68108700A75B9A /* AppDelegate.h */,
+ 13B07FB01A68108700A75B9A /* AppDelegate.m */,
+ 13B07FB51A68108700A75B9A /* Images.xcassets */,
+ 13B07FB61A68108700A75B9A /* Info.plist */,
+ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
+ 13B07FB71A68108700A75B9A /* main.m */,
+ );
+ name = VideoPlayer;
+ sourceTree = "";
+ };
+ 146834001AC3E56700842450 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 146834041AC3E56700842450 /* libReact.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 78C398B11ACF4ADC00677621 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 146833FF1AC3E56700842450 /* React.xcodeproj */,
+ 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
+ 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
+ 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
+ 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
+ 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
+ 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
+ 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
+ 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
+ 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
+ 1AAB246A2EAD48DC803233C0 /* RCTVideo.xcodeproj */,
+ );
+ name = Libraries;
+ sourceTree = "";
+ };
+ 832341B11AAA6A8300B99B32 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 832341B51AAA6A8300B99B32 /* libRCTText.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 83CBB9F61A601CBA00E9B192 = {
+ isa = PBXGroup;
+ children = (
+ 13B07FAE1A68108700A75B9A /* VideoPlayer */,
+ 832341AE1AAA6A7D00B99B32 /* Libraries */,
+ 00E356EF1AD99517003FC87E /* VideoPlayerTests */,
+ 83CBBA001A601CBA00E9B192 /* Products */,
+ );
+ indentWidth = 2;
+ sourceTree = "";
+ tabWidth = 2;
+ };
+ 83CBBA001A601CBA00E9B192 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 13B07F961A680F5B00A75B9A /* VideoPlayer.app */,
+ 00E356EE1AD99517003FC87E /* VideoPlayerTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 00E356ED1AD99517003FC87E /* VideoPlayerTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "VideoPlayerTests" */;
+ buildPhases = (
+ 00E356EA1AD99517003FC87E /* Sources */,
+ 00E356EB1AD99517003FC87E /* Frameworks */,
+ 00E356EC1AD99517003FC87E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 00E356F51AD99517003FC87E /* PBXTargetDependency */,
+ );
+ name = VideoPlayerTests;
+ productName = VideoPlayerTests;
+ productReference = 00E356EE1AD99517003FC87E /* VideoPlayerTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 13B07F861A680F5B00A75B9A /* VideoPlayer */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "VideoPlayer" */;
+ buildPhases = (
+ 13B07F871A680F5B00A75B9A /* Sources */,
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */,
+ 13B07F8E1A680F5B00A75B9A /* Resources */,
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = VideoPlayer;
+ productName = "Hello World";
+ productReference = 13B07F961A680F5B00A75B9A /* VideoPlayer.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 83CBB9F71A601CBA00E9B192 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 610;
+ ORGANIZATIONNAME = Facebook;
+ TargetAttributes = {
+ 00E356ED1AD99517003FC87E = {
+ CreatedOnToolsVersion = 6.2;
+ TestTargetID = 13B07F861A680F5B00A75B9A;
+ };
+ };
+ };
+ buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "VideoPlayer" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 83CBB9F61A601CBA00E9B192;
+ productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
+ ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
+ },
+ {
+ ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
+ ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
+ },
+ {
+ ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;
+ ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
+ },
+ {
+ ProductGroup = 78C398B11ACF4ADC00677621 /* Products */;
+ ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
+ },
+ {
+ ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
+ ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
+ },
+ {
+ ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;
+ ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
+ },
+ {
+ ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
+ ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
+ },
+ {
+ ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */;
+ ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
+ },
+ {
+ ProductGroup = 139FDEE71B06529A00C62182 /* Products */;
+ ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
+ },
+ {
+ ProductGroup = 146834001AC3E56700842450 /* Products */;
+ ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 13B07F861A680F5B00A75B9A /* VideoPlayer */,
+ 00E356ED1AD99517003FC87E /* VideoPlayerTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTActionSheet.a;
+ remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTGeolocation.a;
+ remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTImage.a;
+ remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTNetwork.a;
+ remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTVibration.a;
+ remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTSettings.a;
+ remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTWebSocket.a;
+ remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 146834041AC3E56700842450 /* libReact.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libReact.a;
+ remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTLinking.a;
+ remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTText.a;
+ remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 00E356EC1AD99517003FC87E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 13B07F8E1A680F5B00A75B9A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
+ 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Bundle React Native code and images";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
+ showEnvVarsInLog = 1;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 00E356EA1AD99517003FC87E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 00E356F31AD99517003FC87E /* VideoPlayerTests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 13B07F871A680F5B00A75B9A /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
+ 13B07FC11A68108700A75B9A /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 13B07F861A680F5B00A75B9A /* VideoPlayer */;
+ targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 13B07FB21A68108700A75B9A /* Base */,
+ );
+ name = LaunchScreen.xib;
+ path = VideoPlayer;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 00E356F61AD99517003FC87E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(inherited)",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ INFOPLIST_FILE = VideoPlayerTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VideoPlayer.app/VideoPlayer";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ };
+ name = Debug;
+ };
+ 00E356F71AD99517003FC87E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(inherited)",
+ );
+ INFOPLIST_FILE = VideoPlayerTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VideoPlayer.app/VideoPlayer";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ };
+ name = Release;
+ };
+ 13B07F941A680F5B00A75B9A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ DEAD_CODE_STRIPPING = NO;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../node_modules/react-native/React/**",
+ "$(SRCROOT)/../node_modules/react-native-video",
+ );
+ INFOPLIST_FILE = "VideoPlayer/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = VideoPlayer;
+ };
+ name = Debug;
+ };
+ 13B07F951A680F5B00A75B9A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../node_modules/react-native/React/**",
+ "$(SRCROOT)/../node_modules/react-native-video",
+ );
+ INFOPLIST_FILE = "VideoPlayer/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = VideoPlayer;
+ };
+ name = Release;
+ };
+ 83CBBA201A601CBA00E9B192 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../node_modules/react-native/React/**",
+ "$(SRCROOT)/../node_modules/react-native-video",
+ );
+ IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 83CBBA211A601CBA00E9B192 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../node_modules/react-native/React/**",
+ "$(SRCROOT)/../node_modules/react-native-video",
+ );
+ IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "VideoPlayerTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 00E356F61AD99517003FC87E /* Debug */,
+ 00E356F71AD99517003FC87E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "VideoPlayer" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 13B07F941A680F5B00A75B9A /* Debug */,
+ 13B07F951A680F5B00A75B9A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "VideoPlayer" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 83CBBA201A601CBA00E9B192 /* Debug */,
+ 83CBBA211A601CBA00E9B192 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
+}
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme b/Examples/VideoPlayer/iOS/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme
new file mode 100644
index 00000000..f277fa26
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer.xcodeproj/xcshareddata/xcschemes/VideoPlayer.xcscheme
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer/AppDelegate.h b/Examples/VideoPlayer/iOS/VideoPlayer/AppDelegate.h
new file mode 100644
index 00000000..a9654d5e
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer/AppDelegate.h
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import
+
+@interface AppDelegate : UIResponder
+
+@property (nonatomic, strong) UIWindow *window;
+
+@end
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer/AppDelegate.m b/Examples/VideoPlayer/iOS/VideoPlayer/AppDelegate.m
new file mode 100644
index 00000000..9c9c0490
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer/AppDelegate.m
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import "AppDelegate.h"
+
+#import "RCTRootView.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ NSURL *jsCodeLocation;
+
+ /**
+ * Loading JavaScript code - uncomment the one you want.
+ *
+ * OPTION 1
+ * Load from development server. Start the server from the repository root:
+ *
+ * $ npm start
+ *
+ * To run on device, change `localhost` to the IP address of your computer
+ * (you can get this by typing `ifconfig` into the terminal and selecting the
+ * `inet` value under `en0:`) and make sure your computer and iOS device are
+ * on the same Wi-Fi network.
+ */
+
+ jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
+
+ /**
+ * OPTION 2
+ * Load from pre-bundled file on disk. The static bundle is automatically
+ * generated by the "Bundle React Native code and images" build step when
+ * running the project on an actual device or running the project on the
+ * simulator in the "Release" build configuration.
+ */
+
+// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+
+ RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
+ moduleName:@"VideoPlayer"
+ initialProperties:nil
+ launchOptions:launchOptions];
+
+ self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+ UIViewController *rootViewController = [UIViewController new];
+ rootViewController.view = rootView;
+ self.window.rootViewController = rootViewController;
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+@end
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer/Base.lproj/LaunchScreen.xib b/Examples/VideoPlayer/iOS/VideoPlayer/Base.lproj/LaunchScreen.xib
new file mode 100644
index 00000000..9d8b0c89
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer/Base.lproj/LaunchScreen.xib
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/VideoPlayer/iOS/VideoPlayer/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..118c98f7
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,38 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer/Info.plist b/Examples/VideoPlayer/iOS/VideoPlayer/Info.plist
new file mode 100644
index 00000000..91963b26
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer/Info.plist
@@ -0,0 +1,48 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+ NSLocationWhenInUseUsageDescription
+
+ NSAppTransportSecurity
+
+
+ NSAllowsArbitraryLoads
+
+
+
+
diff --git a/Examples/VideoPlayer/iOS/VideoPlayer/main.m b/Examples/VideoPlayer/iOS/VideoPlayer/main.m
new file mode 100644
index 00000000..3d767fcb
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayer/main.m
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import
+
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/Examples/VideoPlayer/iOS/VideoPlayerTests/Info.plist b/Examples/VideoPlayer/iOS/VideoPlayerTests/Info.plist
new file mode 100644
index 00000000..886825cc
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayerTests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/Examples/VideoPlayer/iOS/VideoPlayerTests/VideoPlayerTests.m b/Examples/VideoPlayer/iOS/VideoPlayerTests/VideoPlayerTests.m
new file mode 100644
index 00000000..e5ef148e
--- /dev/null
+++ b/Examples/VideoPlayer/iOS/VideoPlayerTests/VideoPlayerTests.m
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import
+#import
+
+#import "RCTLog.h"
+#import "RCTRootView.h"
+
+#define TIMEOUT_SECONDS 240
+#define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
+
+@interface VideoPlayerTests : XCTestCase
+
+@end
+
+@implementation VideoPlayerTests
+
+- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
+{
+ if (test(view)) {
+ return YES;
+ }
+ for (UIView *subview in [view subviews]) {
+ if ([self findSubviewInView:subview matching:test]) {
+ return YES;
+ }
+ }
+ return NO;
+}
+
+- (void)testRendersWelcomeScreen
+{
+ UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
+ NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
+ BOOL foundElement = NO;
+
+ __block NSString *redboxError = nil;
+ RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
+ if (level >= RCTLogLevelError) {
+ redboxError = message;
+ }
+ });
+
+ while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
+ [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
+ [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
+
+ foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
+ if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
+ return YES;
+ }
+ return NO;
+ }];
+ }
+
+ RCTSetLogFunction(RCTDefaultLogFunction);
+
+ XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
+ XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
+}
+
+
+@end
diff --git a/Examples/VideoPlayer/index.android.js b/Examples/VideoPlayer/index.android.js
index c2533f28..21ee336a 100644
--- a/Examples/VideoPlayer/index.android.js
+++ b/Examples/VideoPlayer/index.android.js
@@ -1,35 +1,39 @@
'use strict';
-var React = require('react-native');
-var {
+import React, {
AppRegistry,
+ Component,
StyleSheet,
Text,
- View,
TouchableOpacity,
-} = React;
+ View,
+} from 'react-native';
-var Video = require('react-native-video');
+import Video from 'react-native-video';
-var VideoPlayer = React.createClass({
- getInitialState() {
- return {
- rate: 1,
- volume: 1,
- muted: false,
- resizeMode: 'contain',
- duration: 0.0,
- currentTime: 0.0,
- }
- },
+class VideoPlayer extends Component {
+ constructor(props) {
+ super(props);
+ this.onLoad = this.onLoad.bind(this);
+ this.onProgress = this.onProgress.bind(this);
+ }
+
+ state = {
+ rate: 1,
+ volume: 1,
+ muted: false,
+ resizeMode: 'contain',
+ duration: 0.0,
+ currentTime: 0.0,
+ };
onLoad(data) {
this.setState({duration: data.duration});
- },
+ }
onProgress(data) {
this.setState({currentTime: data.currentTime});
- },
+ }
getCurrentTimePercentage() {
if (this.state.currentTime > 0) {
@@ -37,10 +41,10 @@ var VideoPlayer = React.createClass({
} else {
return 0;
}
- },
+ }
renderRateControl(rate) {
- var isSelected = (this.state.rate == rate);
+ const isSelected = (this.state.rate == rate);
return (
{ this.setState({rate: rate}) }}>
@@ -49,10 +53,10 @@ var VideoPlayer = React.createClass({
)
- },
+ }
renderResizeModeControl(resizeMode) {
- var isSelected = (this.state.resizeMode == resizeMode);
+ const isSelected = (this.state.resizeMode == resizeMode);
return (
{ this.setState({resizeMode: resizeMode}) }}>
@@ -61,10 +65,10 @@ var VideoPlayer = React.createClass({
)
- },
+ }
renderVolumeControl(volume) {
- var isSelected = (this.state.volume == volume);
+ const isSelected = (this.state.volume == volume);
return (
{ this.setState({volume: volume}) }}>
@@ -73,11 +77,11 @@ var VideoPlayer = React.createClass({
)
- },
+ }
render() {
- var flexCompleted = this.getCurrentTimePercentage() * 100;
- var flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
+ const flexCompleted = this.getCurrentTimePercentage() * 100;
+ const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
return (
@@ -128,10 +132,10 @@ var VideoPlayer = React.createClass({
);
}
-});
+}
-var styles = StyleSheet.create({
+const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
diff --git a/Examples/VideoPlayer/index.ios.js b/Examples/VideoPlayer/index.ios.js
index c77f53d5..e6e5f838 100644
--- a/Examples/VideoPlayer/index.ios.js
+++ b/Examples/VideoPlayer/index.ios.js
@@ -1,36 +1,42 @@
'use strict';
-var React = require('react-native');
-var {
+import React, {
+ AlertIOS,
AppRegistry,
+ Component,
StyleSheet,
Text,
- View,
TouchableOpacity,
- AlertIOS,
-} = React;
+ View,
+} from 'react-native';
-var Video = require('react-native-video');
+import Video from 'react-native-video';
-var VideoPlayer = React.createClass({
- getInitialState() {
- return {
- rate: 1,
- volume: 1,
- muted: false,
- resizeMode: 'contain',
- duration: 0.0,
- currentTime: 0.0,
- }
- },
+class VideoPlayer extends Component {
+ constructor(props) {
+ super(props);
+ this.onLoad = this.onLoad.bind(this);
+ this.onProgress = this.onProgress.bind(this);
+ }
+ state = {
+ rate: 1,
+ volume: 1,
+ muted: false,
+ resizeMode: 'contain',
+ duration: 0.0,
+ currentTime: 0.0,
+ controls: false,
+ paused: true,
+ skin: 'custom'
+ };
onLoad(data) {
this.setState({duration: data.duration});
- },
+ }
onProgress(data) {
this.setState({currentTime: data.currentTime});
- },
+ }
getCurrentTimePercentage() {
if (this.state.currentTime > 0) {
@@ -38,10 +44,25 @@ var VideoPlayer = React.createClass({
} else {
return 0;
}
- },
+ }
+
+ renderSkinControl(skin) {
+ const isSelected = this.state.skin == skin;
+ const selectControls = skin == 'native' || skin == 'embed';
+ return (
+ { this.setState({
+ controls: selectControls,
+ skin: skin
+ }) }}>
+
+ {skin}
+
+
+ );
+ }
renderRateControl(rate) {
- var isSelected = (this.state.rate == rate);
+ const isSelected = (this.state.rate == rate);
return (
{ this.setState({rate: rate}) }}>
@@ -50,10 +71,10 @@ var VideoPlayer = React.createClass({
)
- },
+ }
renderResizeModeControl(resizeMode) {
- var isSelected = (this.state.resizeMode == resizeMode);
+ const isSelected = (this.state.resizeMode == resizeMode);
return (
{ this.setState({resizeMode: resizeMode}) }}>
@@ -62,10 +83,10 @@ var VideoPlayer = React.createClass({
)
- },
+ }
renderVolumeControl(volume) {
- var isSelected = (this.state.volume == volume);
+ const isSelected = (this.state.volume == volume);
return (
{ this.setState({volume: volume}) }}>
@@ -74,35 +95,42 @@ var VideoPlayer = React.createClass({
)
- },
+ }
- render() {
- var flexCompleted = this.getCurrentTimePercentage() * 100;
- var flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
+ renderCustomSkin() {
+ const flexCompleted = this.getCurrentTimePercentage() * 100;
+ const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
return (
{this.setState({paused: !this.state.paused})}}>
-
+
+
+ {this.renderSkinControl('custom')}
+ {this.renderSkinControl('native')}
+ {this.renderSkinControl('embed')}
+
+
- {this.renderRateControl(0.25)}
{this.renderRateControl(0.5)}
{this.renderRateControl(1.0)}
- {this.renderRateControl(1.5)}
{this.renderRateControl(2.0)}
@@ -129,10 +157,66 @@ var VideoPlayer = React.createClass({
);
}
-});
+ renderNativeSkin() {
+ const videoStyle = this.state.skin == 'embed' ? styles.nativeVideoControls : styles.fullScreen;
+ return (
+
+
+ { AlertIOS.alert('Done!') }}
+ repeat={true}
+ controls={this.state.controls}
+ />
+
+
+
+
+ {this.renderSkinControl('custom')}
+ {this.renderSkinControl('native')}
+ {this.renderSkinControl('embed')}
+
+
+
+
+ {this.renderRateControl(0.5)}
+ {this.renderRateControl(1.0)}
+ {this.renderRateControl(2.0)}
+
-var styles = StyleSheet.create({
+
+ {this.renderVolumeControl(0.5)}
+ {this.renderVolumeControl(1)}
+ {this.renderVolumeControl(1.5)}
+
+
+
+ {this.renderResizeModeControl('cover')}
+ {this.renderResizeModeControl('contain')}
+ {this.renderResizeModeControl('stretch')}
+
+
+
+
+
+ );
+ }
+
+ render() {
+ return this.state.controls ? this.renderNativeSkin() : this.renderCustomSkin();
+ }
+}
+
+const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
@@ -150,9 +234,9 @@ var styles = StyleSheet.create({
backgroundColor: "transparent",
borderRadius: 5,
position: 'absolute',
- bottom: 20,
- left: 20,
- right: 20,
+ bottom: 44,
+ left: 4,
+ right: 4,
},
progress: {
flex: 1,
@@ -171,10 +255,14 @@ var styles = StyleSheet.create({
generalControls: {
flex: 1,
flexDirection: 'row',
- borderRadius: 4,
overflow: 'hidden',
paddingBottom: 10,
},
+ skinControl: {
+ flex: 1,
+ flexDirection: 'row',
+ justifyContent: 'center',
+ },
rateControl: {
flex: 1,
flexDirection: 'row',
@@ -189,7 +277,7 @@ var styles = StyleSheet.create({
flex: 1,
flexDirection: 'row',
alignItems: 'center',
- justifyContent: 'center',
+ justifyContent: 'center'
},
controlOption: {
alignSelf: 'center',
@@ -199,6 +287,10 @@ var styles = StyleSheet.create({
paddingRight: 2,
lineHeight: 12,
},
+ nativeVideoControls: {
+ top: 184,
+ height: 300
+ }
});
AppRegistry.registerComponent('VideoPlayer', () => VideoPlayer);
diff --git a/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj b/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj
deleted file mode 100644
index e6ddaaf1..00000000
--- a/Examples/VideoPlayer/node_modules/react-native-video/RCTVideo.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,260 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 46;
- objects = {
-
-/* Begin PBXBuildFile section */
- BBD49E3F1AC8DEF000610F8E /* RCTVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */; };
- BBD49E401AC8DEF000610F8E /* RCTVideoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXCopyFilesBuildPhase section */
- 58B511D91A9E6C8500147676 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "include/$(PRODUCT_NAME)";
- dstSubfolderSpec = 16;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
- 134814201AA4EA6300B7C361 /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTVideo.a; sourceTree = BUILT_PRODUCTS_DIR; };
- BBD49E391AC8DEF000610F8E /* RCTVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideo.h; sourceTree = ""; };
- BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVideo.m; sourceTree = ""; };
- BBD49E3B1AC8DEF000610F8E /* RCTVideoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideoManager.h; sourceTree = ""; };
- BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVideoManager.m; sourceTree = ""; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- 58B511D81A9E6C8500147676 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- 134814211AA4EA7D00B7C361 /* Products */ = {
- isa = PBXGroup;
- children = (
- 134814201AA4EA6300B7C361 /* libRCTVideo.a */,
- );
- name = Products;
- sourceTree = "";
- };
- 58B511D21A9E6C8500147676 = {
- isa = PBXGroup;
- children = (
- BBD49E391AC8DEF000610F8E /* RCTVideo.h */,
- BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */,
- BBD49E3B1AC8DEF000610F8E /* RCTVideoManager.h */,
- BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */,
- 134814211AA4EA7D00B7C361 /* Products */,
- );
- sourceTree = "";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- 58B511DA1A9E6C8500147676 /* RCTVideo */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTVideo" */;
- buildPhases = (
- 58B511D71A9E6C8500147676 /* Sources */,
- 58B511D81A9E6C8500147676 /* Frameworks */,
- 58B511D91A9E6C8500147676 /* CopyFiles */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = RCTVideo;
- productName = RCTDataManager;
- productReference = 134814201AA4EA6300B7C361 /* libRCTVideo.a */;
- productType = "com.apple.product-type.library.static";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- 58B511D31A9E6C8500147676 /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastUpgradeCheck = 0610;
- ORGANIZATIONNAME = Facebook;
- TargetAttributes = {
- 58B511DA1A9E6C8500147676 = {
- CreatedOnToolsVersion = 6.1.1;
- };
- };
- };
- buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTVideo" */;
- compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- );
- mainGroup = 58B511D21A9E6C8500147676;
- productRefGroup = 58B511D21A9E6C8500147676;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- 58B511DA1A9E6C8500147676 /* RCTVideo */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXSourcesBuildPhase section */
- 58B511D71A9E6C8500147676 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- BBD49E3F1AC8DEF000610F8E /* RCTVideo.m in Sources */,
- BBD49E401AC8DEF000610F8E /* RCTVideoManager.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin XCBuildConfiguration section */
- 58B511ED1A9E6C8500147676 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- COPY_PHASE_STRIP = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 7.0;
- MTL_ENABLE_DEBUG_INFO = YES;
- ONLY_ACTIVE_ARCH = YES;
- SDKROOT = iphoneos;
- };
- name = Debug;
- };
- 58B511EE1A9E6C8500147676 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- COPY_PHASE_STRIP = YES;
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 7.0;
- MTL_ENABLE_DEBUG_INFO = NO;
- SDKROOT = iphoneos;
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- 58B511F01A9E6C8500147676 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- HEADER_SEARCH_PATHS = (
- "$(inherited)",
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
- "$(SRCROOT)/../../React/**",
- "$(SRCROOT)/../react-native/React/**",
- "$(SRCROOT)/node_modules/react-native/React/**",
- );
- LIBRARY_SEARCH_PATHS = "$(inherited)";
- OTHER_LDFLAGS = "-ObjC";
- PRODUCT_NAME = RCTVideo;
- SKIP_INSTALL = YES;
- };
- name = Debug;
- };
- 58B511F11A9E6C8500147676 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- HEADER_SEARCH_PATHS = (
- "$(inherited)",
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
- "$(SRCROOT)/../../React/**",
- "$(SRCROOT)/../react-native/React/**",
- "$(SRCROOT)/node_modules/react-native/React/**",
- );
- LIBRARY_SEARCH_PATHS = "$(inherited)";
- OTHER_LDFLAGS = "-ObjC";
- PRODUCT_NAME = RCTVideo;
- SKIP_INSTALL = YES;
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTVideo" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 58B511ED1A9E6C8500147676 /* Debug */,
- 58B511EE1A9E6C8500147676 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTVideo" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 58B511F01A9E6C8500147676 /* Debug */,
- 58B511F11A9E6C8500147676 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = 58B511D31A9E6C8500147676 /* Project object */;
-}
diff --git a/Examples/VideoPlayer/package.json b/Examples/VideoPlayer/package.json
index 2d097498..b343603e 100644
--- a/Examples/VideoPlayer/package.json
+++ b/Examples/VideoPlayer/package.json
@@ -1,12 +1,13 @@
{
"name": "VideoPlayer",
- "version": "0.0.1",
+ "version": "1.0.0",
"private": true,
"scripts": {
"start": "node_modules/react-native/packager/packager.sh"
},
"dependencies": {
- "react-native": "^0.16.0",
- "react-native-video": "brentvatne/react-native-video#feature/android-support"
+ "react": "^0.14.8",
+ "react-native": "0.23.0",
+ "react-native-video": "../../"
}
}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..dc7f43c8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Brent Vatne, Baris Sencan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/RCTVideo.h b/RCTVideo.h
index 1fc82e43..6f8aeab2 100644
--- a/RCTVideo.h
+++ b/RCTVideo.h
@@ -1,9 +1,16 @@
#import "RCTView.h"
+#import
+#import "AVKit/AVKit.h"
+#import "UIView+FindUIViewController.h"
+#import "RCTVideoPlayerViewController.h"
+#import "RCTVideoPlayerViewControllerDelegate.h"
@class RCTEventDispatcher;
-@interface RCTVideo : UIView
+@interface RCTVideo : UIView
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
+- (AVPlayerViewController*)createPlayerViewController:(AVPlayer*)player withPlayerItem:(AVPlayerItem*)playerItem;
+
@end
diff --git a/RCTVideo.m b/RCTVideo.m
index 11e74428..11ae0798 100644
--- a/RCTVideo.m
+++ b/RCTVideo.m
@@ -3,17 +3,19 @@
#import "RCTBridgeModule.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"
-#import
static NSString *const statusKeyPath = @"status";
static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp";
+static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
@implementation RCTVideo
{
AVPlayer *_player;
AVPlayerItem *_playerItem;
BOOL _playerItemObserversSet;
+ BOOL _playerBufferEmpty;
AVPlayerLayer *_playerLayer;
+ AVPlayerViewController *_playerViewController;
NSURL *_videoURL;
/* Required to publish events */
@@ -24,9 +26,9 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
float _lastSeekTime;
/* For sending videoProgress events */
- id _progressUpdateTimer;
- int _progressUpdateInterval;
- NSDate *_prevProgressUpdateTime;
+ Float64 _progressUpdateInterval;
+ BOOL _controls;
+ id _timeObserver;
/* Keep track of any modifiers, need to be applied after each play */
float _volume;
@@ -36,6 +38,8 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
BOOL _repeat;
BOOL _playInBackground;
NSString * _resizeMode;
+ BOOL _fullscreenPlayerPresented;
+ UIViewController * _presentingViewController;
}
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
@@ -49,7 +53,10 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
_pendingSeek = false;
_pendingSeekTime = 0.0f;
_lastSeekTime = 0.0f;
- _playInBackground = false;
+ _progressUpdateInterval = 250;
+ _controls = NO;
+ _playerBufferEmpty = YES;
+ _playInBackground = false;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillResignActive:)
@@ -65,6 +72,44 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
return self;
}
+- (AVPlayerViewController*)createPlayerViewController:(AVPlayer*)player withPlayerItem:(AVPlayerItem*)playerItem {
+ RCTVideoPlayerViewController* playerLayer= [[RCTVideoPlayerViewController alloc] init];
+ playerLayer.showsPlaybackControls = NO;
+ playerLayer.rctDelegate = self;
+ playerLayer.view.frame = self.bounds;
+ playerLayer.player = _player;
+ playerLayer.view.frame = self.bounds;
+ return playerLayer;
+}
+
+/* ---------------------------------------------------------
+ ** Get the duration for a AVPlayerItem.
+ ** ------------------------------------------------------- */
+
+- (CMTime)playerItemDuration
+{
+ AVPlayerItem *playerItem = [_player currentItem];
+ if (playerItem.status == AVPlayerItemStatusReadyToPlay)
+ {
+ return([playerItem duration]);
+ }
+
+ return(kCMTimeInvalid);
+}
+
+
+/* Cancels the previously registered time observer. */
+-(void)removePlayerTimeObserver
+{
+ if (_timeObserver)
+ {
+ [_player removeTimeObserver:_timeObserver];
+ _timeObserver = nil;
+ }
+}
+
+#pragma mark - Progress
+
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
@@ -74,15 +119,14 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
- (void)applicationWillResignActive:(NSNotification *)notification
{
- if (!_paused && !_playInBackground) {
- [self stopProgressTimer];
+ if (!_paused && !_playInBackground) {
+ [_player pause];
[_player setRate:0.0];
}
}
- (void)applicationWillEnterForeground:(NSNotification *)notification
{
- [self startProgressTimer];
[self applyModifiers];
}
@@ -90,18 +134,29 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
- (void)sendProgressUpdate
{
- AVPlayerItem *video = [_player currentItem];
- if (video == nil || video.status != AVPlayerItemStatusReadyToPlay) {
- return;
- }
+ AVPlayerItem *video = [_player currentItem];
+ if (video == nil || video.status != AVPlayerItemStatusReadyToPlay) {
+ return;
+ }
+
+ CMTime playerDuration = [self playerItemDuration];
+ if (CMTIME_IS_INVALID(playerDuration)) {
+ return;
+ }
- if (_prevProgressUpdateTime == nil || (([_prevProgressUpdateTime timeIntervalSinceNow] * -1000.0) >= _progressUpdateInterval)) {
- [_eventDispatcher sendInputEventWithName:@"onVideoProgress"
- body:@{@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(video.currentTime)],
- @"playableDuration": [self calculatePlayableDuration],
- @"target": self.reactTag}];
- _prevProgressUpdateTime = [NSDate date];
- }
+ CMTime currentTime = _player.currentTime;
+ const Float64 duration = CMTimeGetSeconds(playerDuration);
+ const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime);
+ if( currentTimeSecs >= 0 && currentTimeSecs <= duration) {
+ [_eventDispatcher sendInputEventWithName:@"onVideoProgress"
+ body:@{
+ @"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(currentTime)],
+ @"playableDuration": [self calculatePlayableDuration],
+ @"atValue": [NSNumber numberWithLongLong:currentTime.value],
+ @"atTimescale": [NSNumber numberWithInt:currentTime.timescale],
+ @"target": self.reactTag
+ }];
+ }
}
/*!
@@ -129,25 +184,10 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
return [NSNumber numberWithInteger:0];
}
-- (void)stopProgressTimer
-{
- [_progressUpdateTimer invalidate];
-}
-
-- (void)startProgressTimer
-{
- _progressUpdateInterval = 250;
- _prevProgressUpdateTime = nil;
-
- [self stopProgressTimer];
-
- _progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(sendProgressUpdate)];
- [_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
-}
-
- (void)addPlayerItemObservers
{
[_playerItem addObserver:self forKeyPath:statusKeyPath options:0 context:nil];
+ [_playerItem addObserver:self forKeyPath:playbackBufferEmptyKeyPath options:0 context:nil];
[_playerItem addObserver:self forKeyPath:playbackLikelyToKeepUpKeyPath options:0 context:nil];
_playerItemObserversSet = YES;
}
@@ -159,6 +199,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
{
if (_playerItemObserversSet) {
[_playerItem removeObserver:self forKeyPath:statusKeyPath];
+ [_playerItem removeObserver:self forKeyPath:playbackBufferEmptyKeyPath];
[_playerItem removeObserver:self forKeyPath:playbackLikelyToKeepUpKeyPath];
_playerItemObserversSet = NO;
}
@@ -168,25 +209,27 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
- (void)setSrc:(NSDictionary *)source
{
+ [self removePlayerTimeObserver];
[self removePlayerItemObservers];
_playerItem = [self playerItemForSource:source];
[self addPlayerItemObservers];
[_player pause];
[_playerLayer removeFromSuperlayer];
+ _playerLayer = nil;
+ [_playerViewController.view removeFromSuperview];
+ _playerViewController = nil;
_player = [AVPlayer playerWithPlayerItem:_playerItem];
_player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
- _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
- _playerLayer.frame = self.bounds;
- _playerLayer.needsDisplayOnBoundsChange = YES;
-
- [self applyModifiers];
-
- [self.layer addSublayer:_playerLayer];
- self.layer.needsDisplayOnBoundsChange = YES;
-
+ const Float64 progressUpdateIntervalMS = _progressUpdateInterval / 1000;
+ // @see endScrubbing in AVPlayerDemoPlaybackViewController.m of https://developer.apple.com/library/ios/samplecode/AVPlayerDemo/Introduction/Intro.html
+ __weak RCTVideo *weakSelf = self;
+ _timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(progressUpdateIntervalMS, NSEC_PER_SEC)
+ queue:NULL
+ usingBlock:^(CMTime time) { [weakSelf sendProgressUpdate]; }
+ ];
[_eventDispatcher sendInputEventWithName:@"onVideoLoadStart"
body:@{@"src": @{
@"uri": [source objectForKey:@"uri"],
@@ -216,7 +259,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
- if (object == _playerItem) {
+ if (object == _playerItem) {
if ([keyPath isEqualToString:statusKeyPath]) {
// Handle player item status change.
@@ -226,6 +269,13 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
if (isnan(duration)) {
duration = 0.0;
}
+
+ NSObject *width = @"undefined";
+ NSObject *height = @"undefined";
+ if ([_playerItem.asset tracksWithMediaType:AVMediaTypeVideo].count > 0) {
+ width = [NSNumber numberWithFloat:[_playerItem.asset tracksWithMediaType:AVMediaTypeVideo][0].naturalSize.width];
+ height = [NSNumber numberWithFloat:[_playerItem.asset tracksWithMediaType:AVMediaTypeVideo][0].naturalSize.height];
+ }
[_eventDispatcher sendInputEventWithName:@"onVideoLoad"
body:@{@"duration": [NSNumber numberWithFloat:duration],
@@ -236,9 +286,12 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
@"canPlaySlowReverse": [NSNumber numberWithBool:_playerItem.canPlaySlowReverse],
@"canStepBackward": [NSNumber numberWithBool:_playerItem.canStepBackward],
@"canStepForward": [NSNumber numberWithBool:_playerItem.canStepForward],
+ @"naturalSize": @{
+ @"width": width,
+ @"height": height
+ },
@"target": self.reactTag}];
- [self startProgressTimer];
[self attachListeners];
[self applyModifiers];
} else if(_playerItem.status == AVPlayerItemStatusFailed) {
@@ -248,14 +301,17 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
@"domain": _playerItem.error.domain},
@"target": self.reactTag}];
}
+ } else if ([keyPath isEqualToString:playbackBufferEmptyKeyPath]) {
+ _playerBufferEmpty = YES;
} else if ([keyPath isEqualToString:playbackLikelyToKeepUpKeyPath]) {
// Continue playing (or not if paused) after being paused due to hitting an unbuffered zone.
- if (_playerItem.playbackLikelyToKeepUp) {
+ if ((!_controls || _playerBufferEmpty) && _playerItem.playbackLikelyToKeepUp) {
[self setPaused:_paused];
}
+ _playerBufferEmpty = NO;
}
} else {
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
@@ -283,8 +339,15 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
- (void)setResizeMode:(NSString*)mode
{
+ if( _controls )
+ {
+ _playerViewController.videoGravity = mode;
+ }
+ else
+ {
+ _playerLayer.videoGravity = mode;
+ }
_resizeMode = mode;
- _playerLayer.videoGravity = mode;
}
- (void)setPlayInBackground:(BOOL)playInBackground
@@ -295,16 +358,26 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
- (void)setPaused:(BOOL)paused
{
if (paused) {
- [self stopProgressTimer];
+ [_player pause];
[_player setRate:0.0];
} else {
- [self startProgressTimer];
+ [_player play];
[_player setRate:_rate];
}
-
+
_paused = paused;
}
+- (float)getCurrentTime
+{
+ return _playerItem != NULL ? CMTimeGetSeconds(_playerItem.currentTime) : 0;
+}
+
+- (void)setCurrentTime:(float)currentTime
+{
+ [self setSeek: currentTime];
+}
+
- (void)setSeek:(float)seekTime
{
int timeScale = 10000;
@@ -317,7 +390,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
CMTime current = item.currentTime;
// TODO figure out a good tolerance level
CMTime tolerance = CMTimeMake(1000, timeScale);
-
+
if (CMTimeCompare(current, cmSeekTime) != 0) {
[_player seekToTime:cmSeekTime toleranceBefore:tolerance toleranceAfter:tolerance completionHandler:^(BOOL finished) {
[_eventDispatcher sendInputEventWithName:@"onVideoSeek"
@@ -367,48 +440,195 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
[self setResizeMode:_resizeMode];
[self setRepeat:_repeat];
[self setPaused:_paused];
+ [self setControls:_controls];
}
- (void)setRepeat:(BOOL)repeat {
_repeat = repeat;
}
+- (BOOL)getFullscreen
+{
+ return _fullscreenPlayerPresented;
+}
+
+- (void)setFullscreen:(BOOL)fullscreen
+{
+ if( fullscreen && !_fullscreenPlayerPresented )
+ {
+ // Ensure player view controller is not null
+ if( !_playerViewController )
+ {
+ [self usePlayerViewController];
+ }
+ // Set presentation style to fullscreen
+ [_playerViewController setModalPresentationStyle:UIModalPresentationFullScreen];
+
+ // Find the nearest view controller
+ UIViewController *viewController = [self firstAvailableUIViewController];
+ if( !viewController )
+ {
+ UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
+ viewController = keyWindow.rootViewController;
+ if( viewController.childViewControllers.count > 0 )
+ {
+ viewController = viewController.childViewControllers.lastObject;
+ }
+ }
+ if( viewController )
+ {
+ _presentingViewController = viewController;
+ [_eventDispatcher sendInputEventWithName:@"onVideoFullscreenPlayerWillPresent" body:@{@"target": self.reactTag}];
+ [viewController presentViewController:_playerViewController animated:true completion:^{
+ _playerViewController.showsPlaybackControls = YES;
+ _fullscreenPlayerPresented = fullscreen;
+ [_eventDispatcher sendInputEventWithName:@"onVideoFullscreenPlayerDidPresent" body:@{@"target": self.reactTag}];
+ }];
+ }
+ }
+ else if ( !fullscreen && _fullscreenPlayerPresented )
+ {
+ [self videoPlayerViewControllerWillDismiss:_playerViewController];
+ [_presentingViewController dismissViewControllerAnimated:true completion:^{
+ [self videoPlayerViewControllerDidDismiss:_playerViewController];
+ }];
+ }
+}
+
+- (void)usePlayerViewController
+{
+ if( _player )
+ {
+ _playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem];
+ [self addSubview:_playerViewController.view];
+ }
+}
+
+- (void)usePlayerLayer
+{
+ if( _player )
+ {
+ _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
+ _playerLayer.frame = self.bounds;
+ _playerLayer.needsDisplayOnBoundsChange = YES;
+
+ [self.layer addSublayer:_playerLayer];
+ self.layer.needsDisplayOnBoundsChange = YES;
+ }
+}
+
+- (void)setControls:(BOOL)controls
+{
+ if( _controls != controls || (!_playerLayer && !_playerViewController) )
+ {
+ _controls = controls;
+ if( _controls )
+ {
+ [_playerLayer removeFromSuperlayer];
+ _playerLayer = nil;
+ [self usePlayerViewController];
+ }
+ else
+ {
+ [_playerViewController.view removeFromSuperview];
+ _playerViewController = nil;
+ [self usePlayerLayer];
+ }
+ }
+}
+
+#pragma mark - RCTVideoPlayerViewControllerDelegate
+
+- (void)videoPlayerViewControllerWillDismiss:(AVPlayerViewController *)playerViewController
+{
+ if (_playerViewController == playerViewController && _fullscreenPlayerPresented)
+ {
+ [_eventDispatcher sendInputEventWithName:@"onVideoFullscreenPlayerWillDismiss" body:@{@"target": self.reactTag}];
+ }
+}
+
+- (void)videoPlayerViewControllerDidDismiss:(AVPlayerViewController *)playerViewController
+{
+ if (_playerViewController == playerViewController && _fullscreenPlayerPresented)
+ {
+ _fullscreenPlayerPresented = false;
+ _presentingViewController = nil;
+ [self applyModifiers];
+ [_eventDispatcher sendInputEventWithName:@"onVideoFullscreenPlayerDidDismiss" body:@{@"target": self.reactTag}];
+ }
+}
+
#pragma mark - React View Management
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
{
- RCTLogError(@"video cannot have any subviews");
+ // We are early in the game and somebody wants to set a subview.
+ // That can only be in the context of playerViewController.
+ if( !_controls && !_playerLayer && !_playerViewController )
+ {
+ [self setControls:true];
+ }
+
+ if( _controls )
+ {
+ view.frame = self.bounds;
+ [_playerViewController.contentOverlayView insertSubview:view atIndex:atIndex];
+ }
+ else
+ {
+ RCTLogError(@"video cannot have any subviews");
+ }
return;
}
- (void)removeReactSubview:(UIView *)subview
{
- RCTLogError(@"video cannot have any subviews");
+ if( _controls )
+ {
+ [subview removeFromSuperview];
+ }
+ else
+ {
+ RCTLogError(@"video cannot have any subviews");
+ }
return;
}
- (void)layoutSubviews
{
[super layoutSubviews];
- [CATransaction begin];
- [CATransaction setAnimationDuration:0];
- _playerLayer.frame = self.bounds;
- [CATransaction commit];
+ if( _controls )
+ {
+ _playerViewController.view.frame = self.bounds;
+
+ // also adjust all subviews of contentOverlayView
+ for (UIView* subview in _playerViewController.contentOverlayView.subviews) {
+ subview.frame = self.bounds;
+ }
+ }
+ else
+ {
+ [CATransaction begin];
+ [CATransaction setAnimationDuration:0];
+ _playerLayer.frame = self.bounds;
+ [CATransaction commit];
+ }
}
#pragma mark - Lifecycle
- (void)removeFromSuperview
{
- [_progressUpdateTimer invalidate];
- _prevProgressUpdateTime = nil;
-
[_player pause];
_player = nil;
[_playerLayer removeFromSuperlayer];
_playerLayer = nil;
+
+ [_playerViewController.view removeFromSuperview];
+ _playerViewController = nil;
+ [self removePlayerTimeObserver];
[self removePlayerItemObservers];
_eventDispatcher = nil;
diff --git a/RCTVideo.xcodeproj/project.pbxproj b/RCTVideo.xcodeproj/project.pbxproj
index e6ddaaf1..502dd2a2 100644
--- a/RCTVideo.xcodeproj/project.pbxproj
+++ b/RCTVideo.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
+ 31CAFB211CADA8CD009BCF6F /* UIView+FindUIViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 31CAFB201CADA8CD009BCF6F /* UIView+FindUIViewController.m */; };
+ 31CAFB2F1CADC77F009BCF6F /* RCTVideoPlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 31CAFB2E1CADC77F009BCF6F /* RCTVideoPlayerViewController.m */; };
BBD49E3F1AC8DEF000610F8E /* RCTVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */; };
BBD49E401AC8DEF000610F8E /* RCTVideoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */; };
/* End PBXBuildFile section */
@@ -25,6 +27,11 @@
/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTVideo.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 31CAFB1F1CADA8CD009BCF6F /* UIView+FindUIViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+FindUIViewController.h"; sourceTree = ""; };
+ 31CAFB201CADA8CD009BCF6F /* UIView+FindUIViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+FindUIViewController.m"; sourceTree = ""; };
+ 31CAFB2D1CADC77F009BCF6F /* RCTVideoPlayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideoPlayerViewController.h; sourceTree = ""; };
+ 31CAFB2E1CADC77F009BCF6F /* RCTVideoPlayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVideoPlayerViewController.m; sourceTree = ""; };
+ 31CAFB301CAE6B5F009BCF6F /* RCTVideoPlayerViewControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideoPlayerViewControllerDelegate.h; sourceTree = ""; };
BBD49E391AC8DEF000610F8E /* RCTVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideo.h; sourceTree = ""; };
BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVideo.m; sourceTree = ""; };
BBD49E3B1AC8DEF000610F8E /* RCTVideoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVideoManager.h; sourceTree = ""; };
@@ -55,8 +62,13 @@
children = (
BBD49E391AC8DEF000610F8E /* RCTVideo.h */,
BBD49E3A1AC8DEF000610F8E /* RCTVideo.m */,
+ 31CAFB301CAE6B5F009BCF6F /* RCTVideoPlayerViewControllerDelegate.h */,
+ 31CAFB2D1CADC77F009BCF6F /* RCTVideoPlayerViewController.h */,
+ 31CAFB2E1CADC77F009BCF6F /* RCTVideoPlayerViewController.m */,
BBD49E3B1AC8DEF000610F8E /* RCTVideoManager.h */,
BBD49E3C1AC8DEF000610F8E /* RCTVideoManager.m */,
+ 31CAFB1F1CADA8CD009BCF6F /* UIView+FindUIViewController.h */,
+ 31CAFB201CADA8CD009BCF6F /* UIView+FindUIViewController.m */,
134814211AA4EA7D00B7C361 /* Products */,
);
sourceTree = "";
@@ -87,7 +99,7 @@
58B511D31A9E6C8500147676 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0610;
+ LastUpgradeCheck = 0720;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
58B511DA1A9E6C8500147676 = {
@@ -117,6 +129,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 31CAFB211CADA8CD009BCF6F /* UIView+FindUIViewController.m in Sources */,
+ 31CAFB2F1CADC77F009BCF6F /* RCTVideoPlayerViewController.m in Sources */,
BBD49E3F1AC8DEF000610F8E /* RCTVideo.m in Sources */,
BBD49E401AC8DEF000610F8E /* RCTVideoManager.m in Sources */,
);
@@ -144,6 +158,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -205,7 +220,6 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
- "$(SRCROOT)/../../React/**",
"$(SRCROOT)/../react-native/React/**",
"$(SRCROOT)/node_modules/react-native/React/**",
);
@@ -222,7 +236,6 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
- "$(SRCROOT)/../../React/**",
"$(SRCROOT)/../react-native/React/**",
"$(SRCROOT)/node_modules/react-native/React/**",
);
diff --git a/RCTVideoManager.m b/RCTVideoManager.m
index 02d3ea6d..fcc1451d 100644
--- a/RCTVideoManager.m
+++ b/RCTVideoManager.m
@@ -24,7 +24,11 @@ RCT_EXPORT_MODULE();
@"onVideoError",
@"onVideoProgress",
@"onVideoSeek",
- @"onVideoEnd"
+ @"onVideoEnd",
+ @"onVideoFullscreenPlayerWillPresent",
+ @"onVideoFullscreenPlayerDidPresent",
+ @"onVideoFullscreenPlayerWillDismiss",
+ @"onVideoFullscreenPlayerDidDismiss"
];
}
@@ -38,10 +42,13 @@ RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString);
RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL);
RCT_EXPORT_VIEW_PROPERTY(paused, BOOL);
RCT_EXPORT_VIEW_PROPERTY(muted, BOOL);
+RCT_EXPORT_VIEW_PROPERTY(controls, BOOL);
RCT_EXPORT_VIEW_PROPERTY(volume, float);
RCT_EXPORT_VIEW_PROPERTY(playInBackground, BOOL);
RCT_EXPORT_VIEW_PROPERTY(rate, float);
RCT_EXPORT_VIEW_PROPERTY(seek, float);
+RCT_EXPORT_VIEW_PROPERTY(currentTime, float);
+RCT_EXPORT_VIEW_PROPERTY(fullscreen, BOOL);
- (NSDictionary *)constantsToExport
{
diff --git a/RCTVideoPlayerViewController.h b/RCTVideoPlayerViewController.h
new file mode 100644
index 00000000..d427b63d
--- /dev/null
+++ b/RCTVideoPlayerViewController.h
@@ -0,0 +1,15 @@
+//
+// RCTVideoPlayerViewController.h
+// RCTVideo
+//
+// Created by Stanisław Chmiela on 31.03.2016.
+// Copyright © 2016 Facebook. All rights reserved.
+//
+
+#import
+#import "RCTVideo.h"
+#import "RCTVideoPlayerViewControllerDelegate.h"
+
+@interface RCTVideoPlayerViewController : AVPlayerViewController
+@property (nonatomic, weak) id rctDelegate;
+@end
diff --git a/RCTVideoPlayerViewController.m b/RCTVideoPlayerViewController.m
new file mode 100644
index 00000000..b1b768d7
--- /dev/null
+++ b/RCTVideoPlayerViewController.m
@@ -0,0 +1,28 @@
+//
+// RCTVideoPlayerViewController.m
+// RCTVideo
+//
+// Created by Stanisław Chmiela on 31.03.2016.
+// Copyright © 2016 Facebook. All rights reserved.
+//
+
+#import "RCTVideoPlayerViewController.h"
+
+@interface RCTVideoPlayerViewController ()
+
+@end
+
+@implementation RCTVideoPlayerViewController
+
+- (void)viewDidDisappear:(BOOL)animated
+{
+ [super viewDidDisappear:animated];
+ [_rctDelegate videoPlayerViewControllerDidDismiss:self];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+ [_rctDelegate videoPlayerViewControllerWillDismiss:self];
+ [super viewWillDisappear:animated];
+}
+
+@end
diff --git a/RCTVideoPlayerViewControllerDelegate.h b/RCTVideoPlayerViewControllerDelegate.h
new file mode 100644
index 00000000..ec6500af
--- /dev/null
+++ b/RCTVideoPlayerViewControllerDelegate.h
@@ -0,0 +1,15 @@
+//
+// RCTVideoPlayerViewControllerDelegate.h
+// RCTVideo
+//
+// Created by Stanisław Chmiela on 01.04.2016.
+// Copyright © 2016 Facebook. All rights reserved.
+//
+
+#import
+#import "AVKit/AVKit.h"
+
+@protocol RCTVideoPlayerViewControllerDelegate
+- (void)videoPlayerViewControllerWillDismiss:(AVPlayerViewController *)playerViewController;
+- (void)videoPlayerViewControllerDidDismiss:(AVPlayerViewController *)playerViewController;
+@end
diff --git a/README.md b/README.md
index 4996d34e..d1d4df1f 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
A component for react-native, as seen in
[react-native-login](https://github.com/brentvatne/react-native-login)!
-Requires react-native >= 0.4.4
+Requires react-native >= 0.19.0
### Add it to your project
@@ -11,17 +11,12 @@ Run `npm install react-native-video --save`
#### iOS
-1. Open your project in XCode, right click on `Libraries` and click `Add Files to "Your Project Name"`
- *   (use the RCTVideo project rather than the one pictured in screenshot).
-2. Add `libRTCVideo.a` to `Build Phases -> Link Binary With Libraries`
- .
-3. Add `.mp4` video file to project and to `Build Phases -> Copy Bundle Resources`
-4. Whenever you want to use it within React code now you can: `var Video =
- require('react-native-video');`
+Install [rnpm](https://github.com/rnpm/rnpm) and run `rnpm link react-native-video`
#### Android
-Make the following additions to the given files.
+First, copy your video file to `android/app/src/main/res/raw/`, then
+make the following additions to the given files:
**android/settings.gradle**
```
@@ -70,7 +65,7 @@ Under `.addPackage(new MainReactPackage())`:
style={styles.backgroundVideo} />
// Later on in your styles..
-var styles = Stylesheet.create({
+var styles = StyleSheet.create({
backgroundVideo: {
position: 'absolute',
top: 0,
@@ -89,7 +84,7 @@ Seeks the video to the specified time (in seconds). Access using a ref to the co
## Examples
-- See an [Example integration][1] in `react-native-login`.
+- See an [Example integration][1] in `react-native-login` *note that this example uses an older version of this library, before we used `export default` -- if you use `require` you will need to do `require('react-native-video').default` as per instructions above.
- Try the included [VideoPlayer example][2] yourself:
```sh
@@ -102,12 +97,9 @@ Seeks the video to the specified time (in seconds). Access using a ref to the co
Then `Cmd+R` to start the React Packager, build and run the project in the simulator.
-
## TODOS
-- [ ] Add some way to interface with `seekToTime`
- [ ] Add support for captions
-- [ ] Support `require('video!...')`
- [ ] Add support for playing multiple videos in a sequence (will interfere with current `repeat` implementation)
- [ ] Callback to get buffering progress for remote videos
- [ ] Bring API closer to HTML5 `` [reference](http://www.w3schools.com/tags/ref_av_dom.asp)
diff --git a/UIView+FindUIViewController.h b/UIView+FindUIViewController.h
new file mode 100644
index 00000000..09214261
--- /dev/null
+++ b/UIView+FindUIViewController.h
@@ -0,0 +1,15 @@
+//
+// UIView+FindUIViewController.h
+// RCTVideo
+//
+// Created by Stanisław Chmiela on 31.03.2016.
+// Copyright © 2016 Facebook. All rights reserved.
+//
+// Source: http://stackoverflow.com/a/3732812/1123156
+
+#import
+
+@interface UIView (FindUIViewController)
+- (UIViewController *) firstAvailableUIViewController;
+- (id) traverseResponderChainForUIViewController;
+@end
diff --git a/UIView+FindUIViewController.m b/UIView+FindUIViewController.m
new file mode 100644
index 00000000..bc721b96
--- /dev/null
+++ b/UIView+FindUIViewController.m
@@ -0,0 +1,28 @@
+//
+// UIView+FindUIViewController.m
+// RCTVideo
+//
+// Created by Stanisław Chmiela on 31.03.2016.
+// Copyright © 2016 Facebook. All rights reserved.
+//
+// Source: http://stackoverflow.com/a/3732812/1123156
+
+#import "UIView+FindUIViewController.h"
+
+@implementation UIView (FindUIViewController)
+- (UIViewController *) firstAvailableUIViewController {
+ // convenience function for casting and to "mask" the recursive function
+ return (UIViewController *)[self traverseResponderChainForUIViewController];
+}
+
+- (id) traverseResponderChainForUIViewController {
+ id nextResponder = [self nextResponder];
+ if ([nextResponder isKindOfClass:[UIViewController class]]) {
+ return nextResponder;
+ } else if ([nextResponder isKindOfClass:[UIView class]]) {
+ return [nextResponder traverseResponderChainForUIViewController];
+ } else {
+ return nil;
+ }
+}
+@end
diff --git a/Video.js b/Video.js
index cd8e3ee4..466c3223 100644
--- a/Video.js
+++ b/Video.js
@@ -1,4 +1,6 @@
-const React = require('react-native');
+import React from 'react-native';
+import VideoResizeMode from './VideoResizeMode.js';
+
const {
Component,
StyleSheet,
@@ -8,25 +10,30 @@ const {
View,
} = React;
-const VideoResizeMode = require('./VideoResizeMode');
-
const styles = StyleSheet.create({
base: {
overflow: 'hidden',
},
});
-class Video extends Component {
+export default class Video extends Component {
constructor(props, context) {
super(props, context);
this.seek = this.seek.bind(this);
+ this.presentFullscreenPlayer = this.presentFullscreenPlayer.bind(this);
+ this.dismissFullscreenPlayer = this.dismissFullscreenPlayer.bind(this);
+ this._assignRoot = this._assignRoot.bind(this);
this._onLoadStart = this._onLoadStart.bind(this);
this._onLoad = this._onLoad.bind(this);
this._onError = this._onError.bind(this);
this._onProgress = this._onProgress.bind(this);
this._onSeek = this._onSeek.bind(this);
this._onEnd = this._onEnd.bind(this);
+ this._onFullscreenPlayerWillPresent = this._onFullscreenPlayerWillPresent.bind(this);
+ this._onFullscreenPlayerDidPresent = this._onFullscreenPlayerDidPresent.bind(this);
+ this._onFullscreenPlayerWillDismiss = this._onFullscreenPlayerWillDismiss.bind(this);
+ this._onFullscreenPlayerDidDismiss = this._onFullscreenPlayerDidDismiss.bind(this);
}
setNativeProps(nativeProps) {
@@ -34,48 +41,94 @@ class Video extends Component {
}
seek(time) {
- this.setNativeProps({ seek: parseFloat(time) });
+ this.setNativeProps({ seek: time });
+ }
+
+ presentFullscreenPlayer() {
+ this.setNativeProps({ fullscreen: true });
+ }
+
+ dismissFullscreenPlayer() {
+ this.setNativeProps({ fullscreen: false });
+ }
+
+ _assignRoot(component) {
+ this._root = component;
}
_onLoadStart(event) {
- this.props.onLoadStart && this.props.onLoadStart(event.nativeEvent);
+ if (this.props.onLoadStart) {
+ this.props.onLoadStart(event.nativeEvent);
+ }
}
_onLoad(event) {
- this.props.onLoad && this.props.onLoad(event.nativeEvent);
+ if (this.props.onLoad) {
+ this.props.onLoad(event.nativeEvent);
+ }
}
_onError(event) {
- this.props.onError && this.props.onError(event.nativeEvent);
+ if (this.props.onError) {
+ this.props.onError(event.nativeEvent);
+ }
}
_onProgress(event) {
- this.props.onProgress && this.props.onProgress(event.nativeEvent);
+ if (this.props.onProgress) {
+ this.props.onProgress(event.nativeEvent);
+ }
}
_onSeek(event) {
- this.props.onSeek && this.props.onSeek(event.nativeEvent);
+ if (this.props.onSeek) {
+ this.props.onSeek(event.nativeEvent);
+ }
}
_onEnd(event) {
- this.props.onEnd && this.props.onEnd(event.nativeEvent);
+ if (this.props.onEnd) {
+ this.props.onEnd(event.nativeEvent);
+ }
+ }
+
+ _onFullscreenPlayerWillPresent(event) {
+ if (this.props.onFullscreenPlayerWillPresent) {
+ this.props.onFullscreenPlayerWillPresent(event.nativeEvent);
+ }
+ }
+
+ _onFullscreenPlayerDidPresent(event) {
+ if (this.props.onFullscreenPlayerDidPresent) {
+ this.props.onFullscreenPlayerDidPresent(event.nativeEvent);
+ }
+ }
+
+ _onFullscreenPlayerWillDismiss(event) {
+ if (this.props.onFullscreenPlayerWillDismiss) {
+ this.props.onFullscreenPlayerWillDismiss(event.nativeEvent);
+ }
+ }
+
+ _onFullscreenPlayerDidDismiss(event) {
+ if (this.props.onFullscreenPlayerDidDismiss) {
+ this.props.onFullscreenPlayerDidDismiss(event.nativeEvent);
+ }
}
render() {
const {
- style,
source,
- ref,
resizeMode,
} = this.props;
let uri = source.uri;
if (uri && uri.match(/^\//)) {
- uri = 'file://' + uri;
+ uri = `file://${uri}`;
}
const isNetwork = !!(uri && uri.match(/^https?:/));
- const isAsset = !!(uri && uri.match(/^(assets-library|file):/));
+ const isAsset = !!(uri && uri.match(/^(assets-library|file|content):/));
let nativeResizeMode;
if (resizeMode === VideoResizeMode.stretch) {
@@ -90,10 +143,10 @@ class Video extends Component {
const nativeProps = Object.assign({}, this.props);
Object.assign(nativeProps, {
- style: [styles.base, style],
+ style: [styles.base, nativeProps.style],
resizeMode: nativeResizeMode,
src: {
- uri: uri,
+ uri,
isNetwork,
isAsset,
type: source.type || 'mp4',
@@ -104,12 +157,17 @@ class Video extends Component {
onVideoProgress: this._onProgress,
onVideoSeek: this._onSeek,
onVideoEnd: this._onEnd,
+ onVideoFullscreenPlayerWillPresent: this._onFullscreenPlayerWillPresent,
+ onVideoFullscreenPlayerDidPresent: this._onFullscreenPlayerDidPresent,
+ onVideoFullscreenPlayerWillDismiss: this._onFullscreenPlayerWillDismiss,
+ onVideoFullscreenPlayerDidDismiss: this._onFullscreenPlayerDidDismiss,
});
return (
this._root = component }
- {...nativeProps} />
+ ref={this._assignRoot}
+ {...nativeProps}
+ />
);
}
}
@@ -118,6 +176,7 @@ Video.propTypes = {
/* Native only */
src: PropTypes.object,
seek: PropTypes.number,
+ fullscreen: PropTypes.bool,
/* Wrapper component */
source: PropTypes.object,
@@ -128,12 +187,18 @@ Video.propTypes = {
volume: PropTypes.number,
rate: PropTypes.number,
playInBackground: PropTypes.bool,
+ controls: PropTypes.bool,
+ currentTime: PropTypes.number,
onLoadStart: PropTypes.func,
onLoad: PropTypes.func,
onError: PropTypes.func,
onProgress: PropTypes.func,
onSeek: PropTypes.func,
onEnd: PropTypes.func,
+ onFullscreenPlayerWillPresent: PropTypes.func,
+ onFullscreenPlayerDidPresent: PropTypes.func,
+ onFullscreenPlayerWillDismiss: PropTypes.func,
+ onFullscreenPlayerDidDismiss: PropTypes.func,
/* Required by react-native */
scaleX: React.PropTypes.number,
@@ -148,7 +213,6 @@ const RCTVideo = requireNativeComponent('RCTVideo', Video, {
nativeOnly: {
src: true,
seek: true,
+ fullscreen: true,
},
});
-
-module.exports = Video;
diff --git a/VideoResizeMode.js b/VideoResizeMode.js
index 9d563fc5..15a89773 100644
--- a/VideoResizeMode.js
+++ b/VideoResizeMode.js
@@ -1,11 +1,7 @@
-'use strict';
+import keyMirror from 'keymirror';
-var keyMirror = require('keymirror');
-
-var VideoResizeMode = keyMirror({
+export default keyMirror({
contain: null,
cover: null,
stretch: null,
});
-
-module.exports = VideoResizeMode;
diff --git a/android/build.gradle b/android/build.gradle
index 955ad774..7bed82b6 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -16,6 +16,6 @@ android {
}
dependencies {
- compile 'com.facebook.react:react-native:0.13.+'
+ compile 'com.facebook.react:react-native:0.19.+'
compile 'com.yqritc:android-scalablevideoview:1.0.1'
}
diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoView.java b/android/src/main/java/com/brentvatne/react/ReactVideoView.java
index 0f9a923d..a31f29d3 100644
--- a/android/src/main/java/com/brentvatne/react/ReactVideoView.java
+++ b/android/src/main/java/com/brentvatne/react/ReactVideoView.java
@@ -58,6 +58,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
private String mSrcUriString = null;
private String mSrcType = "mp4";
private boolean mSrcIsNetwork = false;
+ private boolean mSrcIsAsset = false;
private ScalableType mResizeMode = ScalableType.LEFT_TOP;
private boolean mRepeat = false;
private boolean mPaused = false;
@@ -107,10 +108,11 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
}
}
- public void setSrc(final String uriString, final String type, final boolean isNetwork) {
+ public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset) {
mSrcUriString = uriString;
mSrcType = type;
mSrcIsNetwork = isNetwork;
+ mSrcIsAsset = isAsset;
mMediaPlayerValid = false;
mVideoDuration = 0;
@@ -120,7 +122,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
mMediaPlayer.reset();
try {
- if (isNetwork) {
+ if (isNetwork || isAsset) {
setDataSource(uriString);
} else {
setRawData(mThemedReactContext.getResources().getIdentifier(
@@ -281,6 +283,6 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- setSrc(mSrcUriString, mSrcType, mSrcIsNetwork);
+ setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset);
}
}
diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java b/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java
index 3ec693da..6439f757 100644
--- a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java
+++ b/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java
@@ -5,7 +5,7 @@ import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
-import com.facebook.react.uimanager.ReactProp;
+import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.events.RCTEventEmitter;
@@ -22,6 +22,7 @@ public class ReactVideoViewManager extends SimpleViewManager {
public static final String PROP_SRC_URI = "uri";
public static final String PROP_SRC_TYPE = "type";
public static final String PROP_SRC_IS_NETWORK = "isNetwork";
+ public static final String PROP_SRC_IS_ASSET = "isAsset";
public static final String PROP_RESIZE_MODE = "resizeMode";
public static final String PROP_REPEAT = "repeat";
public static final String PROP_PAUSED = "paused";
@@ -66,7 +67,8 @@ public class ReactVideoViewManager extends SimpleViewManager {
videoView.setSrc(
src.getString(PROP_SRC_URI),
src.getString(PROP_SRC_TYPE),
- src.getBoolean(PROP_SRC_IS_NETWORK)
+ src.getBoolean(PROP_SRC_IS_NETWORK),
+ src.getBoolean(PROP_SRC_IS_ASSET)
);
}
diff --git a/package.json b/package.json
index 8dd18d0a..0fc38909 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,9 @@
{
"name": "react-native-video",
- "version": "0.6.1",
+ "version": "0.8.0-beta",
"description": "A element for react-native",
"main": "Video.js",
+ "license": "MIT",
"author": "Brent Vatne (https://github.com/brentvatne)",
"files": [
"android/build.gradle",
@@ -18,9 +19,14 @@
"RCTVideoManager.h",
"RCTVideoManager.m",
"README.md",
+ "UIView+FindUIViewController.h",
+ "UIView+FindUIViewController.m",
+ "RCTVideoPlayerViewController.h",
+ "RCTVideoPlayerViewController.m",
+ "RCTVideoPlayerViewControllerDelegate.h",
"Video.js",
"VideoResizeMode.js",
- "VideoStylePropTypes.js"
+ "react-native-video.podspec"
],
"contributors": [
{
@@ -37,9 +43,16 @@
"url": "git@github.com:brentvatne/react-native-video.git"
},
"devDependencies": {
- "jest-cli": "0.2.1"
+ "jest-cli": "0.2.1",
+ "eslint": "1.10.3",
+ "babel-eslint": "5.0.0-beta8",
+ "eslint-plugin-react": "3.16.1",
+ "eslint-config-airbnb": "4.0.0"
},
"dependencies": {
- "keymirror": "^0.1.1"
+ "keymirror": "0.1.1"
+ },
+ "scripts": {
+ "test": "node_modules/.bin/eslint *.js"
}
}
diff --git a/react-native-video.podspec b/react-native-video.podspec
new file mode 100644
index 00000000..9eb7fd9e
--- /dev/null
+++ b/react-native-video.podspec
@@ -0,0 +1,21 @@
+require "json"
+
+package = JSON.parse(File.read(File.join(__dir__, "package.json")))
+
+Pod::Spec.new do |s|
+ s.name = "react-native-video"
+ s.version = package["version"]
+ s.summary = "A element for react-native"
+ s.author = "Brent Vatne (https://github.com/brentvatne)"
+
+ s.homepage = "https://github.com/brentvatne/react-native-video"
+
+ s.license = "MIT"
+ s.platform = :ios, "7.0"
+
+ s.source = { :git => "https://github.com/brentvatne/react-native-video.git", :tag => "#{s.version}" }
+
+ s.source_files = "*.{h,m}"
+
+ s.dependency "React"
+end