diff --git a/example/.editorconfig b/example/.editorconfig deleted file mode 100644 index 7c286132f..000000000 --- a/example/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -# Windows files -[*.bat] -end_of_line = crlf diff --git a/example/.eslintrc.js b/example/.eslintrc.js index 40c6dcd05..88d926280 100644 --- a/example/.eslintrc.js +++ b/example/.eslintrc.js @@ -1,4 +1,4 @@ module.exports = { - root: true, - extends: '@react-native-community', + root: true, + extends: ['@react-native-community', 'eslint-config-prettier'], }; diff --git a/example/.expo-shared/assets.json b/example/.expo-shared/assets.json new file mode 100644 index 000000000..1e6decfbb --- /dev/null +++ b/example/.expo-shared/assets.json @@ -0,0 +1,4 @@ +{ + "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, + "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true +} diff --git a/example/.gitattributes b/example/.gitattributes deleted file mode 100644 index eb8cfc9a2..000000000 --- a/example/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# specific for windows script files -*.bat text eol=crlf \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore index e08bc42a9..d0da187df 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -1,3 +1,21 @@ +node_modules/ +.expo/ +dist/ +npm-debug.* +*.jks +*.p8 +*.p12 +*.key +*.mobileprovision +*.orig.* +web-build/ + +# macOS +.DS_Store + +# @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8 +# The following patterns were generated by expo-cli + # OSX # .DS_Store @@ -20,6 +38,7 @@ DerivedData *.hmap *.ipa *.xcuserstate +project.xcworkspace # Android/IntelliJ # @@ -42,20 +61,15 @@ buck-out/ *.keystore !debug.keystore -# fastlane -# -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/ - -*/fastlane/report.xml -*/fastlane/Preview.html -*/fastlane/screenshots - -# Bundle artifact +# Bundle artifacts *.jsbundle # CocoaPods /ios/Pods/ -/ios/Podfile.lock \ No newline at end of file + +# Expo +.expo/ +web-build/ +dist/ + +# @end expo-cli \ No newline at end of file diff --git a/example/.watchmanconfig b/example/.watchmanconfig deleted file mode 100644 index 9e26dfeeb..000000000 --- a/example/.watchmanconfig +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/example/App.js b/example/App.js deleted file mode 100644 index 5f86429ec..000000000 --- a/example/App.js +++ /dev/null @@ -1,109 +0,0 @@ -import React, { Component } from 'react'; -import { - Platform, - StyleSheet, - Text, - View, - PermissionsAndroid, - BackHandler, - Alert -} from 'react-native'; - -import { DocumentView, RNPdftron, Config } from 'react-native-pdftron'; - -type Props = {}; -export default class App extends Component { - - constructor(props) { - super(props); - } - - onLeadingNavButtonPressed = () => { - console.log('leading nav button pressed'); - if (this._viewer) { - this._viewer.exportAnnotations().then((xfdf) => { - console.log('xfdf', xfdf); - }); - } - - if (Platform.OS === 'ios') { - Alert.alert( - 'App', - 'onLeadingNavButtonPressed', - [ - {text: 'OK', onPress: () => console.log('OK Pressed')}, - ], - { cancelable: true } - ) - } else { - BackHandler.exitApp(); - } - } - - onDocumentLoaded = () => { - // if (this._viewer) { - // const xfdf = '\n\n\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\tfont: Roboto 24pt;color: #363636\n\t\t\t 1 1 1 RG 1 1 1 rg /F0 24 Tf \n\t\t\tHELLO PDFTRON!!!\n\t\t\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n'; - // this._viewer.importAnnotations(xfdf); - // } - } - - onAnnotationChanged = ({action, annotations}) => { - // console.log('action', action); - // console.log('annotations', annotations); - // if (this._viewer) { - // this._viewer.exportAnnotations({annotList: annotations}).then((xfdf) => { - // console.log('xfdf for annotations', xfdf); - // }); - // } - } - - onZoomChanged = ({zoom}) => { - // console.log('zoom', zoom); - } - - onExportAnnotationCommand = ({action, xfdfCommand}) => { - console.log('action', action); - console.log('xfdfCommand', xfdfCommand); - } - - render() { - const path = "https://pdftron.s3.amazonaws.com/downloads/pl/PDFTRON_about.pdf"; - const myToolbar = { - [Config.CustomToolbarKey.Id]: 'myToolbar', - [Config.CustomToolbarKey.Name]: 'myToolbar', - [Config.CustomToolbarKey.Icon]: Config.ToolbarIcons.FillAndSign, - [Config.CustomToolbarKey.Items]: [Config.Tools.annotationCreateArrow, Config.Tools.annotationCreateCallout, Config.Buttons.undo] - }; - - return ( - this._viewer = c} - // hideDefaultAnnotationToolbars={[Config.DefaultToolbars.Annotate]} - // annotationToolbars={[Config.DefaultToolbars.Annotate, myToolbar]} - hideAnnotationToolbarSwitcher={false} - hideTopToolbars={false} - hideTopAppNavBar={false} - document={path} - padStatusBar={true} - showLeadingNavButton={true} - leadingNavButtonIcon={Platform.OS === 'ios' ? 'ic_close_black_24px.png' : 'ic_arrow_back_white_24dp'} - onLeadingNavButtonPressed={this.onLeadingNavButtonPressed} - onDocumentLoaded={this.onDocumentLoaded} - onAnnotationChanged={this.onAnnotationChanged} - onExportAnnotationCommand={this.onExportAnnotationCommand} - onZoomChanged={this.onZoomChanged} - readOnly={false} - disabledElements={[Config.Buttons.userBookmarkListButton]} - disabledTools={[Config.Tools.annotationCreateLine, Config.Tools.annotationCreateRectangle]} - fitMode={Config.FitMode.FitPage} - layoutMode={Config.LayoutMode.Continuous} - /> - ); - } -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - } -}); diff --git a/example/App.tsx b/example/App.tsx new file mode 100644 index 000000000..19ee3f5c2 --- /dev/null +++ b/example/App.tsx @@ -0,0 +1,60 @@ +import 'react-native-gesture-handler'; + +import React from 'react'; +import {NavigationContainer} from '@react-navigation/native'; +import {createStackNavigator} from '@react-navigation/stack'; +import {SafeAreaProvider} from 'react-native-safe-area-context'; + +import * as FileSystem from 'expo-file-system'; + +import Browser from './components/Browser'; +import PDFViewer from './components/PDFViewer'; + +if (typeof Intl === 'undefined') { + require('intl'); + require('intl/locale-data/jsonp/en'); +} + +type StackParams = { + Browser: {currDir: string; path: string}; + PDFViewer: {currDir: string; path: string}; + MiscFileViewer: {currDir: string; path: string}; +}; + +const Stack = createStackNavigator(); + +export default function App() { + const root: string = FileSystem.documentDirectory || ''; + const path = root.endsWith('/') ? root.substring(0, root.length - 1) : root; + + return ( + + + + ({ + title: route?.params?.currDir || 'Browser', + })} + /> + ({ + title: route?.params?.currDir || 'PDFViewer', + })} + /> + + + + ); +} diff --git a/example/android/.gitignore b/example/android/.gitignore new file mode 100644 index 000000000..64436baaf --- /dev/null +++ b/example/android/.gitignore @@ -0,0 +1,21 @@ +# OSX +# +.DS_Store + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof + +# BUCK +buck-out/ +\.buckd/ +*.keystore +!debug.keystore + +# Bundle artifacts +*.jsbundle diff --git a/example/android/app/_BUCK b/example/android/app/BUCK similarity index 100% rename from example/android/app/_BUCK rename to example/android/app/BUCK diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 2db983dd4..ffc4e5555 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -77,11 +77,17 @@ import com.android.build.OutputFile * ] */ +def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath() + project.ext.react = [ - enableHermes: false, // clean and rebuild if changing + entryFile: ["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android"].execute(null, rootDir).text.trim(), + enableHermes: (findProperty('expo.jsEngine') ?: "jsc") == "hermes", + cliPath: new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/cli.js", + hermesCommand: new File(["node", "--print", "require.resolve('hermes-engine/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/%OS-BIN%/hermesc", + composeSourceMapsPath: new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/scripts/compose-source-maps.js", ] -apply from: "../../node_modules/react-native/react.gradle" +apply from: new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../react.gradle") /** * Set this to true to create two separate APKs instead of one: @@ -96,7 +102,7 @@ def enableSeparateBuildPerCPUArchitecture = false /** * Run Proguard to shrink the Java bytecode in release builds. */ -def enableProguardInReleaseBuilds = false +def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInReleaseBuilds') ?: false).toBoolean() /** * The preferred build flavor of JavaScriptCore. @@ -114,16 +120,19 @@ def jscFlavor = 'org.webkit:android-jsc:+' /** * Whether to enable the Hermes VM. * - * This should be set on project.ext.react and mirrored here. If it is not set + * This should be set on project.ext.react and that value will be read here. If it is not set * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode * and the benefits of using Hermes will therefore be sharply reduced. */ def enableHermes = project.ext.react.get("enableHermes", false); /** - * Architectures to build native code for in debug. + * Architectures to build native code for. */ -def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures") +def reactNativeArchitectures() { + def value = project.getProperties().get("reactNativeArchitectures") + return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] +} android { ndkVersion rootProject.ext.ndkVersion @@ -131,21 +140,89 @@ android { compileSdkVersion rootProject.ext.compileSdkVersion defaultConfig { - applicationId "com.example" + applicationId 'com.example' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 - versionName "1.0" + versionName "1.0.0" + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() multiDexEnabled true - manifestPlaceholders = [pdftronLicenseKey:PDFTRON_LICENSE_KEY] + + if (isNewArchitectureEnabled()) { + // We configure the NDK build only if you decide to opt-in for the New Architecture. + externalNativeBuild { + ndkBuild { + arguments "APP_PLATFORM=android-21", + "APP_STL=c++_shared", + "NDK_TOOLCHAIN_VERSION=clang", + "GENERATED_SRC_DIR=$buildDir/generated/source", + "PROJECT_BUILD_DIR=$buildDir", + "REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid", + "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build", + "NODE_MODULES_DIR=$rootDir/../node_modules" + cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1" + cppFlags "-std=c++17" + // Make sure this target name is the same you specify inside the + // src/main/jni/Android.mk file for the `LOCAL_MODULE` variable. + targets "example_appmodules" + } + } + if (!enableSeparateBuildPerCPUArchitecture) { + ndk { + abiFilters (*reactNativeArchitectures()) + } + } + } } + + if (isNewArchitectureEnabled()) { + // We configure the NDK build only if you decide to opt-in for the New Architecture. + externalNativeBuild { + ndkBuild { + path "$projectDir/src/main/jni/Android.mk" + } + } + def reactAndroidProjectDir = project(':ReactAndroid').projectDir + def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) { + dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck") + from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") + into("$buildDir/react-ndk/exported") + } + def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) { + dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck") + from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") + into("$buildDir/react-ndk/exported") + } + afterEvaluate { + // If you wish to add a custom TurboModule or component locally, + // you should uncomment this line. + // preBuild.dependsOn("generateCodegenArtifactsFromSchema") + preDebugBuild.dependsOn(packageReactNdkDebugLibs) + preReleaseBuild.dependsOn(packageReactNdkReleaseLibs) + + // Due to a bug inside AGP, we have to explicitly set a dependency + // between configureNdkBuild* tasks and the preBuild tasks. + // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732 + configureNdkBuildRelease.dependsOn(preReleaseBuild) + configureNdkBuildDebug.dependsOn(preDebugBuild) + reactNativeArchitectures().each { architecture -> + tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure { + dependsOn("preDebugBuild") + } + tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure { + dependsOn("preReleaseBuild") + } + } + } + } + splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK - include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" + include (*reactNativeArchitectures()) } } signingConfigs { @@ -159,11 +236,6 @@ android { buildTypes { debug { signingConfig signingConfigs.debug - if (nativeArchitectures) { - ndk { - abiFilters nativeArchitectures.split(',') - } - } } release { // Caution! In production, you need to generate your own keystore file. @@ -179,47 +251,107 @@ android { variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // https://developer.android.com/studio/build/configure-apk-splits.html - // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = - defaultConfig.versionCode * 1000 + versionCodes.get(abi) + versionCodes.get(abi) * 1048576 + defaultConfig.versionCode } } } } +// Apply static values from `gradle.properties` to the `android.packagingOptions` +// Accepts values in comma delimited lists, example: +// android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini +["pickFirsts", "excludes", "merges", "doNotStrip"].each { prop -> + // Split option: 'foo,bar' -> ['foo', 'bar'] + def options = (findProperty("android.packagingOptions.$prop") ?: "").split(","); + // Trim all elements in place. + for (i in 0.. 0) { + println "android.packagingOptions.$prop += $options ($options.length)" + // Ex: android.packagingOptions.pickFirsts += '**/SCCS/**' + options.each { + android.packagingOptions[prop] += it + } + } +} + dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation "androidx.multidex:multidex:2.0.1" + //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" // From node_modules - implementation 'androidx.multidex:multidex:2.0.1' + def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true"; + def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true"; + def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true"; + def frescoVersion = rootProject.ext.frescoVersion + + // If your app supports Android versions before Ice Cream Sandwich (API level 14) + if (isGifEnabled || isWebpEnabled) { + implementation "com.facebook.fresco:fresco:${frescoVersion}" + implementation "com.facebook.fresco:imagepipeline-okhttp3:${frescoVersion}" + } + + if (isGifEnabled) { + // For animated gif support + implementation "com.facebook.fresco:animated-gif:${frescoVersion}" + } + if (isWebpEnabled) { + // For webp support + implementation "com.facebook.fresco:webpsupport:${frescoVersion}" + if (isWebpAnimatedEnabled) { + // Animated webp support + implementation "com.facebook.fresco:animated-webp:${frescoVersion}" + } + } + + implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { exclude group:'com.facebook.fbjni' } - debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' exclude group:'com.squareup.okhttp3', module:'okhttp' } - debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' } if (enableHermes) { - def hermesPath = "../../node_modules/hermes-engine/android/"; - debugImplementation files(hermesPath + "hermes-debug.aar") - releaseImplementation files(hermesPath + "hermes-release.aar") + //noinspection GradleDynamicVersion + implementation("com.facebook.react:hermes-engine:+") { // From node_modules + exclude group:'com.facebook.fbjni' + } } else { implementation jscFlavor } } +if (isNewArchitectureEnabled()) { + // If new architecture is enabled, we let you build RN from source + // Otherwise we fallback to a prebuilt .aar bundled in the NPM package. + // This will be applied to all the imported transtitive dependency. + configurations.all { + resolutionStrategy.dependencySubstitution { + substitute(module("com.facebook.react:react-native")) + .using(project(":ReactAndroid")) + .because("On New Architecture we're building React Native from source") + substitute(module("com.facebook.react:hermes-engine")) + .using(project(":ReactAndroid:hermes-engine")) + .because("On New Architecture we're building Hermes from source") + } + } +} + // Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { @@ -227,4 +359,13 @@ task copyDownloadableDepsToLibs(type: Copy) { into 'libs' } -apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) \ No newline at end of file +apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle"); +applyNativeModulesAppBuildGradle(project) + +def isNewArchitectureEnabled() { + // To opt-in for the New Architecture, you can either: + // - Set `newArchEnabled` to true inside the `gradle.properties` file + // - Invoke gradle with `-newArchEnabled=true` + // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} diff --git a/example/android/app/proguard-rules.pro b/example/android/app/proguard-rules.pro index 11b025724..551eb41da 100644 --- a/example/android/app/proguard-rules.pro +++ b/example/android/app/proguard-rules.pro @@ -7,4 +7,8 @@ # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html +# react-native-reanimated +-keep class com.swmansion.reanimated.** { *; } +-keep class com.facebook.react.turbomodule.** { *; } + # Add any project specific keep options here: diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml index b2f3ad9fc..99e38fc5f 100644 --- a/example/android/app/src/debug/AndroidManifest.xml +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -1,13 +1,7 @@ - - - - + diff --git a/example/android/app/src/debug/java/com/example/ReactNativeFlipper.java b/example/android/app/src/debug/java/com/example/ReactNativeFlipper.java index 5c77da91e..697b14081 100644 --- a/example/android/app/src/debug/java/com/example/ReactNativeFlipper.java +++ b/example/android/app/src/debug/java/com/example/ReactNativeFlipper.java @@ -25,48 +25,45 @@ import okhttp3.OkHttpClient; public class ReactNativeFlipper { - public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (FlipperUtils.shouldEnableFlipper(context)) { - final FlipperClient client = AndroidFlipperClient.getInstance(context); - - client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); - client.addPlugin(new ReactFlipperPlugin()); - client.addPlugin(new DatabasesFlipperPlugin(context)); - client.addPlugin(new SharedPreferencesFlipperPlugin(context)); - client.addPlugin(CrashReporterPlugin.getInstance()); - - NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); - NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { - @Override - public void apply(OkHttpClient.Builder builder) { - builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); - } - }); - client.addPlugin(networkFlipperPlugin); - client.start(); - - // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized - // Hence we run if after all native modules have been initialized - ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); - if (reactContext == null) { - reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceManager.ReactInstanceEventListener() { - @Override - public void onReactContextInitialized(ReactContext reactContext) { - reactInstanceManager.removeReactInstanceEventListener(this); - reactContext.runOnNativeModulesQueueThread( - new Runnable() { - @Override - public void run() { - client.addPlugin(new FrescoFlipperPlugin()); - } - }); - } - }); - } else { - client.addPlugin(new FrescoFlipperPlugin()); + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + if (FlipperUtils.shouldEnableFlipper(context)) { + final FlipperClient client = AndroidFlipperClient.getInstance(context); + client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); + client.addPlugin(new ReactFlipperPlugin()); + client.addPlugin(new DatabasesFlipperPlugin(context)); + client.addPlugin(new SharedPreferencesFlipperPlugin(context)); + client.addPlugin(CrashReporterPlugin.getInstance()); + NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); + NetworkingModule.setCustomClientBuilder( + new NetworkingModule.CustomClientBuilder() { + @Override + public void apply(OkHttpClient.Builder builder) { + builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); } - } + }); + client.addPlugin(networkFlipperPlugin); + client.start(); + // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized + // Hence we run if after all native modules have been initialized + ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); + if (reactContext == null) { + reactInstanceManager.addReactInstanceEventListener( + new ReactInstanceManager.ReactInstanceEventListener() { + @Override + public void onReactContextInitialized(ReactContext reactContext) { + reactInstanceManager.removeReactInstanceEventListener(this); + reactContext.runOnNativeModulesQueueThread( + new Runnable() { + @Override + public void run() { + client.addPlugin(new FrescoFlipperPlugin()); + } + }); + } + }); + } else { + client.addPlugin(new FrescoFlipperPlugin()); + } } + } } \ No newline at end of file diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 15ad2df60..d781b75aa 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,34 +1,69 @@ - + - - + + + + + + - + + + + + + + + + + + + + + + + + + - - - - - - - - - - + android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" + android:launchMode="singleTask" + android:windowSoftInputMode="adjustPan" + android:theme="@style/Theme.App.SplashScreen" + android:exported="true" + android:screenOrientation="portrait"> + + + + + + + + + + + + + + + + + + + + + diff --git a/example/android/app/src/main/java/com/example/MainActivity.java b/example/android/app/src/main/java/com/example/MainActivity.java index 8aa8cb2ee..bbb394483 100644 --- a/example/android/app/src/main/java/com/example/MainActivity.java +++ b/example/android/app/src/main/java/com/example/MainActivity.java @@ -1,15 +1,57 @@ package com.example; +import android.os.Build; +import android.os.Bundle; + import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.ReactRootView; + +import expo.modules.ReactActivityDelegateWrapper; public class MainActivity extends ReactActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + // Set the theme to AppTheme BEFORE onCreate to support + // coloring the background, status bar, and navigation bar. + // This is required for expo-splash-screen. + setTheme(R.style.AppTheme); + super.onCreate(null); + } /** - * Returns the name of the main component registered from JavaScript. This is used to schedule - * rendering of the component. + * Returns the name of the main component registered from JavaScript. + * This is used to schedule rendering of the component. */ @Override protected String getMainComponentName() { - return "example"; + return "main"; + } + + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new ReactActivityDelegateWrapper(this, + new ReactActivityDelegate(this, getMainComponentName()) + ); + } + + /** + * Align the back button behavior with Android S + * where moving root activities to background instead of finishing activities. + * @see onBackPressed + */ + @Override + public void invokeDefaultOnBackPressed() { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!moveTaskToBack(false)) { + // For non-root activities, use the default implementation to finish them. + super.invokeDefaultOnBackPressed(); + } + return; + } + + // Use the default back button implementation on Android S + // because it's doing more than {@link Activity#moveTaskToBack} in fact. + super.invokeDefaultOnBackPressed(); } } diff --git a/example/android/app/src/main/java/com/example/MainApplication.java b/example/android/app/src/main/java/com/example/MainApplication.java index f62a45343..5b2293010 100644 --- a/example/android/app/src/main/java/com/example/MainApplication.java +++ b/example/android/app/src/main/java/com/example/MainApplication.java @@ -1,61 +1,87 @@ package com.example; +import androidx.multidex.MultiDexApplication; import android.content.Context; +import android.content.res.Configuration; +import androidx.annotation.NonNull; import com.facebook.react.PackageList; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.soloader.SoLoader; +import com.example.newarchitecture.MainApplicationReactNativeHost; + +import expo.modules.ApplicationLifecycleDispatcher; +import expo.modules.ReactNativeHostWrapper; import java.lang.reflect.InvocationTargetException; import java.util.List; -import androidx.multidex.MultiDexApplication; - public class MainApplication extends MultiDexApplication implements ReactApplication { + private final ReactNativeHost mReactNativeHost = new ReactNativeHostWrapper( + this, + new ReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } - private final ReactNativeHost mReactNativeHost = - new ReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return packages; + } - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") - List packages = new PackageList(this).getPackages(); - // Packages that cannot be autolinked yet can be added manually here, for example: - // packages.add(new MyReactNativePackage()); - return packages; - } + @Override + protected String getJSMainModuleName() { + return "index"; + } + }); - @Override - protected String getJSMainModuleName() { - return "index"; - } - }; + private final ReactNativeHost mNewArchitectureNativeHost = + new ReactNativeHostWrapper(this, new MainApplicationReactNativeHost(this)); @Override public ReactNativeHost getReactNativeHost() { - return mReactNativeHost; + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + return mNewArchitectureNativeHost; + } else { + return mReactNativeHost; + } } @Override public void onCreate() { super.onCreate(); + // If you opted-in for the New Architecture, we enable the TurboModule system + ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; SoLoader.init(this, /* native exopackage */ false); + initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + ApplicationLifecycleDispatcher.onApplicationCreate(this); + } + + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig); } /** - * Loads Flipper in React Native templates. + * Loads Flipper in React Native templates. Call this in the onCreate method with something like + * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); * * @param context + * @param reactInstanceManager */ - private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + private static void initializeFlipper( + Context context, ReactInstanceManager reactInstanceManager) { if (BuildConfig.DEBUG) { try { /* diff --git a/example/android/app/src/main/java/com/example/newarchitecture/MainApplicationReactNativeHost.java b/example/android/app/src/main/java/com/example/newarchitecture/MainApplicationReactNativeHost.java new file mode 100644 index 000000000..68aea2808 --- /dev/null +++ b/example/android/app/src/main/java/com/example/newarchitecture/MainApplicationReactNativeHost.java @@ -0,0 +1,116 @@ +package com.example.newarchitecture; + +import android.app.Application; +import androidx.annotation.NonNull; +import com.facebook.react.PackageList; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.ReactPackageTurboModuleManagerDelegate; +import com.facebook.react.bridge.JSIModulePackage; +import com.facebook.react.bridge.JSIModuleProvider; +import com.facebook.react.bridge.JSIModuleSpec; +import com.facebook.react.bridge.JSIModuleType; +import com.facebook.react.bridge.JavaScriptContextHolder; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.UIManager; +import com.facebook.react.fabric.ComponentFactory; +import com.facebook.react.fabric.CoreComponentsRegistry; +import com.facebook.react.fabric.FabricJSIModuleProvider; +import com.facebook.react.fabric.ReactNativeConfig; +import com.facebook.react.uimanager.ViewManagerRegistry; +import com.example.BuildConfig; +import com.example.newarchitecture.components.MainComponentsRegistry; +import com.example.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate; +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both + * TurboModule delegates and the Fabric Renderer. + * + *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +public class MainApplicationReactNativeHost extends ReactNativeHost { + public MainApplicationReactNativeHost(Application application) { + super(application); + } + + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + // TurboModules must also be loaded here providing a valid TurboReactPackage implementation: + // packages.add(new TurboReactPackage() { ... }); + // If you have custom Fabric Components, their ViewManagers should also be loaded here + // inside a ReactPackage. + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @NonNull + @Override + protected ReactPackageTurboModuleManagerDelegate.Builder + getReactPackageTurboModuleManagerDelegateBuilder() { + // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary + // for the new architecture and to use TurboModules correctly. + return new MainApplicationTurboModuleManagerDelegate.Builder(); + } + + @Override + protected JSIModulePackage getJSIModulePackage() { + return new JSIModulePackage() { + @Override + public List getJSIModules( + final ReactApplicationContext reactApplicationContext, + final JavaScriptContextHolder jsContext) { + final List specs = new ArrayList<>(); + + // Here we provide a new JSIModuleSpec that will be responsible of providing the + // custom Fabric Components. + specs.add( + new JSIModuleSpec() { + @Override + public JSIModuleType getJSIModuleType() { + return JSIModuleType.UIManager; + } + + @Override + public JSIModuleProvider getJSIModuleProvider() { + final ComponentFactory componentFactory = new ComponentFactory(); + CoreComponentsRegistry.register(componentFactory); + + // Here we register a Components Registry. + // The one that is generated with the template contains no components + // and just provides you the one from React Native core. + MainComponentsRegistry.register(componentFactory); + + final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); + + ViewManagerRegistry viewManagerRegistry = + new ViewManagerRegistry( + reactInstanceManager.getOrCreateViewManagers(reactApplicationContext)); + + return new FabricJSIModuleProvider( + reactApplicationContext, + componentFactory, + ReactNativeConfig.DEFAULT_CONFIG, + viewManagerRegistry); + } + }); + return specs; + } + }; + } +} diff --git a/example/android/app/src/main/java/com/example/newarchitecture/components/MainComponentsRegistry.java b/example/android/app/src/main/java/com/example/newarchitecture/components/MainComponentsRegistry.java new file mode 100644 index 000000000..98ff97382 --- /dev/null +++ b/example/android/app/src/main/java/com/example/newarchitecture/components/MainComponentsRegistry.java @@ -0,0 +1,36 @@ +package com.example.newarchitecture.components; + +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.fabric.ComponentFactory; +import com.facebook.soloader.SoLoader; + +/** + * Class responsible to load the custom Fabric Components. This class has native methods and needs a + * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ + * folder for you). + * + *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +@DoNotStrip +public class MainComponentsRegistry { + static { + SoLoader.loadLibrary("fabricjni"); + } + + @DoNotStrip private final HybridData mHybridData; + + @DoNotStrip + private native HybridData initHybrid(ComponentFactory componentFactory); + + @DoNotStrip + private MainComponentsRegistry(ComponentFactory componentFactory) { + mHybridData = initHybrid(componentFactory); + } + + @DoNotStrip + public static MainComponentsRegistry register(ComponentFactory componentFactory) { + return new MainComponentsRegistry(componentFactory); + } +} diff --git a/example/android/app/src/main/java/com/example/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java b/example/android/app/src/main/java/com/example/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java new file mode 100644 index 000000000..b30c50e2d --- /dev/null +++ b/example/android/app/src/main/java/com/example/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java @@ -0,0 +1,48 @@ +package com.example.newarchitecture.modules; + +import com.facebook.jni.HybridData; +import com.facebook.react.ReactPackage; +import com.facebook.react.ReactPackageTurboModuleManagerDelegate; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.soloader.SoLoader; +import java.util.List; + +/** + * Class responsible to load the TurboModules. This class has native methods and needs a + * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ + * folder for you). + * + *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +public class MainApplicationTurboModuleManagerDelegate + extends ReactPackageTurboModuleManagerDelegate { + + private static volatile boolean sIsSoLibraryLoaded; + + protected MainApplicationTurboModuleManagerDelegate( + ReactApplicationContext reactApplicationContext, List packages) { + super(reactApplicationContext, packages); + } + + protected native HybridData initHybrid(); + + native boolean canCreateTurboModule(String moduleName); + + public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { + protected MainApplicationTurboModuleManagerDelegate build( + ReactApplicationContext context, List packages) { + return new MainApplicationTurboModuleManagerDelegate(context, packages); + } + } + + @Override + protected synchronized void maybeLoadOtherSoLibraries() { + if (!sIsSoLibraryLoaded) { + // If you change the name of your application .so file in the Android.mk file, + // make sure you update the name here as well. + SoLoader.loadLibrary("example_appmodules"); + sIsSoLibraryLoaded = true; + } + } +} diff --git a/example/android/app/src/main/jni/Android.mk b/example/android/app/src/main/jni/Android.mk new file mode 100644 index 000000000..bb9c6712c --- /dev/null +++ b/example/android/app/src/main/jni/Android.mk @@ -0,0 +1,48 @@ +THIS_DIR := $(call my-dir) + +include $(REACT_ANDROID_DIR)/Android-prebuilt.mk + +# If you wish to add a custom TurboModule or Fabric component in your app you +# will have to include the following autogenerated makefile. +# include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk +include $(CLEAR_VARS) + +LOCAL_PATH := $(THIS_DIR) + +# You can customize the name of your application .so file here. +LOCAL_MODULE := example_appmodules + +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) + +# If you wish to add a custom TurboModule or Fabric component in your app you +# will have to uncomment those lines to include the generated source +# files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni) +# +# LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni +# LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp) +# LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni + +# Here you should add any native library you wish to depend on. +LOCAL_SHARED_LIBRARIES := \ + libfabricjni \ + libfbjni \ + libfolly_runtime \ + libglog \ + libjsi \ + libreact_codegen_rncore \ + libreact_debug \ + libreact_nativemodule_core \ + libreact_render_componentregistry \ + libreact_render_core \ + libreact_render_debug \ + libreact_render_graphics \ + librrc_view \ + libruntimeexecutor \ + libturbomodulejsijni \ + libyoga + +LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall + +include $(BUILD_SHARED_LIBRARY) diff --git a/example/android/app/src/main/jni/MainApplicationModuleProvider.cpp b/example/android/app/src/main/jni/MainApplicationModuleProvider.cpp new file mode 100644 index 000000000..0ac23cc62 --- /dev/null +++ b/example/android/app/src/main/jni/MainApplicationModuleProvider.cpp @@ -0,0 +1,24 @@ +#include "MainApplicationModuleProvider.h" + +#include + +namespace facebook { +namespace react { + +std::shared_ptr MainApplicationModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms) { + // Here you can provide your own module provider for TurboModules coming from + // either your application or from external libraries. The approach to follow + // is similar to the following (for a library called `samplelibrary`: + // + // auto module = samplelibrary_ModuleProvider(moduleName, params); + // if (module != nullptr) { + // return module; + // } + // return rncore_ModuleProvider(moduleName, params); + return rncore_ModuleProvider(moduleName, params); +} + +} // namespace react +} // namespace facebook diff --git a/example/android/app/src/main/jni/MainApplicationModuleProvider.h b/example/android/app/src/main/jni/MainApplicationModuleProvider.h new file mode 100644 index 000000000..0fa43fa69 --- /dev/null +++ b/example/android/app/src/main/jni/MainApplicationModuleProvider.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +#include + +namespace facebook { +namespace react { + +std::shared_ptr MainApplicationModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms); + +} // namespace react +} // namespace facebook diff --git a/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp b/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp new file mode 100644 index 000000000..dbbdc3d13 --- /dev/null +++ b/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp @@ -0,0 +1,45 @@ +#include "MainApplicationTurboModuleManagerDelegate.h" +#include "MainApplicationModuleProvider.h" + +namespace facebook { +namespace react { + +jni::local_ref +MainApplicationTurboModuleManagerDelegate::initHybrid( + jni::alias_ref) { + return makeCxxInstance(); +} + +void MainApplicationTurboModuleManagerDelegate::registerNatives() { + registerHybrid({ + makeNativeMethod( + "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), + makeNativeMethod( + "canCreateTurboModule", + MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), + }); +} + +std::shared_ptr +MainApplicationTurboModuleManagerDelegate::getTurboModule( + const std::string name, + const std::shared_ptr jsInvoker) { + // Not implemented yet: provide pure-C++ NativeModules here. + return nullptr; +} + +std::shared_ptr +MainApplicationTurboModuleManagerDelegate::getTurboModule( + const std::string name, + const JavaTurboModule::InitParams ¶ms) { + return MainApplicationModuleProvider(name, params); +} + +bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( + std::string name) { + return getTurboModule(name, nullptr) != nullptr || + getTurboModule(name, {.moduleName = name}) != nullptr; +} + +} // namespace react +} // namespace facebook diff --git a/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h b/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h new file mode 100644 index 000000000..9dc2af651 --- /dev/null +++ b/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h @@ -0,0 +1,38 @@ +#include +#include + +#include +#include + +namespace facebook { +namespace react { + +class MainApplicationTurboModuleManagerDelegate + : public jni::HybridClass< + MainApplicationTurboModuleManagerDelegate, + TurboModuleManagerDelegate> { + public: + // Adapt it to the package you used for your Java class. + static constexpr auto kJavaDescriptor = + "Lcom/example/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; + + static jni::local_ref initHybrid(jni::alias_ref); + + static void registerNatives(); + + std::shared_ptr getTurboModule( + const std::string name, + const std::shared_ptr jsInvoker) override; + std::shared_ptr getTurboModule( + const std::string name, + const JavaTurboModule::InitParams ¶ms) override; + + /** + * Test-only method. Allows user to verify whether a TurboModule can be + * created by instances of this class. + */ + bool canCreateTurboModule(std::string name); +}; + +} // namespace react +} // namespace facebook diff --git a/example/android/app/src/main/jni/MainComponentsRegistry.cpp b/example/android/app/src/main/jni/MainComponentsRegistry.cpp new file mode 100644 index 000000000..8f7edffd6 --- /dev/null +++ b/example/android/app/src/main/jni/MainComponentsRegistry.cpp @@ -0,0 +1,61 @@ +#include "MainComponentsRegistry.h" + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {} + +std::shared_ptr +MainComponentsRegistry::sharedProviderRegistry() { + auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); + + // Custom Fabric Components go here. You can register custom + // components coming from your App or from 3rd party libraries here. + // + // providerRegistry->add(concreteComponentDescriptorProvider< + // AocViewerComponentDescriptor>()); + return providerRegistry; +} + +jni::local_ref +MainComponentsRegistry::initHybrid( + jni::alias_ref, + ComponentFactory *delegate) { + auto instance = makeCxxInstance(delegate); + + auto buildRegistryFunction = + [](EventDispatcher::Weak const &eventDispatcher, + ContextContainer::Shared const &contextContainer) + -> ComponentDescriptorRegistry::Shared { + auto registry = MainComponentsRegistry::sharedProviderRegistry() + ->createComponentDescriptorRegistry( + {eventDispatcher, contextContainer}); + + auto mutableRegistry = + std::const_pointer_cast(registry); + + mutableRegistry->setFallbackComponentDescriptor( + std::make_shared( + ComponentDescriptorParameters{ + eventDispatcher, contextContainer, nullptr})); + + return registry; + }; + + delegate->buildRegistryFunction = buildRegistryFunction; + return instance; +} + +void MainComponentsRegistry::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid), + }); +} + +} // namespace react +} // namespace facebook diff --git a/example/android/app/src/main/jni/MainComponentsRegistry.h b/example/android/app/src/main/jni/MainComponentsRegistry.h new file mode 100644 index 000000000..23a9cace3 --- /dev/null +++ b/example/android/app/src/main/jni/MainComponentsRegistry.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +class MainComponentsRegistry + : public facebook::jni::HybridClass { + public: + // Adapt it to the package you used for your Java class. + constexpr static auto kJavaDescriptor = + "Lcom/example/newarchitecture/components/MainComponentsRegistry;"; + + static void registerNatives(); + + MainComponentsRegistry(ComponentFactory *delegate); + + private: + static std::shared_ptr + sharedProviderRegistry(); + + static jni::local_ref initHybrid( + jni::alias_ref, + ComponentFactory *delegate); +}; + +} // namespace react +} // namespace facebook diff --git a/example/android/app/src/main/jni/OnLoad.cpp b/example/android/app/src/main/jni/OnLoad.cpp new file mode 100644 index 000000000..c569b6e86 --- /dev/null +++ b/example/android/app/src/main/jni/OnLoad.cpp @@ -0,0 +1,11 @@ +#include +#include "MainApplicationTurboModuleManagerDelegate.h" +#include "MainComponentsRegistry.h" + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { + return facebook::jni::initialize(vm, [] { + facebook::react::MainApplicationTurboModuleManagerDelegate:: + registerNatives(); + facebook::react::MainComponentsRegistry::registerNatives(); + }); +} diff --git a/example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png b/example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png new file mode 100644 index 000000000..c52c2c680 Binary files /dev/null and b/example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png differ diff --git a/example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png b/example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png new file mode 100644 index 000000000..c52c2c680 Binary files /dev/null and b/example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png differ diff --git a/example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png b/example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png new file mode 100644 index 000000000..c52c2c680 Binary files /dev/null and b/example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png differ diff --git a/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png b/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png new file mode 100644 index 000000000..c52c2c680 Binary files /dev/null and b/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png differ diff --git a/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png b/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png new file mode 100644 index 000000000..c52c2c680 Binary files /dev/null and b/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png differ diff --git a/example/android/app/src/main/res/drawable/rn_edit_text_material.xml b/example/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 000000000..f35d99620 --- /dev/null +++ b/example/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/example/android/app/src/main/res/drawable/splashscreen.xml b/example/android/app/src/main/res/drawable/splashscreen.xml new file mode 100644 index 000000000..c8568e162 --- /dev/null +++ b/example/android/app/src/main/res/drawable/splashscreen.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..3941bea9b --- /dev/null +++ b/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..3941bea9b --- /dev/null +++ b/example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index a2f590828..7fae0ccbc 100644 Binary files a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..135d15eec Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index 1b5239980..afa0a4ef4 100644 Binary files a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index ff10afd6e..78aaf4541 100644 Binary files a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..880334f48 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index 115a4c768..c4f6e101e 100644 Binary files a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index dcd3cd808..7a0f085fa 100644 Binary files a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..6f951effb Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 459ca609d..6c2d40bf5 100644 Binary files a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 8ca12fe02..730e3fa55 100644 Binary files a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..0cdce03a8 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index 8e19b410a..345261586 100644 Binary files a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index b824ebdd4..b11a322ab 100644 Binary files a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..eaa8cd141 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index 4c19a13c2..b51fd15c2 100644 Binary files a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/values-night/colors.xml b/example/android/app/src/main/res/values-night/colors.xml new file mode 100644 index 000000000..3c05de5be --- /dev/null +++ b/example/android/app/src/main/res/values-night/colors.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/example/android/app/src/main/res/values/colors.xml b/example/android/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..bb2087f7b --- /dev/null +++ b/example/android/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + #ffffff + #FFFFFF + #023c69 + #ffffff + \ No newline at end of file diff --git a/example/android/app/src/main/res/values/strings.xml b/example/android/app/src/main/res/values/strings.xml index d75426c8a..eb4bdb110 100644 --- a/example/android/app/src/main/res/values/strings.xml +++ b/example/android/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ - example + example + contain + false diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml index 24bc06136..f03e23f85 100644 --- a/example/android/app/src/main/res/values/styles.xml +++ b/example/android/app/src/main/res/values/styles.xml @@ -1,8 +1,17 @@ - - - - - - + + + + + \ No newline at end of file diff --git a/example/android/build.gradle b/example/android/build.gradle index c76a80387..a19a7b074 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,20 +1,34 @@ +import org.apache.tools.ant.taskdefs.condition.Os + // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext { - buildToolsVersion = "30.0.2" - minSdkVersion = 21 - compileSdkVersion = 31 - targetSdkVersion = 31 - ndkVersion = "21.4.7075529" + buildToolsVersion = findProperty('android.buildToolsVersion') ?: '31.0.0' + minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '21') + compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '31') + targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '31') + if (findProperty('android.kotlinVersion')) { + kotlinVersion = findProperty('android.kotlinVersion') + } + frescoVersion = findProperty('expo.frescoVersion') ?: '2.5.0' + + if (System.properties['os.arch'] == 'aarch64') { + // For M1 Users we need to use the NDK 24 which added support for aarch64 + ndkVersion = '24.0.8215888' + } else { + // Otherwise we default to the side-by-side NDK version from AGP. + ndkVersion = '21.4.7075529' + } } repositories { google() mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:4.2.2") - + classpath('com.android.tools.build:gradle:7.1.1') + classpath('com.facebook.react:react-native-gradle-plugin') + classpath('de.undercouch:gradle-download-task:5.0.1') // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -25,15 +39,21 @@ allprojects { mavenLocal() maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url("$rootDir/../node_modules/react-native/android") + url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android')) } maven { // Android JSC is installed from npm - url("$rootDir/../node_modules/jsc-android/dist") + url(new File(['node', '--print', "require.resolve('jsc-android/package.json')"].execute(null, rootDir).text.trim(), '../dist')) } google() - mavenCentral() + mavenCentral { + // We don't want to fetch react-native from Maven Central as there are + // older versions over there. + content { + excludeGroup 'com.facebook.react' + } + } maven { url 'https://www.jitpack.io' } } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index bf0590c00..4674f52f1 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -9,19 +9,47 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true + +# Automatically convert third-party libraries to use AndroidX android.enableJetifier=true + # Version of flipper SDK to use with React Native -FLIPPER_VERSION=0.99.0 +FLIPPER_VERSION=0.125.0 + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# The hosted JavaScript engine +# Supported values: expo.jsEngine = "hermes" | "jsc" +expo.jsEngine=jsc -org.gradle.jvmargs=-Xmx2560M +# Enable GIF support in React Native images (~200 B increase) +expo.gif.enabled=true +# Enable webp support in React Native images (~85 KB increase) +expo.webp.enabled=true +# Enable animated webp support (~3.4 MB increase) +# Disabled by default because iOS doesn't support animated webp +expo.webp.animated=false -PDFTRON_LICENSE_KEY= \ No newline at end of file +PDFTRON_LICENSE_KEY= diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/example/android/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf01..7454180f2 100644 Binary files a/example/android/gradle/wrapper/gradle-wrapper.jar and b/example/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 7665b0fa9..669386b87 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/example/android/gradlew b/example/android/gradlew old mode 100644 new mode 100755 index 022f46f65..1b6c78733 --- a/example/android/gradlew +++ b/example/android/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,79 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/example/android/gradlew.bat b/example/android/gradlew.bat index 477c89664..107acd32c 100644 --- a/example/android/gradlew.bat +++ b/example/android/gradlew.bat @@ -86,4 +86,4 @@ exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal -:omega \ No newline at end of file +:omega diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 263c9e8ca..b93b61ec5 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,3 +1,17 @@ rootProject.name = 'example' -apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) + +apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle"); +useExpoModules() + +apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle"); +applyNativeModulesSettingsGradle(settings) + include ':app' +includeBuild(new File(["node", "--print", "require.resolve('react-native-gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile()) + +if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") { + include(":ReactAndroid") + project(":ReactAndroid").projectDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../ReactAndroid"); + include(":ReactAndroid:hermes-engine") + project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/ReactAndroid/hermes-engine') +} diff --git a/example/app.json b/example/app.json index 486d55b07..1f2907f0a 100644 --- a/example/app.json +++ b/example/app.json @@ -1,4 +1,35 @@ { - "name": "example", - "displayName": "example" -} \ No newline at end of file + "expo": { + "name": "example", + "slug": "example", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/icon.png", + "userInterfaceStyle": "light", + "splash": { + "image": "./assets/splash.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" + }, + "updates": { + "fallbackToCacheTimeout": 0 + }, + "assetBundlePatterns": [ + "**/*" + ], + "ios": { + "supportsTablet": true, + "bundleIdentifier": "example" + }, + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#FFFFFF" + }, + "package": "com.example" + }, + "web": { + "favicon": "./assets/favicon.png" + } + } +} diff --git a/example/assets/adaptive-icon.png b/example/assets/adaptive-icon.png new file mode 100644 index 000000000..03d6f6b6c Binary files /dev/null and b/example/assets/adaptive-icon.png differ diff --git a/example/assets/favicon.png b/example/assets/favicon.png new file mode 100644 index 000000000..e75f697b1 Binary files /dev/null and b/example/assets/favicon.png differ diff --git a/example/assets/icon.png b/example/assets/icon.png new file mode 100644 index 000000000..a0b1526fc Binary files /dev/null and b/example/assets/icon.png differ diff --git a/example/assets/splash.png b/example/assets/splash.png new file mode 100644 index 000000000..0e89705a9 Binary files /dev/null and b/example/assets/splash.png differ diff --git a/example/babel.config.js b/example/babel.config.js index f842b77fc..2900afe9d 100644 --- a/example/babel.config.js +++ b/example/babel.config.js @@ -1,3 +1,6 @@ -module.exports = { - presets: ['module:metro-react-native-babel-preset'], +module.exports = function(api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + }; }; diff --git a/example/components/BottomSheet.tsx b/example/components/BottomSheet.tsx new file mode 100644 index 000000000..cd6c12e10 --- /dev/null +++ b/example/components/BottomSheet.tsx @@ -0,0 +1,137 @@ +import React from 'react'; +import { + Animated, + StyleSheet, + TouchableOpacity, + TouchableWithoutFeedback, + View, + Text, + FlatList, + Dimensions, + Platform, +} from 'react-native'; +import Modal from 'react-native-modal'; + +import {MaterialCommunityIcons} from '@expo/vector-icons'; +import {useSafeAreaInsets} from 'react-native-safe-area-context'; + +type BottomSheetProps = { + visible: boolean; + onClose: () => void; + items: string[]; + itemIcons: React.ComponentProps['name'][]; + onItemPress: Array<() => void>; + title?: string; +}; + +type BottomSheetItemProps = { + item: string; + icon: React.ComponentProps['name']; + onPress: () => void; +}; + +const BottomSheetItem = ({item, icon, onPress}: BottomSheetItemProps) => { + return ( + + + + + {item} + + ); +}; + +const BottomSheet = ({ + visible, + onClose, + items, + itemIcons, + onItemPress, + title, +}: BottomSheetProps) => { + const insets = useSafeAreaInsets(); + + return ( + + + {title && ( + + {title} + + )} + item} + renderItem={({item, index}) => ( + { + onItemPress[index](); + onClose(); + }} + /> + )} + /> + + + ); +}; + +export default BottomSheet; + +const styles = StyleSheet.create({ + modal: { + margin: 0, + }, + modalBody: { + width: Dimensions.get('window').width, + backgroundColor: 'white', + position: 'absolute', + bottom: 0, + padding: 10, + borderTopLeftRadius: 10, + borderTopEndRadius: 10, + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.2, + shadowRadius: 8, + }, + titleContainer: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + paddingBottom: 15, + }, + titleText: { + color: 'black', + fontSize: 16, + textAlign: 'center', + }, + itemStyle: { + height: 45, + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-start', + }, + itemText: { + color: 'black', + fontSize: 15, + }, + iconContainer: { + marginLeft: 5, + marginRight: 10, + }, +}); diff --git a/example/components/Browser.tsx b/example/components/Browser.tsx new file mode 100644 index 000000000..5abd3aba7 --- /dev/null +++ b/example/components/Browser.tsx @@ -0,0 +1,343 @@ +import React, {useEffect, useState} from 'react'; +import { + FlatList, + StyleSheet, + Text, + TouchableOpacity, + View, + Alert, + Platform, +} from 'react-native'; +import {Snackbar, Menu, Provider} from 'react-native-paper'; +import * as FileSystem from 'expo-file-system'; +import * as DocumentPicker from 'expo-document-picker'; +import {StatusBar} from 'expo-status-bar'; + +import {StackScreenProps} from '@react-navigation/stack'; +import {useSafeAreaInsets} from 'react-native-safe-area-context'; + +import {MaterialCommunityIcons, MaterialIcons} from '@expo/vector-icons'; +import mime from 'react-native-mime-types'; +import {DateTime} from 'luxon'; + +import BottomSheet from './BottomSheet'; +import FileItem, {FileInfo} from './FileItem'; +import InputDialog from './InputDialog'; +import LoadingDialog from './LoadingDialog'; +import {pdfUrls} from '../utils/Utils'; + +type BrowserParams = { + Browser: {currDir: string; path: string}; +}; + +type BrowserProps = StackScreenProps; + +const Browser = ({navigation, route}: BrowserProps) => { + const [plusVisible, setPlusVisible] = useState(false); + + const [newFileBottomSheet, setNewFileBottomSheet] = useState(false); + const [downloadDialogVisible, setDownloadDialogVisible] = useState(false); + const [folderDialogVisible, setFolderDialogVisible] = useState(false); + const [loadingDialogVisible, setLoadingDialogVisible] = useState(false); + + const [snackMessage, setSnackMessage] = useState(''); + const [snackVisible, setSnackVisible] = useState(false); + + const [files, setFiles] = useState([]); + + const [currentDir] = useState(route.params.path + '/' + route.params.currDir); + + const insets = useSafeAreaInsets(); + + const getFiles = React.useCallback(() => { + FileSystem.readDirectoryAsync(currentDir).then(names => { + const fileInfos = names.map(name => + FileSystem.getInfoAsync(currentDir + '/' + name), + ); + Promise.all(fileInfos).then(results => { + let tempFiles: FileInfo[] = results.map((file, index) => { + return Object({ + ...file, + name: names[index], + selected: false, + }); + }); + setFiles(tempFiles); + }); + }); + }, [currentDir]); + + const renderFile = ({item}: {item: FileInfo}) => ( + + ); + + const handleDownload = async (url: string) => { + setLoadingDialogVisible(true); + + const res = await fetch(url); + const fileExt = mime.extension(res.headers.get('Content-Type')); + const fileName = + '/DL_' + DateTime.now().toFormat('yyyyMMddHHmmss') + '.' + fileExt; + + FileSystem.downloadAsync(url, currentDir + fileName) + .catch(e => console.log(e)) + .finally(() => { + getFiles(); + setLoadingDialogVisible(false); + }); + }; + + const createDirectory = (name: string) => { + FileSystem.makeDirectoryAsync(currentDir + '/' + name) + .then(() => { + getFiles(); + }) + .catch(() => { + setSnack('Folder could not be created or already exists.'); + }); + }; + + const pickFromStorage = () => { + setPlusVisible(false); + + const pick = () => { + DocumentPicker.getDocumentAsync({ + copyToCacheDirectory: false, + }) + .then(result => { + if (result.type === 'success') { + FileSystem.getInfoAsync(currentDir + '/' + result.name).then( + res => { + const copy = () => { + FileSystem.copyAsync({ + from: result.uri, + to: currentDir + '/' + result.name, + }) + .then(() => { + getFiles(); + }) + .catch(() => { + setSnack('File could not be copied successfully.'); + }); + }; + + if (res.exists) { + Alert.alert( + 'Conflicting File', + `The destination has a file with the same name ${result.name}.`, + [ + {text: 'Cancel', style: 'cancel'}, + {text: 'Replace', style: 'default', onPress: copy}, + ], + ); + } else copy(); + }, + ); + } + }) + .catch(() => { + setSnack('Failed opening the document picker.'); + }); + }; + + if (Platform.OS === 'ios') setTimeout(pick, 500); + else pick(); + }; + + const setSnack = (msg: string) => { + setSnackMessage(msg); + setSnackVisible(true); + }; + + // effect to automatically download sample PDF files to the root folder + React.useEffect(() => { + const root: string = FileSystem.documentDirectory || ''; + const path = root.endsWith('/') ? root + 'Browser' : root + '/' + 'Browser'; + if (currentDir !== path) return; + + FileSystem.makeDirectoryAsync(path) + .then(() => { + // browser root folder newly created, therefore download sample files + setLoadingDialogVisible(true); + const download = pdfUrls.map(url => + FileSystem.downloadAsync( + url, + path + '/' + url.substring(url.lastIndexOf('/') + 1), + ), + ); + + Promise.all(download) + .catch(e => console.log(e)) + .finally(() => { + getFiles(); + setLoadingDialogVisible(false); + }); + }) + .catch(() => { + // browser root folder already exists, do nothing + }); + }, [currentDir, getFiles]); + + // load in files when currentDir is set + useEffect(() => { + getFiles(); + }, [getFiles]); + + // reload files when this screen comes back in focus (i.e. when user navigates back to it) + useEffect(() => { + return navigation.addListener('focus', () => { + getFiles(); + }); + }, [getFiles, navigation]); + + return ( + + + setSnackVisible(false)}> + {snackMessage} + + { + pickFromStorage(); + setNewFileBottomSheet(false); + }, + () => { + // https://pdftron.s3.amazonaws.com/downloads/pl/PDFTRON_mobile_about.pdf + setDownloadDialogVisible(true); + setNewFileBottomSheet(false); + }, + ]} + onClose={() => setNewFileBottomSheet(false)} + /> + + + + + {route.params.currDir === 'Browser' ? ( + + ) : ( + navigation.goBack()} + style={styles.topRowLeft}> + + + {route.params.path.split('/').pop()} + + + )} + + {route?.params?.currDir} + + +

