diff --git a/examples/LaftelVideo/.buckconfig b/examples/LaftelVideo/.buckconfig
new file mode 100644
index 00000000..934256cb
--- /dev/null
+++ b/examples/LaftelVideo/.buckconfig
@@ -0,0 +1,6 @@
+
+[android]
+ target = Google Inc.:Google APIs:23
+
+[maven_repositories]
+ central = https://repo1.maven.org/maven2
diff --git a/examples/LaftelVideo/.bundle/config b/examples/LaftelVideo/.bundle/config
new file mode 100644
index 00000000..848943bb
--- /dev/null
+++ b/examples/LaftelVideo/.bundle/config
@@ -0,0 +1,2 @@
+BUNDLE_PATH: "vendor/bundle"
+BUNDLE_FORCE_RUBY_PLATFORM: 1
diff --git a/examples/LaftelVideo/.eslintrc.js b/examples/LaftelVideo/.eslintrc.js
new file mode 100644
index 00000000..dcf0be08
--- /dev/null
+++ b/examples/LaftelVideo/.eslintrc.js
@@ -0,0 +1,16 @@
+module.exports = {
+ root: true,
+ extends: '@react-native-community',
+ parser: '@typescript-eslint/parser',
+ plugins: ['@typescript-eslint'],
+ overrides: [
+ {
+ files: ['*.ts', '*.tsx'],
+ rules: {
+ '@typescript-eslint/no-shadow': ['error'],
+ 'no-shadow': 'off',
+ 'no-undef': 'off',
+ },
+ },
+ ],
+};
diff --git a/examples/LaftelVideo/.gitignore b/examples/LaftelVideo/.gitignore
new file mode 100644
index 00000000..2423126f
--- /dev/null
+++ b/examples/LaftelVideo/.gitignore
@@ -0,0 +1,64 @@
+# 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
+ios/.xcode.env.local
+
+# Android/IntelliJ
+#
+build/
+.idea
+.gradle
+local.properties
+*.iml
+*.hprof
+.cxx/
+
+# node.js
+#
+node_modules/
+npm-debug.log
+yarn-error.log
+
+# BUCK
+buck-out/
+\.buckd/
+*.keystore
+!debug.keystore
+
+# fastlane
+#
+# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
+# screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/
+
+**/fastlane/report.xml
+**/fastlane/Preview.html
+**/fastlane/screenshots
+**/fastlane/test_output
+
+# Bundle artifact
+*.jsbundle
+
+# Ruby / CocoaPods
+/ios/Pods/
+/vendor/bundle/
diff --git a/examples/LaftelVideo/.prettierrc.js b/examples/LaftelVideo/.prettierrc.js
new file mode 100644
index 00000000..2b540746
--- /dev/null
+++ b/examples/LaftelVideo/.prettierrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+ arrowParens: 'avoid',
+ bracketSameLine: true,
+ bracketSpacing: false,
+ singleQuote: true,
+ trailingComma: 'all',
+};
diff --git a/examples/LaftelVideo/.ruby-version b/examples/LaftelVideo/.ruby-version
new file mode 100644
index 00000000..a603bb50
--- /dev/null
+++ b/examples/LaftelVideo/.ruby-version
@@ -0,0 +1 @@
+2.7.5
diff --git a/examples/LaftelVideo/.watchmanconfig b/examples/LaftelVideo/.watchmanconfig
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/examples/LaftelVideo/.watchmanconfig
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/examples/LaftelVideo/App.tsx b/examples/LaftelVideo/App.tsx
new file mode 100644
index 00000000..753aeb86
--- /dev/null
+++ b/examples/LaftelVideo/App.tsx
@@ -0,0 +1,120 @@
+/**
+ * Sample React Native App
+ * https://github.com/facebook/react-native
+ *
+ * Generated with the TypeScript template
+ * https://github.com/react-native-community/react-native-template-typescript
+ *
+ * @format
+ */
+
+import React, {type PropsWithChildren} from 'react';
+import {
+ SafeAreaView,
+ ScrollView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ useColorScheme,
+ View,
+} from 'react-native';
+
+import {
+ Colors,
+ DebugInstructions,
+ Header,
+ LearnMoreLinks,
+ ReloadInstructions,
+} from 'react-native/Libraries/NewAppScreen';
+
+const Section: React.FC<
+ PropsWithChildren<{
+ title: string;
+ }>
+> = ({children, title}) => {
+ const isDarkMode = useColorScheme() === 'dark';
+ return (
+
+
+ {title}
+
+
+ {children}
+
+
+ );
+};
+
+const App = () => {
+ const isDarkMode = useColorScheme() === 'dark';
+
+ const backgroundStyle = {
+ backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
+ };
+
+ return (
+
+
+
+
+
+
+ Edit App.tsx to change this
+ screen and then come back to see your edits.
+
+
+
+
+
+
+
+
+ Read the docs to discover what to do next:
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ sectionContainer: {
+ marginTop: 32,
+ paddingHorizontal: 24,
+ },
+ sectionTitle: {
+ fontSize: 24,
+ fontWeight: '600',
+ },
+ sectionDescription: {
+ marginTop: 8,
+ fontSize: 18,
+ fontWeight: '400',
+ },
+ highlight: {
+ fontWeight: '700',
+ },
+});
+
+export default App;
diff --git a/examples/LaftelVideo/Gemfile b/examples/LaftelVideo/Gemfile
new file mode 100644
index 00000000..5efda89f
--- /dev/null
+++ b/examples/LaftelVideo/Gemfile
@@ -0,0 +1,6 @@
+source 'https://rubygems.org'
+
+# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
+ruby '2.7.5'
+
+gem 'cocoapods', '~> 1.11', '>= 1.11.2'
diff --git a/examples/LaftelVideo/Gemfile.lock b/examples/LaftelVideo/Gemfile.lock
new file mode 100644
index 00000000..be0b95a4
--- /dev/null
+++ b/examples/LaftelVideo/Gemfile.lock
@@ -0,0 +1,98 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ CFPropertyList (3.0.6)
+ rexml
+ activesupport (7.0.4.3)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ addressable (2.8.4)
+ public_suffix (>= 2.0.2, < 6.0)
+ algoliasearch (1.27.5)
+ httpclient (~> 2.8, >= 2.8.3)
+ json (>= 1.5.1)
+ atomos (0.1.3)
+ claide (1.1.0)
+ cocoapods (1.12.0)
+ addressable (~> 2.8)
+ claide (>= 1.0.2, < 2.0)
+ cocoapods-core (= 1.12.0)
+ cocoapods-deintegrate (>= 1.0.3, < 2.0)
+ cocoapods-downloader (>= 1.6.0, < 2.0)
+ cocoapods-plugins (>= 1.0.0, < 2.0)
+ cocoapods-search (>= 1.0.0, < 2.0)
+ cocoapods-trunk (>= 1.6.0, < 2.0)
+ cocoapods-try (>= 1.1.0, < 2.0)
+ colored2 (~> 3.1)
+ escape (~> 0.0.4)
+ fourflusher (>= 2.3.0, < 3.0)
+ gh_inspector (~> 1.0)
+ molinillo (~> 0.8.0)
+ nap (~> 1.0)
+ ruby-macho (>= 2.3.0, < 3.0)
+ xcodeproj (>= 1.21.0, < 2.0)
+ cocoapods-core (1.12.0)
+ activesupport (>= 5.0, < 8)
+ addressable (~> 2.8)
+ algoliasearch (~> 1.0)
+ concurrent-ruby (~> 1.1)
+ fuzzy_match (~> 2.0.4)
+ nap (~> 1.0)
+ netrc (~> 0.11)
+ public_suffix (~> 4.0)
+ typhoeus (~> 1.0)
+ cocoapods-deintegrate (1.0.5)
+ cocoapods-downloader (1.6.3)
+ cocoapods-plugins (1.0.0)
+ nap
+ cocoapods-search (1.0.1)
+ cocoapods-trunk (1.6.0)
+ nap (>= 0.8, < 2.0)
+ netrc (~> 0.11)
+ cocoapods-try (1.2.0)
+ colored2 (3.1.2)
+ concurrent-ruby (1.2.2)
+ escape (0.0.4)
+ ethon (0.16.0)
+ ffi (>= 1.15.0)
+ ffi (1.15.5)
+ fourflusher (2.3.1)
+ fuzzy_match (2.0.4)
+ gh_inspector (1.1.3)
+ httpclient (2.8.3)
+ i18n (1.12.0)
+ concurrent-ruby (~> 1.0)
+ json (2.6.3)
+ minitest (5.18.0)
+ molinillo (0.8.0)
+ nanaimo (0.3.0)
+ nap (1.1.0)
+ netrc (0.11.0)
+ public_suffix (4.0.7)
+ rexml (3.2.5)
+ ruby-macho (2.5.1)
+ typhoeus (1.4.0)
+ ethon (>= 0.9.0)
+ tzinfo (2.0.6)
+ concurrent-ruby (~> 1.0)
+ xcodeproj (1.22.0)
+ CFPropertyList (>= 2.3.3, < 4.0)
+ atomos (~> 0.1.3)
+ claide (>= 1.0.2, < 2.0)
+ colored2 (~> 3.1)
+ nanaimo (~> 0.3.0)
+ rexml (~> 3.2.4)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ cocoapods (~> 1.11, >= 1.11.2)
+
+RUBY VERSION
+ ruby 2.7.5p203
+
+BUNDLED WITH
+ 2.4.5
diff --git a/examples/LaftelVideo/__tests__/App-test.tsx b/examples/LaftelVideo/__tests__/App-test.tsx
new file mode 100644
index 00000000..17847669
--- /dev/null
+++ b/examples/LaftelVideo/__tests__/App-test.tsx
@@ -0,0 +1,14 @@
+/**
+ * @format
+ */
+
+import 'react-native';
+import React from 'react';
+import App from '../App';
+
+// Note: test renderer must be required after react-native.
+import renderer from 'react-test-renderer';
+
+it('renders correctly', () => {
+ renderer.create();
+});
diff --git a/examples/LaftelVideo/_node-version b/examples/LaftelVideo/_node-version
new file mode 100644
index 00000000..b6a7d89c
--- /dev/null
+++ b/examples/LaftelVideo/_node-version
@@ -0,0 +1 @@
+16
diff --git a/examples/LaftelVideo/android/app/_BUCK b/examples/LaftelVideo/android/app/_BUCK
new file mode 100644
index 00000000..90eb5940
--- /dev/null
+++ b/examples/LaftelVideo/android/app/_BUCK
@@ -0,0 +1,55 @@
+# To learn about Buck see [Docs](https://buckbuild.com/).
+# To run your application with Buck:
+# - install Buck
+# - `npm start` - to start the packager
+# - `cd android`
+# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
+# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
+# - `buck install -r android/app` - compile, install and run application
+#
+
+load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
+
+lib_deps = []
+
+create_aar_targets(glob(["libs/*.aar"]))
+
+create_jar_targets(glob(["libs/*.jar"]))
+
+android_library(
+ name = "all-libs",
+ exported_deps = lib_deps,
+)
+
+android_library(
+ name = "app-code",
+ srcs = glob([
+ "src/main/java/**/*.java",
+ ]),
+ deps = [
+ ":all-libs",
+ ":build_config",
+ ":res",
+ ],
+)
+
+android_build_config(
+ name = "build_config",
+ package = "com.laftelvideo",
+)
+
+android_resource(
+ name = "res",
+ package = "com.laftelvideo",
+ res = "src/main/res",
+)
+
+android_binary(
+ name = "app",
+ keystore = "//android/keystores:debug",
+ manifest = "src/main/AndroidManifest.xml",
+ package_type = "debug",
+ deps = [
+ ":app-code",
+ ],
+)
diff --git a/examples/LaftelVideo/android/app/build.gradle b/examples/LaftelVideo/android/app/build.gradle
new file mode 100644
index 00000000..c1a675f4
--- /dev/null
+++ b/examples/LaftelVideo/android/app/build.gradle
@@ -0,0 +1,313 @@
+apply plugin: "com.android.application"
+
+import com.android.build.OutputFile
+import org.apache.tools.ant.taskdefs.condition.Os
+
+/**
+ * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
+ * and bundleReleaseJsAndAssets).
+ * These basically call `react-native bundle` with the correct arguments during the Android build
+ * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
+ * bundle directly from the development server. Below you can see all the possible configurations
+ * and their defaults. If you decide to add a configuration block, make sure to add it before the
+ * `apply from: "../../node_modules/react-native/react.gradle"` line.
+ *
+ * project.ext.react = [
+ * // the name of the generated asset file containing your JS bundle
+ * bundleAssetName: "index.android.bundle",
+ *
+ * // the entry file for bundle generation. If none specified and
+ * // "index.android.js" exists, it will be used. Otherwise "index.js" is
+ * // default. Can be overridden with ENTRY_FILE environment variable.
+ * entryFile: "index.android.js",
+ *
+ * // https://reactnative.dev/docs/performance#enable-the-ram-format
+ * bundleCommand: "ram-bundle",
+ *
+ * // whether to bundle JS and assets in debug mode
+ * bundleInDebug: false,
+ *
+ * // whether to bundle JS and assets in release mode
+ * bundleInRelease: true,
+ *
+ * // whether to bundle JS and assets in another build variant (if configured).
+ * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
+ * // The configuration property can be in the following formats
+ * // 'bundleIn${productFlavor}${buildType}'
+ * // 'bundleIn${buildType}'
+ * // bundleInFreeDebug: true,
+ * // bundleInPaidRelease: true,
+ * // bundleInBeta: true,
+ *
+ * // whether to disable dev mode in custom build variants (by default only disabled in release)
+ * // for example: to disable dev mode in the staging build type (if configured)
+ * devDisabledInStaging: true,
+ * // The configuration property can be in the following formats
+ * // 'devDisabledIn${productFlavor}${buildType}'
+ * // 'devDisabledIn${buildType}'
+ *
+ * // the root of your project, i.e. where "package.json" lives
+ * root: "../../",
+ *
+ * // where to put the JS bundle asset in debug mode
+ * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
+ *
+ * // where to put the JS bundle asset in release mode
+ * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in debug mode
+ * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in release mode
+ * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
+ *
+ * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
+ * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
+ * // date; if you have any other folders that you want to ignore for performance reasons (gradle
+ * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
+ * // for example, you might want to remove it from here.
+ * inputExcludes: ["android/**", "ios/**"],
+ *
+ * // override which node gets called and with what additional arguments
+ * nodeExecutableAndArgs: ["node"],
+ *
+ * // supply additional arguments to the packager
+ * extraPackagerArgs: []
+ * ]
+ */
+
+project.ext.react = [
+ enableHermes: true, // clean and rebuild if changing
+]
+
+apply from: "../../node_modules/react-native/react.gradle"
+
+/**
+ * Set this to true to create two separate APKs instead of one:
+ * - 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
+
+/**
+ * The preferred build flavor of JavaScriptCore.
+ *
+ * For example, to use the international variant, you can use:
+ * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
+ *
+ * The international variant includes ICU i18n library and necessary data
+ * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
+ * give correct results when using with locales other than en-US. Note that
+ * this variant is about 6MiB larger per architecture than default.
+ */
+def jscFlavor = 'org.webkit:android-jsc:+'
+
+/**
+ * Whether to enable the Hermes VM.
+ *
+ * This should be set on project.ext.react and that value will be read here. If it is not set
+ * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
+ * and the benefits of using Hermes will therefore be sharply reduced.
+ */
+def enableHermes = project.ext.react.get("enableHermes", false);
+
+/**
+ * Architectures to build native code for.
+ */
+def reactNativeArchitectures() {
+ def value = project.getProperties().get("reactNativeArchitectures")
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
+}
+
+android {
+ ndkVersion rootProject.ext.ndkVersion
+
+ compileSdkVersion rootProject.ext.compileSdkVersion
+
+ defaultConfig {
+ applicationId "com.laftelvideo"
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+ versionCode 1
+ versionName "1.0"
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
+
+ if (isNewArchitectureEnabled()) {
+ // We configure the CMake build only if you decide to opt-in for the New Architecture.
+ externalNativeBuild {
+ cmake {
+ arguments "-DPROJECT_BUILD_DIR=$buildDir",
+ "-DREACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
+ "-DREACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
+ "-DNODE_MODULES_DIR=$rootDir/../node_modules",
+ "-DANDROID_STL=c++_shared"
+ }
+ }
+ if (!enableSeparateBuildPerCPUArchitecture) {
+ ndk {
+ abiFilters (*reactNativeArchitectures())
+ }
+ }
+ }
+ }
+
+ if (isNewArchitectureEnabled()) {
+ // We configure the NDK build only if you decide to opt-in for the New Architecture.
+ externalNativeBuild {
+ cmake {
+ path "$projectDir/src/main/jni/CMakeLists.txt"
+ }
+ }
+ def reactAndroidProjectDir = project(':ReactAndroid').projectDir
+ def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
+ dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
+ from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
+ into("$buildDir/react-ndk/exported")
+ }
+ def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
+ dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
+ from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
+ into("$buildDir/react-ndk/exported")
+ }
+ afterEvaluate {
+ // If you wish to add a custom TurboModule or component locally,
+ // you should uncomment this line.
+ // preBuild.dependsOn("generateCodegenArtifactsFromSchema")
+ preDebugBuild.dependsOn(packageReactNdkDebugLibs)
+ preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
+
+ // Due to a bug inside AGP, we have to explicitly set a dependency
+ // between configureCMakeDebug* tasks and the preBuild tasks.
+ // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
+ configureCMakeRelWithDebInfo.dependsOn(preReleaseBuild)
+ configureCMakeDebug.dependsOn(preDebugBuild)
+ reactNativeArchitectures().each { architecture ->
+ tasks.findByName("configureCMakeDebug[${architecture}]")?.configure {
+ dependsOn("preDebugBuild")
+ }
+ tasks.findByName("configureCMakeRelWithDebInfo[${architecture}]")?.configure {
+ dependsOn("preReleaseBuild")
+ }
+ }
+ }
+ }
+
+ splits {
+ abi {
+ reset()
+ enable enableSeparateBuildPerCPUArchitecture
+ universalApk false // If true, also generate a universal APK
+ include (*reactNativeArchitectures())
+ }
+ }
+ signingConfigs {
+ debug {
+ storeFile file('debug.keystore')
+ storePassword 'android'
+ keyAlias 'androiddebugkey'
+ keyPassword 'android'
+ }
+ }
+ buildTypes {
+ debug {
+ signingConfig signingConfigs.debug
+ }
+ release {
+ // Caution! In production, you need to generate your own keystore file.
+ // see https://reactnative.dev/docs/signed-apk-android.
+ signingConfig signingConfigs.debug
+ 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:
+ // https://developer.android.com/studio/build/configure-apk-splits.html
+ // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
+ def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
+ def abi = output.getFilter(OutputFile.ABI)
+ if (abi != null) { // null for the universal-debug, universal-release variants
+ output.versionCodeOverride =
+ defaultConfig.versionCode * 1000 + versionCodes.get(abi)
+ }
+
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+
+ //noinspection GradleDynamicVersion
+ implementation "com.facebook.react:react-native:+" // From node_modules
+
+ implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
+
+ debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
+ exclude group:'com.facebook.fbjni'
+ }
+
+ debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
+ exclude group:'com.facebook.flipper'
+ exclude group:'com.squareup.okhttp3', module:'okhttp'
+ }
+
+ debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
+ exclude group:'com.facebook.flipper'
+ }
+
+ if (enableHermes) {
+ //noinspection GradleDynamicVersion
+ implementation("com.facebook.react:hermes-engine:+") { // From node_modules
+ exclude group:'com.facebook.fbjni'
+ }
+ } else {
+ implementation jscFlavor
+ }
+}
+
+if (isNewArchitectureEnabled()) {
+ // If new architecture is enabled, we let you build RN from source
+ // Otherwise we fallback to a prebuilt .aar bundled in the NPM package.
+ // This will be applied to all the imported transtitive dependency.
+ configurations.all {
+ resolutionStrategy.dependencySubstitution {
+ substitute(module("com.facebook.react:react-native"))
+ .using(project(":ReactAndroid"))
+ .because("On New Architecture we're building React Native from source")
+ substitute(module("com.facebook.react:hermes-engine"))
+ .using(project(":ReactAndroid:hermes-engine"))
+ .because("On New Architecture we're building Hermes from source")
+ }
+ }
+}
+
+// Run this once to be able to run the application with BUCK
+// puts all compile dependencies into folder libs for BUCK to use
+task copyDownloadableDepsToLibs(type: Copy) {
+ from configurations.implementation
+ into 'libs'
+}
+
+apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
+
+def isNewArchitectureEnabled() {
+ // To opt-in for the New Architecture, you can either:
+ // - Set `newArchEnabled` to true inside the `gradle.properties` file
+ // - Invoke gradle with `-newArchEnabled=true`
+ // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
+ return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
+}
diff --git a/examples/LaftelVideo/android/app/build_defs.bzl b/examples/LaftelVideo/android/app/build_defs.bzl
new file mode 100644
index 00000000..fff270f8
--- /dev/null
+++ b/examples/LaftelVideo/android/app/build_defs.bzl
@@ -0,0 +1,19 @@
+"""Helper definitions to glob .aar and .jar targets"""
+
+def create_aar_targets(aarfiles):
+ for aarfile in aarfiles:
+ name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
+ lib_deps.append(":" + name)
+ android_prebuilt_aar(
+ name = name,
+ aar = aarfile,
+ )
+
+def create_jar_targets(jarfiles):
+ for jarfile in jarfiles:
+ name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
+ lib_deps.append(":" + name)
+ prebuilt_jar(
+ name = name,
+ binary_jar = jarfile,
+ )
diff --git a/examples/LaftelVideo/android/app/debug.keystore b/examples/LaftelVideo/android/app/debug.keystore
new file mode 100644
index 00000000..364e105e
Binary files /dev/null and b/examples/LaftelVideo/android/app/debug.keystore differ
diff --git a/examples/LaftelVideo/android/app/proguard-rules.pro b/examples/LaftelVideo/android/app/proguard-rules.pro
new file mode 100644
index 00000000..11b02572
--- /dev/null
+++ b/examples/LaftelVideo/android/app/proguard-rules.pro
@@ -0,0 +1,10 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
diff --git a/examples/LaftelVideo/android/app/src/debug/AndroidManifest.xml b/examples/LaftelVideo/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 00000000..4b185bc1
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/examples/LaftelVideo/android/app/src/debug/java/com/laftelvideo/ReactNativeFlipper.java b/examples/LaftelVideo/android/app/src/debug/java/com/laftelvideo/ReactNativeFlipper.java
new file mode 100644
index 00000000..952e8001
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/debug/java/com/laftelvideo/ReactNativeFlipper.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ *
This source code is licensed under the MIT license found in the LICENSE file in the root
+ * directory of this source tree.
+ */
+package com.laftelvideo;
+
+import android.content.Context;
+import com.facebook.flipper.android.AndroidFlipperClient;
+import com.facebook.flipper.android.utils.FlipperUtils;
+import com.facebook.flipper.core.FlipperClient;
+import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
+import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
+import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
+import com.facebook.flipper.plugins.inspector.DescriptorMapping;
+import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
+import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
+import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
+import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
+import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
+import com.facebook.react.ReactInstanceEventListener;
+import com.facebook.react.ReactInstanceManager;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.modules.network.NetworkingModule;
+import okhttp3.OkHttpClient;
+
+public class ReactNativeFlipper {
+ public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
+ if (FlipperUtils.shouldEnableFlipper(context)) {
+ final FlipperClient client = AndroidFlipperClient.getInstance(context);
+
+ client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
+ client.addPlugin(new ReactFlipperPlugin());
+ client.addPlugin(new DatabasesFlipperPlugin(context));
+ client.addPlugin(new SharedPreferencesFlipperPlugin(context));
+ client.addPlugin(CrashReporterPlugin.getInstance());
+
+ NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
+ NetworkingModule.setCustomClientBuilder(
+ new NetworkingModule.CustomClientBuilder() {
+ @Override
+ public void apply(OkHttpClient.Builder builder) {
+ builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
+ }
+ });
+ client.addPlugin(networkFlipperPlugin);
+ client.start();
+
+ // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
+ // Hence we run if after all native modules have been initialized
+ ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
+ if (reactContext == null) {
+ reactInstanceManager.addReactInstanceEventListener(
+ new ReactInstanceEventListener() {
+ @Override
+ public void onReactContextInitialized(ReactContext reactContext) {
+ reactInstanceManager.removeReactInstanceEventListener(this);
+ reactContext.runOnNativeModulesQueueThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ client.addPlugin(new FrescoFlipperPlugin());
+ }
+ });
+ }
+ });
+ } else {
+ client.addPlugin(new FrescoFlipperPlugin());
+ }
+ }
+ }
+}
diff --git a/examples/LaftelVideo/android/app/src/main/AndroidManifest.xml b/examples/LaftelVideo/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..149b936d
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/MainActivity.java b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/MainActivity.java
new file mode 100644
index 00000000..63ea418f
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/MainActivity.java
@@ -0,0 +1,48 @@
+package com.laftelvideo;
+
+import com.facebook.react.ReactActivity;
+import com.facebook.react.ReactActivityDelegate;
+import com.facebook.react.ReactRootView;
+
+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 String getMainComponentName() {
+ return "LaftelVideo";
+ }
+
+ /**
+ * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
+ * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
+ * (Paper).
+ */
+ @Override
+ protected ReactActivityDelegate createReactActivityDelegate() {
+ return new MainActivityDelegate(this, getMainComponentName());
+ }
+
+ public static class MainActivityDelegate extends ReactActivityDelegate {
+ public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
+ super(activity, mainComponentName);
+ }
+
+ @Override
+ protected ReactRootView createRootView() {
+ ReactRootView reactRootView = new ReactRootView(getContext());
+ // If you opted-in for the New Architecture, we enable the Fabric Renderer.
+ reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
+ return reactRootView;
+ }
+
+ @Override
+ protected boolean isConcurrentRootEnabled() {
+ // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
+ // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
+ return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
+ }
+ }
+}
diff --git a/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/MainApplication.java b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/MainApplication.java
new file mode 100644
index 00000000..5ddb2dfa
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/MainApplication.java
@@ -0,0 +1,91 @@
+package com.laftelvideo;
+
+import android.app.Application;
+import android.content.Context;
+import com.facebook.react.PackageList;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactInstanceManager;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.config.ReactFeatureFlags;
+import com.facebook.soloader.SoLoader;
+import com.laftelvideo.newarchitecture.MainApplicationReactNativeHost;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+public class MainApplication extends Application implements ReactApplication {
+
+ private final ReactNativeHost mReactNativeHost =
+ new ReactNativeHost(this) {
+ @Override
+ public boolean getUseDeveloperSupport() {
+ return BuildConfig.DEBUG;
+ }
+
+ @Override
+ protected List getPackages() {
+ @SuppressWarnings("UnnecessaryLocalVariable")
+ List packages = new PackageList(this).getPackages();
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // packages.add(new MyReactNativePackage());
+ return packages;
+ }
+
+ @Override
+ protected String getJSMainModuleName() {
+ return "index";
+ }
+ };
+
+ private final ReactNativeHost mNewArchitectureNativeHost =
+ new MainApplicationReactNativeHost(this);
+
+ @Override
+ public ReactNativeHost getReactNativeHost() {
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ return mNewArchitectureNativeHost;
+ } else {
+ return mReactNativeHost;
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ // If you opted-in for the New Architecture, we enable the TurboModule system
+ ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
+ SoLoader.init(this, /* native exopackage */ false);
+ initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
+ }
+
+ /**
+ * Loads Flipper in React Native templates. Call this in the onCreate method with something like
+ * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
+ *
+ * @param context
+ * @param reactInstanceManager
+ */
+ private static void initializeFlipper(
+ Context context, ReactInstanceManager reactInstanceManager) {
+ if (BuildConfig.DEBUG) {
+ try {
+ /*
+ We use reflection here to pick up the class that initializes Flipper,
+ since Flipper library is not available in release mode
+ */
+ Class> aClass = Class.forName("com.laftelvideo.ReactNativeFlipper");
+ aClass
+ .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
+ .invoke(null, context, reactInstanceManager);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/MainApplicationReactNativeHost.java b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/MainApplicationReactNativeHost.java
new file mode 100644
index 00000000..98fd2193
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/MainApplicationReactNativeHost.java
@@ -0,0 +1,116 @@
+package com.laftelvideo.newarchitecture;
+
+import android.app.Application;
+import androidx.annotation.NonNull;
+import com.facebook.react.PackageList;
+import com.facebook.react.ReactInstanceManager;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
+import com.facebook.react.bridge.JSIModulePackage;
+import com.facebook.react.bridge.JSIModuleProvider;
+import com.facebook.react.bridge.JSIModuleSpec;
+import com.facebook.react.bridge.JSIModuleType;
+import com.facebook.react.bridge.JavaScriptContextHolder;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.UIManager;
+import com.facebook.react.fabric.ComponentFactory;
+import com.facebook.react.fabric.CoreComponentsRegistry;
+import com.facebook.react.fabric.FabricJSIModuleProvider;
+import com.facebook.react.fabric.ReactNativeConfig;
+import com.facebook.react.uimanager.ViewManagerRegistry;
+import com.laftelvideo.BuildConfig;
+import com.laftelvideo.newarchitecture.components.MainComponentsRegistry;
+import com.laftelvideo.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
+ * TurboModule delegates and the Fabric Renderer.
+ *
+ *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
+ * `newArchEnabled` property). Is ignored otherwise.
+ */
+public class MainApplicationReactNativeHost extends ReactNativeHost {
+ public MainApplicationReactNativeHost(Application application) {
+ super(application);
+ }
+
+ @Override
+ public boolean getUseDeveloperSupport() {
+ return BuildConfig.DEBUG;
+ }
+
+ @Override
+ protected List getPackages() {
+ List packages = new PackageList(this).getPackages();
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // packages.add(new MyReactNativePackage());
+ // TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
+ // packages.add(new TurboReactPackage() { ... });
+ // If you have custom Fabric Components, their ViewManagers should also be loaded here
+ // inside a ReactPackage.
+ return packages;
+ }
+
+ @Override
+ protected String getJSMainModuleName() {
+ return "index";
+ }
+
+ @NonNull
+ @Override
+ protected ReactPackageTurboModuleManagerDelegate.Builder
+ getReactPackageTurboModuleManagerDelegateBuilder() {
+ // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
+ // for the new architecture and to use TurboModules correctly.
+ return new MainApplicationTurboModuleManagerDelegate.Builder();
+ }
+
+ @Override
+ protected JSIModulePackage getJSIModulePackage() {
+ return new JSIModulePackage() {
+ @Override
+ public List getJSIModules(
+ final ReactApplicationContext reactApplicationContext,
+ final JavaScriptContextHolder jsContext) {
+ final List specs = new ArrayList<>();
+
+ // Here we provide a new JSIModuleSpec that will be responsible of providing the
+ // custom Fabric Components.
+ specs.add(
+ new JSIModuleSpec() {
+ @Override
+ public JSIModuleType getJSIModuleType() {
+ return JSIModuleType.UIManager;
+ }
+
+ @Override
+ public JSIModuleProvider getJSIModuleProvider() {
+ final ComponentFactory componentFactory = new ComponentFactory();
+ CoreComponentsRegistry.register(componentFactory);
+
+ // Here we register a Components Registry.
+ // The one that is generated with the template contains no components
+ // and just provides you the one from React Native core.
+ MainComponentsRegistry.register(componentFactory);
+
+ final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
+
+ ViewManagerRegistry viewManagerRegistry =
+ new ViewManagerRegistry(
+ reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
+
+ return new FabricJSIModuleProvider(
+ reactApplicationContext,
+ componentFactory,
+ ReactNativeConfig.DEFAULT_CONFIG,
+ viewManagerRegistry);
+ }
+ });
+ return specs;
+ }
+ };
+ }
+}
diff --git a/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/components/MainComponentsRegistry.java b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/components/MainComponentsRegistry.java
new file mode 100644
index 00000000..ffd90b72
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/components/MainComponentsRegistry.java
@@ -0,0 +1,36 @@
+package com.laftelvideo.newarchitecture.components;
+
+import com.facebook.jni.HybridData;
+import com.facebook.proguard.annotations.DoNotStrip;
+import com.facebook.react.fabric.ComponentFactory;
+import com.facebook.soloader.SoLoader;
+
+/**
+ * Class responsible to load the custom Fabric Components. This class has native methods and needs a
+ * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
+ * folder for you).
+ *
+ *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
+ * `newArchEnabled` property). Is ignored otherwise.
+ */
+@DoNotStrip
+public class MainComponentsRegistry {
+ static {
+ SoLoader.loadLibrary("fabricjni");
+ }
+
+ @DoNotStrip private final HybridData mHybridData;
+
+ @DoNotStrip
+ private native HybridData initHybrid(ComponentFactory componentFactory);
+
+ @DoNotStrip
+ private MainComponentsRegistry(ComponentFactory componentFactory) {
+ mHybridData = initHybrid(componentFactory);
+ }
+
+ @DoNotStrip
+ public static MainComponentsRegistry register(ComponentFactory componentFactory) {
+ return new MainComponentsRegistry(componentFactory);
+ }
+}
diff --git a/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java
new file mode 100644
index 00000000..93a8f348
--- /dev/null
+++ b/examples/LaftelVideo/android/app/src/main/java/com/laftelvideo/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java
@@ -0,0 +1,48 @@
+package com.laftelvideo.newarchitecture.modules;
+
+import com.facebook.jni.HybridData;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.soloader.SoLoader;
+import java.util.List;
+
+/**
+ * Class responsible to load the TurboModules. This class has native methods and needs a
+ * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
+ * folder for you).
+ *
+ *