getTurboModule(
27 | const std::string name,
28 | const JavaTurboModule::InitParams ¶ms) override;
29 |
30 | /**
31 | * Test-only method. Allows user to verify whether a TurboModule can be
32 | * created by instances of this class.
33 | */
34 | bool canCreateTurboModule(std::string name);
35 | };
36 |
37 | } // namespace react
38 | } // namespace facebook
39 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/newarchitecture/newarchitecture/components/MainComponentsRegistry.java:
--------------------------------------------------------------------------------
1 | package com.newarchitecture.newarchitecture.components;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.proguard.annotations.DoNotStrip;
5 | import com.facebook.react.fabric.ComponentFactory;
6 | import com.facebook.soloader.SoLoader;
7 |
8 | /**
9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a
10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
11 | * folder for you).
12 | *
13 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
14 | * `newArchEnabled` property). Is ignored otherwise.
15 | */
16 | @DoNotStrip
17 | public class MainComponentsRegistry {
18 | static {
19 | SoLoader.loadLibrary("fabricjni");
20 | }
21 |
22 | @DoNotStrip private final HybridData mHybridData;
23 |
24 | @DoNotStrip
25 | private native HybridData initHybrid(ComponentFactory componentFactory);
26 |
27 | @DoNotStrip
28 | private MainComponentsRegistry(ComponentFactory componentFactory) {
29 | mHybridData = initHybrid(componentFactory);
30 | }
31 |
32 | @DoNotStrip
33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) {
34 | return new MainComponentsRegistry(componentFactory);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ios/RNLottieView/LottieTypes.h:
--------------------------------------------------------------------------------
1 | //
2 | // LottieTypes.h
3 | // animationperftests
4 | //
5 | // Created by Hanno Gödecke on 31.05.22.
6 | //
7 |
8 | #ifndef LottieTypes_h
9 | #define LottieTypes_h
10 |
11 | typedef struct LottieWrapper{
12 | public:
13 | static void convertToCanvasFormat(rlottie::Surface &s);
14 | };
15 |
16 | typedef struct LottieInfo{
17 | ~LottieInfo() {
18 | if (decompressBuffer != nullptr) {
19 | delete[]decompressBuffer;
20 | decompressBuffer = nullptr;
21 | }
22 | }
23 |
24 | public:
25 | std::unique_ptr animation;
26 | size_t frameCount = 0;
27 | int32_t fps = 30;
28 | double_t duration = 0;
29 | bool precache = false;
30 | bool createCache = false;
31 | bool limitFps = false;
32 | std::string path;
33 | std::string cacheFile;
34 | uint8_t *decompressBuffer = nullptr;
35 | uint32_t decompressBufferSize = 0;
36 | volatile uint32_t maxFrameSize = 0;
37 | uint32_t imageSize = 0;
38 | uint32_t fileOffset = 0;
39 | bool nextFrameIsCacheFrame = false;
40 |
41 | FILE *precacheFile = nullptr;
42 | char *compressBuffer = nullptr;
43 | const char *buffer = nullptr;
44 | bool firstFrame = false;
45 | int bufferSize;
46 | int compressBound;
47 | int firstFrameSize;
48 | volatile uint32_t framesAvailableInCache = 0;
49 | };
50 |
51 | #endif /* LottieTypes_h */
52 |
--------------------------------------------------------------------------------
/android/src/newarch/java/nl/skillnation/rlottie/RLottieViewManager.java:
--------------------------------------------------------------------------------
1 | package nl.skillnation.rlottie;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | import com.facebook.react.bridge.ReactApplicationContext;
6 | import com.facebook.react.module.annotations.ReactModule;
7 | import com.facebook.react.uimanager.ViewManagerDelegate;
8 | import com.facebook.react.viewmanagers.RLottieViewManagerDelegate;
9 | import com.facebook.react.viewmanagers.RLottieViewManagerInterface;
10 |
11 | @ReactModule(name = RLottieViewManager.NAME)
12 | public class RLottieViewManager extends RLottieViewManagerImpl
13 | implements RLottieViewManagerInterface {
14 |
15 | public static final String NAME = "RLottieView";
16 |
17 | private final ViewManagerDelegate mDelegate;
18 |
19 | public RLottieViewManager(ReactApplicationContext reactContext) {
20 | super(reactContext);
21 | mDelegate = new RLottieViewManagerDelegate<>(this);
22 | }
23 |
24 | @Nullable
25 | @Override
26 | protected ViewManagerDelegate getDelegate() {
27 | return mDelegate;
28 | }
29 |
30 | @Override
31 | public void setDecodeWidth(RLottieView view, float value) {
32 | this.setDecodeWidth(view, Math.round(value));
33 | }
34 |
35 | @Override
36 | public void setDecodeHeight(RLottieView view, float value) {
37 | this.setDecodeHeight(view, Math.round(value));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/example/src/screens/ManualControlScreen.tsx:
--------------------------------------------------------------------------------
1 | import React, {useRef} from 'react';
2 | import {
3 | View,
4 | StyleSheet,
5 | Dimensions,
6 | Button,
7 | Animated,
8 | Text,
9 | } from 'react-native';
10 | import RLottieView from 'react-native-rlottie';
11 |
12 | const anim = require('../../assets/icon_trophy.json');
13 | const AnimatedRLottieView = Animated.createAnimatedComponent(RLottieView);
14 |
15 | export const ManualControlScreen = () => {
16 | const animation = useRef(new Animated.Value(0)).current;
17 |
18 | const onPressStart = () => {
19 | animation.setValue(0);
20 | Animated.timing(animation, {
21 | toValue: 1,
22 | useNativeDriver: true,
23 | duration: 2000,
24 | }).start();
25 | };
26 |
27 | return (
28 |
29 | Note: This is android only currently 🤖🚫
30 |
36 |
37 |
38 | );
39 | };
40 |
41 | const styles = StyleSheet.create({
42 | container: {
43 | flex: 1,
44 | justifyContent: 'center',
45 | alignItems: 'center',
46 | },
47 | bold: {
48 | fontWeight: 'bold',
49 | fontSize: 18,
50 | },
51 | anim: {
52 | width: Dimensions.get('window').width,
53 | height: Dimensions.get('window').width,
54 | },
55 | });
56 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/newarchitecture/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.newarchitecture;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.ReactRootView;
6 |
7 | public class MainActivity extends ReactActivity {
8 |
9 | /**
10 | * Returns the name of the main component registered from JavaScript. This is used to schedule
11 | * rendering of the component.
12 | */
13 | @Override
14 | protected String getMainComponentName() {
15 | return "NewArchitecture";
16 | }
17 |
18 | /**
19 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
20 | * you can specify the rendered you wish to use (Fabric or the older renderer).
21 | */
22 | @Override
23 | protected ReactActivityDelegate createReactActivityDelegate() {
24 | return new MainActivityDelegate(this, getMainComponentName());
25 | }
26 |
27 | public static class MainActivityDelegate extends ReactActivityDelegate {
28 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
29 | super(activity, mainComponentName);
30 | }
31 |
32 | @Override
33 | protected ReactRootView createRootView() {
34 | ReactRootView reactRootView = new ReactRootView(getContext());
35 | // If you opted-in for the New Architecture, we enable the Fabric Renderer.
36 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
37 | return reactRootView;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/example/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.newarchitecture",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.newarchitecture",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp:
--------------------------------------------------------------------------------
1 | #include "MainApplicationTurboModuleManagerDelegate.h"
2 | #include "MainApplicationModuleProvider.h"
3 |
4 | namespace facebook {
5 | namespace react {
6 |
7 | jni::local_ref
8 | MainApplicationTurboModuleManagerDelegate::initHybrid(
9 | jni::alias_ref) {
10 | return makeCxxInstance();
11 | }
12 |
13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() {
14 | registerHybrid({
15 | makeNativeMethod(
16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
17 | makeNativeMethod(
18 | "canCreateTurboModule",
19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
20 | });
21 | }
22 |
23 | std::shared_ptr
24 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
25 | const std::string name,
26 | const std::shared_ptr jsInvoker) {
27 | // Not implemented yet: provide pure-C++ NativeModules here.
28 | return nullptr;
29 | }
30 |
31 | std::shared_ptr
32 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
33 | const std::string name,
34 | const JavaTurboModule::InitParams ¶ms) {
35 | return MainApplicationModuleProvider(name, params);
36 | }
37 |
38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
39 | std::string name) {
40 | return getTurboModule(name, nullptr) != nullptr ||
41 | getTurboModule(name, {.moduleName = name}) != nullptr;
42 | }
43 |
44 | } // namespace react
45 | } // namespace facebook
46 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "newarchitecture",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "test": "jest",
10 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
11 | },
12 | "dependencies": {
13 | "@react-navigation/native": "^6.0.10",
14 | "@react-navigation/native-stack": "^6.6.2",
15 | "lottie-react-native": "^5.1.3",
16 | "react": "17.0.2",
17 | "react-native": "0.68.2",
18 | "react-native-performance-stats": "^0.2.3",
19 | "react-native-rlottie": "link:../",
20 | "react-native-safe-area-context": "^4.2.5",
21 | "react-native-screens": "^3.13.1",
22 | "react-native-vector-icons": "^9.1.0"
23 | },
24 | "devDependencies": {
25 | "@babel/core": "^7.12.9",
26 | "@babel/runtime": "^7.12.5",
27 | "@react-native-community/eslint-config": "^2.0.0",
28 | "@types/jest": "^26.0.23",
29 | "@types/react-native": "^0.67.8",
30 | "@types/react-native-vector-icons": "^6.4.10",
31 | "@types/react-test-renderer": "^17.0.1",
32 | "@typescript-eslint/eslint-plugin": "^5.17.0",
33 | "@typescript-eslint/parser": "^5.17.0",
34 | "babel-jest": "^26.6.3",
35 | "babel-plugin-module-resolver": "^4.0.0",
36 | "eslint": "^7.32.0",
37 | "jest": "^26.6.3",
38 | "metro-react-native-babel-preset": "^0.67.0",
39 | "react-test-renderer": "17.0.2",
40 | "typescript": "^4.4.4"
41 | },
42 | "resolutions": {
43 | "@types/react": "^17"
44 | },
45 | "jest": {
46 | "preset": "react-native",
47 | "moduleFileExtensions": [
48 | "ts",
49 | "tsx",
50 | "js",
51 | "jsx",
52 | "json",
53 | "node"
54 | ]
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.safeExtGet = {prop, fallback ->
3 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
4 | }
5 | repositories {
6 | google()
7 | gradlePluginPortal()
8 | }
9 | dependencies {
10 | classpath("com.android.tools.build:gradle:7.0.4")
11 | }
12 | }
13 |
14 | def isNewArchitectureEnabled() {
15 | return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
16 | }
17 |
18 | apply plugin: 'com.android.library'
19 | if (isNewArchitectureEnabled()) {
20 | apply plugin: 'com.facebook.react'
21 | }
22 |
23 | android {
24 | compileSdkVersion safeExtGet('compileSdkVersion', 31)
25 |
26 | defaultConfig {
27 | minSdkVersion safeExtGet('minSdkVersion', 21)
28 | targetSdkVersion safeExtGet('targetSdkVersion', 31)
29 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
30 | }
31 |
32 | sourceSets {
33 | main {
34 | if (isNewArchitectureEnabled()) {
35 | java.srcDirs += ['src/newarch']
36 | } else {
37 | java.srcDirs += ['src/oldarch']
38 | }
39 | }
40 | }
41 | }
42 |
43 | repositories {
44 | maven {
45 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
46 | url "$projectDir/../node_modules/react-native/android"
47 | }
48 | mavenCentral()
49 | google()
50 | }
51 |
52 | dependencies {
53 | implementation 'com.facebook.react:react-native:+'
54 | implementation 'io.github.aghajari:AXrLottie:1.3.1'
55 | }
56 |
57 | if (isNewArchitectureEnabled()) {
58 | react {
59 | jsRootDir = file("../src/")
60 | libraryName = "rlottieview"
61 | codegenJavaPackageName = "nl.skillnation.rlottie"
62 | }
63 | }
--------------------------------------------------------------------------------
/react-native-rlottie.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | folly_version = '2021.06.28.00-v2'
6 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
7 | Pod::Spec.new do |s|
8 | s.name = "react-native-rlottie"
9 | s.version = package["version"]
10 | s.summary = package["description"]
11 | s.description = package["description"]
12 | s.homepage = package["homepage"]
13 | s.license = package["license"]
14 | s.platforms = { :ios => "11.0" }
15 | s.author = package["author"]
16 | s.source = { :git => package["repository"], :tag => "#{s.version}" }
17 |
18 | s.source_files = "ios/**/*.{h,m,mm,swift}"
19 |
20 | s.dependency "React-Core"
21 | s.dependency "librlottie"
22 |
23 | # Make c++ header visible to objc++
24 | s.pod_target_xcconfig = {
25 | 'HEADER_SEARCH_PATHS' => '$(inherited) "${PODS_ROOT}/librlottie/include"',
26 | }
27 |
28 | # This guard prevent to install the dependencies when we run `pod install` in the old architecture.
29 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
30 | s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
31 | s.pod_target_xcconfig = {
32 | "HEADER_SEARCH_PATHS" => '"$(PODS_ROOT)/boost" ' +
33 | '"${PODS_ROOT}/librlottie/include"',
34 | "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
35 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
36 | }
37 |
38 | s.dependency "React-RCTFabric"
39 | s.dependency "React-Codegen"
40 | s.dependency "RCT-Folly", folly_version
41 | s.dependency "RCTRequired"
42 | s.dependency "RCTTypeSafety"
43 | s.dependency "ReactCommon/turbomodule/core"
44 | end
45 | end
--------------------------------------------------------------------------------
/example/ios/NewArchitecture/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIAppFonts
6 |
7 | FontAwesome.ttf
8 |
9 | CFBundleDevelopmentRegion
10 | en
11 | CFBundleDisplayName
12 | NewArchitecture
13 | CFBundleExecutable
14 | $(EXECUTABLE_NAME)
15 | CFBundleIdentifier
16 | $(PRODUCT_BUNDLE_IDENTIFIER)
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundleName
20 | $(PRODUCT_NAME)
21 | CFBundlePackageType
22 | APPL
23 | CFBundleShortVersionString
24 | 1.0
25 | CFBundleSignature
26 | ????
27 | CFBundleVersion
28 | 1
29 | LSRequiresIPhoneOS
30 |
31 | NSAppTransportSecurity
32 |
33 | NSExceptionDomains
34 |
35 | localhost
36 |
37 | NSExceptionAllowsInsecureHTTPLoads
38 |
39 |
40 |
41 |
42 | NSLocationWhenInUseUsageDescription
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIRequiredDeviceCapabilities
47 |
48 | armv7
49 |
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 | UIViewControllerBasedStatusBarAppearance
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.125.0
29 |
30 | # Use this property to specify which architecture you want to build.
31 | # You can also override it from the CLI using
32 | # ./gradlew -PreactNativeArchitectures=x86_64
33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
34 |
35 | # Use this property to enable support to the new architecture.
36 | # This will allow you to use TurboModules and the Fabric render in
37 | # your application. You should enable this flag either if you want
38 | # to write custom TurboModules/Fabric components OR use libraries that
39 | # are providing them.
40 | newArchEnabled=true
41 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | import org.apache.tools.ant.taskdefs.condition.Os
2 |
3 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
4 |
5 | buildscript {
6 | ext {
7 | buildToolsVersion = "31.0.0"
8 | minSdkVersion = 21
9 | compileSdkVersion = 31
10 | targetSdkVersion = 31
11 |
12 | if (System.properties['os.arch'] == "aarch64") {
13 | // For M1 Users we need to use the NDK 24 which added support for aarch64
14 | ndkVersion = "24.0.8215888"
15 | } else {
16 | // Otherwise we default to the side-by-side NDK version from AGP.
17 | ndkVersion = "21.4.7075529"
18 | }
19 | }
20 | repositories {
21 | google()
22 | mavenCentral()
23 | }
24 | dependencies {
25 | classpath("com.android.tools.build:gradle:7.0.4")
26 | classpath("com.facebook.react:react-native-gradle-plugin")
27 | classpath("de.undercouch:gradle-download-task:4.1.2")
28 | // NOTE: Do not place your application dependencies here; they belong
29 | // in the individual module build.gradle files
30 | }
31 | }
32 |
33 | allprojects {
34 | repositories {
35 | maven {
36 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
37 | url("$rootDir/../node_modules/react-native/android")
38 | }
39 | maven {
40 | // Android JSC is installed from npm
41 | url("$rootDir/../node_modules/jsc-android/dist")
42 | }
43 | mavenCentral {
44 | // We don't want to fetch react-native from Maven Central as there are
45 | // older versions over there.
46 | content {
47 | excludeGroup "com.facebook.react"
48 | }
49 | }
50 | google()
51 | maven { url 'https://www.jitpack.io' }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/example/src/components/PerformanceScreen.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {useState} from 'react';
3 | import {View, Button, StyleSheet, Dimensions} from 'react-native';
4 | import PerformanceStats, {
5 | PerformanceStatsData,
6 | } from 'react-native-performance-stats';
7 |
8 | const anim = require('../../assets/icon_trophy.json');
9 |
10 | type Props = {
11 | LottieComponent: React.ComponentType<{
12 | style?: any;
13 | source: any;
14 | autoPlay?: boolean;
15 | }>;
16 | };
17 |
18 | export const PerformanceScreen: React.FC = ({LottieComponent}) => {
19 | const [showAnim, setShowAnim] = useState(false);
20 |
21 | const onPressStart = () => {
22 | console.log('Start performance measurement: base');
23 | let phase = 'BASE';
24 | const perfData: (PerformanceStatsData & {phase: string})[] = [];
25 | PerformanceStats.addListener(data => {
26 | perfData.push({
27 | phase,
28 | // @ts-expect-error doesn't know performance
29 | time: performance.now(),
30 | ...data,
31 | });
32 | });
33 |
34 | PerformanceStats.start(true);
35 |
36 | setTimeout(() => {
37 | phase = 'animation_running';
38 | console.log('Performance measurement: running');
39 | setShowAnim(true);
40 | setTimeout(() => {
41 | PerformanceStats.stop();
42 | setShowAnim(false);
43 | console.log(perfData);
44 | }, 10000);
45 | }, 5000);
46 | };
47 |
48 | return (
49 |
50 |
51 | {showAnim && (
52 |
53 | )}
54 |
55 | );
56 | };
57 |
58 | const styles = StyleSheet.create({
59 | container: {
60 | flex: 1,
61 | justifyContent: 'center',
62 | alignItems: 'center',
63 | },
64 | anim: {
65 | width: Dimensions.get('window').width,
66 | height: Dimensions.get('window').width,
67 | },
68 | });
69 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/newarchitecture/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java:
--------------------------------------------------------------------------------
1 | package com.newarchitecture.newarchitecture.modules;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.react.ReactPackage;
5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.soloader.SoLoader;
8 | import java.util.List;
9 |
10 | /**
11 | * Class responsible to load the TurboModules. This class has native methods and needs a
12 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
13 | * folder for you).
14 | *
15 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
16 | * `newArchEnabled` property). Is ignored otherwise.
17 | */
18 | public class MainApplicationTurboModuleManagerDelegate
19 | extends ReactPackageTurboModuleManagerDelegate {
20 |
21 | private static volatile boolean sIsSoLibraryLoaded;
22 |
23 | protected MainApplicationTurboModuleManagerDelegate(
24 | ReactApplicationContext reactApplicationContext, List packages) {
25 | super(reactApplicationContext, packages);
26 | }
27 |
28 | protected native HybridData initHybrid();
29 |
30 | native boolean canCreateTurboModule(String moduleName);
31 |
32 | public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
33 | protected MainApplicationTurboModuleManagerDelegate build(
34 | ReactApplicationContext context, List packages) {
35 | return new MainApplicationTurboModuleManagerDelegate(context, packages);
36 | }
37 | }
38 |
39 | @Override
40 | protected synchronized void maybeLoadOtherSoLibraries() {
41 | if (!sIsSoLibraryLoaded) {
42 | // If you change the name of your application .so file in the Android.mk file,
43 | // make sure you update the name here as well.
44 | SoLoader.loadLibrary("newarchitecture_appmodules");
45 | sIsSoLibraryLoaded = true;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | THIS_DIR := $(call my-dir)
2 |
3 | include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
4 |
5 | # If you wish to add a custom TurboModule or Fabric component in your app you
6 | # will have to include the following autogenerated makefile.
7 | # include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
8 |
9 | # Includes the MK file for `react-native-rlottie`
10 | include $(NODE_MODULES_DIR)/react-native-rlottie/android/build/generated/source/codegen/jni/Android.mk
11 | include $(NODE_MODULES_DIR)/react-native-performance-stats/android/build/generated/source/codegen/jni/Android.mk
12 |
13 | include $(CLEAR_VARS)
14 |
15 | LOCAL_PATH := $(THIS_DIR)
16 |
17 | # You can customize the name of your application .so file here.
18 | LOCAL_MODULE := newarchitecture_appmodules
19 |
20 | LOCAL_C_INCLUDES := $(LOCAL_PATH)
21 | LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
22 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
23 |
24 | # If you wish to add a custom TurboModule or Fabric component in your app you
25 | # will have to uncomment those lines to include the generated source
26 | # files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
27 | #
28 | # LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
29 | # LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
30 | # LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
31 |
32 | # Here you should add any native library you wish to depend on.
33 | LOCAL_SHARED_LIBRARIES := \
34 | libfabricjni \
35 | libfbjni \
36 | libfolly_futures \
37 | libfolly_json \
38 | libglog \
39 | libjsi \
40 | libreact_codegen_rncore \
41 | libreact_codegen_rlottieview \
42 | libreact_codegen_performancestats \
43 | libreact_debug \
44 | libreact_nativemodule_core \
45 | libreact_render_componentregistry \
46 | libreact_render_core \
47 | libreact_render_debug \
48 | libreact_render_graphics \
49 | librrc_view \
50 | libruntimeexecutor \
51 | libturbomodulejsijni \
52 | libyoga
53 |
54 | LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall
55 |
56 | include $(BUILD_SHARED_LIBRARY)
57 |
--------------------------------------------------------------------------------
/example/ios/NewArchitectureTests/NewArchitectureTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface NewArchitectureTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation NewArchitectureTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(
38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
39 | if (level >= RCTLogLevelError) {
40 | redboxError = message;
41 | }
42 | });
43 | #endif
44 |
45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
48 |
49 | foundElement = [self findSubviewInView:vc.view
50 | matching:^BOOL(UIView *view) {
51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
52 | return YES;
53 | }
54 | return NO;
55 | }];
56 | }
57 |
58 | #ifdef DEBUG
59 | RCTSetLogFunction(RCTDefaultLogFunction);
60 | #endif
61 |
62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainComponentsRegistry.cpp:
--------------------------------------------------------------------------------
1 | #include "MainComponentsRegistry.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace facebook {
10 | namespace react {
11 |
12 | MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
13 |
14 | std::shared_ptr
15 | MainComponentsRegistry::sharedProviderRegistry() {
16 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
17 |
18 | // Custom Fabric Components go here. You can register custom
19 | // components coming from your App or from 3rd party libraries here.
20 | //
21 | // providerRegistry->add(concreteComponentDescriptorProvider<
22 | // AocViewerComponentDescriptor>());
23 | providerRegistry->add(concreteComponentDescriptorProvider());
24 | return providerRegistry;
25 | }
26 |
27 | jni::local_ref
28 | MainComponentsRegistry::initHybrid(
29 | jni::alias_ref,
30 | ComponentFactory *delegate) {
31 | auto instance = makeCxxInstance(delegate);
32 |
33 | auto buildRegistryFunction =
34 | [](EventDispatcher::Weak const &eventDispatcher,
35 | ContextContainer::Shared const &contextContainer)
36 | -> ComponentDescriptorRegistry::Shared {
37 | auto registry = MainComponentsRegistry::sharedProviderRegistry()
38 | ->createComponentDescriptorRegistry(
39 | {eventDispatcher, contextContainer});
40 |
41 | auto mutableRegistry =
42 | std::const_pointer_cast(registry);
43 |
44 | mutableRegistry->setFallbackComponentDescriptor(
45 | std::make_shared(
46 | ComponentDescriptorParameters{
47 | eventDispatcher, contextContainer, nullptr}));
48 |
49 | return registry;
50 | };
51 |
52 | delegate->buildRegistryFunction = buildRegistryFunction;
53 | return instance;
54 | }
55 |
56 | void MainComponentsRegistry::registerNatives() {
57 | registerHybrid({
58 | makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
59 | });
60 | }
61 |
62 | } // namespace react
63 | } // namespace facebook
64 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/android/src/main/java/nl/skillnation/rlottie/RLottieViewManagerImpl.java:
--------------------------------------------------------------------------------
1 | package nl.skillnation.rlottie;
2 |
3 | import android.widget.ImageView;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | import com.aghajari.rlottie.AXrLottie;
8 | import com.facebook.react.bridge.ReactApplicationContext;
9 | import com.facebook.react.uimanager.SimpleViewManager;
10 | import com.facebook.react.uimanager.ThemedReactContext;
11 | import com.facebook.react.uimanager.annotations.ReactProp;
12 |
13 | public class RLottieViewManagerImpl extends SimpleViewManager {
14 |
15 | public static final String NAME = "RLottieView";
16 |
17 | protected ReactApplicationContext mCallerContext;
18 |
19 | public RLottieViewManagerImpl(ReactApplicationContext reactContext) {
20 | mCallerContext = reactContext;
21 | AXrLottie.init(reactContext);
22 | }
23 |
24 | @NonNull
25 | @Override
26 | public String getName() {
27 | return NAME;
28 | }
29 |
30 | @NonNull
31 | @Override
32 | protected RLottieView createViewInstance(@NonNull ThemedReactContext context) {
33 | return new RLottieView(context);
34 | }
35 |
36 | @ReactProp(name="isAutoPlay")
37 | public void setIsAutoPlay(RLottieView view, boolean isAutoPlay) {
38 | view.setAutoPlay(isAutoPlay);
39 | }
40 |
41 | @ReactProp(name="src")
42 | public void setSrc(RLottieView view, String jsonString) {
43 | view.setJSONStringSource(jsonString);
44 | }
45 |
46 | @ReactProp(name="progress")
47 | public void setProgress(RLottieView view, float progress) {
48 | if (view == null || view.getLottieDrawable() == null) return; // TODO: With new arch setProgress isn't called (thus the animation isn't running)
49 | view.getLottieDrawable().setProgress(progress);
50 | }
51 |
52 | @ReactProp(name="decodeHeight")
53 | public void setDecodeHeight(RLottieView view, int height) {
54 | view.setDecodeHeight(height);
55 | }
56 |
57 | @ReactProp(name="decodeWidth")
58 | public void setDecodeWidth(RLottieView view, int width) {
59 | view.setDecodeWidth(width);
60 | }
61 |
62 | @ReactProp(name="resizeMode")
63 | public void setResizeMode(RLottieView view, String resizeMode) {
64 | ImageView.ScaleType mode = null;
65 | if ("cover".equals(resizeMode)) {
66 | mode = ImageView.ScaleType.CENTER_CROP;
67 | } else if ("contain".equals(resizeMode)) {
68 | mode = ImageView.ScaleType.CENTER;
69 | } else if ("center".equals(resizeMode)) {
70 | mode = ImageView.ScaleType.CENTER_INSIDE;
71 | }
72 | view.setScaleType(mode);
73 | }
74 |
75 | @ReactProp(name="loop")
76 | public void setLoop(RLottieView view, boolean loop) {
77 | view.setIsLoop(loop);
78 | }
79 |
80 | @ReactProp(name="speed")
81 | public void setSpeed(RLottieView view, float speed) {
82 | view.setSpeed(speed);
83 | }
84 |
85 | @Override
86 | public void onDropViewInstance(@NonNull RLottieView view) {
87 | super.onDropViewInstance(view);
88 | view.release();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/newarchitecture/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.newarchitecture;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.react.config.ReactFeatureFlags;
11 | import com.facebook.soloader.SoLoader;
12 | import com.newarchitecture.newarchitecture.MainApplicationReactNativeHost;
13 | import java.lang.reflect.InvocationTargetException;
14 | import java.util.List;
15 |
16 | public class MainApplication extends Application implements ReactApplication {
17 |
18 | private final ReactNativeHost mReactNativeHost =
19 | new ReactNativeHost(this) {
20 | @Override
21 | public boolean getUseDeveloperSupport() {
22 | return BuildConfig.DEBUG;
23 | }
24 |
25 | @Override
26 | protected List getPackages() {
27 | @SuppressWarnings("UnnecessaryLocalVariable")
28 | List packages = new PackageList(this).getPackages();
29 | // Packages that cannot be autolinked yet can be added manually here, for example:
30 | // packages.add(new MyReactNativePackage());
31 | return packages;
32 | }
33 |
34 | @Override
35 | protected String getJSMainModuleName() {
36 | return "index";
37 | }
38 | };
39 |
40 | private final ReactNativeHost mNewArchitectureNativeHost =
41 | new MainApplicationReactNativeHost(this);
42 |
43 | @Override
44 | public ReactNativeHost getReactNativeHost() {
45 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
46 | return mNewArchitectureNativeHost;
47 | } else {
48 | return mReactNativeHost;
49 | }
50 | }
51 |
52 | @Override
53 | public void onCreate() {
54 | super.onCreate();
55 | // If you opted-in for the New Architecture, we enable the TurboModule system
56 | ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
57 | SoLoader.init(this, /* native exopackage */ false);
58 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
59 | }
60 |
61 | /**
62 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like
63 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
64 | *
65 | * @param context
66 | * @param reactInstanceManager
67 | */
68 | private static void initializeFlipper(
69 | Context context, ReactInstanceManager reactInstanceManager) {
70 | if (BuildConfig.DEBUG) {
71 | try {
72 | /*
73 | We use reflection here to pick up the class that initializes Flipper,
74 | since Flipper library is not available in release mode
75 | */
76 | Class> aClass = Class.forName("com.newarchitecture.ReactNativeFlipper");
77 | aClass
78 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
79 | .invoke(null, context, reactInstanceManager);
80 | } catch (ClassNotFoundException e) {
81 | e.printStackTrace();
82 | } catch (NoSuchMethodException e) {
83 | e.printStackTrace();
84 | } catch (IllegalAccessException e) {
85 | e.printStackTrace();
86 | } catch (InvocationTargetException e) {
87 | e.printStackTrace();
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/java/com/newarchitecture/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.newarchitecture;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceEventListener;
23 | import com.facebook.react.ReactInstanceManager;
24 | import com.facebook.react.bridge.ReactContext;
25 | import com.facebook.react.modules.network.NetworkingModule;
26 | import okhttp3.OkHttpClient;
27 |
28 | public class ReactNativeFlipper {
29 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
30 | if (FlipperUtils.shouldEnableFlipper(context)) {
31 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
32 |
33 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
34 | client.addPlugin(new ReactFlipperPlugin());
35 | client.addPlugin(new DatabasesFlipperPlugin(context));
36 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
37 | client.addPlugin(CrashReporterPlugin.getInstance());
38 |
39 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
40 | NetworkingModule.setCustomClientBuilder(
41 | new NetworkingModule.CustomClientBuilder() {
42 | @Override
43 | public void apply(OkHttpClient.Builder builder) {
44 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
45 | }
46 | });
47 | client.addPlugin(networkFlipperPlugin);
48 | client.start();
49 |
50 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
51 | // Hence we run if after all native modules have been initialized
52 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
53 | if (reactContext == null) {
54 | reactInstanceManager.addReactInstanceEventListener(
55 | new ReactInstanceEventListener() {
56 | @Override
57 | public void onReactContextInitialized(ReactContext reactContext) {
58 | reactInstanceManager.removeReactInstanceEventListener(this);
59 | reactContext.runOnNativeModulesQueueThread(
60 | new Runnable() {
61 | @Override
62 | public void run() {
63 | client.addPlugin(new FrescoFlipperPlugin());
64 | }
65 | });
66 | }
67 | });
68 | } else {
69 | client.addPlugin(new FrescoFlipperPlugin());
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-rlottie",
3 | "version": "0.1.0-alpha.3",
4 | "description": "RLottie for react native",
5 | "react-native": "src/index.tsx",
6 | "source": "src/index",
7 | "main": "lib/commonjs/index.js",
8 | "module": "lib/module/index.js",
9 | "types": "lib/typescript/index.d.ts",
10 | "files": [
11 | "src",
12 | "lib",
13 | "!**/__tests__",
14 | "!**/__fixtures__",
15 | "!**/__mocks__",
16 | "android",
17 | "ios",
18 | "react-native-rlottie.podspec",
19 | "!android/build",
20 | "!ios/build"
21 | ],
22 | "scripts": {
23 | "typescript": "tsc --noEmit",
24 | "prepare": "bob build",
25 | "release": "release-it",
26 | "lint": "eslint \"**/*.{js,ts,tsx}\""
27 | },
28 | "keywords": [
29 | "react-native",
30 | "ios",
31 | "android",
32 | "rlottie",
33 | "react-native-rlottie"
34 | ],
35 | "repository": "https://github.com/skillnation/react-native-rlottie",
36 | "author": "Hanno Goedecke die.drei99@yahoo.de (https://github.com/hannojg)",
37 | "license": "MIT",
38 | "bugs": {
39 | "url": "https://github.com/skillnation/react-native-rlottie/issues"
40 | },
41 | "homepage": "https://github.com/skillnation/react-native-rlottie#readme",
42 | "devDependencies": {
43 | "@commitlint/config-conventional": "^11.0.0",
44 | "@react-native-community/eslint-config": "^2.0.0",
45 | "@release-it/conventional-changelog": "^2.0.0",
46 | "@types/jest": "^26.0.0",
47 | "@types/react": "^16.9.19",
48 | "@types/react-native": "0.62.13",
49 | "commitlint": "^11.0.0",
50 | "eslint": "^7.2.0",
51 | "eslint-config-prettier": "^7.0.0",
52 | "eslint-plugin-prettier": "^3.1.3",
53 | "prettier": "^2.0.5",
54 | "react-native": "^0.68.2",
55 | "react-native-builder-bob": "^0.18.2",
56 | "release-it": "^14.2.2",
57 | "typescript": "^4.1.3"
58 | },
59 | "publishConfig": {
60 | "access": "public",
61 | "registry": "https://registry.npmjs.org"
62 | },
63 | "peerDependencies": {
64 | "react": "*",
65 | "react-native": "*"
66 | },
67 | "codegenConfig": {
68 | "libraries": [
69 | {
70 | "name": "RLottieViewSpec",
71 | "type": "components",
72 | "jsSrcsDir": "src"
73 | }
74 | ]
75 | },
76 | "react-native-builder-bob": {
77 | "source": "src",
78 | "output": "lib",
79 | "targets": [
80 | "commonjs",
81 | "module",
82 | [
83 | "typescript",
84 | {
85 | "project": "tsconfig.build.json"
86 | }
87 | ]
88 | ]
89 | },
90 | "eslintIgnore": [
91 | "node_modules/",
92 | "lib/"
93 | ],
94 | "commitlint": {
95 | "extends": [
96 | "@commitlint/config-conventional"
97 | ]
98 | },
99 | "release-it": {
100 | "git": {
101 | "commitMessage": "chore: release ${version}",
102 | "tagName": "v${version}"
103 | },
104 | "npm": {
105 | "publish": true
106 | },
107 | "github": {
108 | "release": true
109 | },
110 | "plugins": {
111 | "@release-it/conventional-changelog": {
112 | "preset": "angular"
113 | }
114 | }
115 | },
116 | "eslintConfig": {
117 | "root": true,
118 | "extends": [
119 | "@react-native-community",
120 | "prettier"
121 | ],
122 | "rules": {
123 | "prettier/prettier": [
124 | "error",
125 | {
126 | "quoteProps": "consistent",
127 | "singleQuote": true,
128 | "tabWidth": 2,
129 | "trailingComma": "es5",
130 | "useTabs": false
131 | }
132 | ]
133 | }
134 | },
135 | "prettier": {
136 | "quoteProps": "consistent",
137 | "singleQuote": true,
138 | "tabWidth": 2,
139 | "trailingComma": "es5",
140 | "useTabs": false
141 | },
142 | "resolutions": {
143 | "@types/react": "17.0.2",
144 | "@types/react-dom": "17.0.2"
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/android/src/main/java/nl/skillnation/rlottie/RLottieView.java:
--------------------------------------------------------------------------------
1 | package nl.skillnation.rlottie;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.Nullable;
8 |
9 | import com.aghajari.rlottie.AXrLottieDrawable;
10 | import com.aghajari.rlottie.AXrLottieImageView;
11 |
12 | public class RLottieView extends AXrLottieImageView {
13 | private boolean isAutoPlay = false;
14 | private float speed = 1.0f;
15 |
16 | private int decodeWidth, decodeHeight;
17 | private String jsonString;
18 | private boolean isInit;
19 |
20 | public RLottieView(@NonNull Context context) {
21 | super(context);
22 | }
23 |
24 | public RLottieView(@NonNull Context context, @Nullable AttributeSet attrs) {
25 | super(context, attrs);
26 | }
27 |
28 | public RLottieView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
29 | super(context, attrs, defStyleAttr);
30 | }
31 |
32 | //#region Layout size
33 | @Override
34 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
35 | super.onLayout(changed, left, top, right, bottom);
36 | if (decodeWidth == 0) {
37 | decodeWidth = getWidth();
38 | }
39 | if (decodeHeight == 0) {
40 | decodeHeight = getHeight();
41 | }
42 |
43 | maybeInitAnimation();
44 | }
45 |
46 | public void setDecodeWidth(int decodeWidth) {
47 | this.decodeWidth = decodeWidth;
48 | maybeInitAnimation();
49 | }
50 |
51 | public void setDecodeHeight(int decodeHeight) {
52 | this.decodeHeight = decodeHeight;
53 | maybeInitAnimation();
54 | }
55 | //#endregion
56 |
57 | //#region Animation
58 | public void setJSONStringSource(String jsonString) {
59 | this.jsonString = jsonString;
60 | maybeInitAnimation();
61 | }
62 |
63 | private String getCacheKey() {
64 | if (jsonString == null || decodeWidth == 0 || decodeHeight == 0) {
65 | return null;
66 | }
67 | return jsonString.hashCode() + "-" + decodeWidth + "-" + decodeHeight;
68 | }
69 |
70 | private void maybeInitAnimation() {
71 | if (isInit) return;
72 | String cacheKey = getCacheKey();
73 | if (cacheKey == null) return;
74 | isInit = true;
75 |
76 | setLottieDrawable(
77 | AXrLottieDrawable.fromJson(jsonString, cacheKey)
78 | .setSize(decodeWidth, decodeHeight)
79 | .setSpeed(speed)
80 | .build()
81 | );
82 |
83 | maybeAutoStartAnimation();
84 | }
85 | //#endregion
86 |
87 | //#region AutoStart
88 | public void setAutoPlay(boolean autoPlay) {
89 | isAutoPlay = autoPlay;
90 | maybeAutoStartAnimation();
91 | if (!autoPlay && isInit && getLottieDrawable() != null && !getLottieDrawable().isRunning()) {
92 | this.stopAnimation();
93 | }
94 | }
95 |
96 | private void maybeAutoStartAnimation() {
97 | if (isAutoPlay && getLottieDrawable() != null && !getLottieDrawable().isRunning()) {
98 | playAnimation();
99 | }
100 | }
101 | //#endregion
102 |
103 | //#region Properties: Loop, speed
104 | public void setIsLoop(boolean loop) {
105 | super.setAutoRepeat(loop);
106 | if (getLottieDrawable() != null) {
107 | if (!loop) {
108 | stopAnimation();
109 | }
110 |
111 | isInit = false;
112 | maybeInitAnimation();
113 | }
114 | }
115 |
116 | public void setSpeed(float speed) {
117 | this.speed = speed;
118 | if (getLottieDrawable() != null) {
119 | if (speed <= 0) {
120 | stopAnimation();
121 | } else {
122 | isInit = false;
123 | maybeInitAnimation();
124 | }
125 | }
126 | }
127 | //#endregion
128 | }
129 |
--------------------------------------------------------------------------------
/example/ios/NewArchitecture/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #import
8 |
9 | #if RCT_NEW_ARCH_ENABLED
10 | #import
11 | #import
12 | #import
13 | #import
14 | #import
15 | #import
16 |
17 | #import
18 |
19 | @interface AppDelegate () {
20 | RCTTurboModuleManager *_turboModuleManager;
21 | RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
22 | std::shared_ptr _reactNativeConfig;
23 | facebook::react::ContextContainer::Shared _contextContainer;
24 | }
25 | @end
26 | #endif
27 |
28 | @implementation AppDelegate
29 |
30 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
31 | {
32 | RCTAppSetupPrepareApp(application);
33 |
34 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
35 |
36 | #if RCT_NEW_ARCH_ENABLED
37 | _contextContainer = std::make_shared();
38 | _reactNativeConfig = std::make_shared();
39 | _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
40 | _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
41 | bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
42 | #endif
43 |
44 | UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"NewArchitecture", nil);
45 |
46 | if (@available(iOS 13.0, *)) {
47 | rootView.backgroundColor = [UIColor systemBackgroundColor];
48 | } else {
49 | rootView.backgroundColor = [UIColor whiteColor];
50 | }
51 |
52 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
53 | UIViewController *rootViewController = [UIViewController new];
54 | rootViewController.view = rootView;
55 | self.window.rootViewController = rootViewController;
56 | [self.window makeKeyAndVisible];
57 | return YES;
58 | }
59 |
60 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
61 | {
62 | #if DEBUG
63 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
64 | #else
65 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
66 | #endif
67 | }
68 |
69 | #if RCT_NEW_ARCH_ENABLED
70 |
71 | #pragma mark - RCTCxxBridgeDelegate
72 |
73 | - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge
74 | {
75 | _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
76 | delegate:self
77 | jsInvoker:bridge.jsCallInvoker];
78 | return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
79 | }
80 |
81 | #pragma mark RCTTurboModuleManagerDelegate
82 |
83 | - (Class)getModuleClassFromName:(const char *)name
84 | {
85 | return RCTCoreModulesClassProvider(name);
86 | }
87 |
88 | - (std::shared_ptr)getTurboModule:(const std::string &)name
89 | jsInvoker:(std::shared_ptr)jsInvoker
90 | {
91 | return nullptr;
92 | }
93 |
94 | - (std::shared_ptr)getTurboModule:(const std::string &)name
95 | initParams:
96 | (const facebook::react::ObjCTurboModule::InitParams &)params
97 | {
98 | return nullptr;
99 | }
100 |
101 | - (id)getModuleInstanceFromClass:(Class)moduleClass
102 | {
103 | return RCTAppSetupDefaultModuleFromClass(moduleClass);
104 | }
105 |
106 | #endif
107 |
108 | @end
109 |
--------------------------------------------------------------------------------
/example/ios/NewArchitecture/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | Animated,
4 | requireNativeComponent,
5 | ViewProps,
6 | Platform,
7 | StyleProp,
8 | ViewStyle,
9 | PixelRatio,
10 | StyleSheet,
11 | View,
12 | } from 'react-native';
13 |
14 | // @ts-expect-error
15 | const isFabricEnabled = global.nativeFabricUIManager != null;
16 |
17 | export type RLottieViewProps = ViewProps & {
18 | source: string; // TODO: support "AnimationObject | { uri: string }" as well;
19 | /**
20 | * @default true
21 | */
22 | autoPlay?: boolean;
23 | autoSize?: boolean;
24 | loop?: boolean;
25 | resizeMode?: 'contain' | 'cover' | 'center';
26 | /**
27 | * @default 1.0
28 | */
29 | speed?: number;
30 | progress?: number | Animated.Value | Animated.AnimatedInterpolation;
31 | /**
32 | * This is the size the animation is going to get decoded to bitmap with.
33 | * Setting this ensures the component renders as fast as possible, as we
34 | * internally don't have to wait for a measure.
35 | *
36 | * By default, if you set a numeric height/width in the styles of the view,
37 | * it will use these as values.
38 | *
39 | * You can also set this to a lower or higher value than the actual view's
40 | * size to increase or decrease quality of the animation.
41 | * (Lower size decodes faster and more effortlessly)
42 | */
43 | decodeWidth?: number;
44 | /**
45 | * Same as {@see decodeWidth} but for height.
46 | */
47 | decodeHeight?: number;
48 | };
49 |
50 | const NativeRLottieView = isFabricEnabled
51 | ? require('./RLottieViewNativeComponent').default
52 | : requireNativeComponent('RLottieView');
53 |
54 | const LINKING_ERROR =
55 | `The package 'react-native-rlottie' doesn't seem to be linked. Make sure: \n\n` +
56 | Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
57 | '- You rebuilt the app after installing the package\n' +
58 | '- You are not using Expo managed workflow\n';
59 |
60 | if (NativeRLottieView == null) {
61 | throw new Error(LINKING_ERROR);
62 | }
63 |
64 | const getSizeFromStyles = (
65 | style: StyleProp,
66 | property: 'width' | 'height'
67 | ) => {
68 | if (
69 | typeof style === 'object' &&
70 | style != null &&
71 | property in style &&
72 | // @ts-expect-error typings for StyleProp<> are really hard
73 | typeof style[property] === 'number'
74 | ) {
75 | // @ts-expect-error typings for StyleProp<> are really hard
76 | return style[property];
77 | }
78 | };
79 |
80 | const maybeApplyPixelRatio = (x?: number) =>
81 | x != null ? PixelRatio.getPixelSizeForLayoutSize(x) : undefined;
82 |
83 | export default class RLottieView extends React.PureComponent {
84 | static displayName = 'RLottieView';
85 |
86 | constructor(props: RLottieViewProps) {
87 | super(props);
88 | }
89 |
90 | render() {
91 | const {
92 | source,
93 | loop = true,
94 | autoPlay = true,
95 | autoSize = false,
96 | resizeMode = 'contain',
97 | style,
98 | decodeWidth,
99 | decodeHeight,
100 | ...otherProps
101 | } = this.props;
102 |
103 | const sourceJson =
104 | typeof source === 'object' ? JSON.stringify(source) : source;
105 |
106 | const aspectRatioStyle =
107 | typeof source === 'object'
108 | ? // @ts-expect-error Can't type the incoming JSON
109 | { aspectRatio: source.w / source.h }
110 | : undefined;
111 | const styleObject = StyleSheet.flatten(style);
112 | let sizeStyle;
113 | if (
114 | !styleObject ||
115 | (styleObject.width === undefined && styleObject.height === undefined)
116 | ) {
117 | sizeStyle =
118 | // @ts-expect-error Can't type the incoming JSON
119 | autoSize && sourceJson ? { width: source.w } : StyleSheet.absoluteFill;
120 | }
121 |
122 | const _decodeWidth = maybeApplyPixelRatio(
123 | decodeWidth ?? getSizeFromStyles(style, 'width')
124 | );
125 | const _decodeHeight = maybeApplyPixelRatio(
126 | decodeHeight ?? getSizeFromStyles(style, 'height')
127 | );
128 |
129 | return (
130 |
131 |
145 |
146 | );
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/newarchitecture/newarchitecture/MainApplicationReactNativeHost.java:
--------------------------------------------------------------------------------
1 | package com.newarchitecture.newarchitecture;
2 |
3 | import android.app.Application;
4 | import androidx.annotation.NonNull;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactInstanceManager;
7 | import com.facebook.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
10 | import com.facebook.react.bridge.JSIModulePackage;
11 | import com.facebook.react.bridge.JSIModuleProvider;
12 | import com.facebook.react.bridge.JSIModuleSpec;
13 | import com.facebook.react.bridge.JSIModuleType;
14 | import com.facebook.react.bridge.JavaScriptContextHolder;
15 | import com.facebook.react.bridge.ReactApplicationContext;
16 | import com.facebook.react.bridge.UIManager;
17 | import com.facebook.react.fabric.ComponentFactory;
18 | import com.facebook.react.fabric.CoreComponentsRegistry;
19 | import com.facebook.react.fabric.EmptyReactNativeConfig;
20 | import com.facebook.react.fabric.FabricJSIModuleProvider;
21 | import com.facebook.react.uimanager.ViewManagerRegistry;
22 | import com.newarchitecture.BuildConfig;
23 | import com.newarchitecture.newarchitecture.components.MainComponentsRegistry;
24 | import com.newarchitecture.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | /**
29 | * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
30 | * TurboModule delegates and the Fabric Renderer.
31 | *
32 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
33 | * `newArchEnabled` property). Is ignored otherwise.
34 | */
35 | public class MainApplicationReactNativeHost extends ReactNativeHost {
36 | public MainApplicationReactNativeHost(Application application) {
37 | super(application);
38 | }
39 |
40 | @Override
41 | public boolean getUseDeveloperSupport() {
42 | return BuildConfig.DEBUG;
43 | }
44 |
45 | @Override
46 | protected List getPackages() {
47 | List packages = new PackageList(this).getPackages();
48 | // Packages that cannot be autolinked yet can be added manually here, for example:
49 | // packages.add(new MyReactNativePackage());
50 | // TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
51 | // packages.add(new TurboReactPackage() { ... });
52 | // If you have custom Fabric Components, their ViewManagers should also be loaded here
53 | // inside a ReactPackage.
54 | return packages;
55 | }
56 |
57 | @Override
58 | protected String getJSMainModuleName() {
59 | return "index";
60 | }
61 |
62 | @NonNull
63 | @Override
64 | protected ReactPackageTurboModuleManagerDelegate.Builder
65 | getReactPackageTurboModuleManagerDelegateBuilder() {
66 | // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
67 | // for the new architecture and to use TurboModules correctly.
68 | return new MainApplicationTurboModuleManagerDelegate.Builder();
69 | }
70 |
71 | @Override
72 | protected JSIModulePackage getJSIModulePackage() {
73 | return new JSIModulePackage() {
74 | @Override
75 | public List getJSIModules(
76 | final ReactApplicationContext reactApplicationContext,
77 | final JavaScriptContextHolder jsContext) {
78 | final List specs = new ArrayList<>();
79 |
80 | // Here we provide a new JSIModuleSpec that will be responsible of providing the
81 | // custom Fabric Components.
82 | specs.add(
83 | new JSIModuleSpec() {
84 | @Override
85 | public JSIModuleType getJSIModuleType() {
86 | return JSIModuleType.UIManager;
87 | }
88 |
89 | @Override
90 | public JSIModuleProvider getJSIModuleProvider() {
91 | final ComponentFactory componentFactory = new ComponentFactory();
92 | CoreComponentsRegistry.register(componentFactory);
93 |
94 | // Here we register a Components Registry.
95 | // The one that is generated with the template contains no components
96 | // and just provides you the one from React Native core.
97 | MainComponentsRegistry.register(componentFactory);
98 |
99 | final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
100 |
101 | ViewManagerRegistry viewManagerRegistry =
102 | new ViewManagerRegistry(
103 | reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
104 |
105 | return new FabricJSIModuleProvider(
106 | reactApplicationContext,
107 | componentFactory,
108 | new EmptyReactNativeConfig(),
109 | viewManagerRegistry);
110 | }
111 | });
112 | return specs;
113 | }
114 | };
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/ios/RNLottieView/RLottieView.mm:
--------------------------------------------------------------------------------
1 | //
2 | // RLottieView.m
3 | // animationperftests
4 | //
5 | // Created by Hanno Gödecke on 31.05.22.
6 | //
7 |
8 | #import
9 |
10 | #import "RLottieView.h"
11 | #import "rlottie/rlottie.h"
12 | #import "LottieTypes.h"
13 |
14 | // This guard prevent the code from being compiled in the old architecture
15 | #ifdef RCT_NEW_ARCH_ENABLED
16 |
17 | #import
18 | #import
19 | #import
20 | #import
21 |
22 | #import "RCTFabricComponentsPlugins.h"
23 |
24 | using namespace facebook::react;
25 |
26 | @interface RLottieView ()
27 |
28 | @end
29 | #endif
30 |
31 | @implementation RLottieView
32 | {
33 | LottieInfo* info;
34 | UIImageView* _view;
35 | }
36 |
37 | #ifdef RCT_NEW_ARCH_ENABLED
38 | + (ComponentDescriptorProvider)componentDescriptorProvider
39 | {
40 | return concreteComponentDescriptorProvider();
41 | }
42 |
43 | Class RLottieViewCls(void)
44 | {
45 | return RLottieView.class;
46 | }
47 |
48 | - (instancetype)initWithFrame:(CGRect)frame
49 | {
50 | if (self = [super initWithFrame:frame]) {
51 | static const auto defaultProps = std::make_shared();
52 | _props = defaultProps;
53 |
54 | _view = [[UIImageView alloc] init];
55 |
56 | self.contentView = _view;
57 | }
58 | return self;
59 | }
60 |
61 | - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
62 | {
63 | const auto &oldViewProps = *std::static_pointer_cast(_props);
64 | const auto &newViewProps = *std::static_pointer_cast(props);
65 |
66 | if (oldViewProps.src != newViewProps.src) {
67 | [self updateSrc:newViewProps.src];
68 | }
69 |
70 | [super updateProps:props oldProps:oldProps];
71 | }
72 | #endif
73 |
74 | - (instancetype)init
75 | {
76 | self = [super init];
77 | // https://github.com/Aghajari/AXrLottie/blob/b0f431b652958c63dd2bd6b22a3f62a051b496d8/AXrLottie/src/main/cpp/lottie.cpp#L21
78 | info = new LottieInfo();
79 | return self;
80 | }
81 |
82 | // Expecting a string with JSON content
83 | - (void)setSrc:(NSString*)source // Called by old arch ViewManager
84 | {
85 | auto src = std::string([source UTF8String]);
86 | [self updateSrc:src];
87 | }
88 |
89 | - (void)updateSrc:(std::string)source
90 | {
91 | // https://github.com/Aghajari/AXrLottie/blob/b0f431b652958c63dd2bd6b22a3f62a051b496d8/AXrLottie/src/main/cpp/lottie.cpp#L91
92 | info->animation = rlottie::Animation::loadFromData(source, "randomCacheKey");
93 | if (info->animation == nullptr) {
94 | [NSException raise:@"Failed to read animation." format:@"Expected a string that is a JSON lottie animation"];
95 | return;
96 | }
97 |
98 | info->frameCount = info->animation->totalFrame();
99 | info->fps = (int) info->animation->frameRate();
100 | info->duration = info->animation->duration();
101 |
102 | // render all the frames
103 | size_t width, height;
104 | info->animation->size(width, height);
105 | // https://github.com/SDWebImage/SDWebImageLottieCoder/blob/c9f65679a9b0510b89673507f548a7c0f17ba95f/SDWebImageLottieCoder/Classes/SDImageLottieCoder.m#L324
106 | CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
107 | bitmapInfo |= kCGImageAlphaPremultipliedFirst;
108 | CGContextRef _canvas = CGBitmapContextCreate(NULL, width, height, 8, 0, self.colorSpaceGetDeviceRGB, bitmapInfo);
109 | size_t bytesPerRow = CGBitmapContextGetBytesPerRow(_canvas);
110 | uint32_t* buffer = (uint32_t *)CGBitmapContextGetData(_canvas);
111 |
112 | // https://github.com/SDWebImage/SDWebImageLottieCoder/blob/c9f65679a9b0510b89673507f548a7c0f17ba95f/SDWebImageLottieCoder/Classes/SDImageLottieCoder.m#L180
113 | NSMutableArray *animatedImages = [NSMutableArray arrayWithCapacity:info->frameCount];
114 | auto surface = std::make_unique(buffer, width, height, bytesPerRow);
115 | CFAbsoluteTime timeInSeconds = CFAbsoluteTimeGetCurrent();
116 |
117 | for (size_t i = 0; i < info->frameCount; i++) {
118 | info->animation->renderSync(i, *surface);
119 | CGImageRef imageRef = CGBitmapContextCreateImage(_canvas);
120 | if (!imageRef) {
121 | continue;
122 | }
123 | UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:1 orientation:UIImageOrientationUp];
124 | CGImageRelease(imageRef);
125 | [animatedImages addObject:image];
126 | }
127 | NSLog(@"Frame calculation took %f", CFAbsoluteTimeGetCurrent() - timeInSeconds);
128 |
129 | UIImage* animatedImage = [UIImage animatedImageWithImages:animatedImages duration:info->duration];
130 | #ifdef RCT_NEW_ARCH_ENABLED
131 | _view.image = animatedImage;
132 | #else
133 | self.image = animatedImage;
134 | #endif
135 | }
136 |
137 | // https://github.com/SDWebImage/SDWebImage/blob/fda0a57de98d391e8244cc0f80c583e2c67d9e8f/SDWebImage/Core/SDImageCoderHelper.m#L191
138 | - (CGColorSpaceRef)colorSpaceGetDeviceRGB {
139 | static CGColorSpaceRef colorSpace;
140 | static dispatch_once_t onceToken;
141 | dispatch_once(&onceToken, ^{
142 | colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
143 | });
144 | return colorSpace;
145 | }
146 |
147 | @end
148 |
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🌈 react-native-rlottie
2 |
3 | ## Features
4 |
5 | - ▶️ Uses [rlottie](https://github.com/Samsung/rlottie) to run lottie animations
6 | - 🌠 rlottie creates rasterized bitmaps for each frame of the animation (instead of using the platform's animation API to continuisly run the animation).
7 | - This also gives us the possibility to pre-render the animation into cache, so even complex animation can start and run in 60 FPS
8 | - ✅ Compatible with the new architecture (Fabric)
9 | - 🤖 Especially on android, using rlottie can be more performant than [lottie-android](https://github.com/airbnb/lottie-android) (which is used by [lottie-react-native](https://github.com/lottie-react-native/lottie-react-native)):
10 | - 📉 Using less CPU and RAM
11 | - 🏃♂️ Puts less pressure on the UI/main Thread, ensuring 60 FPS even on low end devices
12 | - Read more in [Performance Comparison](#performance-comparison)
13 |
14 | ## Usage
15 |
16 | We try to be as close to the [lottie-react-native](https://github.com/lottie-react-native/lottie-react-native) implementation API, so you can use this library as drop-in replacement/complement.
17 |
18 | So loading a local animation really is the same:
19 |
20 | ```jsx
21 | import React from 'react';
22 | import {View} from 'react-native';
23 | import RLottieView from 'react-native-rlottie';
24 |
25 | const lottieAnim = require('./assets/icon_trophy.json');
26 |
27 | const App = () => {
28 | return (
29 |
30 |
31 |
32 | );
33 | };
34 |
35 | const styles = StyleSheet.create({
36 | animation: {
37 | height: 700,
38 | width: 700,
39 | },
40 | });
41 |
42 | export default App;
43 | ```
44 |
45 | ## Performance Comparison
46 |
47 | All data for the comparison can be found here: https://docs.google.com/spreadsheets/d/1Akz2As7HSJ7n9kmpIMYG966GY4QybOkJth5nNewYZhs/edit?usp=sharing
48 |
49 | We compared react-native-rlottie with lottie-react-native:
50 |
51 |
52 | ### 🤖 Android
53 |
54 | 
55 |
56 | #### Key observations
57 |
58 | - Running the animation consumes less CPU (-76%) and memory (-41%).
59 | - The animation runs fluently in 60 FPS, whereas lottie-android causes the FPS to drop.
60 | - This is due to the fact that the animation used for testing is a "complex" one, and running the animation with the platform's animated/art API is more expensive then to render the animation as bitmaps.
61 |
62 | ### 🍎 iOS
63 |
64 | ```
65 | // TODO: Comparison for ios
66 | ```
67 |
68 | #### Key observations
69 |
70 | - Running the animation with lottie-react-native adds CPU pressure. Using the example with an iPhone 7+ there is a ~10% CPU pressure during running the animation with lottie-rn, whereas with rlottie its 0%
71 |
72 | ### Overall key points
73 |
74 | - Constantly running an animation with rlottie is in general more resource-saving, thus it can ensure more stable FPS, specially on low end devices.
75 | - **HOWEVER**, the first time you render the animation rlottie will use _more_ resources than lottie-rn, as it needs to decode all frames for the first time. For large and complex animations this can be a severe factor. That's why, especially on iOS, its recommanded to pre-load an animation.
76 | - In general, you should check the performance implications for each animation you are using, and test yourself if you are getting better results with lottie-rn or rlottie.
77 |
78 | _Note:_ The performance results have been recorded with [react-native-performance-stats](https://github.com/skillnation/react-native-performance-stats).
79 |
80 | ### How to test yourself
81 |
82 |
83 | Click to expand:
84 |
85 | - Setup the example app on your machine
86 | - You might want to replace the animation to test with your own. Simply replace the file `example/assets/icon_trophy.json`
87 | - First, open the "Performance test: RLottie" screen in the example app and press start.
88 | - Wait ~20 seconds until an array is printed to your console output
89 | - Copy that data to a online service that convert JSON data in CSV: https://www.convertcsv.com/json-to-csv.htm
90 | - Copy the resulting table and paste the data in a copy of the benchmark google sheet named earlier
91 | - Repeat the same with the lottie-react-native screen
92 |
93 |
94 | ## Installation
95 |
96 | ```bash
97 | yarn add react-native-rlottie@alpha
98 |
99 | npm i react-native-rlottie@alpha
100 | ```
101 |
102 | ### iOS
103 |
104 | Run pod install:
105 |
106 | ```bash
107 | npx pod-install
108 | ```
109 |
110 | ### Android
111 |
112 | No additional steps for android are required, except when using the new react native architecture:
113 |
114 |
115 | Click to expand for the instructions:
116 |
117 | (_Note:_ This setup is required to to the fact that the on android Autolinking doesn't work with the new architecture out of the box. This procedure will change in the future.)
118 |
119 | 1. Open `android/app/build.gradle` file and update the file as it follows:
120 | ```diff
121 | defaultConfig {
122 | ...
123 | "PROJECT_BUILD_DIR=$buildDir",
124 | "REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
125 | - "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build"
126 | + "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
127 | + "NODE_MODULES_DIR=$rootDir/../node_modules/"
128 | cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
129 | cppFlags "-std=c++17"
130 | ```
131 | 1. Open the `android/app/src/main/jni/Android.mk` file and update the file as it follows:
132 | ```diff
133 | # If you wish to add a custom TurboModule or Fabric component in your app you
134 | # will have to include the following autogenerated makefile.
135 | # include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
136 | +
137 | + # Includes the MK file for `react-native-rlottie`
138 | + include $(NODE_MODULES_DIR)/react-native-rlottie/android/build/generated/source/codegen/jni/Android.mk
139 | +
140 | include $(CLEAR_VARS)
141 | ```
142 | 1. In the same file above, go to the `LOCAL_SHARED_LIBRARIES` setting and add the following line:
143 | ```diff
144 | libreact_codegen_rncore \
145 | + libreact_codegen_rlottieview \
146 | libreact_debug \
147 | ```
148 | 1. Open the `android/app/src/main/jni/MainComponentsRegistry.cpp` file and update the file as it follows:
149 | 1. Add the import for the RLottieView:
150 | ```diff
151 | #include
152 | + #include
153 | #include
154 | ```
155 | 1. Add the following check in the `sharedProviderRegistry` constructor:
156 | ```diff
157 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
158 |
159 | // Custom Fabric Components go here. You can register custom
160 | // components coming from your App or from 3rd party libraries here.
161 | //
162 | // providerRegistry->add(concreteComponentDescriptorProvider<
163 | // AocViewerComponentDescriptor>());
164 | + providerRegistry->add(concreteComponentDescriptorProvider());
165 |
166 | return providerRegistry;
167 | }
168 | ```
169 |
170 |
171 | ## Supported After Effects Features
172 |
173 | This has full feature parity with rlottie, so check their [supported features here](https://github.com/Samsung/rlottie#supported-after-effects-features)
174 |
175 | ## Caveats
176 |
177 | In our testing, on iOS, there is a blocking of the UI thread and it takes some time until the animation is ready (for our most complex animation its 2s!).
178 | On iOS we are still missing some of the optimziation that we have already on android such as async/threaded frame decoding on the fly.
179 | Once we add those features we believe the performance can be similar to android. However, more development/research is needed.
180 | If you are an iOS dev, we welcome you to take on the challenge and improve or provide wisdom 🙌
181 |
182 | ## Development
183 |
184 | We are open for and welcoming contribution of any kind!
185 |
186 | To develop this library use the `example/`. Simply install the dependencies in the root dir
187 | with `yarn` and then install the dependencies in the `example/`.
188 |
189 | As this library is compatible with the old and the new arch, it can be useful to check both versions during development.
190 |
191 | ### 🤖 Switching arch:
192 |
193 | In `example/android/gradle.properties` you can simply toggle the `newArchEnabled` variable.
194 |
195 | ### 🍎 Switching arch:
196 |
197 | Go into `example/ios` and run the following command setting `RCT_NEW_ARCH_ENABLED` to `1` or `0` depending on which arch you want to test:
198 |
199 | ```bash
200 | cd ios && RCT_NEW_ARCH_ENABLED=1 pod install && cd ..
201 | ```
202 |
203 | ## References / Used libraries / Thanks
204 |
205 | - https://github.com/Aghajari/AXrLottie - Used for android implementation, does all the heavy lifting, thx <3
206 | - https://github.com/SDWebImage/librlottie-Xcode - Providing rlottie as cocoapods package, ready to be consumed by XCode, thx <3
207 |
--------------------------------------------------------------------------------
/ios/RNLottieView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 55;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | ACA064E02848B98200B7AE47 /* RNLottieViewManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACA064DF2848B98200B7AE47 /* RNLottieViewManager.mm */; };
11 | ACA064EE2848C18600B7AE47 /* RLottieView.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACA064ED2848C18600B7AE47 /* RLottieView.mm */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXCopyFilesBuildPhase section */
15 | ACA064D92848B98200B7AE47 /* CopyFiles */ = {
16 | isa = PBXCopyFilesBuildPhase;
17 | buildActionMask = 2147483647;
18 | dstPath = "include/$(PRODUCT_NAME)";
19 | dstSubfolderSpec = 16;
20 | files = (
21 | );
22 | runOnlyForDeploymentPostprocessing = 0;
23 | };
24 | /* End PBXCopyFilesBuildPhase section */
25 |
26 | /* Begin PBXFileReference section */
27 | ACA064DB2848B98200B7AE47 /* libRNLottieView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNLottieView.a; sourceTree = BUILT_PRODUCTS_DIR; };
28 | ACA064DF2848B98200B7AE47 /* RNLottieViewManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RNLottieViewManager.mm; sourceTree = ""; };
29 | ACA064EB2848C18600B7AE47 /* LottieTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LottieTypes.h; sourceTree = ""; };
30 | ACA064EC2848C18600B7AE47 /* RLottieView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLottieView.h; sourceTree = ""; };
31 | ACA064ED2848C18600B7AE47 /* RLottieView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RLottieView.mm; sourceTree = ""; };
32 | /* End PBXFileReference section */
33 |
34 | /* Begin PBXFrameworksBuildPhase section */
35 | ACA064D82848B98200B7AE47 /* Frameworks */ = {
36 | isa = PBXFrameworksBuildPhase;
37 | buildActionMask = 2147483647;
38 | files = (
39 | );
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXFrameworksBuildPhase section */
43 |
44 | /* Begin PBXGroup section */
45 | ACA064D22848B98200B7AE47 = {
46 | isa = PBXGroup;
47 | children = (
48 | ACA064DD2848B98200B7AE47 /* RNLottieView */,
49 | ACA064DC2848B98200B7AE47 /* Products */,
50 | );
51 | sourceTree = "";
52 | };
53 | ACA064DC2848B98200B7AE47 /* Products */ = {
54 | isa = PBXGroup;
55 | children = (
56 | ACA064DB2848B98200B7AE47 /* libRNLottieView.a */,
57 | );
58 | name = Products;
59 | sourceTree = "";
60 | };
61 | ACA064DD2848B98200B7AE47 /* RNLottieView */ = {
62 | isa = PBXGroup;
63 | children = (
64 | ACA064EB2848C18600B7AE47 /* LottieTypes.h */,
65 | ACA064EC2848C18600B7AE47 /* RLottieView.h */,
66 | ACA064ED2848C18600B7AE47 /* RLottieView.mm */,
67 | ACA064DF2848B98200B7AE47 /* RNLottieViewManager.mm */,
68 | );
69 | path = RNLottieView;
70 | sourceTree = "";
71 | };
72 | /* End PBXGroup section */
73 |
74 | /* Begin PBXNativeTarget section */
75 | ACA064DA2848B98200B7AE47 /* RNLottieView */ = {
76 | isa = PBXNativeTarget;
77 | buildConfigurationList = ACA064E42848B98200B7AE47 /* Build configuration list for PBXNativeTarget "RNLottieView" */;
78 | buildPhases = (
79 | ACA064D72848B98200B7AE47 /* Sources */,
80 | ACA064D82848B98200B7AE47 /* Frameworks */,
81 | ACA064D92848B98200B7AE47 /* CopyFiles */,
82 | );
83 | buildRules = (
84 | );
85 | dependencies = (
86 | );
87 | name = RNLottieView;
88 | productName = RNLottieView;
89 | productReference = ACA064DB2848B98200B7AE47 /* libRNLottieView.a */;
90 | productType = "com.apple.product-type.library.static";
91 | };
92 | /* End PBXNativeTarget section */
93 |
94 | /* Begin PBXProject section */
95 | ACA064D32848B98200B7AE47 /* Project object */ = {
96 | isa = PBXProject;
97 | attributes = {
98 | BuildIndependentTargetsInParallel = 1;
99 | LastUpgradeCheck = 1340;
100 | TargetAttributes = {
101 | ACA064DA2848B98200B7AE47 = {
102 | CreatedOnToolsVersion = 13.4;
103 | };
104 | };
105 | };
106 | buildConfigurationList = ACA064D62848B98200B7AE47 /* Build configuration list for PBXProject "RNLottieView" */;
107 | compatibilityVersion = "Xcode 13.0";
108 | developmentRegion = en;
109 | hasScannedForEncodings = 0;
110 | knownRegions = (
111 | en,
112 | Base,
113 | );
114 | mainGroup = ACA064D22848B98200B7AE47;
115 | productRefGroup = ACA064DC2848B98200B7AE47 /* Products */;
116 | projectDirPath = "";
117 | projectRoot = "";
118 | targets = (
119 | ACA064DA2848B98200B7AE47 /* RNLottieView */,
120 | );
121 | };
122 | /* End PBXProject section */
123 |
124 | /* Begin PBXSourcesBuildPhase section */
125 | ACA064D72848B98200B7AE47 /* Sources */ = {
126 | isa = PBXSourcesBuildPhase;
127 | buildActionMask = 2147483647;
128 | files = (
129 | ACA064EE2848C18600B7AE47 /* RLottieView.mm in Sources */,
130 | ACA064E02848B98200B7AE47 /* RNLottieViewManager.mm in Sources */,
131 | );
132 | runOnlyForDeploymentPostprocessing = 0;
133 | };
134 | /* End PBXSourcesBuildPhase section */
135 |
136 | /* Begin XCBuildConfiguration section */
137 | ACA064E22848B98200B7AE47 /* Debug */ = {
138 | isa = XCBuildConfiguration;
139 | buildSettings = {
140 | ALWAYS_SEARCH_USER_PATHS = NO;
141 | CLANG_ANALYZER_NONNULL = YES;
142 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
143 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
144 | CLANG_ENABLE_MODULES = YES;
145 | CLANG_ENABLE_OBJC_ARC = YES;
146 | CLANG_ENABLE_OBJC_WEAK = YES;
147 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
148 | CLANG_WARN_BOOL_CONVERSION = YES;
149 | CLANG_WARN_COMMA = YES;
150 | CLANG_WARN_CONSTANT_CONVERSION = YES;
151 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
152 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
153 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
154 | CLANG_WARN_EMPTY_BODY = YES;
155 | CLANG_WARN_ENUM_CONVERSION = YES;
156 | CLANG_WARN_INFINITE_RECURSION = YES;
157 | CLANG_WARN_INT_CONVERSION = YES;
158 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
159 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
160 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
161 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
162 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
163 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
164 | CLANG_WARN_STRICT_PROTOTYPES = YES;
165 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
166 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
167 | CLANG_WARN_UNREACHABLE_CODE = YES;
168 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
169 | COPY_PHASE_STRIP = NO;
170 | DEBUG_INFORMATION_FORMAT = dwarf;
171 | ENABLE_STRICT_OBJC_MSGSEND = YES;
172 | ENABLE_TESTABILITY = YES;
173 | GCC_C_LANGUAGE_STANDARD = gnu11;
174 | GCC_DYNAMIC_NO_PIC = NO;
175 | GCC_NO_COMMON_BLOCKS = YES;
176 | GCC_OPTIMIZATION_LEVEL = 0;
177 | GCC_PREPROCESSOR_DEFINITIONS = (
178 | "DEBUG=1",
179 | "$(inherited)",
180 | );
181 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
182 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
183 | GCC_WARN_UNDECLARED_SELECTOR = YES;
184 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
185 | GCC_WARN_UNUSED_FUNCTION = YES;
186 | GCC_WARN_UNUSED_VARIABLE = YES;
187 | IPHONEOS_DEPLOYMENT_TARGET = 15.5;
188 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
189 | MTL_FAST_MATH = YES;
190 | ONLY_ACTIVE_ARCH = YES;
191 | SDKROOT = iphoneos;
192 | };
193 | name = Debug;
194 | };
195 | ACA064E32848B98200B7AE47 /* Release */ = {
196 | isa = XCBuildConfiguration;
197 | buildSettings = {
198 | ALWAYS_SEARCH_USER_PATHS = NO;
199 | CLANG_ANALYZER_NONNULL = YES;
200 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
201 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
202 | CLANG_ENABLE_MODULES = YES;
203 | CLANG_ENABLE_OBJC_ARC = YES;
204 | CLANG_ENABLE_OBJC_WEAK = YES;
205 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
206 | CLANG_WARN_BOOL_CONVERSION = YES;
207 | CLANG_WARN_COMMA = YES;
208 | CLANG_WARN_CONSTANT_CONVERSION = YES;
209 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
210 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
211 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
212 | CLANG_WARN_EMPTY_BODY = YES;
213 | CLANG_WARN_ENUM_CONVERSION = YES;
214 | CLANG_WARN_INFINITE_RECURSION = YES;
215 | CLANG_WARN_INT_CONVERSION = YES;
216 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
217 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
218 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
219 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
220 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
221 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
222 | CLANG_WARN_STRICT_PROTOTYPES = YES;
223 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
224 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
225 | CLANG_WARN_UNREACHABLE_CODE = YES;
226 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
227 | COPY_PHASE_STRIP = NO;
228 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
229 | ENABLE_NS_ASSERTIONS = NO;
230 | ENABLE_STRICT_OBJC_MSGSEND = YES;
231 | GCC_C_LANGUAGE_STANDARD = gnu11;
232 | GCC_NO_COMMON_BLOCKS = YES;
233 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
234 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
235 | GCC_WARN_UNDECLARED_SELECTOR = YES;
236 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
237 | GCC_WARN_UNUSED_FUNCTION = YES;
238 | GCC_WARN_UNUSED_VARIABLE = YES;
239 | IPHONEOS_DEPLOYMENT_TARGET = 15.5;
240 | MTL_ENABLE_DEBUG_INFO = NO;
241 | MTL_FAST_MATH = YES;
242 | SDKROOT = iphoneos;
243 | VALIDATE_PRODUCT = YES;
244 | };
245 | name = Release;
246 | };
247 | ACA064E52848B98200B7AE47 /* Debug */ = {
248 | isa = XCBuildConfiguration;
249 | buildSettings = {
250 | CODE_SIGN_STYLE = Automatic;
251 | DEVELOPMENT_TEAM = 9L8A66Q8SQ;
252 | OTHER_LDFLAGS = "-ObjC";
253 | PRODUCT_NAME = "$(TARGET_NAME)";
254 | SKIP_INSTALL = YES;
255 | TARGETED_DEVICE_FAMILY = "1,2";
256 | };
257 | name = Debug;
258 | };
259 | ACA064E62848B98200B7AE47 /* Release */ = {
260 | isa = XCBuildConfiguration;
261 | buildSettings = {
262 | CODE_SIGN_STYLE = Automatic;
263 | DEVELOPMENT_TEAM = 9L8A66Q8SQ;
264 | OTHER_LDFLAGS = "-ObjC";
265 | PRODUCT_NAME = "$(TARGET_NAME)";
266 | SKIP_INSTALL = YES;
267 | TARGETED_DEVICE_FAMILY = "1,2";
268 | };
269 | name = Release;
270 | };
271 | /* End XCBuildConfiguration section */
272 |
273 | /* Begin XCConfigurationList section */
274 | ACA064D62848B98200B7AE47 /* Build configuration list for PBXProject "RNLottieView" */ = {
275 | isa = XCConfigurationList;
276 | buildConfigurations = (
277 | ACA064E22848B98200B7AE47 /* Debug */,
278 | ACA064E32848B98200B7AE47 /* Release */,
279 | );
280 | defaultConfigurationIsVisible = 0;
281 | defaultConfigurationName = Release;
282 | };
283 | ACA064E42848B98200B7AE47 /* Build configuration list for PBXNativeTarget "RNLottieView" */ = {
284 | isa = XCConfigurationList;
285 | buildConfigurations = (
286 | ACA064E52848B98200B7AE47 /* Debug */,
287 | ACA064E62848B98200B7AE47 /* Release */,
288 | );
289 | defaultConfigurationIsVisible = 0;
290 | defaultConfigurationName = Release;
291 | };
292 | /* End XCConfigurationList section */
293 | };
294 | rootObject = ACA064D32848B98200B7AE47 /* Project object */;
295 | }
296 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 | apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
3 |
4 | import com.android.build.OutputFile
5 | import org.apache.tools.ant.taskdefs.condition.Os
6 |
7 | /**
8 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
9 | * and bundleReleaseJsAndAssets).
10 | * These basically call `react-native bundle` with the correct arguments during the Android build
11 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
12 | * bundle directly from the development server. Below you can see all the possible configurations
13 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
14 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
15 | *
16 | * project.ext.react = [
17 | * // the name of the generated asset file containing your JS bundle
18 | * bundleAssetName: "index.android.bundle",
19 | *
20 | * // the entry file for bundle generation. If none specified and
21 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is
22 | * // default. Can be overridden with ENTRY_FILE environment variable.
23 | * entryFile: "index.android.js",
24 | *
25 | * // https://reactnative.dev/docs/performance#enable-the-ram-format
26 | * bundleCommand: "ram-bundle",
27 | *
28 | * // whether to bundle JS and assets in debug mode
29 | * bundleInDebug: false,
30 | *
31 | * // whether to bundle JS and assets in release mode
32 | * bundleInRelease: true,
33 | *
34 | * // whether to bundle JS and assets in another build variant (if configured).
35 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
36 | * // The configuration property can be in the following formats
37 | * // 'bundleIn${productFlavor}${buildType}'
38 | * // 'bundleIn${buildType}'
39 | * // bundleInFreeDebug: true,
40 | * // bundleInPaidRelease: true,
41 | * // bundleInBeta: true,
42 | *
43 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
44 | * // for example: to disable dev mode in the staging build type (if configured)
45 | * devDisabledInStaging: true,
46 | * // The configuration property can be in the following formats
47 | * // 'devDisabledIn${productFlavor}${buildType}'
48 | * // 'devDisabledIn${buildType}'
49 | *
50 | * // the root of your project, i.e. where "package.json" lives
51 | * root: "../../",
52 | *
53 | * // where to put the JS bundle asset in debug mode
54 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
55 | *
56 | * // where to put the JS bundle asset in release mode
57 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
58 | *
59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
60 | * // require('./image.png')), in debug mode
61 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
62 | *
63 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
64 | * // require('./image.png')), in release mode
65 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
66 | *
67 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
68 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
69 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
70 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
71 | * // for example, you might want to remove it from here.
72 | * inputExcludes: ["android/**", "ios/**"],
73 | *
74 | * // override which node gets called and with what additional arguments
75 | * nodeExecutableAndArgs: ["node"],
76 | *
77 | * // supply additional arguments to the packager
78 | * extraPackagerArgs: []
79 | * ]
80 | */
81 |
82 | project.ext.react = [
83 | enableHermes: true, // clean and rebuild if changing
84 | ]
85 |
86 | apply from: "../../node_modules/react-native/react.gradle"
87 |
88 | /**
89 | * Set this to true to create two separate APKs instead of one:
90 | * - An APK that only works on ARM devices
91 | * - An APK that only works on x86 devices
92 | * The advantage is the size of the APK is reduced by about 4MB.
93 | * Upload all the APKs to the Play Store and people will download
94 | * the correct one based on the CPU architecture of their device.
95 | */
96 | def enableSeparateBuildPerCPUArchitecture = false
97 |
98 | /**
99 | * Run Proguard to shrink the Java bytecode in release builds.
100 | */
101 | def enableProguardInReleaseBuilds = false
102 |
103 | /**
104 | * The preferred build flavor of JavaScriptCore.
105 | *
106 | * For example, to use the international variant, you can use:
107 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
108 | *
109 | * The international variant includes ICU i18n library and necessary data
110 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
111 | * give correct results when using with locales other than en-US. Note that
112 | * this variant is about 6MiB larger per architecture than default.
113 | */
114 | def jscFlavor = 'org.webkit:android-jsc:+'
115 |
116 | /**
117 | * Whether to enable the Hermes VM.
118 | *
119 | * This should be set on project.ext.react and that value will be read here. If it is not set
120 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
121 | * and the benefits of using Hermes will therefore be sharply reduced.
122 | */
123 | def enableHermes = project.ext.react.get("enableHermes", false);
124 |
125 | /**
126 | * Architectures to build native code for.
127 | */
128 | def reactNativeArchitectures() {
129 | def value = project.getProperties().get("reactNativeArchitectures")
130 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
131 | }
132 |
133 | android {
134 | ndkVersion rootProject.ext.ndkVersion
135 |
136 | compileSdkVersion rootProject.ext.compileSdkVersion
137 |
138 | defaultConfig {
139 | applicationId "com.newarchitecture"
140 | minSdkVersion rootProject.ext.minSdkVersion
141 | targetSdkVersion rootProject.ext.targetSdkVersion
142 | versionCode 1
143 | versionName "1.0"
144 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
145 |
146 | if (isNewArchitectureEnabled()) {
147 | // We configure the NDK build only if you decide to opt-in for the New Architecture.
148 | externalNativeBuild {
149 | ndkBuild {
150 | arguments "APP_PLATFORM=android-21",
151 | "APP_STL=c++_shared",
152 | "NDK_TOOLCHAIN_VERSION=clang",
153 | "GENERATED_SRC_DIR=$buildDir/generated/source",
154 | "PROJECT_BUILD_DIR=$buildDir",
155 | "REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
156 | "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
157 | "NODE_MODULES_DIR=$rootDir/../node_modules/"
158 | cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
159 | cppFlags "-std=c++17"
160 | // Make sure this target name is the same you specify inside the
161 | // src/main/jni/Android.mk file for the `LOCAL_MODULE` variable.
162 | targets "newarchitecture_appmodules"
163 |
164 | // Fix for windows limit on number of character in file paths and in command lines
165 | if (Os.isFamily(Os.FAMILY_WINDOWS)) {
166 | arguments "NDK_APP_SHORT_COMMANDS=true"
167 | }
168 | }
169 | }
170 | if (!enableSeparateBuildPerCPUArchitecture) {
171 | ndk {
172 | abiFilters (*reactNativeArchitectures())
173 | }
174 | }
175 | }
176 | }
177 |
178 | if (isNewArchitectureEnabled()) {
179 | // We configure the NDK build only if you decide to opt-in for the New Architecture.
180 | externalNativeBuild {
181 | ndkBuild {
182 | path "$projectDir/src/main/jni/Android.mk"
183 | }
184 | }
185 | def reactAndroidProjectDir = project(':ReactAndroid').projectDir
186 | def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
187 | dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
188 | from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
189 | into("$buildDir/react-ndk/exported")
190 | }
191 | def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
192 | dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
193 | from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
194 | into("$buildDir/react-ndk/exported")
195 | }
196 | afterEvaluate {
197 | // If you wish to add a custom TurboModule or component locally,
198 | // you should uncomment this line.
199 | // preBuild.dependsOn("generateCodegenArtifactsFromSchema")
200 | preDebugBuild.dependsOn(packageReactNdkDebugLibs)
201 | preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
202 |
203 | // Due to a bug inside AGP, we have to explicitly set a dependency
204 | // between configureNdkBuild* tasks and the preBuild tasks.
205 | // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
206 | configureNdkBuildRelease.dependsOn(preReleaseBuild)
207 | configureNdkBuildDebug.dependsOn(preDebugBuild)
208 | reactNativeArchitectures().each { architecture ->
209 | tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
210 | dependsOn("preDebugBuild")
211 | }
212 | tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
213 | dependsOn("preReleaseBuild")
214 | }
215 | }
216 | }
217 | }
218 |
219 | splits {
220 | abi {
221 | reset()
222 | enable enableSeparateBuildPerCPUArchitecture
223 | universalApk false // If true, also generate a universal APK
224 | include (*reactNativeArchitectures())
225 | }
226 | }
227 | signingConfigs {
228 | debug {
229 | storeFile file('debug.keystore')
230 | storePassword 'android'
231 | keyAlias 'androiddebugkey'
232 | keyPassword 'android'
233 | }
234 | }
235 | buildTypes {
236 | debug {
237 | signingConfig signingConfigs.debug
238 | }
239 | release {
240 | // Caution! In production, you need to generate your own keystore file.
241 | // see https://reactnative.dev/docs/signed-apk-android.
242 | signingConfig signingConfigs.debug
243 | minifyEnabled enableProguardInReleaseBuilds
244 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
245 | }
246 | }
247 |
248 | // applicationVariants are e.g. debug, release
249 | applicationVariants.all { variant ->
250 | variant.outputs.each { output ->
251 | // For each separate APK per architecture, set a unique version code as described here:
252 | // https://developer.android.com/studio/build/configure-apk-splits.html
253 | // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
254 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
255 | def abi = output.getFilter(OutputFile.ABI)
256 | if (abi != null) { // null for the universal-debug, universal-release variants
257 | output.versionCodeOverride =
258 | defaultConfig.versionCode * 1000 + versionCodes.get(abi)
259 | }
260 |
261 | }
262 | }
263 | }
264 |
265 | dependencies {
266 | implementation fileTree(dir: "libs", include: ["*.jar"])
267 |
268 | //noinspection GradleDynamicVersion
269 | implementation "com.facebook.react:react-native:+" // From node_modules
270 |
271 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
272 |
273 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
274 | exclude group:'com.facebook.fbjni'
275 | }
276 |
277 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
278 | exclude group:'com.facebook.flipper'
279 | exclude group:'com.squareup.okhttp3', module:'okhttp'
280 | }
281 |
282 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
283 | exclude group:'com.facebook.flipper'
284 | }
285 |
286 | if (enableHermes) {
287 | def hermesPath = "../../node_modules/hermes-engine/android/";
288 | debugImplementation files(hermesPath + "hermes-debug.aar")
289 | releaseImplementation files(hermesPath + "hermes-release.aar")
290 | } else {
291 | implementation jscFlavor
292 | }
293 | }
294 |
295 | if (isNewArchitectureEnabled()) {
296 | // If new architecture is enabled, we let you build RN from source
297 | // Otherwise we fallback to a prebuilt .aar bundled in the NPM package.
298 | // This will be applied to all the imported transtitive dependency.
299 | configurations.all {
300 | resolutionStrategy.dependencySubstitution {
301 | substitute(module("com.facebook.react:react-native"))
302 | .using(project(":ReactAndroid")).because("On New Architecture we're building React Native from source")
303 | }
304 | }
305 | }
306 |
307 | // Run this once to be able to run the application with BUCK
308 | // puts all compile dependencies into folder libs for BUCK to use
309 | task copyDownloadableDepsToLibs(type: Copy) {
310 | from configurations.implementation
311 | into 'libs'
312 | }
313 |
314 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
315 |
316 | def isNewArchitectureEnabled() {
317 | // To opt-in for the New Architecture, you can either:
318 | // - Set `newArchEnabled` to true inside the `gradle.properties` file
319 | // - Invoke gradle with `-newArchEnabled=true`
320 | // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
321 | return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
322 | }
323 |
--------------------------------------------------------------------------------
/example/ios/NewArchitecture.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 00E356F31AD99517003FC87E /* NewArchitectureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* NewArchitectureTests.m */; };
11 | 0C80B921A6F3F58F76C31292 /* libPods-NewArchitecture.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-NewArchitecture.a */; };
12 | 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
14 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
15 | 7699B88040F8A987B510C191 /* libPods-NewArchitecture-NewArchitectureTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-NewArchitecture-NewArchitectureTests.a */; };
16 | 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXContainerItemProxy section */
20 | 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
21 | isa = PBXContainerItemProxy;
22 | containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
23 | proxyType = 1;
24 | remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
25 | remoteInfo = NewArchitecture;
26 | };
27 | /* End PBXContainerItemProxy section */
28 |
29 | /* Begin PBXFileReference section */
30 | 00E356EE1AD99517003FC87E /* NewArchitectureTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NewArchitectureTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
31 | 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
32 | 00E356F21AD99517003FC87E /* NewArchitectureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NewArchitectureTests.m; sourceTree = ""; };
33 | 13B07F961A680F5B00A75B9A /* NewArchitecture.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NewArchitecture.app; sourceTree = BUILT_PRODUCTS_DIR; };
34 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = NewArchitecture/AppDelegate.h; sourceTree = ""; };
35 | 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = NewArchitecture/AppDelegate.mm; sourceTree = ""; };
36 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = NewArchitecture/Images.xcassets; sourceTree = ""; };
37 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NewArchitecture/Info.plist; sourceTree = ""; };
38 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NewArchitecture/main.m; sourceTree = ""; };
39 | 19F6CBCC0A4E27FBF8BF4A61 /* libPods-NewArchitecture-NewArchitectureTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewArchitecture-NewArchitectureTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
40 | 3B4392A12AC88292D35C810B /* Pods-NewArchitecture.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewArchitecture.debug.xcconfig"; path = "Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture.debug.xcconfig"; sourceTree = ""; };
41 | 5709B34CF0A7D63546082F79 /* Pods-NewArchitecture.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewArchitecture.release.xcconfig"; path = "Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture.release.xcconfig"; sourceTree = ""; };
42 | 5B7EB9410499542E8C5724F5 /* Pods-NewArchitecture-NewArchitectureTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewArchitecture-NewArchitectureTests.debug.xcconfig"; path = "Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests.debug.xcconfig"; sourceTree = ""; };
43 | 5DCACB8F33CDC322A6C60F78 /* libPods-NewArchitecture.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewArchitecture.a"; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = NewArchitecture/LaunchScreen.storyboard; sourceTree = ""; };
45 | 89C6BE57DB24E9ADA2F236DE /* Pods-NewArchitecture-NewArchitectureTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewArchitecture-NewArchitectureTests.release.xcconfig"; path = "Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests.release.xcconfig"; sourceTree = ""; };
46 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
47 | /* End PBXFileReference section */
48 |
49 | /* Begin PBXFrameworksBuildPhase section */
50 | 00E356EB1AD99517003FC87E /* Frameworks */ = {
51 | isa = PBXFrameworksBuildPhase;
52 | buildActionMask = 2147483647;
53 | files = (
54 | 7699B88040F8A987B510C191 /* libPods-NewArchitecture-NewArchitectureTests.a in Frameworks */,
55 | );
56 | runOnlyForDeploymentPostprocessing = 0;
57 | };
58 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
59 | isa = PBXFrameworksBuildPhase;
60 | buildActionMask = 2147483647;
61 | files = (
62 | 0C80B921A6F3F58F76C31292 /* libPods-NewArchitecture.a in Frameworks */,
63 | );
64 | runOnlyForDeploymentPostprocessing = 0;
65 | };
66 | /* End PBXFrameworksBuildPhase section */
67 |
68 | /* Begin PBXGroup section */
69 | 00E356EF1AD99517003FC87E /* NewArchitectureTests */ = {
70 | isa = PBXGroup;
71 | children = (
72 | 00E356F21AD99517003FC87E /* NewArchitectureTests.m */,
73 | 00E356F01AD99517003FC87E /* Supporting Files */,
74 | );
75 | path = NewArchitectureTests;
76 | sourceTree = "";
77 | };
78 | 00E356F01AD99517003FC87E /* Supporting Files */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 00E356F11AD99517003FC87E /* Info.plist */,
82 | );
83 | name = "Supporting Files";
84 | sourceTree = "";
85 | };
86 | 13B07FAE1A68108700A75B9A /* NewArchitecture */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */,
90 | 13B07FB01A68108700A75B9A /* AppDelegate.mm */,
91 | 13B07FB51A68108700A75B9A /* Images.xcassets */,
92 | 13B07FB61A68108700A75B9A /* Info.plist */,
93 | 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
94 | 13B07FB71A68108700A75B9A /* main.m */,
95 | );
96 | name = NewArchitecture;
97 | sourceTree = "";
98 | };
99 | 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
100 | isa = PBXGroup;
101 | children = (
102 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
103 | 5DCACB8F33CDC322A6C60F78 /* libPods-NewArchitecture.a */,
104 | 19F6CBCC0A4E27FBF8BF4A61 /* libPods-NewArchitecture-NewArchitectureTests.a */,
105 | );
106 | name = Frameworks;
107 | sourceTree = "";
108 | };
109 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
110 | isa = PBXGroup;
111 | children = (
112 | );
113 | name = Libraries;
114 | sourceTree = "";
115 | };
116 | 83CBB9F61A601CBA00E9B192 = {
117 | isa = PBXGroup;
118 | children = (
119 | 13B07FAE1A68108700A75B9A /* NewArchitecture */,
120 | 832341AE1AAA6A7D00B99B32 /* Libraries */,
121 | 00E356EF1AD99517003FC87E /* NewArchitectureTests */,
122 | 83CBBA001A601CBA00E9B192 /* Products */,
123 | 2D16E6871FA4F8E400B85C8A /* Frameworks */,
124 | BBD78D7AC51CEA395F1C20DB /* Pods */,
125 | );
126 | indentWidth = 2;
127 | sourceTree = "";
128 | tabWidth = 2;
129 | usesTabs = 0;
130 | };
131 | 83CBBA001A601CBA00E9B192 /* Products */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 13B07F961A680F5B00A75B9A /* NewArchitecture.app */,
135 | 00E356EE1AD99517003FC87E /* NewArchitectureTests.xctest */,
136 | );
137 | name = Products;
138 | sourceTree = "";
139 | };
140 | BBD78D7AC51CEA395F1C20DB /* Pods */ = {
141 | isa = PBXGroup;
142 | children = (
143 | 3B4392A12AC88292D35C810B /* Pods-NewArchitecture.debug.xcconfig */,
144 | 5709B34CF0A7D63546082F79 /* Pods-NewArchitecture.release.xcconfig */,
145 | 5B7EB9410499542E8C5724F5 /* Pods-NewArchitecture-NewArchitectureTests.debug.xcconfig */,
146 | 89C6BE57DB24E9ADA2F236DE /* Pods-NewArchitecture-NewArchitectureTests.release.xcconfig */,
147 | );
148 | path = Pods;
149 | sourceTree = "";
150 | };
151 | /* End PBXGroup section */
152 |
153 | /* Begin PBXNativeTarget section */
154 | 00E356ED1AD99517003FC87E /* NewArchitectureTests */ = {
155 | isa = PBXNativeTarget;
156 | buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "NewArchitectureTests" */;
157 | buildPhases = (
158 | A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */,
159 | 00E356EA1AD99517003FC87E /* Sources */,
160 | 00E356EB1AD99517003FC87E /* Frameworks */,
161 | 00E356EC1AD99517003FC87E /* Resources */,
162 | C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */,
163 | F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */,
164 | );
165 | buildRules = (
166 | );
167 | dependencies = (
168 | 00E356F51AD99517003FC87E /* PBXTargetDependency */,
169 | );
170 | name = NewArchitectureTests;
171 | productName = NewArchitectureTests;
172 | productReference = 00E356EE1AD99517003FC87E /* NewArchitectureTests.xctest */;
173 | productType = "com.apple.product-type.bundle.unit-test";
174 | };
175 | 13B07F861A680F5B00A75B9A /* NewArchitecture */ = {
176 | isa = PBXNativeTarget;
177 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NewArchitecture" */;
178 | buildPhases = (
179 | C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
180 | FD10A7F022414F080027D42C /* Start Packager */,
181 | 13B07F871A680F5B00A75B9A /* Sources */,
182 | 13B07F8C1A680F5B00A75B9A /* Frameworks */,
183 | 13B07F8E1A680F5B00A75B9A /* Resources */,
184 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
185 | 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
186 | E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
187 | );
188 | buildRules = (
189 | );
190 | dependencies = (
191 | );
192 | name = NewArchitecture;
193 | productName = NewArchitecture;
194 | productReference = 13B07F961A680F5B00A75B9A /* NewArchitecture.app */;
195 | productType = "com.apple.product-type.application";
196 | };
197 | /* End PBXNativeTarget section */
198 |
199 | /* Begin PBXProject section */
200 | 83CBB9F71A601CBA00E9B192 /* Project object */ = {
201 | isa = PBXProject;
202 | attributes = {
203 | LastUpgradeCheck = 1210;
204 | TargetAttributes = {
205 | 00E356ED1AD99517003FC87E = {
206 | CreatedOnToolsVersion = 6.2;
207 | TestTargetID = 13B07F861A680F5B00A75B9A;
208 | };
209 | 13B07F861A680F5B00A75B9A = {
210 | LastSwiftMigration = 1120;
211 | };
212 | };
213 | };
214 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NewArchitecture" */;
215 | compatibilityVersion = "Xcode 12.0";
216 | developmentRegion = en;
217 | hasScannedForEncodings = 0;
218 | knownRegions = (
219 | en,
220 | Base,
221 | );
222 | mainGroup = 83CBB9F61A601CBA00E9B192;
223 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
224 | projectDirPath = "";
225 | projectRoot = "";
226 | targets = (
227 | 13B07F861A680F5B00A75B9A /* NewArchitecture */,
228 | 00E356ED1AD99517003FC87E /* NewArchitectureTests */,
229 | );
230 | };
231 | /* End PBXProject section */
232 |
233 | /* Begin PBXResourcesBuildPhase section */
234 | 00E356EC1AD99517003FC87E /* Resources */ = {
235 | isa = PBXResourcesBuildPhase;
236 | buildActionMask = 2147483647;
237 | files = (
238 | );
239 | runOnlyForDeploymentPostprocessing = 0;
240 | };
241 | 13B07F8E1A680F5B00A75B9A /* Resources */ = {
242 | isa = PBXResourcesBuildPhase;
243 | buildActionMask = 2147483647;
244 | files = (
245 | 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
246 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
247 | );
248 | runOnlyForDeploymentPostprocessing = 0;
249 | };
250 | /* End PBXResourcesBuildPhase section */
251 |
252 | /* Begin PBXShellScriptBuildPhase section */
253 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
254 | isa = PBXShellScriptBuildPhase;
255 | buildActionMask = 2147483647;
256 | files = (
257 | );
258 | inputPaths = (
259 | );
260 | name = "Bundle React Native code and images";
261 | outputPaths = (
262 | );
263 | runOnlyForDeploymentPostprocessing = 0;
264 | shellPath = /bin/sh;
265 | shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
266 | };
267 | 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = {
268 | isa = PBXShellScriptBuildPhase;
269 | buildActionMask = 2147483647;
270 | files = (
271 | );
272 | inputFileListPaths = (
273 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture-frameworks-${CONFIGURATION}-input-files.xcfilelist",
274 | );
275 | name = "[CP] Embed Pods Frameworks";
276 | outputFileListPaths = (
277 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture-frameworks-${CONFIGURATION}-output-files.xcfilelist",
278 | );
279 | runOnlyForDeploymentPostprocessing = 0;
280 | shellPath = /bin/sh;
281 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture-frameworks.sh\"\n";
282 | showEnvVarsInLog = 0;
283 | };
284 | A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = {
285 | isa = PBXShellScriptBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | );
289 | inputFileListPaths = (
290 | );
291 | inputPaths = (
292 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
293 | "${PODS_ROOT}/Manifest.lock",
294 | );
295 | name = "[CP] Check Pods Manifest.lock";
296 | outputFileListPaths = (
297 | );
298 | outputPaths = (
299 | "$(DERIVED_FILE_DIR)/Pods-NewArchitecture-NewArchitectureTests-checkManifestLockResult.txt",
300 | );
301 | runOnlyForDeploymentPostprocessing = 0;
302 | shellPath = /bin/sh;
303 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
304 | showEnvVarsInLog = 0;
305 | };
306 | C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
307 | isa = PBXShellScriptBuildPhase;
308 | buildActionMask = 2147483647;
309 | files = (
310 | );
311 | inputFileListPaths = (
312 | );
313 | inputPaths = (
314 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
315 | "${PODS_ROOT}/Manifest.lock",
316 | );
317 | name = "[CP] Check Pods Manifest.lock";
318 | outputFileListPaths = (
319 | );
320 | outputPaths = (
321 | "$(DERIVED_FILE_DIR)/Pods-NewArchitecture-checkManifestLockResult.txt",
322 | );
323 | runOnlyForDeploymentPostprocessing = 0;
324 | shellPath = /bin/sh;
325 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
326 | showEnvVarsInLog = 0;
327 | };
328 | C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = {
329 | isa = PBXShellScriptBuildPhase;
330 | buildActionMask = 2147483647;
331 | files = (
332 | );
333 | inputFileListPaths = (
334 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
335 | );
336 | name = "[CP] Embed Pods Frameworks";
337 | outputFileListPaths = (
338 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
339 | );
340 | runOnlyForDeploymentPostprocessing = 0;
341 | shellPath = /bin/sh;
342 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests-frameworks.sh\"\n";
343 | showEnvVarsInLog = 0;
344 | };
345 | E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
346 | isa = PBXShellScriptBuildPhase;
347 | buildActionMask = 2147483647;
348 | files = (
349 | );
350 | inputFileListPaths = (
351 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture-resources-${CONFIGURATION}-input-files.xcfilelist",
352 | );
353 | name = "[CP] Copy Pods Resources";
354 | outputFileListPaths = (
355 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture-resources-${CONFIGURATION}-output-files.xcfilelist",
356 | );
357 | runOnlyForDeploymentPostprocessing = 0;
358 | shellPath = /bin/sh;
359 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NewArchitecture/Pods-NewArchitecture-resources.sh\"\n";
360 | showEnvVarsInLog = 0;
361 | };
362 | F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = {
363 | isa = PBXShellScriptBuildPhase;
364 | buildActionMask = 2147483647;
365 | files = (
366 | );
367 | inputFileListPaths = (
368 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests-resources-${CONFIGURATION}-input-files.xcfilelist",
369 | );
370 | name = "[CP] Copy Pods Resources";
371 | outputFileListPaths = (
372 | "${PODS_ROOT}/Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests-resources-${CONFIGURATION}-output-files.xcfilelist",
373 | );
374 | runOnlyForDeploymentPostprocessing = 0;
375 | shellPath = /bin/sh;
376 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NewArchitecture-NewArchitectureTests/Pods-NewArchitecture-NewArchitectureTests-resources.sh\"\n";
377 | showEnvVarsInLog = 0;
378 | };
379 | FD10A7F022414F080027D42C /* Start Packager */ = {
380 | isa = PBXShellScriptBuildPhase;
381 | buildActionMask = 2147483647;
382 | files = (
383 | );
384 | inputFileListPaths = (
385 | );
386 | inputPaths = (
387 | );
388 | name = "Start Packager";
389 | outputFileListPaths = (
390 | );
391 | outputPaths = (
392 | );
393 | runOnlyForDeploymentPostprocessing = 0;
394 | shellPath = /bin/sh;
395 | shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
396 | showEnvVarsInLog = 0;
397 | };
398 | /* End PBXShellScriptBuildPhase section */
399 |
400 | /* Begin PBXSourcesBuildPhase section */
401 | 00E356EA1AD99517003FC87E /* Sources */ = {
402 | isa = PBXSourcesBuildPhase;
403 | buildActionMask = 2147483647;
404 | files = (
405 | 00E356F31AD99517003FC87E /* NewArchitectureTests.m in Sources */,
406 | );
407 | runOnlyForDeploymentPostprocessing = 0;
408 | };
409 | 13B07F871A680F5B00A75B9A /* Sources */ = {
410 | isa = PBXSourcesBuildPhase;
411 | buildActionMask = 2147483647;
412 | files = (
413 | 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
414 | 13B07FC11A68108700A75B9A /* main.m in Sources */,
415 | );
416 | runOnlyForDeploymentPostprocessing = 0;
417 | };
418 | /* End PBXSourcesBuildPhase section */
419 |
420 | /* Begin PBXTargetDependency section */
421 | 00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
422 | isa = PBXTargetDependency;
423 | target = 13B07F861A680F5B00A75B9A /* NewArchitecture */;
424 | targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
425 | };
426 | /* End PBXTargetDependency section */
427 |
428 | /* Begin XCBuildConfiguration section */
429 | 00E356F61AD99517003FC87E /* Debug */ = {
430 | isa = XCBuildConfiguration;
431 | baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-NewArchitecture-NewArchitectureTests.debug.xcconfig */;
432 | buildSettings = {
433 | BUNDLE_LOADER = "$(TEST_HOST)";
434 | GCC_PREPROCESSOR_DEFINITIONS = (
435 | "DEBUG=1",
436 | "$(inherited)",
437 | );
438 | INFOPLIST_FILE = NewArchitectureTests/Info.plist;
439 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
440 | LD_RUNPATH_SEARCH_PATHS = (
441 | "$(inherited)",
442 | "@executable_path/Frameworks",
443 | "@loader_path/Frameworks",
444 | );
445 | OTHER_LDFLAGS = (
446 | "-ObjC",
447 | "-lc++",
448 | "$(inherited)",
449 | );
450 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
451 | PRODUCT_NAME = "$(TARGET_NAME)";
452 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewArchitecture.app/NewArchitecture";
453 | };
454 | name = Debug;
455 | };
456 | 00E356F71AD99517003FC87E /* Release */ = {
457 | isa = XCBuildConfiguration;
458 | baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-NewArchitecture-NewArchitectureTests.release.xcconfig */;
459 | buildSettings = {
460 | BUNDLE_LOADER = "$(TEST_HOST)";
461 | COPY_PHASE_STRIP = NO;
462 | INFOPLIST_FILE = NewArchitectureTests/Info.plist;
463 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
464 | LD_RUNPATH_SEARCH_PATHS = (
465 | "$(inherited)",
466 | "@executable_path/Frameworks",
467 | "@loader_path/Frameworks",
468 | );
469 | OTHER_LDFLAGS = (
470 | "-ObjC",
471 | "-lc++",
472 | "$(inherited)",
473 | );
474 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
475 | PRODUCT_NAME = "$(TARGET_NAME)";
476 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewArchitecture.app/NewArchitecture";
477 | };
478 | name = Release;
479 | };
480 | 13B07F941A680F5B00A75B9A /* Debug */ = {
481 | isa = XCBuildConfiguration;
482 | baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-NewArchitecture.debug.xcconfig */;
483 | buildSettings = {
484 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
485 | CLANG_ENABLE_MODULES = YES;
486 | CURRENT_PROJECT_VERSION = 1;
487 | ENABLE_BITCODE = NO;
488 | INFOPLIST_FILE = NewArchitecture/Info.plist;
489 | LD_RUNPATH_SEARCH_PATHS = (
490 | "$(inherited)",
491 | "@executable_path/Frameworks",
492 | );
493 | OTHER_LDFLAGS = (
494 | "$(inherited)",
495 | "-ObjC",
496 | "-lc++",
497 | );
498 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
499 | PRODUCT_NAME = NewArchitecture;
500 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
501 | SWIFT_VERSION = 5.0;
502 | VERSIONING_SYSTEM = "apple-generic";
503 | };
504 | name = Debug;
505 | };
506 | 13B07F951A680F5B00A75B9A /* Release */ = {
507 | isa = XCBuildConfiguration;
508 | baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-NewArchitecture.release.xcconfig */;
509 | buildSettings = {
510 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
511 | CLANG_ENABLE_MODULES = YES;
512 | CURRENT_PROJECT_VERSION = 1;
513 | INFOPLIST_FILE = NewArchitecture/Info.plist;
514 | LD_RUNPATH_SEARCH_PATHS = (
515 | "$(inherited)",
516 | "@executable_path/Frameworks",
517 | );
518 | OTHER_LDFLAGS = (
519 | "$(inherited)",
520 | "-ObjC",
521 | "-lc++",
522 | );
523 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
524 | PRODUCT_NAME = NewArchitecture;
525 | SWIFT_VERSION = 5.0;
526 | VERSIONING_SYSTEM = "apple-generic";
527 | };
528 | name = Release;
529 | };
530 | 83CBBA201A601CBA00E9B192 /* Debug */ = {
531 | isa = XCBuildConfiguration;
532 | buildSettings = {
533 | ALWAYS_SEARCH_USER_PATHS = NO;
534 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
535 | CLANG_CXX_LANGUAGE_STANDARD = "c++17";
536 | CLANG_CXX_LIBRARY = "libc++";
537 | CLANG_ENABLE_MODULES = YES;
538 | CLANG_ENABLE_OBJC_ARC = YES;
539 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
540 | CLANG_WARN_BOOL_CONVERSION = YES;
541 | CLANG_WARN_COMMA = YES;
542 | CLANG_WARN_CONSTANT_CONVERSION = YES;
543 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
544 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
545 | CLANG_WARN_EMPTY_BODY = YES;
546 | CLANG_WARN_ENUM_CONVERSION = YES;
547 | CLANG_WARN_INFINITE_RECURSION = YES;
548 | CLANG_WARN_INT_CONVERSION = YES;
549 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
550 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
551 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
552 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
553 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
554 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
555 | CLANG_WARN_STRICT_PROTOTYPES = YES;
556 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
557 | CLANG_WARN_UNREACHABLE_CODE = YES;
558 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
559 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
560 | COPY_PHASE_STRIP = NO;
561 | ENABLE_STRICT_OBJC_MSGSEND = YES;
562 | ENABLE_TESTABILITY = YES;
563 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
564 | GCC_C_LANGUAGE_STANDARD = gnu99;
565 | GCC_DYNAMIC_NO_PIC = NO;
566 | GCC_NO_COMMON_BLOCKS = YES;
567 | GCC_OPTIMIZATION_LEVEL = 0;
568 | GCC_PREPROCESSOR_DEFINITIONS = (
569 | "DEBUG=1",
570 | "$(inherited)",
571 | );
572 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
573 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
574 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
575 | GCC_WARN_UNDECLARED_SELECTOR = YES;
576 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
577 | GCC_WARN_UNUSED_FUNCTION = YES;
578 | GCC_WARN_UNUSED_VARIABLE = YES;
579 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
580 | LD_RUNPATH_SEARCH_PATHS = (
581 | /usr/lib/swift,
582 | "$(inherited)",
583 | );
584 | LIBRARY_SEARCH_PATHS = (
585 | "\"$(SDKROOT)/usr/lib/swift\"",
586 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
587 | "\"$(inherited)\"",
588 | );
589 | MTL_ENABLE_DEBUG_INFO = YES;
590 | ONLY_ACTIVE_ARCH = YES;
591 | OTHER_CPLUSPLUSFLAGS = (
592 | "$(OTHER_CFLAGS)",
593 | "-DFOLLY_NO_CONFIG",
594 | "-DFOLLY_MOBILE=1",
595 | "-DFOLLY_USE_LIBCPP=1",
596 | );
597 | SDKROOT = iphoneos;
598 | };
599 | name = Debug;
600 | };
601 | 83CBBA211A601CBA00E9B192 /* Release */ = {
602 | isa = XCBuildConfiguration;
603 | buildSettings = {
604 | ALWAYS_SEARCH_USER_PATHS = NO;
605 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
606 | CLANG_CXX_LANGUAGE_STANDARD = "c++17";
607 | CLANG_CXX_LIBRARY = "libc++";
608 | CLANG_ENABLE_MODULES = YES;
609 | CLANG_ENABLE_OBJC_ARC = YES;
610 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
611 | CLANG_WARN_BOOL_CONVERSION = YES;
612 | CLANG_WARN_COMMA = YES;
613 | CLANG_WARN_CONSTANT_CONVERSION = YES;
614 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
615 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
616 | CLANG_WARN_EMPTY_BODY = YES;
617 | CLANG_WARN_ENUM_CONVERSION = YES;
618 | CLANG_WARN_INFINITE_RECURSION = YES;
619 | CLANG_WARN_INT_CONVERSION = YES;
620 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
621 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
622 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
623 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
624 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
625 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
626 | CLANG_WARN_STRICT_PROTOTYPES = YES;
627 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
628 | CLANG_WARN_UNREACHABLE_CODE = YES;
629 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
630 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
631 | COPY_PHASE_STRIP = YES;
632 | ENABLE_NS_ASSERTIONS = NO;
633 | ENABLE_STRICT_OBJC_MSGSEND = YES;
634 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
635 | GCC_C_LANGUAGE_STANDARD = gnu99;
636 | GCC_NO_COMMON_BLOCKS = YES;
637 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
638 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
639 | GCC_WARN_UNDECLARED_SELECTOR = YES;
640 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
641 | GCC_WARN_UNUSED_FUNCTION = YES;
642 | GCC_WARN_UNUSED_VARIABLE = YES;
643 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
644 | LD_RUNPATH_SEARCH_PATHS = (
645 | /usr/lib/swift,
646 | "$(inherited)",
647 | );
648 | LIBRARY_SEARCH_PATHS = (
649 | "\"$(SDKROOT)/usr/lib/swift\"",
650 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
651 | "\"$(inherited)\"",
652 | );
653 | MTL_ENABLE_DEBUG_INFO = NO;
654 | OTHER_CPLUSPLUSFLAGS = (
655 | "$(OTHER_CFLAGS)",
656 | "-DFOLLY_NO_CONFIG",
657 | "-DFOLLY_MOBILE=1",
658 | "-DFOLLY_USE_LIBCPP=1",
659 | );
660 | SDKROOT = iphoneos;
661 | VALIDATE_PRODUCT = YES;
662 | };
663 | name = Release;
664 | };
665 | /* End XCBuildConfiguration section */
666 |
667 | /* Begin XCConfigurationList section */
668 | 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "NewArchitectureTests" */ = {
669 | isa = XCConfigurationList;
670 | buildConfigurations = (
671 | 00E356F61AD99517003FC87E /* Debug */,
672 | 00E356F71AD99517003FC87E /* Release */,
673 | );
674 | defaultConfigurationIsVisible = 0;
675 | defaultConfigurationName = Release;
676 | };
677 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NewArchitecture" */ = {
678 | isa = XCConfigurationList;
679 | buildConfigurations = (
680 | 13B07F941A680F5B00A75B9A /* Debug */,
681 | 13B07F951A680F5B00A75B9A /* Release */,
682 | );
683 | defaultConfigurationIsVisible = 0;
684 | defaultConfigurationName = Release;
685 | };
686 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NewArchitecture" */ = {
687 | isa = XCConfigurationList;
688 | buildConfigurations = (
689 | 83CBBA201A601CBA00E9B192 /* Debug */,
690 | 83CBBA211A601CBA00E9B192 /* Release */,
691 | );
692 | defaultConfigurationIsVisible = 0;
693 | defaultConfigurationName = Release;
694 | };
695 | /* End XCConfigurationList section */
696 | };
697 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
698 | }
699 |
--------------------------------------------------------------------------------