setPlusVisible(true)}> + + + } + onDismiss={() => setPlusVisible(false)}> + { + setPlusVisible(false); + setNewFileBottomSheet(true); + }} + title="Add File..." + /> + { + setPlusVisible(false); + setFolderDialogVisible(true); + }} + title="Add Folder" + /> + + + + + item.name} + /> + + + + + ); +}; + +export default Browser; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + topRow: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginVertical: 10, + marginHorizontal: 15, + }, + topRowLeft: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'center', + width: '33%', + }, + topRowBackText: { + marginLeft: -3, + width: '70%', + }, + topRowText: { + textAlign: 'center', + width: '33%', + }, + topRowRight: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-end', + alignItems: 'center', + width: '33%', + }, + topRowButton: { + paddingHorizontal: 3, + }, + fileList: { + flex: 1, + marginHorizontal: 15, + marginVertical: 5, + }, +}); diff --git a/example/components/FileItem.tsx b/example/components/FileItem.tsx new file mode 100644 index 000000000..e9e374d80 --- /dev/null +++ b/example/components/FileItem.tsx @@ -0,0 +1,353 @@ +import React, {useState} from 'react'; +import { + StyleSheet, + View, + Text, + Image, + TouchableOpacity, + Alert, + Platform, +} from 'react-native'; +import {useNavigation} from '@react-navigation/native'; +import {StackNavigationProp} from '@react-navigation/stack'; + +import * as FileSystem from 'expo-file-system'; +import * as Sharing from 'expo-sharing'; +import FileViewer from 'react-native-file-viewer'; + +import * as mime from 'react-native-mime-types'; +import {DateTime} from 'luxon'; +import {RNPdftron} from 'react-native-pdftron'; + +import BottomSheet from './BottomSheet'; +import InputDialog from './InputDialog'; +import {fileIcons, officeFileTypes, humanFileSize} from '../utils/Utils'; + +import {MaterialCommunityIcons} from '@expo/vector-icons'; + +export type FileInfo = { + name: string; + selected?: boolean; + exists: true; + uri: string; + size: number; + isDirectory: boolean; + modificationTime: number; + md5?: string; +}; + +type FileItemProps = { + file: FileInfo; + currentDir: string; + refreshFiles: () => void; + setSnack: (msg: string) => void; +}; + +type FileThumbnailProps = { + type: string; + format: string; + uri: string; +}; + +const FileThumbnail = ({type, format, uri}: FileThumbnailProps) => { + switch (type) { + case 'dir': + return ; + case 'image': + case 'video': + return ; + case 'audio': + return ; + case 'font': + return ; + case 'application': + case 'text': + return ( + + ); + default: + return ; + } +}; + +const FileItem = ({ + file, + currentDir, + refreshFiles, + setSnack, +}: FileItemProps) => { + const navigation = useNavigation>(); + + const [itemActionsVisible, setItemActionsVisible] = useState(false); + const [renameDialogVisible, setRenameDialogVisible] = useState(false); + + // splitting the file name from its extension; fileName is empty if there is no extension + const fileName = file.name.substring(0, file.name.indexOf('.')); + const fileExt = file.name.substring(file.name.indexOf('.') + 1); + + const fileMime = mime.lookup(file.uri) || ''; + const fileType: string = file.isDirectory ? 'dir' : fileMime.split('/')[0]; + const fileFormat: string = file.isDirectory ? 'dir' : fileMime.split('/')[1]; + + const onItemPress = () => { + if (file.isDirectory) { + navigation.push('Browser', { + currDir: file.name, + path: currentDir, + }); + } else if (fileFormat === 'pdf') { + navigation.push('PDFViewer', { + currDir: file.name, + path: currentDir, + }); + } else { + FileViewer.open(file.uri).catch(() => { + setSnack('Could not open file. File format may be unsupported.'); + }); + } + }; + + const rename = (input: string) => { + const name = fileName === '' ? input : input + '.' + fileExt; + + FileSystem.getInfoAsync(currentDir + '/' + name).then(res => { + if (res.exists) { + setSnack('A folder or file with the same name already exists.'); + } else + FileSystem.moveAsync({ + from: file.uri, + to: currentDir + '/' + name, + }) + .then(() => { + setRenameDialogVisible(false); + refreshFiles(); + }) + .catch(e => { + console.log(e); + setSnack( + `Error renaming the ${file.isDirectory ? 'folder' : 'file'}.`, + ); + }); + }); + }; + + const share = () => { + setItemActionsVisible(false); + + const openShare = () => { + Sharing.isAvailableAsync().then(canShare => { + if (canShare) { + Sharing.shareAsync(file.uri).catch(() => + setSnack('Error opening sharing options.'), + ); + } + }); + }; + + if (Platform.OS === 'ios') setTimeout(openShare, 500); + else openShare(); + }; + + const deleteFile = () => { + Alert.alert( + 'Confirm Delete', + 'Are you sure you want to delete this file?', + [ + { + text: 'Cancel', + onPress: () => {}, + style: 'cancel', + }, + { + text: 'Delete', + onPress: () => { + FileSystem.deleteAsync(file.uri) + .catch(err => { + setSnack( + `Error deleting the ${file.isDirectory ? 'folder' : 'file'}.`, + ); + console.log(err); + }) + .finally(refreshFiles); + }, + }, + ], + ); + }; + + let items = ['Rename', 'Share', 'Delete']; + let itemIcons: React.ComponentProps['name'][] = + ['pencil', 'share', 'delete']; + let itemActions = [ + () => { + setItemActionsVisible(false); + setRenameDialogVisible(true); + }, + share, + deleteFile, + ]; + + // if this file is an office file, include the option to export to PDF in the bottom sheet + if (officeFileTypes.includes(fileFormat)) { + items.splice(1, 0, 'Export to PDF'); + itemIcons.splice(1, 0, 'file-pdf-box'); + + itemActions.splice(1, 0, async () => { + const prefix = 'file://'; + let path = null; + + try { + path = await RNPdftron.pdfFromOffice( + file.uri.substring(prefix.length), + { + applyPageBreaksToSheet: true, + displayChangeTracking: true, + excelDefaultCellBorderWidth: 1, + excelMaxAllowedCellCount: 250000, + locale: 'en-US', + }, + ); + + await FileSystem.copyAsync({ + from: prefix + path, + to: + file.uri.substring(0, file.uri.lastIndexOf('/') + 1) + + fileName + + '.pdf', + }); + } catch (e) { + console.log(e); + setSnack('Error converting selected file to PDF.'); + } + + if (path) { + FileSystem.deleteAsync(prefix + path) + .catch(e => { + console.log(e); + setSnack('Error deleting the temporary file.'); + }) + .finally(refreshFiles); + } + }); + } + + return ( + + setItemActionsVisible(false)} + /> + + + + + + + + + {file.name} + + + {humanFileSize(file.size)} + + {file.modificationTime && ( + + {DateTime.fromSeconds(file.modificationTime).toRelative()} + + )} + + + setItemActionsVisible(true)}> + + {!file.selected ? ( + + ) : ( + + )} + + + + + ); +}; + +export default FileItem; + +const styles = StyleSheet.create({ + container: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + height: 75, + }, + itemContainer: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + width: '100%', + height: '100%', + }, + itemLeft: { + height: '100%', + width: '83%', + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + itemThumbnail: { + height: '100%', + marginLeft: 8, + width: '17%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + itemDetails: { + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + justifyContent: 'center', + height: '100%', + width: '83%', + overflow: 'hidden', + }, + itemActionButton: { + width: '8%', + height: '100%', + }, + image: { + margin: 1, + width: 40, + height: 50, + resizeMode: 'cover', + borderRadius: 5, + }, + fileMenu: { + marginRight: 5, + height: 60, + display: 'flex', + justifyContent: 'center', + }, + fileName: { + fontSize: 15, + }, + fileDetailText: { + fontSize: 10, + }, +}); diff --git a/example/components/InputDialog.tsx b/example/components/InputDialog.tsx new file mode 100644 index 000000000..7b0df9694 --- /dev/null +++ b/example/components/InputDialog.tsx @@ -0,0 +1,71 @@ +import React from 'react'; +import {StyleSheet, TouchableOpacity, Text, TextInput} from 'react-native'; +import {Dialog, Portal} from 'react-native-paper'; + +type InputDialogProps = { + title: string; + visible: boolean; + setVisible: (state: boolean) => void; + handleInput: (input: string) => void; + initialValue?: string; +}; + +const InputDialog = ({ + title, + visible, + setVisible, + handleInput, + initialValue, +}: InputDialogProps) => { + const initialState = initialValue || ''; + const [input, setInput] = React.useState(initialState); + + return ( + + setVisible(false)}> + {title} + + setInput(text)} + /> + + + { + setVisible(false); + setInput(''); + }}> + Cancel + + { + handleInput(input); + setVisible(false); + setInput(''); + }}> + OK + + + + + ); +}; + +export default InputDialog; + +const styles = StyleSheet.create({ + title: { + fontSize: 15, + }, + input: { + paddingVertical: 5, + borderBottomWidth: 1, + }, + button: { + padding: 10, + }, +}); diff --git a/example/components/LoadingDialog.tsx b/example/components/LoadingDialog.tsx new file mode 100644 index 000000000..ff9df8972 --- /dev/null +++ b/example/components/LoadingDialog.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import {StyleSheet, Modal, View, Text, ActivityIndicator} from 'react-native'; + +const LoadingDialog = ({visible}: {visible: boolean}) => { + return ( + {}} + visible={visible}> + + + + + + + ); +}; + +export default LoadingDialog; + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + modal: { + backgroundColor: 'black', + opacity: 0.5, + borderRadius: 10, + padding: 20, + }, +}); diff --git a/example/components/PDFViewer.tsx b/example/components/PDFViewer.tsx new file mode 100644 index 000000000..bee78291a --- /dev/null +++ b/example/components/PDFViewer.tsx @@ -0,0 +1,148 @@ +import React from 'react'; +import { + Platform, + StyleSheet, + PermissionsAndroid, + BackHandler, + Alert, + View, + Text, +} from 'react-native'; + +import * as FileSystem from 'expo-file-system'; +import {StackScreenProps} from '@react-navigation/stack'; +import {useSafeAreaInsets} from 'react-native-safe-area-context'; + +import {DocumentView, RNPdftron, Config} from 'react-native-pdftron'; + +type PDFViewerParams = { + PDFViewer: {currDir: string; path: string}; +}; + +type PDFViewerProps = StackScreenProps; + +const PDFViewer = ({navigation, route}: PDFViewerProps) => { + const _viewer = React.useRef(null); + const insets = useSafeAreaInsets(); + + const root: string = FileSystem.documentDirectory || ''; + const path = route.params.path + '/' + route.params.currDir; + + const myToolbar = { + [Config.CustomToolbarKey.Id]: 'myToolbar', + [Config.CustomToolbarKey.Name]: 'myToolbar', + [Config.CustomToolbarKey.Icon]: Config.ToolbarIcons.FillAndSign, + [Config.CustomToolbarKey.Items]: [ + Config.Tools.annotationCreateArrow, + Config.Tools.annotationCreateCallout, + Config.Buttons.undo, + ], + }; + + const onLeadingNavButtonPressed = () => { + if (navigation.canGoBack()) navigation.goBack(); + + // console.log('leading nav button pressed'); + // if (_viewer.current) { + // _viewer.current.exportAnnotations().then(xfdf => { + // console.log('xfdf', xfdf); + // }); + // } + // + // if (Platform.OS === 'ios') { + // Alert.alert( + // 'App', + // 'onLeadingNavButtonPressed', + // [{text: 'OK', onPress: () => console.log('OK Pressed')}], + // {cancelable: true}, + // ); + // } else { + // BackHandler.exitApp(); + // } + }; + + const onDocumentLoaded = () => { + // if (_viewer.current) { + // const xfdf = + // '\n\n\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\tfont: Roboto 24pt;color: #363636\n\t\t\t 1 1 1 RG 1 1 1 rg /F0 24 Tf \n\t\t\tHELLO PDFTRON!!!\n\t\t\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n'; + // _viewer.current.importAnnotations(xfdf); + // } + }; + + const onAnnotationChanged = ({ + action, + annotations, + }: { + action: string; + annotations: []; + }) => { + // console.log('action', action); + // console.log('annotations', annotations); + // if (_viewer.current) { + // _viewer.current.exportAnnotations({annotList: annotations}).then(xfdf => { + // console.log('xfdf for annotations', xfdf); + // }); + // } + }; + + const onZoomChanged = ({zoom}: {zoom: number}) => { + // console.log('zoom', zoom); + }; + + const onExportAnnotationCommand = ({ + action, + xfdfCommand, + }: { + action: string; + xfdfCommand: string; + }) => { + console.log('action', action); + console.log('xfdfCommand', xfdfCommand); + }; + + return ( + + + + ); +}; + +export default PDFViewer; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); diff --git a/example/index.d.ts b/example/index.d.ts new file mode 100644 index 000000000..a376f9b69 --- /dev/null +++ b/example/index.d.ts @@ -0,0 +1,2 @@ +declare module 'react-native-mime-types'; +declare module 'luxon'; diff --git a/example/index.js b/example/index.js index a850d031d..1d6e981ef 100644 --- a/example/index.js +++ b/example/index.js @@ -1,9 +1,8 @@ -/** - * @format - */ +import { registerRootComponent } from 'expo'; -import {AppRegistry} from 'react-native'; import App from './App'; -import {name as appName} from './app.json'; -AppRegistry.registerComponent(appName, () => App); +// registerRootComponent calls AppRegistry.registerComponent('main', () => App); +// It also ensures that whether you load the app in Expo Go or in a native build, +// the environment is set up appropriately +registerRootComponent(App); diff --git a/example/ios/.gitignore b/example/ios/.gitignore new file mode 100644 index 000000000..2b1351993 --- /dev/null +++ b/example/ios/.gitignore @@ -0,0 +1,29 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + +# Bundle artifacts +*.jsbundle + +# CocoaPods +/Pods/ diff --git a/example/ios/.xcode.env b/example/ios/.xcode.env new file mode 100644 index 000000000..3d5782c71 --- /dev/null +++ b/example/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/example/ios/.xcode.env.local b/example/ios/.xcode.env.local new file mode 100644 index 000000000..5563a685d --- /dev/null +++ b/example/ios/.xcode.env.local @@ -0,0 +1 @@ +export NODE_BINARY="/Users/terryyoon/.nvm/versions/node/v16.15.1/bin/node" diff --git a/example/ios/Podfile b/example/ios/Podfile index 6307903d5..8cb361534 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,36 +1,47 @@ -require_relative '../node_modules/react-native/scripts/react_native_pods' -require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' +require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking") +require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods") +require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules") -platform :ios, '11.0' +require 'json' +podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {} + +platform :ios, podfile_properties['ios.deploymentTarget'] || '12.4' +install! 'cocoapods', + :deterministic_uuids => false + +production = ENV["PRODUCTION"] == "1" target 'example' do - # PDFTron - use_frameworks! - pod 'PDFNet', podspec: 'https://pdftron.com/downloads/ios/react-native/latest.podspec' - pod 'RNPdftron', :path => '../node_modules/react-native-pdftron' + use_expo_modules! config = use_native_modules! + pod 'PDFNet', podspec: 'https://pdftron.com/downloads/ios/react-native/latest.podspec' + + use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks'] + + # Flags change depending on the env values. + flags = get_default_flags() use_react_native!( :path => config[:reactNativePath], - # to enable hermes on iOS, change `false` to `true` and then install pods - :hermes_enabled => false + :production => production, + :hermes_enabled => flags[:hermes_enabled] || podfile_properties['expo.jsEngine'] == 'hermes', + :fabric_enabled => flags[:fabric_enabled], + :flipper_configuration => FlipperConfiguration.enabled, + # An absolute path to your application root. + :app_path => "#{Dir.pwd}/.." ) - - target 'exampleTests' do - inherit! :complete - # Pods for testing - end - - # Enables Flipper. - # - # Note that if you have use_frameworks! enabled, Flipper will not work and - # you should disable the next line. - # use_flipper!() - post_install do |installer| react_native_post_install(installer) __apply_Xcode_12_5_M1_post_install_workaround(installer) end -end + post_integrate do |installer| + begin + expo_patch_react_imports!(installer) + rescue => e + Pod::UI.warn e + end + end + +end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 000000000..d3c91dc39 --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,654 @@ +PODS: + - boost (1.76.0) + - CocoaAsyncSocket (7.6.5) + - DoubleConversion (1.1.6) + - EXApplication (4.2.2): + - ExpoModulesCore + - EXConstants (13.2.3): + - ExpoModulesCore + - EXDocumentPicker (10.3.0): + - ExpoModulesCore + - EXFileSystem (14.1.0): + - ExpoModulesCore + - EXFont (10.2.0): + - ExpoModulesCore + - Expo (46.0.8): + - ExpoModulesCore + - ExpoKeepAwake (10.2.0): + - ExpoModulesCore + - ExpoModulesCore (0.11.4): + - React-Core + - ReactCommon/turbomodule/core + - EXSharing (10.3.0): + - ExpoModulesCore + - EXSplashScreen (0.16.1): + - ExpoModulesCore + - React-Core + - FBLazyVector (0.69.4) + - FBReactNativeSpec (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - RCTRequired (= 0.69.4) + - RCTTypeSafety (= 0.69.4) + - React-Core (= 0.69.4) + - React-jsi (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - Flipper (0.125.0): + - Flipper-Folly (~> 2.6) + - Flipper-RSocket (~> 1.4) + - Flipper-Boost-iOSX (1.76.0.1.11) + - Flipper-DoubleConversion (3.2.0.1) + - Flipper-Fmt (7.1.7) + - Flipper-Folly (2.6.10): + - Flipper-Boost-iOSX + - Flipper-DoubleConversion + - Flipper-Fmt (= 7.1.7) + - Flipper-Glog + - libevent (~> 2.1.12) + - OpenSSL-Universal (= 1.1.1100) + - Flipper-Glog (0.5.0.5) + - Flipper-PeerTalk (0.0.4) + - Flipper-RSocket (1.4.3): + - Flipper-Folly (~> 2.6) + - FlipperKit (0.125.0): + - FlipperKit/Core (= 0.125.0) + - FlipperKit/Core (0.125.0): + - Flipper (~> 0.125.0) + - FlipperKit/CppBridge + - FlipperKit/FBCxxFollyDynamicConvert + - FlipperKit/FBDefines + - FlipperKit/FKPortForwarding + - SocketRocket (~> 0.6.0) + - FlipperKit/CppBridge (0.125.0): + - Flipper (~> 0.125.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.125.0): + - Flipper-Folly (~> 2.6) + - FlipperKit/FBDefines (0.125.0) + - FlipperKit/FKPortForwarding (0.125.0): + - CocoaAsyncSocket (~> 7.6) + - Flipper-PeerTalk (~> 0.0.4) + - FlipperKit/FlipperKitHighlightOverlay (0.125.0) + - FlipperKit/FlipperKitLayoutHelpers (0.125.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutTextSearchable + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.125.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutHelpers + - YogaKit (~> 1.18) + - FlipperKit/FlipperKitLayoutPlugin (0.125.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutHelpers + - FlipperKit/FlipperKitLayoutIOSDescriptors + - FlipperKit/FlipperKitLayoutTextSearchable + - YogaKit (~> 1.18) + - FlipperKit/FlipperKitLayoutTextSearchable (0.125.0) + - FlipperKit/FlipperKitNetworkPlugin (0.125.0): + - FlipperKit/Core + - FlipperKit/FlipperKitReactPlugin (0.125.0): + - FlipperKit/Core + - FlipperKit/FlipperKitUserDefaultsPlugin (0.125.0): + - FlipperKit/Core + - FlipperKit/SKIOSNetworkPlugin (0.125.0): + - FlipperKit/Core + - FlipperKit/FlipperKitNetworkPlugin + - fmt (6.2.1) + - glog (0.3.5) + - libevent (2.1.12) + - OpenSSL-Universal (1.1.1100) + - PDFNet (3.0.2-beta.121) + - RCT-Folly (2021.06.28.00-v2): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - RCT-Folly/Default (= 2021.06.28.00-v2) + - RCT-Folly/Default (2021.06.28.00-v2): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - RCTRequired (0.69.4) + - RCTTypeSafety (0.69.4): + - FBLazyVector (= 0.69.4) + - RCTRequired (= 0.69.4) + - React-Core (= 0.69.4) + - React (0.69.4): + - React-Core (= 0.69.4) + - React-Core/DevSupport (= 0.69.4) + - React-Core/RCTWebSocket (= 0.69.4) + - React-RCTActionSheet (= 0.69.4) + - React-RCTAnimation (= 0.69.4) + - React-RCTBlob (= 0.69.4) + - React-RCTImage (= 0.69.4) + - React-RCTLinking (= 0.69.4) + - React-RCTNetwork (= 0.69.4) + - React-RCTSettings (= 0.69.4) + - React-RCTText (= 0.69.4) + - React-RCTVibration (= 0.69.4) + - React-bridging (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - React-jsi (= 0.69.4) + - React-callinvoker (0.69.4) + - React-Codegen (0.69.4): + - FBReactNativeSpec (= 0.69.4) + - RCT-Folly (= 2021.06.28.00-v2) + - RCTRequired (= 0.69.4) + - RCTTypeSafety (= 0.69.4) + - React-Core (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-Core (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default (= 0.69.4) + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/CoreModulesHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/Default (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/DevSupport (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default (= 0.69.4) + - React-Core/RCTWebSocket (= 0.69.4) + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-jsinspector (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTActionSheetHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTAnimationHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTBlobHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTImageHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTLinkingHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTNetworkHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTSettingsHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTTextHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTVibrationHeaders (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-Core/RCTWebSocket (0.69.4): + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-Core/Default (= 0.69.4) + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsiexecutor (= 0.69.4) + - React-perflogger (= 0.69.4) + - Yoga + - React-CoreModules (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - RCTTypeSafety (= 0.69.4) + - React-Codegen (= 0.69.4) + - React-Core/CoreModulesHeaders (= 0.69.4) + - React-jsi (= 0.69.4) + - React-RCTImage (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-cxxreact (0.69.4): + - boost (= 1.76.0) + - DoubleConversion + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-callinvoker (= 0.69.4) + - React-jsi (= 0.69.4) + - React-jsinspector (= 0.69.4) + - React-logger (= 0.69.4) + - React-perflogger (= 0.69.4) + - React-runtimeexecutor (= 0.69.4) + - React-jsi (0.69.4): + - boost (= 1.76.0) + - DoubleConversion + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-jsi/Default (= 0.69.4) + - React-jsi/Default (0.69.4): + - boost (= 1.76.0) + - DoubleConversion + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-jsiexecutor (0.69.4): + - DoubleConversion + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-perflogger (= 0.69.4) + - React-jsinspector (0.69.4) + - React-logger (0.69.4): + - glog + - react-native-safe-area-context (4.3.1): + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React + - ReactCommon/turbomodule/core + - React-perflogger (0.69.4) + - React-RCTActionSheet (0.69.4): + - React-Core/RCTActionSheetHeaders (= 0.69.4) + - React-RCTAnimation (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - RCTTypeSafety (= 0.69.4) + - React-Codegen (= 0.69.4) + - React-Core/RCTAnimationHeaders (= 0.69.4) + - React-jsi (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-RCTBlob (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - React-Codegen (= 0.69.4) + - React-Core/RCTBlobHeaders (= 0.69.4) + - React-Core/RCTWebSocket (= 0.69.4) + - React-jsi (= 0.69.4) + - React-RCTNetwork (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-RCTImage (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - RCTTypeSafety (= 0.69.4) + - React-Codegen (= 0.69.4) + - React-Core/RCTImageHeaders (= 0.69.4) + - React-jsi (= 0.69.4) + - React-RCTNetwork (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-RCTLinking (0.69.4): + - React-Codegen (= 0.69.4) + - React-Core/RCTLinkingHeaders (= 0.69.4) + - React-jsi (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-RCTNetwork (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - RCTTypeSafety (= 0.69.4) + - React-Codegen (= 0.69.4) + - React-Core/RCTNetworkHeaders (= 0.69.4) + - React-jsi (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-RCTSettings (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - RCTTypeSafety (= 0.69.4) + - React-Codegen (= 0.69.4) + - React-Core/RCTSettingsHeaders (= 0.69.4) + - React-jsi (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-RCTText (0.69.4): + - React-Core/RCTTextHeaders (= 0.69.4) + - React-RCTVibration (0.69.4): + - RCT-Folly (= 2021.06.28.00-v2) + - React-Codegen (= 0.69.4) + - React-Core/RCTVibrationHeaders (= 0.69.4) + - React-jsi (= 0.69.4) + - ReactCommon/turbomodule/core (= 0.69.4) + - React-runtimeexecutor (0.69.4): + - React-jsi (= 0.69.4) + - ReactCommon/turbomodule/core (0.69.4): + - DoubleConversion + - glog + - RCT-Folly (= 2021.06.28.00-v2) + - React-bridging (= 0.69.4) + - React-callinvoker (= 0.69.4) + - React-Core (= 0.69.4) + - React-cxxreact (= 0.69.4) + - React-jsi (= 0.69.4) + - React-logger (= 0.69.4) + - React-perflogger (= 0.69.4) + - RNFileViewer (2.1.5): + - React-Core + - RNGestureHandler (2.5.0): + - React-Core + - RNPdftron (3.0.2-beta.123): + - PDFNet + - React-Core + - RNScreens (3.15.0): + - React-Core + - React-RCTImage + - SocketRocket (0.6.0) + - Yoga (1.14.0) + - YogaKit (1.18.1): + - Yoga (~> 1.14) + +DEPENDENCIES: + - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - EXApplication (from `../node_modules/expo-application/ios`) + - EXConstants (from `../node_modules/expo-constants/ios`) + - EXDocumentPicker (from `../node_modules/expo-document-picker/ios`) + - EXFileSystem (from `../node_modules/expo-file-system/ios`) + - EXFont (from `../node_modules/expo-font/ios`) + - Expo (from `../node_modules/expo`) + - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) + - ExpoModulesCore (from `../node_modules/expo-modules-core/ios`) + - EXSharing (from `../node_modules/expo-sharing/ios`) + - EXSplashScreen (from `../node_modules/expo-splash-screen/ios`) + - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) + - Flipper (= 0.125.0) + - Flipper-Boost-iOSX (= 1.76.0.1.11) + - Flipper-DoubleConversion (= 3.2.0.1) + - Flipper-Fmt (= 7.1.7) + - Flipper-Folly (= 2.6.10) + - Flipper-Glog (= 0.5.0.5) + - Flipper-PeerTalk (= 0.0.4) + - Flipper-RSocket (= 1.4.3) + - FlipperKit (= 0.125.0) + - FlipperKit/Core (= 0.125.0) + - FlipperKit/CppBridge (= 0.125.0) + - FlipperKit/FBCxxFollyDynamicConvert (= 0.125.0) + - FlipperKit/FBDefines (= 0.125.0) + - FlipperKit/FKPortForwarding (= 0.125.0) + - FlipperKit/FlipperKitHighlightOverlay (= 0.125.0) + - FlipperKit/FlipperKitLayoutPlugin (= 0.125.0) + - FlipperKit/FlipperKitLayoutTextSearchable (= 0.125.0) + - FlipperKit/FlipperKitNetworkPlugin (= 0.125.0) + - FlipperKit/FlipperKitReactPlugin (= 0.125.0) + - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.125.0) + - FlipperKit/SKIOSNetworkPlugin (= 0.125.0) + - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) + - OpenSSL-Universal (= 1.1.1100) + - PDFNet (from `https://pdftron.com/downloads/ios/react-native/latest.podspec`) + - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) + - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../node_modules/react-native/`) + - React-bridging (from `../node_modules/react-native/ReactCommon`) + - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) + - React-Codegen (from `build/generated/ios`) + - React-Core (from `../node_modules/react-native/`) + - React-Core/DevSupport (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) + - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) + - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) + - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - RNFileViewer (from `../node_modules/react-native-file-viewer`) + - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - RNPdftron (from `../node_modules/react-native-pdftron`) + - RNScreens (from `../node_modules/react-native-screens`) + - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + +SPEC REPOS: + trunk: + - CocoaAsyncSocket + - Flipper + - Flipper-Boost-iOSX + - Flipper-DoubleConversion + - Flipper-Fmt + - Flipper-Folly + - Flipper-Glog + - Flipper-PeerTalk + - Flipper-RSocket + - FlipperKit + - fmt + - libevent + - OpenSSL-Universal + - SocketRocket + - YogaKit + +EXTERNAL SOURCES: + boost: + :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + DoubleConversion: + :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + EXApplication: + :path: "../node_modules/expo-application/ios" + EXConstants: + :path: "../node_modules/expo-constants/ios" + EXDocumentPicker: + :path: "../node_modules/expo-document-picker/ios" + EXFileSystem: + :path: "../node_modules/expo-file-system/ios" + EXFont: + :path: "../node_modules/expo-font/ios" + Expo: + :path: "../node_modules/expo" + ExpoKeepAwake: + :path: "../node_modules/expo-keep-awake/ios" + ExpoModulesCore: + :path: "../node_modules/expo-modules-core/ios" + EXSharing: + :path: "../node_modules/expo-sharing/ios" + EXSplashScreen: + :path: "../node_modules/expo-splash-screen/ios" + FBLazyVector: + :path: "../node_modules/react-native/Libraries/FBLazyVector" + FBReactNativeSpec: + :path: "../node_modules/react-native/React/FBReactNativeSpec" + glog: + :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + PDFNet: + :podspec: https://pdftron.com/downloads/ios/react-native/latest.podspec + RCT-Folly: + :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTRequired: + :path: "../node_modules/react-native/Libraries/RCTRequired" + RCTTypeSafety: + :path: "../node_modules/react-native/Libraries/TypeSafety" + React: + :path: "../node_modules/react-native/" + React-bridging: + :path: "../node_modules/react-native/ReactCommon" + React-callinvoker: + :path: "../node_modules/react-native/ReactCommon/callinvoker" + React-Codegen: + :path: build/generated/ios + React-Core: + :path: "../node_modules/react-native/" + React-CoreModules: + :path: "../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-jsi: + :path: "../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../node_modules/react-native/ReactCommon/jsinspector" + React-logger: + :path: "../node_modules/react-native/ReactCommon/logger" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" + React-perflogger: + :path: "../node_modules/react-native/ReactCommon/reactperflogger" + React-RCTActionSheet: + :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../node_modules/react-native/Libraries/NativeAnimation" + React-RCTBlob: + :path: "../node_modules/react-native/Libraries/Blob" + React-RCTImage: + :path: "../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../node_modules/react-native/Libraries/Network" + React-RCTSettings: + :path: "../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../node_modules/react-native/Libraries/Vibration" + React-runtimeexecutor: + :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + ReactCommon: + :path: "../node_modules/react-native/ReactCommon" + RNFileViewer: + :path: "../node_modules/react-native-file-viewer" + RNGestureHandler: + :path: "../node_modules/react-native-gesture-handler" + RNPdftron: + :path: "../node_modules/react-native-pdftron" + RNScreens: + :path: "../node_modules/react-native-screens" + Yoga: + :path: "../node_modules/react-native/ReactCommon/yoga" + +SPEC CHECKSUMS: + boost: a7c83b31436843459a1961bfd74b96033dc77234 + CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 + DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 + EXApplication: e418d737a036e788510f2c4ad6c10a7d54d18586 + EXConstants: 75c40827af38bd6bfcf69f880a5b45037eeff9c9 + EXDocumentPicker: 027b15cd90ed2d6c6063dcc90369d23c7fa0f2a3 + EXFileSystem: 927e0a8885aa9c49e50fc38eaba2c2389f2f1019 + EXFont: a5d80bd9b3452b2d5abbce2487da89b0150e6487 + Expo: 2322364db3fe1adaa179787edb7e1bc6e5159c78 + ExpoKeepAwake: 0e8f18142e71bbf2c7f6aa66ebed249ba1420320 + ExpoModulesCore: e281bb7b78ea47e227dd5af94d04b24d8b2e1255 + EXSharing: 8530ef08cb899328a7c61de7f4836af6208b567b + EXSplashScreen: 31ab6df6d23e97e074d1330224741979943f1d82 + FBLazyVector: c71b8c429a8af2aff1013934a7152e9d9d0c937d + FBReactNativeSpec: cb0df4f0084281b394f76bb9b4d1d9540f35963f + Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 + Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c + Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 + Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b + Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 + Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 + Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 + Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 + FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86 + fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 + glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a + libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 + OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c + PDFNet: 3d94a82e04eef8d813085517211b20e81a80966e + RCT-Folly: b9d9fe1fc70114b751c076104e52f3b1b5e5a95a + RCTRequired: bd9d2ab0fda10171fcbcf9ba61a7df4dc15a28f4 + RCTTypeSafety: e44e139bf6ec8042db396201834fc2372f6a21cd + React: 482cd1ba23c471be1aed3800180be2427418d7be + React-bridging: c2ea4fed6fe4ed27c12fd71e88b5d5d3da107fde + React-callinvoker: d4d1f98163fb5e35545e910415ef6c04796bb188 + React-Codegen: ff35fb9c7f6ec2ed34fb6de2e1099d88dfb25f2f + React-Core: 4d3443a45b67c71d74d7243ddde9569d1e4f4fad + React-CoreModules: 70be25399366b5632ab18ecf6fe444a8165a7bea + React-cxxreact: 822d3794fc0bf206f4691592f90e086dd4f92228 + React-jsi: ffa51cbc9a78cc156cf61f79ed52ecb76dc6013b + React-jsiexecutor: a27badbbdbc0ff781813370736a2d1c7261181d4 + React-jsinspector: 8a3d3f5dcd23a91e8c80b1bf0e96902cd1dca999 + React-logger: 1088859f145b8f6dd0d3ed051a647ef0e3e80fad + react-native-safe-area-context: 6c12e3859b6f27b25de4fee8201cfb858432d8de + React-perflogger: cb386fd44c97ec7f8199c04c12b22066b0f2e1e0 + React-RCTActionSheet: f803a85e46cf5b4066c2ac5e122447f918e9c6e5 + React-RCTAnimation: 19c80fa950ccce7f4db76a2a7f2cf79baae07fc7 + React-RCTBlob: f36ab97e2d515c36df14a1571e50056be80413d5 + React-RCTImage: 2c8f0a329a116248e82f8972ffe806e47c6d1cfa + React-RCTLinking: 670f0223075aff33be3b89714f1da4f5343fc4af + React-RCTNetwork: 09385b73f4ff1f46bd5d749540fb33f69a7e5908 + React-RCTSettings: 33b12d3ac7a1f2eba069ec7bd1b84345263b3bbe + React-RCTText: a1a3ea902403bd9ae4cf6f7960551dc1d25711b5 + React-RCTVibration: 9adb4a3cbb598d1bbd46a05256f445e4b8c70603 + React-runtimeexecutor: 61ee22a8cdf8b6bb2a7fb7b4ba2cc763e5285196 + ReactCommon: 8f67bd7e0a6afade0f20718f859dc8c2275f2e83 + RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592 + RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50 + RNPdftron: 412a3374eda012829eb8c2a92f14a9c288f0b82c + RNScreens: 4a1af06327774490d97342c00aee0c2bafb497b7 + SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 + Yoga: ff994563b2fd98c982ca58e8cd9db2cdaf4dda74 + YogaKit: f782866e155069a2cca2517aafea43200b01fd5a + +PODFILE CHECKSUM: 577fd8613579820dad9e6afdb9d60f6dea3cdfd1 + +COCOAPODS: 1.11.3 diff --git a/example/ios/example.xcodeproj/project.pbxproj b/example/ios/example.xcodeproj/project.pbxproj index 1182886e6..6bcafbc5a 100644 --- a/example/ios/example.xcodeproj/project.pbxproj +++ b/example/ios/example.xcodeproj/project.pbxproj @@ -3,85 +3,62 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ - 00E356F31AD99517003FC87E /* exampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* exampleTests.m */; }; - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; }; + 7A6FB6FC615544288B4CA928 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C542F602B014A0DAED7F49E /* noop-file.swift */; }; + 96905EF65AED1B983A6B3ABC /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-example.a */; }; + B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; }; + BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 13B07F861A680F5B00A75B9A; - remoteInfo = example; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXFileReference section */ - 00E356EE1AD99517003FC87E /* exampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = exampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00E356F21AD99517003FC87E /* exampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = exampleTests.m; sourceTree = ""; }; + 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = example/AppDelegate.m; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = example/AppDelegate.mm; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = ""; }; - 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = ""; }; + 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5C542F602B014A0DAED7F49E /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "example/noop-file.swift"; sourceTree = ""; }; + 6C2E3173556A471DD304B334 /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = ""; }; + 7A4D352CD337FB3A3BF06240 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = ""; }; + AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = example/SplashScreen.storyboard; sourceTree = ""; }; + BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-example/ExpoModulesProvider.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 00E356EB1AD99517003FC87E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 96905EF65AED1B983A6B3ABC /* libPods-example.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 00E356EF1AD99517003FC87E /* exampleTests */ = { - isa = PBXGroup; - children = ( - 00E356F21AD99517003FC87E /* exampleTests.m */, - 00E356F01AD99517003FC87E /* Supporting Files */, - ); - path = exampleTests; - sourceTree = ""; - }; - 00E356F01AD99517003FC87E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 00E356F11AD99517003FC87E /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; 13B07FAE1A68108700A75B9A /* example */ = { isa = PBXGroup; children = ( + BB2F792B24A3F905000567C9 /* Supporting */, + 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, - 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 13B07FB01A68108700A75B9A /* AppDelegate.mm */, 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, - 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB71A68108700A75B9A /* main.m */, + AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */, + 5C542F602B014A0DAED7F49E /* noop-file.swift */, ); name = example; sourceTree = ""; @@ -90,6 +67,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-example.a */, ); name = Frameworks; sourceTree = ""; @@ -106,10 +84,10 @@ children = ( 13B07FAE1A68108700A75B9A /* example */, 832341AE1AAA6A7D00B99B32 /* Libraries */, - 00E356EF1AD99517003FC87E /* exampleTests */, 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, - CDA0EE31E7D3E42F21731B64 /* Pods */, + D65327D7A22EEC0BE12398D9 /* Pods */, + D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */, ); indentWidth = 2; sourceTree = ""; @@ -120,48 +98,59 @@ isa = PBXGroup; children = ( 13B07F961A680F5B00A75B9A /* example.app */, - 00E356EE1AD99517003FC87E /* exampleTests.xctest */, ); name = Products; sourceTree = ""; }; - CDA0EE31E7D3E42F21731B64 /* Pods */ = { + 92DBD88DE9BF7D494EA9DA96 /* example */ = { isa = PBXGroup; children = ( + FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */, ); - path = Pods; + name = example; sourceTree = ""; }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 00E356ED1AD99517003FC87E /* exampleTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */; - buildPhases = ( - 00E356EA1AD99517003FC87E /* Sources */, - 00E356EB1AD99517003FC87E /* Frameworks */, - 00E356EC1AD99517003FC87E /* Resources */, + BB2F792B24A3F905000567C9 /* Supporting */ = { + isa = PBXGroup; + children = ( + BB2F792C24A3F905000567C9 /* Expo.plist */, ); - buildRules = ( + name = Supporting; + path = example/Supporting; + sourceTree = ""; + }; + D65327D7A22EEC0BE12398D9 /* Pods */ = { + isa = PBXGroup; + children = ( + 6C2E3173556A471DD304B334 /* Pods-example.debug.xcconfig */, + 7A4D352CD337FB3A3BF06240 /* Pods-example.release.xcconfig */, ); - dependencies = ( - 00E356F51AD99517003FC87E /* PBXTargetDependency */, + path = Pods; + sourceTree = ""; + }; + D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = { + isa = PBXGroup; + children = ( + 92DBD88DE9BF7D494EA9DA96 /* example */, ); - name = exampleTests; - productName = exampleTests; - productReference = 00E356EE1AD99517003FC87E /* exampleTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + name = ExpoModulesProviders; + sourceTree = ""; }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ 13B07F861A680F5B00A75B9A /* example */ = { isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */; buildPhases = ( + 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */, FD10A7F022414F080027D42C /* Start Packager */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */, + A11D3C4A4B8D345C4D5F1B3D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -178,19 +167,15 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1210; + LastUpgradeCheck = 1130; TargetAttributes = { - 00E356ED1AD99517003FC87E = { - CreatedOnToolsVersion = 6.2; - TestTargetID = 13B07F861A680F5B00A75B9A; - }; 13B07F861A680F5B00A75B9A = { - LastSwiftMigration = 1120; + LastSwiftMigration = 1250; }; }; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */; - compatibilityVersion = "Xcode 12.0"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -203,25 +188,18 @@ projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* example */, - 00E356ED1AD99517003FC87E /* exampleTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 00E356EC1AD99517003FC87E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F8E1A680F5B00A75B9A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + BB2F792D24A3F905000567C9 /* Expo.plist in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -240,9 +218,9 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + shellScript = "export NODE_BINARY=node\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\n`node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n"; }; - FD10A7F022414F080027D42C /* Start Packager */ = { + 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -250,115 +228,127 @@ inputFileListPaths = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "Start Packager"; + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - 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"; + 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"; showEnvVarsInLog = 0; }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 00E356EA1AD99517003FC87E /* Sources */ = { - isa = PBXSourcesBuildPhase; + 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", + "${PODS_ROOT}/PDFNet/Tools-Localization", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Tools-Localization", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + A11D3C4A4B8D345C4D5F1B3D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-Glog/glog.framework/glog", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/PDFNet/PDFNet.framework/PDFNet", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/PDFNet/Tools.framework/Tools", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PDFNet.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Tools.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + FD10A7F022414F080027D42C /* Start Packager */ = { + isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( - 00E356F31AD99517003FC87E /* exampleTests.m in Sources */, + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Start Packager"; + outputFileListPaths = ( + ); + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > `node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/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 `node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/launchPackager.command'\"` || echo \"Can't start packager automatically\"\n fi\nfi\n"; + showEnvVarsInLog = 0; }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ 13B07F871A680F5B00A75B9A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */, + 7A6FB6FC615544288B4CA928 /* noop-file.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 13B07F861A680F5B00A75B9A /* example */; - targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ - 00E356F61AD99517003FC87E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = exampleTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - "$(inherited)", - ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example"; - }; - name = Debug; - }; - 00E356F71AD99517003FC87E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COPY_PHASE_STRIP = NO; - INFOPLIST_FILE = exampleTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - "$(inherited)", - ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example"; - }; - name = Release; - }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = example/example.entitlements; CURRENT_PROJECT_VERSION = 1; ENABLE_BITCODE = NO; - INFOPLIST_FILE = example/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( + GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", - "@executable_path/Frameworks", + "FB_SONARKIT_ENABLED=1", ); + INFOPLIST_FILE = example/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; + PRODUCT_BUNDLE_IDENTIFIER = example; PRODUCT_NAME = example; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -369,21 +359,22 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = example/example.entitlements; CURRENT_PROJECT_VERSION = 1; INFOPLIST_FILE = example/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; + PRODUCT_BUNDLE_IDENTIFIER = example; PRODUCT_NAME = example; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -396,7 +387,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -414,7 +405,6 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -424,7 +414,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 "; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -440,19 +430,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - /usr/lib/swift, - "$(inherited)", - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SDKROOT)/usr/lib/swift\"", - "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", - "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", - "\"$(inherited)\"", - ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; + LIBRARY_SEARCH_PATHS = "\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; }; name = Debug; @@ -462,7 +445,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -480,7 +463,6 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -490,7 +472,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 "; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -499,18 +481,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - /usr/lib/swift, - "$(inherited)", - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SDKROOT)/usr/lib/swift\"", - "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", - "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", - "\"$(inherited)\"", - ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; + LIBRARY_SEARCH_PATHS = "\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = NO; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; @@ -519,15 +494,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 00E356F61AD99517003FC87E /* Debug */, - 00E356F71AD99517003FC87E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme b/example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme index fef9df78a..cfc53ba56 100644 --- a/example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme +++ b/example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme @@ -1,6 +1,6 @@ #import #import -@interface AppDelegate : UIResponder +#import -@property (nonatomic, strong) UIWindow *window; +@interface AppDelegate : EXAppDelegateWrapper @end diff --git a/example/ios/example/AppDelegate.m b/example/ios/example/AppDelegate.m deleted file mode 100644 index 0604625f8..000000000 --- a/example/ios/example/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -#import "AppDelegate.h" - -#import -#import -#import - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - - RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; - RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge - moduleName:@"example" - initialProperties:nil]; - - if (@available(iOS 13.0, *)) { - rootView.backgroundColor = [UIColor systemBackgroundColor]; - } else { - rootView.backgroundColor = [UIColor whiteColor]; - } - - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [UIViewController new]; - rootViewController.view = rootView; - self.window.rootViewController = rootViewController; - [self.window makeKeyAndVisible]; - return YES; -} - -- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge -{ -#if DEBUG - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; -#else - return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; -#endif -} - -@end diff --git a/example/ios/example/AppDelegate.mm b/example/ios/example/AppDelegate.mm new file mode 100644 index 000000000..137cc8453 --- /dev/null +++ b/example/ios/example/AppDelegate.mm @@ -0,0 +1,168 @@ +#import "AppDelegate.h" + +#import +#import +#import +#import +#import + +#import + +#if RCT_NEW_ARCH_ENABLED +#import +#import +#import +#import +#import +#import + +#import + +static NSString *const kRNConcurrentRoot = @"concurrentRoot"; + +@interface AppDelegate () { + RCTTurboModuleManager *_turboModuleManager; + RCTSurfacePresenterBridgeAdapter *_bridgeAdapter; + std::shared_ptr _reactNativeConfig; + facebook::react::ContextContainer::Shared _contextContainer; +} +@end +#endif + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + RCTAppSetupPrepareApp(application); + + RCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:launchOptions]; + +#if RCT_NEW_ARCH_ENABLED + _contextContainer = std::make_shared(); + _reactNativeConfig = std::make_shared(); + _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); + _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer]; + bridge.surfacePresenter = _bridgeAdapter.surfacePresenter; +#endif + + NSDictionary *initProps = [self prepareInitialProps]; + UIView *rootView = [self.reactDelegate createRootViewWithBridge:bridge moduleName:@"main" initialProperties:initProps]; + + rootView.backgroundColor = [UIColor whiteColor]; + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [self.reactDelegate createRootViewController]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + + [super application:application didFinishLaunchingWithOptions:launchOptions]; + + return YES; +} + +/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off. +/// +/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html +/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture). +/// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`. +- (BOOL)concurrentRootEnabled +{ + // Switch this bool to turn on and off the concurrent root + return true; +} + +- (NSDictionary *)prepareInitialProps +{ + NSMutableDictionary *initProps = [NSMutableDictionary new]; + +#ifdef RCT_NEW_ARCH_ENABLED + initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]); +#endif + + return initProps; +} + +- (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge +{ + // If you'd like to export some custom RCTBridgeModules, add them here! + return @[]; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +// Linking API +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options { + return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options]; +} + +// Universal Links +- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { + BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; + return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result; +} + +// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +{ + return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; +} + +// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + return [super application:application didFailToRegisterForRemoteNotificationsWithError:error]; +} + +// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler +{ + return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; +} + +#if RCT_NEW_ARCH_ENABLED + +#pragma mark - RCTCxxBridgeDelegate + +- (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge +{ + _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge + delegate:self + jsInvoker:bridge.jsCallInvoker]; + return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager); +} + +#pragma mark RCTTurboModuleManagerDelegate + +- (Class)getModuleClassFromName:(const char *)name +{ + return RCTCoreModulesClassProvider(name); +} + +- (std::shared_ptr)getTurboModule:(const std::string &)name + jsInvoker:(std::shared_ptr)jsInvoker +{ + return nullptr; +} + +- (std::shared_ptr)getTurboModule:(const std::string &)name + initParams: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return nullptr; +} + +- (id)getModuleInstanceFromClass:(Class)moduleClass +{ + return RCTAppSetupDefaultModuleFromClass(moduleClass); +} + +#endif + +@end diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png new file mode 100644 index 000000000..ae598628b Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png new file mode 100644 index 000000000..ff9d54105 Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png new file mode 100644 index 000000000..ba7913561 Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png new file mode 100644 index 000000000..d2b59a92b Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png new file mode 100644 index 000000000..597bdb4bd Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png new file mode 100644 index 000000000..2f0e2b621 Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png new file mode 100644 index 000000000..ff9d54105 Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png new file mode 100644 index 000000000..3b831397f Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png new file mode 100644 index 000000000..6cd063f2d Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png new file mode 100644 index 000000000..6cd063f2d Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png new file mode 100644 index 000000000..523900936 Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png new file mode 100644 index 000000000..69908aedf Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png new file mode 100644 index 000000000..04580c448 Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png new file mode 100644 index 000000000..74e8e26bb Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png differ diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json b/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json index 81213230d..f920cb0ec 100644 --- a/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,53 +1,122 @@ { - "images" : [ + "images": [ { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" + "idiom": "iphone", + "size": "20x20", + "scale": "2x", + "filename": "App-Icon-20x20@2x.png" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" + "idiom": "iphone", + "size": "20x20", + "scale": "3x", + "filename": "App-Icon-20x20@3x.png" }, { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" + "idiom": "iphone", + "size": "29x29", + "scale": "1x", + "filename": "App-Icon-29x29@1x.png" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" + "idiom": "iphone", + "size": "29x29", + "scale": "2x", + "filename": "App-Icon-29x29@2x.png" }, { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" + "idiom": "iphone", + "size": "29x29", + "scale": "3x", + "filename": "App-Icon-29x29@3x.png" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" + "idiom": "iphone", + "size": "40x40", + "scale": "2x", + "filename": "App-Icon-40x40@2x.png" }, { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" + "idiom": "iphone", + "size": "40x40", + "scale": "3x", + "filename": "App-Icon-40x40@3x.png" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" + "idiom": "iphone", + "size": "60x60", + "scale": "2x", + "filename": "App-Icon-60x60@2x.png" }, { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" + "idiom": "iphone", + "size": "60x60", + "scale": "3x", + "filename": "App-Icon-60x60@3x.png" + }, + { + "idiom": "ipad", + "size": "20x20", + "scale": "1x", + "filename": "App-Icon-20x20@1x.png" + }, + { + "idiom": "ipad", + "size": "20x20", + "scale": "2x", + "filename": "App-Icon-20x20@2x.png" + }, + { + "idiom": "ipad", + "size": "29x29", + "scale": "1x", + "filename": "App-Icon-29x29@1x.png" + }, + { + "idiom": "ipad", + "size": "29x29", + "scale": "2x", + "filename": "App-Icon-29x29@2x.png" + }, + { + "idiom": "ipad", + "size": "40x40", + "scale": "1x", + "filename": "App-Icon-40x40@1x.png" + }, + { + "idiom": "ipad", + "size": "40x40", + "scale": "2x", + "filename": "App-Icon-40x40@2x.png" + }, + { + "idiom": "ipad", + "size": "76x76", + "scale": "1x", + "filename": "App-Icon-76x76@1x.png" + }, + { + "idiom": "ipad", + "size": "76x76", + "scale": "2x", + "filename": "App-Icon-76x76@2x.png" + }, + { + "idiom": "ipad", + "size": "83.5x83.5", + "scale": "2x", + "filename": "App-Icon-83.5x83.5@2x.png" + }, + { + "idiom": "ios-marketing", + "size": "1024x1024", + "scale": "1x", + "filename": "ItunesArtwork@2x.png" } ], - "info" : { - "author" : "xcode", - "version" : 1 + "info": { + "version": 1, + "author": "expo" } -} +} \ No newline at end of file diff --git a/example/ios/example/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/example/ios/example/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png new file mode 100644 index 000000000..2732229fa Binary files /dev/null and b/example/ios/example/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png differ diff --git a/example/ios/example/Images.xcassets/Contents.json b/example/ios/example/Images.xcassets/Contents.json index 73c00596a..ed285c2e5 100644 --- a/example/ios/example/Images.xcassets/Contents.json +++ b/example/ios/example/Images.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "author" : "xcode", - "version" : 1 + "version" : 1, + "author" : "expo" } } diff --git a/example/ios/example/Images.xcassets/SplashScreen.imageset/Contents.json b/example/ios/example/Images.xcassets/SplashScreen.imageset/Contents.json new file mode 100644 index 000000000..3cf848977 --- /dev/null +++ b/example/ios/example/Images.xcassets/SplashScreen.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images": [ + { + "idiom": "universal", + "filename": "image.png", + "scale": "1x" + }, + { + "idiom": "universal", + "scale": "2x" + }, + { + "idiom": "universal", + "scale": "3x" + } + ], + "info": { + "version": 1, + "author": "expo" + } +} \ No newline at end of file diff --git a/example/ios/example/Images.xcassets/SplashScreen.imageset/image.png b/example/ios/example/Images.xcassets/SplashScreen.imageset/image.png new file mode 100644 index 000000000..c52c2c680 Binary files /dev/null and b/example/ios/example/Images.xcassets/SplashScreen.imageset/image.png differ diff --git a/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/Contents.json b/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/Contents.json new file mode 100644 index 000000000..3cf848977 --- /dev/null +++ b/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images": [ + { + "idiom": "universal", + "filename": "image.png", + "scale": "1x" + }, + { + "idiom": "universal", + "scale": "2x" + }, + { + "idiom": "universal", + "scale": "3x" + } + ], + "info": { + "version": 1, + "author": "expo" + } +} \ No newline at end of file diff --git a/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/image.png b/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/image.png new file mode 100644 index 000000000..33ddf20bb Binary files /dev/null and b/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/image.png differ diff --git a/example/ios/example/Info.plist b/example/ios/example/Info.plist index 20fb35c96..767d56459 100644 --- a/example/ios/example/Info.plist +++ b/example/ios/example/Info.plist @@ -1,57 +1,76 @@ - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - example - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSExceptionDomains - - localhost - - NSExceptionAllowsInsecureHTTPLoads - - - - - NSLocationWhenInUseUsageDescription - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleURLSchemes + + example + + + + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + + UILaunchStoryboardName + SplashScreen + UIRequiredDeviceCapabilities + + armv7 + + UIRequiresFullScreen + + UIStatusBarStyle + UIStatusBarStyleDefault + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIUserInterfaceStyle + Light + UIViewControllerBasedStatusBarAppearance + + diff --git a/example/ios/example/LaunchScreen.storyboard b/example/ios/example/LaunchScreen.storyboard deleted file mode 100644 index d931165dc..000000000 --- a/example/ios/example/LaunchScreen.storyboard +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/example/ios/example/SplashScreen.storyboard b/example/ios/example/SplashScreen.storyboard new file mode 100644 index 000000000..d209ca660 --- /dev/null +++ b/example/ios/example/SplashScreen.storyboard @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/ios/example/Supporting/Expo.plist b/example/ios/example/Supporting/Expo.plist new file mode 100644 index 000000000..acd284c91 --- /dev/null +++ b/example/ios/example/Supporting/Expo.plist @@ -0,0 +1,16 @@ + + + + + EXUpdatesCheckOnLaunch + ALWAYS + EXUpdatesEnabled + + EXUpdatesLaunchWaitMs + 0 + EXUpdatesSDKVersion + 45.0.0 + EXUpdatesURL + https://exp.host/@anonymous/example + + diff --git a/example/ios/example/example.entitlements b/example/ios/example/example.entitlements new file mode 100644 index 000000000..903def2af --- /dev/null +++ b/example/ios/example/example.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/example/ios/example/main.m b/example/ios/example/main.m index b1df44b95..25181b6cc 100644 --- a/example/ios/example/main.m +++ b/example/ios/example/main.m @@ -7,3 +7,4 @@ int main(int argc, char * argv[]) { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } + diff --git a/example/ios/example/noop-file.swift b/example/ios/example/noop-file.swift new file mode 100644 index 000000000..b2ffafbfc --- /dev/null +++ b/example/ios/example/noop-file.swift @@ -0,0 +1,4 @@ +// +// @generated +// A blank Swift file must be created for native modules with Swift files to work correctly. +// diff --git a/example/ios/exampleTests/Info.plist b/example/ios/exampleTests/Info.plist deleted file mode 100644 index ba72822e8..000000000 --- a/example/ios/exampleTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/example/ios/exampleTests/exampleTests.m b/example/ios/exampleTests/exampleTests.m deleted file mode 100644 index dd23e596e..000000000 --- a/example/ios/exampleTests/exampleTests.m +++ /dev/null @@ -1,65 +0,0 @@ -#import -#import - -#import -#import - -#define TIMEOUT_SECONDS 600 -#define TEXT_TO_LOOK_FOR @"Welcome to React" - -@interface exampleTests : XCTestCase - -@end - -@implementation exampleTests - -- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test -{ - if (test(view)) { - return YES; - } - for (UIView *subview in [view subviews]) { - if ([self findSubviewInView:subview matching:test]) { - return YES; - } - } - return NO; -} - -- (void)testRendersWelcomeScreen -{ - UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; - NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; - BOOL foundElement = NO; - - __block NSString *redboxError = nil; -#ifdef DEBUG - RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { - if (level >= RCTLogLevelError) { - redboxError = message; - } - }); -#endif - - while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { - [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - - foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { - if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { - return YES; - } - return NO; - }]; - } - -#ifdef DEBUG - RCTSetLogFunction(RCTDefaultLogFunction); -#endif - - XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); - XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); -} - - -@end diff --git a/example/metro.config.js b/example/metro.config.js index e91aba937..9430b0f9b 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -1,17 +1,4 @@ -/** - * Metro configuration for React Native - * https://github.com/facebook/react-native - * - * @format - */ +// Learn more https://docs.expo.io/guides/customizing-metro +const { getDefaultConfig } = require('expo/metro-config'); -module.exports = { - transformer: { - getTransformOptions: async () => ({ - transform: { - experimentalImportSupport: false, - inlineRequires: true, - }, - }), - }, -}; +module.exports = getDefaultConfig(__dirname); diff --git a/example/package.json b/example/package.json index ea8cef287..d24924da6 100644 --- a/example/package.json +++ b/example/package.json @@ -3,36 +3,47 @@ "version": "0.0.1", "private": true, "scripts": { - "preandroid": "cd node_modules/react-native-pdftron && npm start && cd ../../", - "android": "react-native run-android", - "preios": "cd node_modules/react-native-pdftron && npm start && cd ../../", - "ios": "react-native run-ios", - "prestart": "cd node_modules/react-native-pdftron && npm start && cd ../../", - "start": "react-native start", - "test": "jest", - "lint": "eslint ." + "start": "expo start --dev-client", + "android": "expo run:android", + "ios": "expo run:ios", + "web": "expo start --web", + "eject": "expo eject" }, "dependencies": { - "react": "^17.0.2", - "react-native": "^0.66.4", - "react-native-pdftron": "file:../" + "@expo/vector-icons": "^13.0.0", + "@react-navigation/native": "^6.0.11", + "@react-navigation/stack": "^6.2.2", + "expo": "^46.0.0", + "expo-constants": "~13.2.3", + "expo-document-picker": "~10.3.0", + "expo-file-system": "~14.1.0", + "expo-sharing": "~10.3.0", + "expo-splash-screen": "~0.16.1", + "expo-status-bar": "~1.4.0", + "intl": "^1.2.5", + "luxon": "^3.0.1", + "react": "18.0.0", + "react-dom": "18.0.0", + "react-native": "0.69.4", + "react-native-file-viewer": "^2.1.5", + "react-native-gesture-handler": "~2.5.0", + "react-native-mime-types": "^2.3.0", + "react-native-modal": "^13.0.1", + "react-native-paper": "^4.12.4", + "react-native-pdftron": "file:../", + "react-native-safe-area-context": "4.3.1", + "react-native-screens": "~3.15.0", + "react-native-web": "~0.18.7" }, "devDependencies": { - "@babel/core": "^7.12.9", - "@babel/runtime": "^7.12.5", - "@react-native-community/cli": "^6.0.0", - "@react-native-community/cli-platform-android": "^6.0.0", - "@react-native-community/cli-platform-ios": "^6.0.0", - "@react-native-community/eslint-config": "^2.0.0", - "@types/react": "^17.0.38", - "@types/react-native": "^0.66.12", - "babel-jest": "^26.6.3", - "eslint": "7.14.0", - "jest": "^26.6.3", - "metro-react-native-babel-preset": "^0.66.2", - "react-test-renderer": "17.0.2" - }, - "jest": { - "preset": "react-native" + "@babel/core": "^7.18.6", + "@react-native-community/eslint-config": "^3.1.0", + "@types/react": "~18.0.0", + "@types/react-native": "~0.69.1", + "@typescript-eslint/eslint-plugin": "^5.32.0", + "eslint": "^8.21.0", + "eslint-config-prettier": "^8.5.0", + "prettier": "^2.7.1", + "typescript": "^4.6.3" } } diff --git a/example/tsconfig.json b/example/tsconfig.json new file mode 100644 index 000000000..b9567f605 --- /dev/null +++ b/example/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "expo/tsconfig.base", + "compilerOptions": { + "strict": true + } +} diff --git a/example/utils/Utils.tsx b/example/utils/Utils.tsx new file mode 100644 index 000000000..34cfc6020 --- /dev/null +++ b/example/utils/Utils.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import {MaterialCommunityIcons} from '@expo/vector-icons'; + +export const pdfUrls: Array = [ + 'https://www.pdftron.com/webviewer/demo/gallery/PDFTRON_about.pdf', + 'https://www.pdftron.com/webviewer/demo/gallery/Report_2011.pdf', + 'https://www.pdftron.com/webviewer/demo/gallery/floorplan.pdf', + 'https://www.pdftron.com/webviewer/demo/gallery/chart_supported.pdf', + 'https://www.pdftron.com/webviewer/demo/gallery/magazine.pdf', +]; + +export const fileIcons: { + [key: string]: React.ComponentProps['name']; +} = { + json: 'code-json', + pdf: 'file-pdf-box', + msword: 'file-word-outline', + 'vnd.openxmlformats-officedocument.wordprocessingml.document': + 'file-word-outline', + 'vnd.ms-excel': 'file-excel-outline', + 'vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'file-excel-outline', + 'vnd.ms-powerpoint': 'file-powerpoint-outline', + 'vnd.openxmlformats-officedocument.presentationml.presentation': + 'file-powerpoint-outline', + zip: 'folder-zip-outline', + 'vnd.rar': 'folder-zip-outline', + 'x-7z-compressed': 'folder-zip-outline', + xml: 'xml', + css: 'language-css3', + csv: 'file-delimited-outline', + html: 'language-html5', + javascript: 'language-javascript', + plain: 'text-box-outline', +}; + +export const officeFileTypes = [ + 'vnd.openxmlformats-officedocument.wordprocessingml.document', + 'vnd.ms-excel', + 'vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'vnd.ms-powerpoint', + 'vnd.openxmlformats-officedocument.presentationml.presentation', +]; + +export const humanFileSize = (bytes: number) => { + const threshold = 1000; + const dp = 1; + const r = 10 ** dp; + const units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + + if (Math.abs(bytes) < threshold) { + return bytes + ' B'; + } + + let u = -1; + do { + bytes /= threshold; + ++u; + } while ( + Math.round(Math.abs(bytes) * r) / r >= threshold && + u < units.length - 1 + ); + + return bytes.toFixed(dp) + ' ' + units[u]; +}; diff --git a/package.json b/package.json index 52d089c0a..3a70b8105 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-native-pdftron", "title": "React Native Pdftron", - "version": "3.0.2-beta.123", + "version": "3.0.2-beta.124", "description": "React Native Pdftron", "main": "./lib/index.js", "typings": "index.ts",