getPackages() {
+ return Arrays.asList(
+ new MainReactPackage(),
+ new ReactSliderPackage(),
+ new ReactVideoPackage(),
+ new SvgPackage(),
+ // passing null because we do not need log handlers in the demo app
+ new ReactAztecPackage(null, null),
+ new LinearGradientPackage(),
+ new RNGetRandomValuesPackage(),
+ mRnReactNativeGutenbergBridgePackage);
+ }
+
+ @Override
+ protected String getJSMainModuleName() {
+ return "index";
+ }
+ };
+ }
+
+ private boolean isDarkMode() {
+ Configuration configuration = getResources().getConfiguration();
+ int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
+
+ return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
+ }
+
+ private void openGutenbergWebView(String content,
+ String blockId,
+ String blockName) {
+ Intent intent = new Intent(this, GutenbergWebViewActivity.class);
+ intent.putExtra(GutenbergWebViewActivity.ARG_BLOCK_CONTENT, content);
+ intent.putExtra(GutenbergWebViewActivity.ARG_BLOCK_ID, blockId);
+ intent.putExtra(GutenbergWebViewActivity.ARG_BLOCK_NAME, blockName);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+
+ @Override
+ public ReactNativeHost getReactNativeHost() {
+ if (mReactNativeHost == null) {
+ mReactNativeHost = createReactNativeHost();
+ createCustomDevOptions(mReactNativeHost);
+ }
+
+ return mReactNativeHost;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ SoLoader.init(this, /* native exopackage */ false);
+ }
+
+ private void createCustomDevOptions(ReactNativeHost reactNativeHost) {
+ DevSupportManager devSupportManager = reactNativeHost.getReactInstanceManager().getDevSupportManager();
+
+ devSupportManager.addCustomDevOption("Show html", new DevOptionHandler() {
+ @Override
+ public void onOptionSelected() {
+ mRnReactNativeGutenbergBridgePackage.getRNReactNativeGutenbergBridgeModule().toggleEditorMode();
+ }
+ });
+ }
+
+ @Override
+ public void saveContent(String content, String blockId) {
+ if (mReplaceUnsupportedBlockCallback != null) {
+ mReplaceUnsupportedBlockCallback.replaceUnsupportedBlock(content, blockId);
+ }
+ }
+}
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/react-native-editor/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000000000..a2f5908281d070
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/packages/react-native-editor/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 00000000000000..1b523998081149
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/react-native-editor/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000000000..ff10afd6e182ed
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/packages/react-native-editor/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 00000000000000..115a4c768a20c9
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/react-native-editor/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000000000..dcd3cd80833582
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/packages/react-native-editor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 00000000000000..459ca609d3ae0d
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/react-native-editor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000000000..8ca12fe024be86
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/packages/react-native-editor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000000000..8e19b410a1b15f
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/react-native-editor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000000000..b824ebdd48db91
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/packages/react-native-editor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000000000..4c19a13c239cb6
Binary files /dev/null and b/packages/react-native-editor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-editor/android/app/src/main/res/values/strings.xml b/packages/react-native-editor/android/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000000000..29e2e4d13944c2
--- /dev/null
+++ b/packages/react-native-editor/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Gutenberg
+
diff --git a/packages/react-native-editor/android/app/src/main/res/values/styles.xml b/packages/react-native-editor/android/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000000000..319eb0ca100b5a
--- /dev/null
+++ b/packages/react-native-editor/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/packages/react-native-editor/android/build.gradle b/packages/react-native-editor/android/build.gradle
new file mode 100644
index 00000000000000..641f576b14a14e
--- /dev/null
+++ b/packages/react-native-editor/android/build.gradle
@@ -0,0 +1,37 @@
+buildscript {
+ ext {
+ gradlePluginVersion = '3.4.2'
+ kotlinVersion = '1.3.61'
+ buildToolsVersion = "28.0.3"
+ minSdkVersion = 21
+ compileSdkVersion = 28
+ targetSdkVersion = 28
+ supportLibVersion = '28.0.0'
+ wordpressUtilsVersion = '1.22'
+ }
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:$gradlePluginVersion"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
+ }
+}
+
+// Load the "build from source" flag value but default to `true` since this is the demo gutenberg-mobile project so
+project.ext.buildGutenbergFromSource = project.properties.getOrDefault('wp.BUILD_GUTENBERG_FROM_SOURCE', true).toBoolean()
+
+allprojects {
+ repositories {
+ mavenLocal()
+ maven {
+ // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
+ url("$rootDir/../../../node_modules/react-native/android")
+ }
+
+ google()
+ jcenter()
+ maven { url 'https://jitpack.io' }
+ }
+}
diff --git a/packages/react-native-editor/android/gradle.properties b/packages/react-native-editor/android/gradle.properties
new file mode 100644
index 00000000000000..027ef9db8a3001
--- /dev/null
+++ b/packages/react-native-editor/android/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# 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
+
+# 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
+
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.jar b/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000000000..01b8bf6b1f99ca
Binary files /dev/null and b/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000000000..fb2e41dd7126a4
--- /dev/null
+++ b/packages/react-native-editor/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Jun 10 13:39:31 EDT 2019
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip
diff --git a/packages/react-native-editor/android/gradlew b/packages/react-native-editor/android/gradlew
new file mode 100755
index 00000000000000..cccdd3d517fc52
--- /dev/null
+++ b/packages/react-native-editor/android/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$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=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# 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
+ ;;
+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"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ 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
+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
+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
+
+# 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\""
+ fi
+ i=$((i+1))
+ 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, 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"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/packages/react-native-editor/android/gradlew.bat b/packages/react-native-editor/android/gradlew.bat
new file mode 100644
index 00000000000000..e95643d6a2ca62
--- /dev/null
+++ b/packages/react-native-editor/android/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/packages/react-native-editor/android/keystores/BUCK b/packages/react-native-editor/android/keystores/BUCK
new file mode 100644
index 00000000000000..88e4c31b28d497
--- /dev/null
+++ b/packages/react-native-editor/android/keystores/BUCK
@@ -0,0 +1,8 @@
+keystore(
+ name = "debug",
+ properties = "debug.keystore.properties",
+ store = "debug.keystore",
+ visibility = [
+ "PUBLIC",
+ ],
+)
diff --git a/packages/react-native-editor/android/keystores/debug.keystore.properties b/packages/react-native-editor/android/keystores/debug.keystore.properties
new file mode 100644
index 00000000000000..121bfb49f0dfda
--- /dev/null
+++ b/packages/react-native-editor/android/keystores/debug.keystore.properties
@@ -0,0 +1,4 @@
+key.store=debug.keystore
+key.alias=androiddebugkey
+key.store.password=android
+key.alias.password=android
diff --git a/packages/react-native-editor/android/settings.gradle b/packages/react-native-editor/android/settings.gradle
new file mode 100644
index 00000000000000..f7ae4dfa566f50
--- /dev/null
+++ b/packages/react-native-editor/android/settings.gradle
@@ -0,0 +1,18 @@
+rootProject.name = 'gutenberg'
+
+include ':@wordpress_react-native-bridge'
+project(':@wordpress_react-native-bridge').projectDir = new File(rootProject.projectDir, '../../react-native-bridge/android')
+include ':@wordpress_react-native-aztec'
+project(':@wordpress_react-native-aztec').projectDir = new File(rootProject.projectDir, '../../react-native-aztec/android')
+include ':@react-native-community_slider'
+project(':@react-native-community_slider').projectDir = new File(rootProject.projectDir, '../../../node_modules/@react-native-community/slider/src/android')
+include ':react-native-video'
+project(':react-native-video').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-video/android-exoplayer')
+include ':react-native-svg'
+project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-svg/android')
+include ':react-native-linear-gradient'
+project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-linear-gradient/android')
+include ':react-native-get-random-values'
+project(':react-native-get-random-values').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-get-random-values/android')
+
+include ':app'
diff --git a/packages/react-native-editor/app.json b/packages/react-native-editor/app.json
new file mode 100644
index 00000000000000..4d6b29af714c40
--- /dev/null
+++ b/packages/react-native-editor/app.json
@@ -0,0 +1,4 @@
+{
+ "name": "gutenberg",
+ "displayName": "Gutenberg"
+}
diff --git a/packages/react-native-editor/babel.config.js b/packages/react-native-editor/babel.config.js
new file mode 100644
index 00000000000000..0fd51ac0d10061
--- /dev/null
+++ b/packages/react-native-editor/babel.config.js
@@ -0,0 +1,51 @@
+module.exports = function ( api ) {
+ api.cache( true );
+ return {
+ presets: [ 'module:metro-react-native-babel-preset' ],
+ plugins: [
+ '@babel/plugin-proposal-async-generator-functions',
+ '@babel/plugin-transform-runtime',
+ [
+ 'react-native-platform-specific-extensions',
+ {
+ extensions: [ 'css', 'scss', 'sass' ],
+ },
+ ],
+ ],
+ overrides: [
+ {
+ // Transforms JSX into JS function calls and use `createElement` instead of the default `React.createElement`
+ plugins: [
+ [
+ '@babel/plugin-transform-react-jsx',
+ {
+ pragma: 'createElement',
+ pragmaFrag: 'Fragment',
+ },
+ ],
+ ],
+ exclude: /node_modules\/(react-native|@react-native-community)/,
+ },
+ {
+ // Auto-add `import { createElement } from '@wordpress/element';` when JSX is found
+ plugins: [
+ [
+ '@wordpress/babel-plugin-import-jsx-pragma',
+ {
+ scopeVariable: 'createElement',
+ scopeVariableFrag: 'Fragment',
+ source: '@wordpress/element',
+ isDefault: false,
+ },
+ ],
+ ],
+ exclude: /node_modules\/(react-native|@react-native-community)/,
+ },
+ ],
+ env: {
+ development: {
+ plugins: [ '@babel/transform-react-jsx-source' ],
+ },
+ },
+ };
+};
diff --git a/packages/react-native-editor/docs/Releasing.md b/packages/react-native-editor/docs/Releasing.md
new file mode 100644
index 00000000000000..51d2c4f322452f
--- /dev/null
+++ b/packages/react-native-editor/docs/Releasing.md
@@ -0,0 +1,178 @@
+# Making a release
+
+The `bundle` directory contains the production version of the project's Javascript. This is what the WordPress apps use to avoid having to build Gutenberg.
+
+You can rebuild those files at any time by running
+
+```
+yarn bundle
+```
+
+This is useful in case you want to use an unreleased version of the bundle in the apps. For instance, on a PR that's a work in progress, you might want to include to a specific gutenberg-mobile branch in the apps with an updated bundle so reviewers can see the latest changes before approving them (and releasing a new version).
+
+# Release Checklist Template
+
+Just copy this checklist and replace all occurrences of `X.XX.X` with the applicable release number, when we are ready to
+cut a new release.
+
+```
+
+Gutenberg Mobile X.XX.X – Release Scenario
+
+
+
+This checklist is based on the Release Checklist Template. If you need a checklist for a new gutenberg-mobile release, please copy from that template.
+
+
+
++mobilegutenberg
+
+
+
+Day 1 - create the release branch, update the version
+
+
+
+o Visit all opened PR's in gutenberg-mobile repo that are assigned to milestone X.XX.X and leave proper message with options to merge them or to bump them to the next version.
+
+
+
+o In the gutenberg-mobile
submodule, branch develop
to the release branch (eg. git checkout develop; git pull origin develop; git checkout -b release/X.XX.X
).
+
+
+
+o Update the package.json file with the new version number, run: yarn version
and enter the new version name when you get asked: X.XX.X
(Changes will be committed automatically).
+
+
+
+o Push the release branch, git push origin release/X.XX.X
.
+
+
+
+o Create the gutenberg submodule branch: cd gutenberg; git checkout -b rnmobile/release-X.XX.X
.
+
+
+
+o Push the gutenberg submodule branch: git push origin rnmobile/release-X.XX.X
.
+
+
+
+o Make sure we use a released version of Aztec iOS and Aztec Android: grep WordPress-Aztec-iOS RNTAztecView.podspec
and grep aztecVersion react-native-aztec/android/build.gradle
(should be part of a ./release-check.sh
script). Also insure that the line for testing non-official versions of Aztec on iOS is commented out (this command should find a match: grep "^s*#pod 'WordPress-Aztec-iOS'" ios/Podfile
)
+
+
+
+o Open a PR based on the release branch in Gutenberg-Mobile and target master. Example PR: https://github.com/wordpress-mobile/gutenberg-mobile/pull/1627. There should not be any conflicts with this PR.
+
+
+
+o Create a new branch in the main WP apps (WordPress-iOS, WordPress-Android) named gutenberg/integrate_release_X.XX.X
.
+
+
+
+o Use the commit hash of the head of the release branch in Gutenberg-Mobile as the reference for the main apps.
+
+
+
+o Create a PR in WPAndroid and WPiOS. Example on WPAndroid, WPiOS. To write the PR description: pull the differences between previous and current releases. Update the RELEASE-NOTES.txt files in each PR (get info from the gutenberg-mobile RELEASE-NOTES.txt).
+
+
+
+o In iOS update the file Podfile
to point to the new hash in GB-Mobile and if needed also update the reference to Aztec to the new release. Then run rake dependencies
, commit and push.
+
+
+
+o On Android update the git submodule reference for libs/gutenberg-mobile
(cd libs/gutenberg-mobile && git checkout release/X.XX.X && git pull origin release/X.XX.X && cd .. && git add gutenberg-mobile
) and run python tools/merge_strings_xml.py
to update the main strings.xml file.
+
+
+
+o Create new branches gutenberg/after_X.XX.X
in WPAndroid and WPiOS and keep them up to date with the release branches. These are to be doubles for develop on the main apps for mobile gutenberg dev’s WP app PR’s that didn’t or shouldn’t make it into the X.XX.X editor release.
+
+
+
+New Aztec Release
+
+
+
+o Make sure there is no pending Aztec PR required for this Gutenberg release. Check the commit hash referred in the gutenberg repo is in the Aztec develop
branch. If it's not, make sure pending PRs are merged before next steps.
+
+
+
+o Open a PR on Aztec repo to update the CHANGELOG.md
and README.md
files with the new version name.
+
+
+
+o Create a new release and name it with the tag name from step 1. For Aztec-iOS, follow this process. For Aztec-Android, releases are created via the GitHub releases page by hitting the “Draft new release” button, put the tag name to be created in the tag version field and release title field, and also add the changelog to the release description. The binary assets (.zip, tar.gz files) are attached automatically after hitting “Publish release”.
+
+
+
+(Optional) Specific tasks after a PR has been merged after the freeze
+
+
+
+o After a merge happened in gutenberg-mobile release/X.XX.X
or in gutenberg rnmobile/release-X.XX.X
, make sure the gutenberg
submodule points to the right hash (and make sure the rnmobile/release-X.XX.X
in the gutenberg repo branch has been updated)
+
+
+
+o If there were changes in Gutenberg repo, make sure to cherry-pick the changes that landed in the master branch back to the release branch.
+
+
+
+Last Day
+
+
+
+o Make sure that the bundle files on the Gutenberg-Mobile release branch have been updated to include any changes to the release branch.
+
+
+
+o Merge the Gutenberg-Mobile PR to master. WARNING: Don’t merge the Gutenberg PR to master at this point.
+
+
+
+o Tag the head of Gutenberg release branch that the Gutenberg-Mobile release branch is pointing to with the rnmobile/X.XX.X
tag.
+
+
+
+o Create a new GitHub release pointing to the tag: https://github.com/wordpress-mobile/gutenberg-mobile/releases/new?tag=X.XX.X&target=master&title=X.XX.X. Include a list of changes in the release's description
+
+
+
+o In WPiOS update the reference to point to the tag. For iOS do not forget to remove ‘develop’ branch reference near 3rd party pod specs if any.
+
+
+
+o In WPAndroid, update the submodule to point to the merge commit on master.
+
+
+
+o Main apps PRs should be ready to merge to their develop now. Merge them or get them merged.
+
+
+
+o Once everything is merged, ping our friends in #platform9 and let them know we’ve merged our release so everything is right from our side to cut the main app releases.
+
+
+
+o Open a PR from Gutenberg-Mobile master to bring all the gutenberg/after_X.XX.X
changes to develop
and point to the Gutenberg side PR (if any changes happened specifically for the release). Merge the PR (or PR domino if Gutenberg changes are there)
+
+
+
+AFTER the main apps have cut their release branches
+
+
+
+o Update the gutenberg/after_X.XX.X
branches and open a PR against develop
. If the branches are empty we’ll just delete them. The PR can actually get created as soon as something gets merged to the after-ooo branches. Merge the gutenberg/after_X.XX.X
PR(s) only AFTER the main apps have cut their release branches.
+
+
+
+You're done
+
+
+
+o Pass the baton. Ping the dev who is responsible for the next release
+
+
+
+o Celebrate!
+
+```
diff --git a/packages/react-native-editor/i18n-cache/.gitignore b/packages/react-native-editor/i18n-cache/.gitignore
new file mode 100644
index 00000000000000..4262a76c530230
--- /dev/null
+++ b/packages/react-native-editor/i18n-cache/.gitignore
@@ -0,0 +1,3 @@
+# ignore native version of this module as it will be generated
+
+index.native.js
diff --git a/packages/react-native-editor/i18n-cache/data/.gitignore b/packages/react-native-editor/i18n-cache/data/.gitignore
new file mode 100644
index 00000000000000..e13e2719e01705
--- /dev/null
+++ b/packages/react-native-editor/i18n-cache/data/.gitignore
@@ -0,0 +1,3 @@
+# ignore all the contents of this folder except this file
+*
+!.gitignore
\ No newline at end of file
diff --git a/packages/react-native-editor/i18n-cache/index.js b/packages/react-native-editor/i18n-cache/index.js
new file mode 100644
index 00000000000000..9ff94b17a3f0fc
--- /dev/null
+++ b/packages/react-native-editor/i18n-cache/index.js
@@ -0,0 +1,183 @@
+/* eslint-disable no-console */
+
+/**
+ * External dependencies
+ */
+const fs = require( 'fs' );
+const path = require( 'path' );
+const fetch = require( 'node-fetch' );
+
+const supportedLocales = [
+ 'ar', // Arabic
+ 'bg', // Bulgarian
+ 'bo', // Tibetan
+ 'ca', // Catalan
+ 'cs', // Czech
+ 'cy', // Welsh
+ 'da', // Danish
+ 'de', // German
+ 'en-au', // English (Australia)
+ 'en-ca', // English (Canada)
+ 'en-gb', // English (UK)
+ 'en-nz', // English (New Zealand)
+ 'en-za', // English (South Africa)
+ 'el', // Greek
+ 'es', // Spanish
+ 'es-ar', // Spanish (Argentina)
+ 'es-cl', // Spanish (Chile)
+ 'es-cr', // Spanish (Costa Rica)
+ 'fa', // Persian
+ 'fr', // French
+ 'gl', // Galician
+ 'he', // Hebrew
+ 'hr', // Croatian
+ 'hu', // Hungarian
+ 'id', // Indonesian
+ 'is', // Icelandic
+ 'it', // Italian
+ 'ja', // Japanese
+ 'ka', // Georgian
+ 'ko', // Korean
+ 'nb', // Norwegian (Bokmål)
+ 'nl', // Dutch
+ 'nl-be', // Dutch (Belgium)
+ 'pl', // Polish
+ 'pt', // Portuguese
+ 'pt-br', // Portuguese (Brazil)
+ 'ro', // Romainian
+ 'ru', // Russian
+ 'sk', // Slovak
+ 'sq', // Albanian
+ 'sr', // Serbian
+ 'sv', // Swedish
+ 'th', // Thai
+ 'tr', // Turkish
+ 'uk', // Ukrainian
+ 'ur', // Urdu
+ 'vi', // Vietnamese
+ 'zh-cn', // Chinese (China)
+ 'zh-tw', // Chinese (Taiwan)
+];
+
+const getLanguageUrl = ( locale ) =>
+ `https://translate.wordpress.org/projects/wp-plugins/gutenberg/dev/${ locale }/default/export-translations\?format\=json`;
+const getTranslationFilePath = ( locale ) => `./data/${ locale }.json`;
+
+const getTranslation = ( locale ) =>
+ require( getTranslationFilePath( locale ) );
+
+const fetchTranslation = ( locale ) => {
+ if ( ! process.env.REFRESH_I18N_CACHE ) {
+ try {
+ const localData = getTranslation( locale );
+ console.log( `Using cached locale data for ${ locale }` );
+ return Promise.resolve( {
+ response: localData,
+ locale,
+ inCache: true,
+ } );
+ } catch ( error ) {
+ // translation not found, let's fetch it
+ }
+ }
+
+ console.log( 'fetching', getLanguageUrl( locale ) );
+ const localeUrl = getLanguageUrl( locale );
+ return fetch( localeUrl )
+ .then( ( response ) => response.json() )
+ .then( ( body ) => {
+ return { response: body, locale };
+ } )
+ .catch( () => {
+ console.error( `Could not find translation file ${ localeUrl }` );
+ } );
+};
+
+const fetchTranslations = () => {
+ const fetchPromises = supportedLocales.map( ( locale ) =>
+ fetchTranslation( locale )
+ );
+
+ return Promise.all( fetchPromises ).then( ( results ) => {
+ const fetchedTranslations = results.filter( Boolean );
+ const translationFilePromises = fetchedTranslations.map(
+ ( languageResult ) => {
+ return new Promise( ( resolve, reject ) => {
+ const translationRelativePath = getTranslationFilePath(
+ languageResult.locale
+ );
+
+ if ( languageResult.inCache ) {
+ languageResult.path = translationRelativePath;
+ resolve( translationRelativePath );
+ return;
+ }
+
+ const translationAbsolutePath = path.resolve(
+ __dirname,
+ translationRelativePath
+ );
+
+ fs.writeFile(
+ translationAbsolutePath,
+ JSON.stringify( languageResult.response ),
+ 'utf8',
+ ( err ) => {
+ if ( err ) {
+ reject( err );
+ } else {
+ languageResult.path = translationRelativePath;
+ resolve( translationRelativePath );
+ }
+ }
+ );
+ } );
+ }
+ );
+ return Promise.all( translationFilePromises ).then(
+ () => fetchedTranslations
+ );
+ } );
+};
+
+module.exports = {
+ getTranslation,
+};
+
+// if run as a script
+if ( require.main === module ) {
+ fetchTranslations().then( ( translations ) => {
+ const indexNative = `/* THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. */
+/* eslint-disable prettier/prettier */
+
+const translations = {
+${ translations
+ .filter( Boolean )
+ .map(
+ ( translation ) =>
+ `\t"${ translation.locale }": require( "${ translation.path }" ),`
+ )
+ .join( '\n' ) }
+};
+
+export const getTranslation = ( locale ) => translations[ locale ];
+
+/* eslint-enable prettier/prettier */
+`;
+
+ fs.writeFile(
+ path.join( __dirname, 'index.native.js' ),
+ indexNative,
+ 'utf8',
+ ( error ) => {
+ if ( error ) {
+ console.error( error );
+ return;
+ }
+ console.log( 'Done.' );
+ }
+ );
+ } );
+}
+
+/* eslint-enable no-console */
diff --git a/packages/react-native-editor/images/recommended-extensions.png b/packages/react-native-editor/images/recommended-extensions.png
new file mode 100644
index 00000000000000..1f7acb2ad2f2d7
Binary files /dev/null and b/packages/react-native-editor/images/recommended-extensions.png differ
diff --git a/packages/react-native-editor/index.js b/packages/react-native-editor/index.js
new file mode 100644
index 00000000000000..1417cc0322975d
--- /dev/null
+++ b/packages/react-native-editor/index.js
@@ -0,0 +1,4 @@
+/**
+ * Internal dependencies
+ */
+import './src';
diff --git a/packages/react-native-editor/ios/.bundle/config b/packages/react-native-editor/ios/.bundle/config
new file mode 100644
index 00000000000000..2369228816d467
--- /dev/null
+++ b/packages/react-native-editor/ios/.bundle/config
@@ -0,0 +1,2 @@
+---
+BUNDLE_PATH: "vendor/bundle"
diff --git a/packages/react-native-editor/ios/CustomImageLoader.swift b/packages/react-native-editor/ios/CustomImageLoader.swift
new file mode 100644
index 00000000000000..e543734b8df843
--- /dev/null
+++ b/packages/react-native-editor/ios/CustomImageLoader.swift
@@ -0,0 +1,36 @@
+import Foundation
+
+class CustomImageLoader: NSObject, RCTImageURLLoader {
+
+ static func moduleName() -> String! {
+ return "CustomImageLoader"
+ }
+
+ func canLoadImageURL(_ requestURL: URL!) -> Bool {
+ return !requestURL.isFileURL
+ }
+
+ func loadImage(for imageURL: URL!, size: CGSize, scale: CGFloat, resizeMode: RCTResizeMode, progressHandler: RCTImageLoaderProgressBlock!, partialLoadHandler: RCTImageLoaderPartialLoadBlock!, completionHandler: RCTImageLoaderCompletionBlock!) -> RCTImageLoaderCancellationBlock! {
+ let task = URLSession.shared.dataTask(with: imageURL) { (data, response, error) in
+ if let error = error {
+ completionHandler(error, nil)
+ return
+ }
+ guard let data = data,
+ let image = UIImage.init(data: data) else {
+ completionHandler?(NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil), nil)
+ return;
+ }
+ completionHandler?(nil, image)
+ }
+ task.resume()
+ return { () in
+ task.cancel()
+ }
+ }
+
+ func loaderPriority() -> Float {
+ return 100
+ }
+
+}
diff --git a/packages/react-native-editor/ios/Gemfile b/packages/react-native-editor/ios/Gemfile
new file mode 100644
index 00000000000000..09c4d6ef1eb6f4
--- /dev/null
+++ b/packages/react-native-editor/ios/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org' do
+ gem 'cocoapods', '~> 1.8.0'
+end
diff --git a/packages/react-native-editor/ios/Gemfile.lock b/packages/react-native-editor/ios/Gemfile.lock
new file mode 100644
index 00000000000000..8537a61386f86b
--- /dev/null
+++ b/packages/react-native-editor/ios/Gemfile.lock
@@ -0,0 +1,83 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ CFPropertyList (3.0.1)
+ activesupport (4.2.11.1)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ algoliasearch (1.27.1)
+ httpclient (~> 2.8, >= 2.8.3)
+ json (>= 1.5.1)
+ atomos (0.1.3)
+ claide (1.0.3)
+ cocoapods (1.8.4)
+ activesupport (>= 4.0.2, < 5)
+ claide (>= 1.0.2, < 2.0)
+ cocoapods-core (= 1.8.4)
+ cocoapods-deintegrate (>= 1.0.3, < 2.0)
+ cocoapods-downloader (>= 1.2.2, < 2.0)
+ cocoapods-plugins (>= 1.0.0, < 2.0)
+ cocoapods-search (>= 1.0.0, < 2.0)
+ cocoapods-stats (>= 1.0.0, < 2.0)
+ cocoapods-trunk (>= 1.4.0, < 2.0)
+ cocoapods-try (>= 1.1.0, < 2.0)
+ colored2 (~> 3.1)
+ escape (~> 0.0.4)
+ fourflusher (>= 2.3.0, < 3.0)
+ gh_inspector (~> 1.0)
+ molinillo (~> 0.6.6)
+ nap (~> 1.0)
+ ruby-macho (~> 1.4)
+ xcodeproj (>= 1.11.1, < 2.0)
+ cocoapods-core (1.8.4)
+ activesupport (>= 4.0.2, < 6)
+ algoliasearch (~> 1.0)
+ concurrent-ruby (~> 1.1)
+ fuzzy_match (~> 2.0.4)
+ nap (~> 1.0)
+ cocoapods-deintegrate (1.0.4)
+ cocoapods-downloader (1.3.0)
+ cocoapods-plugins (1.0.0)
+ nap
+ cocoapods-search (1.0.0)
+ cocoapods-stats (1.1.0)
+ cocoapods-trunk (1.4.1)
+ nap (>= 0.8, < 2.0)
+ netrc (~> 0.11)
+ cocoapods-try (1.1.0)
+ colored2 (3.1.2)
+ concurrent-ruby (1.1.5)
+ escape (0.0.4)
+ fourflusher (2.3.1)
+ fuzzy_match (2.0.4)
+ gh_inspector (1.1.3)
+ httpclient (2.8.3)
+ i18n (0.9.5)
+ concurrent-ruby (~> 1.0)
+ json (2.2.0)
+ minitest (5.13.0)
+ molinillo (0.6.6)
+ nanaimo (0.2.6)
+ nap (1.1.0)
+ netrc (0.11.0)
+ ruby-macho (1.4.0)
+ thread_safe (0.3.6)
+ tzinfo (1.2.5)
+ thread_safe (~> 0.1)
+ xcodeproj (1.13.0)
+ CFPropertyList (>= 2.3.3, < 4.0)
+ atomos (~> 0.1.3)
+ claide (>= 1.0.2, < 2.0)
+ colored2 (~> 3.1)
+ nanaimo (~> 0.2.6)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ cocoapods (~> 1.8.0)!
+
+BUNDLED WITH
+ 2.0.2
diff --git a/packages/react-native-editor/ios/Podfile b/packages/react-native-editor/ios/Podfile
new file mode 100644
index 00000000000000..4585276dd919a3
--- /dev/null
+++ b/packages/react-native-editor/ios/Podfile
@@ -0,0 +1,66 @@
+project 'gutenberg.xcodeproj'
+
+# Uncomment the next line to define a global platform for your project
+platform :ios, '11.0'
+require_relative '../../../node_modules/@react-native-community/cli-platform-ios/native_modules'
+
+target 'gutenberg' do
+ # Comment the next line if you don't want to use dynamic frameworks
+ use_frameworks!
+
+ # Pods for gutenberg
+ pod 'FBLazyVector', :path => "../../../node_modules/react-native/Libraries/FBLazyVector"
+ pod 'FBReactNativeSpec', :path => "../../../node_modules/react-native/Libraries/FBReactNativeSpec"
+ pod 'RCTRequired', :path => "../../../node_modules/react-native/Libraries/RCTRequired"
+ pod 'RCTTypeSafety', :path => "../../../node_modules/react-native/Libraries/TypeSafety"
+ pod 'React', :path => '../../../node_modules/react-native/'
+ pod 'React-Core', :path => '../../../node_modules/react-native/'
+ pod 'React-CoreModules', :path => '../../../node_modules/react-native/React/CoreModules'
+ pod 'React-Core/DevSupport', :path => '../../../node_modules/react-native/'
+ pod 'React-RCTActionSheet', :path => '../../../node_modules/react-native/Libraries/ActionSheetIOS'
+ pod 'React-RCTAnimation', :path => '../../../node_modules/react-native/Libraries/NativeAnimation'
+ pod 'React-RCTBlob', :path => '../../../node_modules/react-native/Libraries/Blob'
+ pod 'React-RCTImage', :path => '../../../node_modules/react-native/Libraries/Image'
+ pod 'React-RCTLinking', :path => '../../../node_modules/react-native/Libraries/LinkingIOS'
+ pod 'React-RCTNetwork', :path => '../../../node_modules/react-native/Libraries/Network'
+ pod 'React-RCTSettings', :path => '../../../node_modules/react-native/Libraries/Settings'
+ pod 'React-RCTText', :path => '../../../node_modules/react-native/Libraries/Text'
+ pod 'React-RCTVibration', :path => '../../../node_modules/react-native/Libraries/Vibration'
+ pod 'React-Core/RCTWebSocket', :path => '../../../node_modules/react-native/'
+ pod 'React-cxxreact', :path => '../../../node_modules/react-native/ReactCommon/cxxreact'
+ pod 'React-jsi', :path => '../../../node_modules/react-native/ReactCommon/jsi'
+ pod 'React-jsiexecutor', :path => '../../../node_modules/react-native/ReactCommon/jsiexecutor'
+ pod 'React-jsinspector', :path => '../../../node_modules/react-native/ReactCommon/jsinspector'
+ pod 'ReactCommon/jscallinvoker', :path => "../../../node_modules/react-native/ReactCommon"
+ pod 'ReactCommon/turbomodule/core', :path => "../../../node_modules/react-native/ReactCommon"
+ pod 'Yoga', :path => '../../../node_modules/react-native/ReactCommon/yoga'
+ pod 'DoubleConversion', :podspec => '../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
+ pod 'glog', :podspec => '../../../node_modules/react-native/third-party-podspecs/glog.podspec'
+ pod 'Folly', :podspec => '../../../node_modules/react-native/third-party-podspecs/Folly.podspec'
+ pod 'RNTAztecView', :path => '../../react-native-aztec/RNTAztecView.podspec'
+ #Use for testing non official versions of Aztec
+ #pod 'WordPress-Aztec-iOS', :git => 'https://github.com/wordpress-mobile/WordPress-Aztec-iOS.git', :commit => '29dff741f4b19435d75f21179e27766337de8e9d'
+ pod 'Gutenberg', :path => '../../react-native-bridge/Gutenberg.podspec'
+
+
+
+ target 'gutenbergTests' do
+ inherit! :search_paths
+ # Pods for testing
+ end
+
+ use_native_modules!
+end
+
+target 'gutenberg-tvOS' do
+ # Comment the next line if you don't want to use dynamic frameworks
+ use_frameworks!
+
+ # Pods for gutenberg-tvOS
+
+ target 'gutenberg-tvOSTests' do
+ inherit! :search_paths
+ # Pods for testing
+ end
+
+end
diff --git a/packages/react-native-editor/ios/Podfile.lock b/packages/react-native-editor/ios/Podfile.lock
new file mode 100644
index 00000000000000..a3d2e224932655
--- /dev/null
+++ b/packages/react-native-editor/ios/Podfile.lock
@@ -0,0 +1,408 @@
+PODS:
+ - boost-for-react-native (1.63.0)
+ - BVLinearGradient (2.5.6):
+ - React
+ - DoubleConversion (1.1.6)
+ - FBLazyVector (0.61.5)
+ - FBReactNativeSpec (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - RCTRequired (= 0.61.5)
+ - RCTTypeSafety (= 0.61.5)
+ - React-Core (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - ReactCommon/turbomodule/core (= 0.61.5)
+ - Folly (2018.10.22.00):
+ - boost-for-react-native
+ - DoubleConversion
+ - Folly/Default (= 2018.10.22.00)
+ - glog
+ - Folly/Default (2018.10.22.00):
+ - boost-for-react-native
+ - DoubleConversion
+ - glog
+ - glog (0.3.5)
+ - Gutenberg (8.3.0):
+ - React (= 0.61.5)
+ - React-CoreModules (= 0.61.5)
+ - React-RCTImage (= 0.61.5)
+ - RNTAztecView
+ - RCTRequired (0.61.5)
+ - RCTTypeSafety (0.61.5):
+ - FBLazyVector (= 0.61.5)
+ - Folly (= 2018.10.22.00)
+ - RCTRequired (= 0.61.5)
+ - React-Core (= 0.61.5)
+ - React (0.61.5):
+ - React-Core (= 0.61.5)
+ - React-Core/DevSupport (= 0.61.5)
+ - React-Core/RCTWebSocket (= 0.61.5)
+ - React-RCTActionSheet (= 0.61.5)
+ - React-RCTAnimation (= 0.61.5)
+ - React-RCTBlob (= 0.61.5)
+ - React-RCTImage (= 0.61.5)
+ - React-RCTLinking (= 0.61.5)
+ - React-RCTNetwork (= 0.61.5)
+ - React-RCTSettings (= 0.61.5)
+ - React-RCTText (= 0.61.5)
+ - React-RCTVibration (= 0.61.5)
+ - React-Core (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default (= 0.61.5)
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/CoreModulesHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/Default (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/DevSupport (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default (= 0.61.5)
+ - React-Core/RCTWebSocket (= 0.61.5)
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - React-jsinspector (= 0.61.5)
+ - Yoga
+ - React-Core/RCTActionSheetHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTAnimationHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTBlobHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTImageHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTLinkingHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTNetworkHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTSettingsHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTTextHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTVibrationHeaders (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-Core/RCTWebSocket (0.61.5):
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core/Default (= 0.61.5)
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsiexecutor (= 0.61.5)
+ - Yoga
+ - React-CoreModules (0.61.5):
+ - FBReactNativeSpec (= 0.61.5)
+ - Folly (= 2018.10.22.00)
+ - RCTTypeSafety (= 0.61.5)
+ - React-Core/CoreModulesHeaders (= 0.61.5)
+ - React-RCTImage (= 0.61.5)
+ - ReactCommon/turbomodule/core (= 0.61.5)
+ - React-cxxreact (0.61.5):
+ - boost-for-react-native (= 1.63.0)
+ - DoubleConversion
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-jsinspector (= 0.61.5)
+ - React-jsi (0.61.5):
+ - boost-for-react-native (= 1.63.0)
+ - DoubleConversion
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-jsi/Default (= 0.61.5)
+ - React-jsi/Default (0.61.5):
+ - boost-for-react-native (= 1.63.0)
+ - DoubleConversion
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-jsiexecutor (0.61.5):
+ - DoubleConversion
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-jsinspector (0.61.5)
+ - react-native-get-random-values (1.4.0):
+ - React
+ - react-native-keyboard-aware-scroll-view (0.8.8):
+ - React
+ - react-native-safe-area (0.5.1):
+ - React
+ - react-native-slider (2.0.7):
+ - React
+ - react-native-video (5.0.2):
+ - React
+ - react-native-video/Video (= 5.0.2)
+ - react-native-video/Video (5.0.2):
+ - React
+ - React-RCTActionSheet (0.61.5):
+ - React-Core/RCTActionSheetHeaders (= 0.61.5)
+ - React-RCTAnimation (0.61.5):
+ - React-Core/RCTAnimationHeaders (= 0.61.5)
+ - React-RCTBlob (0.61.5):
+ - React-Core/RCTBlobHeaders (= 0.61.5)
+ - React-Core/RCTWebSocket (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - React-RCTNetwork (= 0.61.5)
+ - React-RCTImage (0.61.5):
+ - React-Core/RCTImageHeaders (= 0.61.5)
+ - React-RCTNetwork (= 0.61.5)
+ - React-RCTLinking (0.61.5):
+ - React-Core/RCTLinkingHeaders (= 0.61.5)
+ - React-RCTNetwork (0.61.5):
+ - React-Core/RCTNetworkHeaders (= 0.61.5)
+ - React-RCTSettings (0.61.5):
+ - React-Core/RCTSettingsHeaders (= 0.61.5)
+ - React-RCTText (0.61.5):
+ - React-Core/RCTTextHeaders (= 0.61.5)
+ - React-RCTVibration (0.61.5):
+ - React-Core/RCTVibrationHeaders (= 0.61.5)
+ - ReactCommon/jscallinvoker (0.61.5):
+ - DoubleConversion
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-cxxreact (= 0.61.5)
+ - ReactCommon/turbomodule/core (0.61.5):
+ - DoubleConversion
+ - Folly (= 2018.10.22.00)
+ - glog
+ - React-Core (= 0.61.5)
+ - React-cxxreact (= 0.61.5)
+ - React-jsi (= 0.61.5)
+ - ReactCommon/jscallinvoker (= 0.61.5)
+ - ReactNativeDarkMode (0.0.10):
+ - React
+ - RNSVG (9.13.6-gb):
+ - React
+ - RNTAztecView (0.1.11):
+ - React-Core
+ - WordPress-Aztec-iOS (~> 1.19.2)
+ - WordPress-Aztec-iOS (1.19.2)
+ - Yoga (1.14.0)
+
+DEPENDENCIES:
+ - BVLinearGradient (from `../../../node_modules/react-native-linear-gradient`)
+ - DoubleConversion (from `../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
+ - FBLazyVector (from `../../../node_modules/react-native/Libraries/FBLazyVector`)
+ - FBReactNativeSpec (from `../../../node_modules/react-native/Libraries/FBReactNativeSpec`)
+ - Folly (from `../../../node_modules/react-native/third-party-podspecs/Folly.podspec`)
+ - glog (from `../../../node_modules/react-native/third-party-podspecs/glog.podspec`)
+ - Gutenberg (from `../../react-native-bridge/Gutenberg.podspec`)
+ - RCTRequired (from `../../../node_modules/react-native/Libraries/RCTRequired`)
+ - RCTTypeSafety (from `../../../node_modules/react-native/Libraries/TypeSafety`)
+ - React (from `../../../node_modules/react-native/`)
+ - 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-native-get-random-values (from `../../../node_modules/react-native-get-random-values`)
+ - react-native-keyboard-aware-scroll-view (from `../../../node_modules/react-native-keyboard-aware-scroll-view`)
+ - react-native-safe-area (from `../../../node_modules/react-native-safe-area`)
+ - "react-native-slider (from `../../../node_modules/@react-native-community/slider`)"
+ - react-native-video (from `../../../node_modules/react-native-video`)
+ - 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`)
+ - ReactCommon/jscallinvoker (from `../../../node_modules/react-native/ReactCommon`)
+ - ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`)
+ - ReactNativeDarkMode (from `../../../node_modules/react-native-dark-mode`)
+ - RNSVG (from `../../../node_modules/react-native-svg`)
+ - RNTAztecView (from `../../react-native-aztec/RNTAztecView.podspec`)
+ - Yoga (from `../../../node_modules/react-native/ReactCommon/yoga`)
+
+SPEC REPOS:
+ trunk:
+ - boost-for-react-native
+ - WordPress-Aztec-iOS
+
+EXTERNAL SOURCES:
+ BVLinearGradient:
+ :path: "../../../node_modules/react-native-linear-gradient"
+ DoubleConversion:
+ :podspec: "../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
+ FBLazyVector:
+ :path: "../../../node_modules/react-native/Libraries/FBLazyVector"
+ FBReactNativeSpec:
+ :path: "../../../node_modules/react-native/Libraries/FBReactNativeSpec"
+ Folly:
+ :podspec: "../../../node_modules/react-native/third-party-podspecs/Folly.podspec"
+ glog:
+ :podspec: "../../../node_modules/react-native/third-party-podspecs/glog.podspec"
+ Gutenberg:
+ :path: "../../react-native-bridge/Gutenberg.podspec"
+ RCTRequired:
+ :path: "../../../node_modules/react-native/Libraries/RCTRequired"
+ RCTTypeSafety:
+ :path: "../../../node_modules/react-native/Libraries/TypeSafety"
+ React:
+ :path: "../../../node_modules/react-native/"
+ 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-native-get-random-values:
+ :path: "../../../node_modules/react-native-get-random-values"
+ react-native-keyboard-aware-scroll-view:
+ :path: "../../../node_modules/react-native-keyboard-aware-scroll-view"
+ react-native-safe-area:
+ :path: "../../../node_modules/react-native-safe-area"
+ react-native-slider:
+ :path: "../../../node_modules/@react-native-community/slider"
+ react-native-video:
+ :path: "../../../node_modules/react-native-video"
+ 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"
+ ReactCommon:
+ :path: "../../../node_modules/react-native/ReactCommon"
+ ReactNativeDarkMode:
+ :path: "../../../node_modules/react-native-dark-mode"
+ RNSVG:
+ :path: "../../../node_modules/react-native-svg"
+ RNTAztecView:
+ :path: "../../react-native-aztec/RNTAztecView.podspec"
+ Yoga:
+ :path: "../../../node_modules/react-native/ReactCommon/yoga"
+
+SPEC CHECKSUMS:
+ boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
+ BVLinearGradient: 60a475b2edfe7707deda00278cb8ce9bfe70e669
+ DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
+ FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
+ FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
+ Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
+ glog: 1f3da668190260b06b429bb211bfbee5cd790c28
+ Gutenberg: 237167a5bb725cedcef0fa56f73b009bc1c389bd
+ RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
+ RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
+ React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
+ React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
+ React-CoreModules: d04f8494c1a328b69ec11db9d1137d667f916dcb
+ React-cxxreact: d0f7bcafa196ae410e5300736b424455e7fb7ba7
+ React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
+ React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
+ React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
+ react-native-get-random-values: 8940331a943a46c165d3ed05802c09c392f8dd46
+ react-native-keyboard-aware-scroll-view: ffa9152671fec9a571197ed2d02e0fcb90206e60
+ react-native-safe-area: e8230b0017d76c00de6b01e2412dcf86b127c6a3
+ react-native-slider: f81b89fa0c1f9a65742d33f889a194ca6653a985
+ react-native-video: 961749da457e73bf0b5565edfbaffc25abfb8974
+ React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
+ React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
+ React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
+ React-RCTImage: 6b8e8df449eb7c814c99a92d6b52de6fe39dea4e
+ React-RCTLinking: 121bb231c7503cf9094f4d8461b96a130fabf4a5
+ React-RCTNetwork: fb353640aafcee84ca8b78957297bd395f065c9a
+ React-RCTSettings: 8db258ea2a5efee381fcf7a6d5044e2f8b68b640
+ React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
+ React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
+ ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
+ ReactNativeDarkMode: f61376360c5d983907e5c316e8e1c853a8c2f348
+ RNSVG: 68a534a5db06dcbdaebfd5079349191598caef7b
+ RNTAztecView: b4c945bdc156b98dbf5c8a676def6c7736efa337
+ WordPress-Aztec-iOS: d01bf0c5e150ae6a046f06ba63b7cc2762061c0b
+ Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
+
+PODFILE CHECKSUM: c8a36f1dc00b0194bc4eb8fad6ae0c674a2dfd2b
+
+COCOAPODS: 1.8.4
diff --git a/packages/react-native-editor/ios/gutenberg-Bridging-Header.h b/packages/react-native-editor/ios/gutenberg-Bridging-Header.h
new file mode 100644
index 00000000000000..5422961cdb05a0
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg-Bridging-Header.h
@@ -0,0 +1,8 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import
+#import
+#import
+#import
diff --git a/packages/react-native-editor/ios/gutenberg-tvOS/Info.plist b/packages/react-native-editor/ios/gutenberg-tvOS/Info.plist
new file mode 100644
index 00000000000000..2fb6a11c2c3356
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg-tvOS/Info.plist
@@ -0,0 +1,54 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+ NSLocationWhenInUseUsageDescription
+
+ NSAppTransportSecurity
+
+
+ NSExceptionDomains
+
+ localhost
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+
+
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg-tvOSTests/Info.plist b/packages/react-native-editor/ios/gutenberg-tvOSTests/Info.plist
new file mode 100644
index 00000000000000..886825ccc9bf0d
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg-tvOSTests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj
new file mode 100644
index 00000000000000..01bb92522a2d0c
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj
@@ -0,0 +1,1152 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 00E356F31AD99517003FC87E /* gutenbergTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* gutenbergTests.m */; };
+ 05908C6EA5B80A39F74C4FEF /* Pods_gutenberg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38E210A05B5C8829E0B3BE83 /* Pods_gutenberg.framework */; };
+ 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+ 1E4F2E752459E6F200EB73E7 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E85944D2449D85A006CC6A0 /* WebViewController.swift */; };
+ 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+ 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D16E6891FA4F8E400B85C8A /* libReact.a */; };
+ 2DCD954D1E0B4F2C00145EB5 /* gutenbergTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* gutenbergTests.m */; };
+ 4858A387C929BA42C247FA16 /* Pods_gutenberg_tvOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE48AF171A9B998D71F3078B /* Pods_gutenberg_tvOSTests.framework */; };
+ 7EC7328F21907E3F00FED2E6 /* GutenbergViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EC7328E21907E3F00FED2E6 /* GutenbergViewController.swift */; };
+ 8C666FF0C9224FB88C2C0447 /* libRNSVG-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9BFAFEB337654221B2F14D03 /* libRNSVG-tvOS.a */; };
+ C05E07BC5927E0FBD17C828D /* Pods_gutenbergTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D57C380A7861BFFC2565FE6E /* Pods_gutenbergTests.framework */; };
+ F151983C2100DC3D000F6E97 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15198392100DC3D000F6E97 /* AppDelegate.swift */; };
+ F151983D2100DC3D000F6E97 /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F151983A2100DC3D000F6E97 /* MediaProvider.swift */; };
+ F1EE6F7821E7F0A500241744 /* NotoSerif-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1EE6F7421E7F0A500241744 /* NotoSerif-BoldItalic.ttf */; };
+ F1EE6F7921E7F0A500241744 /* NotoSerif-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1EE6F7521E7F0A500241744 /* NotoSerif-Regular.ttf */; };
+ F1EE6F7A21E7F0A500241744 /* NotoSerif-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1EE6F7621E7F0A500241744 /* NotoSerif-Italic.ttf */; };
+ F1EE6F7B21E7F0A500241744 /* NotoSerif-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1EE6F7721E7F0A500241744 /* NotoSerif-Bold.ttf */; };
+ FAE17A4A0C1CA38AB8862805 /* Pods_gutenberg_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E418A3212D0A388EEA0698C5 /* Pods_gutenberg_tvOS.framework */; };
+ FF37F903223819FA00AFA3DB /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF37F8D0223819FA00AFA3DB /* JavaScriptCore.framework */; };
+ FF6836C822035EAB00A0C562 /* MediaUploadCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF6836C722035EAB00A0C562 /* MediaUploadCoordinator.swift */; };
+ FF83DAA92226905A00A34C93 /* CustomImageLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF83DAA82226905A00A34C93 /* CustomImageLoader.swift */; };
+ FF9A6F4121FA8E2500D36D14 /* MediaPickCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9A6F1621FA8E2500D36D14 /* MediaPickCoordinator.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
+ remoteInfo = gutenberg;
+ };
+ 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7;
+ remoteInfo = "gutenberg-tvOS";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; };
+ 00E356EE1AD99517003FC87E /* gutenbergTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = gutenbergTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 00E356F21AD99517003FC87E /* gutenbergTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = gutenbergTests.m; sourceTree = ""; };
+ 034874811302E030BA1637A1 /* Pods-gutenbergTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenbergTests.debug.xcconfig"; path = "Target Support Files/Pods-gutenbergTests/Pods-gutenbergTests.debug.xcconfig"; sourceTree = ""; };
+ 083D3CAD9B26701AE0659EEB /* Pods-gutenberg.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenberg.release.xcconfig"; path = "Target Support Files/Pods-gutenberg/Pods-gutenberg.release.xcconfig"; sourceTree = ""; };
+ 0EB766FE2F6D446A80AC6E6A /* libRNSVG.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSVG.a; sourceTree = ""; };
+ 13B07F961A680F5B00A75B9A /* GutenbergDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GutenbergDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
+ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = gutenberg/Images.xcassets; sourceTree = ""; };
+ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = gutenberg/Info.plist; sourceTree = ""; };
+ 1E85944D2449D85A006CC6A0 /* WebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WebViewController.swift; path = gutenberg/WebViewController.swift; sourceTree = ""; };
+ 2D02E47B1E0B4A5D006451C7 /* gutenberg-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "gutenberg-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2D02E4901E0B4A5D006451C7 /* gutenberg-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "gutenberg-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 38E210A05B5C8829E0B3BE83 /* Pods_gutenberg.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_gutenberg.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3ADEFEC092CF4D00BEF1019E /* libRNTAztecView.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNTAztecView.a; sourceTree = ""; };
+ 3D53EF8FEF024C98A7AC9A56 /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTVideo.a; sourceTree = ""; };
+ 549A3E45719DB5BA2F7ECC95 /* Pods-gutenberg-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenberg-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-gutenberg-tvOSTests/Pods-gutenberg-tvOSTests.release.xcconfig"; sourceTree = ""; };
+ 6206F0B13B70AD60CA886558 /* Pods-gutenbergTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenbergTests.release.xcconfig"; path = "Target Support Files/Pods-gutenbergTests/Pods-gutenbergTests.release.xcconfig"; sourceTree = ""; };
+ 69F3DF692A7C4E5994CD3CBB /* libRNSafeArea.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSafeArea.a; sourceTree = ""; };
+ 7EA30CF021AC8CDA0092F894 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
+ 7EC7328E21907E3F00FED2E6 /* GutenbergViewController.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; name = GutenbergViewController.swift; path = gutenberg/GutenbergViewController.swift; sourceTree = ""; tabWidth = 1; };
+ 9193870E2260BA5500E4FBD6 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+ 9193873C2260BA7800E4FBD6 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
+ 9BFAFEB337654221B2F14D03 /* libRNSVG-tvOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = "libRNSVG-tvOS.a"; sourceTree = ""; };
+ A6B9393B15FAEBA6A3C885F2 /* Pods-gutenberg.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenberg.debug.xcconfig"; path = "Target Support Files/Pods-gutenberg/Pods-gutenberg.debug.xcconfig"; sourceTree = ""; };
+ A7031126C4DE90D4D7AAACD5 /* Pods-gutenberg-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenberg-tvOSTests.debug.xcconfig"; path = "Target Support Files/Pods-gutenberg-tvOSTests/Pods-gutenberg-tvOSTests.debug.xcconfig"; sourceTree = ""; };
+ CE48AF171A9B998D71F3078B /* Pods_gutenberg_tvOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_gutenberg_tvOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ D57C380A7861BFFC2565FE6E /* Pods_gutenbergTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_gutenbergTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ D742287512CBBB046F519E11 /* Pods-gutenberg-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenberg-tvOS.release.xcconfig"; path = "Target Support Files/Pods-gutenberg-tvOS/Pods-gutenberg-tvOS.release.xcconfig"; sourceTree = ""; };
+ E418A3212D0A388EEA0698C5 /* Pods_gutenberg_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_gutenberg_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F1289ECA2100E4320091E81D /* Aztec.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Aztec.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F15198372100DC3C000F6E97 /* gutenberg-Bridging-Header.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = "gutenberg-Bridging-Header.h"; sourceTree = ""; tabWidth = 1; };
+ F15198392100DC3D000F6E97 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = gutenberg/AppDelegate.swift; sourceTree = ""; tabWidth = 1; };
+ F151983A2100DC3D000F6E97 /* MediaProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; name = MediaProvider.swift; path = gutenberg/MediaProvider.swift; sourceTree = ""; tabWidth = 1; usesTabs = 0; };
+ F1EE6F7421E7F0A500241744 /* NotoSerif-BoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NotoSerif-BoldItalic.ttf"; sourceTree = ""; };
+ F1EE6F7521E7F0A500241744 /* NotoSerif-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NotoSerif-Regular.ttf"; sourceTree = ""; };
+ F1EE6F7621E7F0A500241744 /* NotoSerif-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NotoSerif-Italic.ttf"; sourceTree = ""; };
+ F1EE6F7721E7F0A500241744 /* NotoSerif-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NotoSerif-Bold.ttf"; sourceTree = ""; };
+ FE6E9E6AEF37DEEE897DAC75 /* Pods-gutenberg-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gutenberg-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-gutenberg-tvOS/Pods-gutenberg-tvOS.debug.xcconfig"; sourceTree = ""; };
+ FF37F8D0223819FA00AFA3DB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
+ FF6836C722035EAB00A0C562 /* MediaUploadCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MediaUploadCoordinator.swift; path = gutenberg/MediaUploadCoordinator.swift; sourceTree = ""; };
+ FF83DAA82226905A00A34C93 /* CustomImageLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomImageLoader.swift; sourceTree = ""; };
+ FF9A6F1621FA8E2500D36D14 /* MediaPickCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MediaPickCoordinator.swift; path = gutenberg/MediaPickCoordinator.swift; sourceTree = ""; };
+ FFFA53E823C794F500829A43 /* Gutenberg.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Gutenberg.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 00E356EB1AD99517003FC87E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ C05E07BC5927E0FBD17C828D /* Pods_gutenbergTests.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FF37F903223819FA00AFA3DB /* JavaScriptCore.framework in Frameworks */,
+ 05908C6EA5B80A39F74C4FEF /* Pods_gutenberg.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2D02E4781E0B4A5D006451C7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */,
+ 8C666FF0C9224FB88C2C0447 /* libRNSVG-tvOS.a in Frameworks */,
+ FAE17A4A0C1CA38AB8862805 /* Pods_gutenberg_tvOS.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2D02E48D1E0B4A5D006451C7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4858A387C929BA42C247FA16 /* Pods_gutenberg_tvOSTests.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 00E356EF1AD99517003FC87E /* gutenbergTests */ = {
+ isa = PBXGroup;
+ children = (
+ 00E356F21AD99517003FC87E /* gutenbergTests.m */,
+ 00E356F01AD99517003FC87E /* Supporting Files */,
+ );
+ path = gutenbergTests;
+ sourceTree = "";
+ };
+ 00E356F01AD99517003FC87E /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 00E356F11AD99517003FC87E /* Info.plist */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+ 13B07FAE1A68108700A75B9A /* gutenberg */ = {
+ isa = PBXGroup;
+ children = (
+ 008F07F21AC5B25A0029DE68 /* main.jsbundle */,
+ F15198372100DC3C000F6E97 /* gutenberg-Bridging-Header.h */,
+ F15198392100DC3D000F6E97 /* AppDelegate.swift */,
+ 7EC7328E21907E3F00FED2E6 /* GutenbergViewController.swift */,
+ 1E85944D2449D85A006CC6A0 /* WebViewController.swift */,
+ FF9A6F1621FA8E2500D36D14 /* MediaPickCoordinator.swift */,
+ FF6836C722035EAB00A0C562 /* MediaUploadCoordinator.swift */,
+ F151983A2100DC3D000F6E97 /* MediaProvider.swift */,
+ 13B07FB51A68108700A75B9A /* Images.xcassets */,
+ 13B07FB61A68108700A75B9A /* Info.plist */,
+ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
+ FF83DAA82226905A00A34C93 /* CustomImageLoader.swift */,
+ );
+ name = gutenberg;
+ sourceTree = "";
+ };
+ 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ FFFA53E823C794F500829A43 /* Gutenberg.framework */,
+ 9193873C2260BA7800E4FBD6 /* CoreServices.framework */,
+ 9193870E2260BA5500E4FBD6 /* MobileCoreServices.framework */,
+ FF37F8D0223819FA00AFA3DB /* JavaScriptCore.framework */,
+ 7EA30CF021AC8CDA0092F894 /* libxml2.tbd */,
+ F1289ECA2100E4320091E81D /* Aztec.framework */,
+ 2D16E6891FA4F8E400B85C8A /* libReact.a */,
+ 38E210A05B5C8829E0B3BE83 /* Pods_gutenberg.framework */,
+ E418A3212D0A388EEA0698C5 /* Pods_gutenberg_tvOS.framework */,
+ CE48AF171A9B998D71F3078B /* Pods_gutenberg_tvOSTests.framework */,
+ D57C380A7861BFFC2565FE6E /* Pods_gutenbergTests.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Libraries;
+ sourceTree = "";
+ };
+ 83CBB9F61A601CBA00E9B192 = {
+ isa = PBXGroup;
+ children = (
+ 13B07FAE1A68108700A75B9A /* gutenberg */,
+ F1EE6F7221E7F0A500241744 /* resources */,
+ 832341AE1AAA6A7D00B99B32 /* Libraries */,
+ 00E356EF1AD99517003FC87E /* gutenbergTests */,
+ 83CBBA001A601CBA00E9B192 /* Products */,
+ 2D16E6871FA4F8E400B85C8A /* Frameworks */,
+ F1B3E79320FFA9990042D8C3 /* Recovered References */,
+ 918EE91F38EF19A86F38D86F /* Pods */,
+ );
+ indentWidth = 2;
+ sourceTree = "";
+ tabWidth = 2;
+ usesTabs = 0;
+ };
+ 83CBBA001A601CBA00E9B192 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 13B07F961A680F5B00A75B9A /* GutenbergDemo.app */,
+ 00E356EE1AD99517003FC87E /* gutenbergTests.xctest */,
+ 2D02E47B1E0B4A5D006451C7 /* gutenberg-tvOS.app */,
+ 2D02E4901E0B4A5D006451C7 /* gutenberg-tvOSTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 918EE91F38EF19A86F38D86F /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ A6B9393B15FAEBA6A3C885F2 /* Pods-gutenberg.debug.xcconfig */,
+ 083D3CAD9B26701AE0659EEB /* Pods-gutenberg.release.xcconfig */,
+ FE6E9E6AEF37DEEE897DAC75 /* Pods-gutenberg-tvOS.debug.xcconfig */,
+ D742287512CBBB046F519E11 /* Pods-gutenberg-tvOS.release.xcconfig */,
+ A7031126C4DE90D4D7AAACD5 /* Pods-gutenberg-tvOSTests.debug.xcconfig */,
+ 549A3E45719DB5BA2F7ECC95 /* Pods-gutenberg-tvOSTests.release.xcconfig */,
+ 034874811302E030BA1637A1 /* Pods-gutenbergTests.debug.xcconfig */,
+ 6206F0B13B70AD60CA886558 /* Pods-gutenbergTests.release.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+ F1B3E79320FFA9990042D8C3 /* Recovered References */ = {
+ isa = PBXGroup;
+ children = (
+ 3ADEFEC092CF4D00BEF1019E /* libRNTAztecView.a */,
+ 0EB766FE2F6D446A80AC6E6A /* libRNSVG.a */,
+ 9BFAFEB337654221B2F14D03 /* libRNSVG-tvOS.a */,
+ 69F3DF692A7C4E5994CD3CBB /* libRNSafeArea.a */,
+ 3D53EF8FEF024C98A7AC9A56 /* libRCTVideo.a */,
+ );
+ name = "Recovered References";
+ sourceTree = "";
+ };
+ F1EE6F7221E7F0A500241744 /* resources */ = {
+ isa = PBXGroup;
+ children = (
+ F1EE6F7321E7F0A500241744 /* fonts */,
+ );
+ name = resources;
+ path = ../resources;
+ sourceTree = "";
+ };
+ F1EE6F7321E7F0A500241744 /* fonts */ = {
+ isa = PBXGroup;
+ children = (
+ F1EE6F7421E7F0A500241744 /* NotoSerif-BoldItalic.ttf */,
+ F1EE6F7521E7F0A500241744 /* NotoSerif-Regular.ttf */,
+ F1EE6F7621E7F0A500241744 /* NotoSerif-Italic.ttf */,
+ F1EE6F7721E7F0A500241744 /* NotoSerif-Bold.ttf */,
+ );
+ path = fonts;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 00E356ED1AD99517003FC87E /* gutenbergTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "gutenbergTests" */;
+ buildPhases = (
+ 70B839CE7B6A174DC4DE8FB6 /* [CP] Check Pods Manifest.lock */,
+ 00E356EA1AD99517003FC87E /* Sources */,
+ 00E356EB1AD99517003FC87E /* Frameworks */,
+ 00E356EC1AD99517003FC87E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 00E356F51AD99517003FC87E /* PBXTargetDependency */,
+ );
+ name = gutenbergTests;
+ productName = gutenbergTests;
+ productReference = 00E356EE1AD99517003FC87E /* gutenbergTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 13B07F861A680F5B00A75B9A /* gutenberg */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "gutenberg" */;
+ buildPhases = (
+ 74E4D376F06BC61DB863CCC7 /* [CP] Check Pods Manifest.lock */,
+ 13B07F871A680F5B00A75B9A /* Sources */,
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */,
+ 13B07F8E1A680F5B00A75B9A /* Resources */,
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
+ 06CE89E9A162D62B604C3B6C /* [CP] Embed Pods Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = gutenberg;
+ productName = "Hello World";
+ productReference = 13B07F961A680F5B00A75B9A /* GutenbergDemo.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 2D02E47A1E0B4A5D006451C7 /* gutenberg-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "gutenberg-tvOS" */;
+ buildPhases = (
+ EAFF01B6A058BE3235FB054C /* [CP] Check Pods Manifest.lock */,
+ 2D02E4771E0B4A5D006451C7 /* Sources */,
+ 2D02E4781E0B4A5D006451C7 /* Frameworks */,
+ 2D02E4791E0B4A5D006451C7 /* Resources */,
+ 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "gutenberg-tvOS";
+ productName = "gutenberg-tvOS";
+ productReference = 2D02E47B1E0B4A5D006451C7 /* gutenberg-tvOS.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 2D02E48F1E0B4A5D006451C7 /* gutenberg-tvOSTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "gutenberg-tvOSTests" */;
+ buildPhases = (
+ 944E2FEABB650B8AB00B7918 /* [CP] Check Pods Manifest.lock */,
+ 2D02E48C1E0B4A5D006451C7 /* Sources */,
+ 2D02E48D1E0B4A5D006451C7 /* Frameworks */,
+ 2D02E48E1E0B4A5D006451C7 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */,
+ );
+ name = "gutenberg-tvOSTests";
+ productName = "gutenberg-tvOSTests";
+ productReference = 2D02E4901E0B4A5D006451C7 /* gutenberg-tvOSTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 83CBB9F71A601CBA00E9B192 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 610;
+ ORGANIZATIONNAME = Facebook;
+ TargetAttributes = {
+ 00E356ED1AD99517003FC87E = {
+ CreatedOnToolsVersion = 6.2;
+ TestTargetID = 13B07F861A680F5B00A75B9A;
+ };
+ 13B07F861A680F5B00A75B9A = {
+ DevelopmentTeam = PZYM8XX95Q;
+ LastSwiftMigration = 940;
+ ProvisioningStyle = Automatic;
+ };
+ 2D02E47A1E0B4A5D006451C7 = {
+ CreatedOnToolsVersion = 8.2.1;
+ ProvisioningStyle = Automatic;
+ };
+ 2D02E48F1E0B4A5D006451C7 = {
+ CreatedOnToolsVersion = 8.2.1;
+ ProvisioningStyle = Automatic;
+ TestTargetID = 2D02E47A1E0B4A5D006451C7;
+ };
+ };
+ };
+ buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "gutenberg" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ English,
+ en,
+ Base,
+ );
+ mainGroup = 83CBB9F61A601CBA00E9B192;
+ productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 13B07F861A680F5B00A75B9A /* gutenberg */,
+ 00E356ED1AD99517003FC87E /* gutenbergTests */,
+ 2D02E47A1E0B4A5D006451C7 /* gutenberg-tvOS */,
+ 2D02E48F1E0B4A5D006451C7 /* gutenberg-tvOSTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 00E356EC1AD99517003FC87E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 13B07F8E1A680F5B00A75B9A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
+ F1EE6F7B21E7F0A500241744 /* NotoSerif-Bold.ttf in Resources */,
+ F1EE6F7921E7F0A500241744 /* NotoSerif-Regular.ttf in Resources */,
+ F1EE6F7A21E7F0A500241744 /* NotoSerif-Italic.ttf in Resources */,
+ 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
+ F1EE6F7821E7F0A500241744 /* NotoSerif-BoldItalic.ttf in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2D02E4791E0B4A5D006451C7 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2D02E48E1E0B4A5D006451C7 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Bundle React Native code and images";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "export NODE_BINARY=node\n../../../node_modules/react-native/scripts/react-native-xcode.sh\n";
+ };
+ 06CE89E9A162D62B604C3B6C /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-gutenberg/Pods-gutenberg-frameworks.sh",
+ "${BUILT_PRODUCTS_DIR}/BVLinearGradient/BVLinearGradient.framework",
+ "${BUILT_PRODUCTS_DIR}/DoubleConversion/DoubleConversion.framework",
+ "${BUILT_PRODUCTS_DIR}/FBReactNativeSpec/FBReactNativeSpec.framework",
+ "${BUILT_PRODUCTS_DIR}/Folly/folly.framework",
+ "${BUILT_PRODUCTS_DIR}/Gutenberg/Gutenberg.framework",
+ "${BUILT_PRODUCTS_DIR}/RCTTypeSafety/RCTTypeSafety.framework",
+ "${BUILT_PRODUCTS_DIR}/RNSVG/RNSVG.framework",
+ "${BUILT_PRODUCTS_DIR}/RNTAztecView/RNTAztecView.framework",
+ "${BUILT_PRODUCTS_DIR}/React-Core/React.framework",
+ "${BUILT_PRODUCTS_DIR}/React-CoreModules/CoreModules.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTActionSheet/RCTActionSheet.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTAnimation/RCTAnimation.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTBlob/RCTBlob.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTImage/RCTImage.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTLinking/RCTLinking.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTNetwork/RCTNetwork.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTSettings/RCTSettings.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTText/RCTText.framework",
+ "${BUILT_PRODUCTS_DIR}/React-RCTVibration/RCTVibration.framework",
+ "${BUILT_PRODUCTS_DIR}/React-cxxreact/cxxreact.framework",
+ "${BUILT_PRODUCTS_DIR}/React-jsi/jsi.framework",
+ "${BUILT_PRODUCTS_DIR}/React-jsiexecutor/jsireact.framework",
+ "${BUILT_PRODUCTS_DIR}/React-jsinspector/jsinspector.framework",
+ "${BUILT_PRODUCTS_DIR}/ReactCommon/ReactCommon.framework",
+ "${BUILT_PRODUCTS_DIR}/ReactNativeDarkMode/ReactNativeDarkMode.framework",
+ "${BUILT_PRODUCTS_DIR}/WordPress-Aztec-iOS/Aztec.framework",
+ "${BUILT_PRODUCTS_DIR}/Yoga/yoga.framework",
+ "${BUILT_PRODUCTS_DIR}/glog/glog.framework",
+ "${BUILT_PRODUCTS_DIR}/react-native-get-random-values/react_native_get_random_values.framework",
+ "${BUILT_PRODUCTS_DIR}/react-native-keyboard-aware-scroll-view/react_native_keyboard_aware_scroll_view.framework",
+ "${BUILT_PRODUCTS_DIR}/react-native-safe-area/react_native_safe_area.framework",
+ "${BUILT_PRODUCTS_DIR}/react-native-slider/react_native_slider.framework",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BVLinearGradient.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DoubleConversion.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBReactNativeSpec.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/folly.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Gutenberg.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTTypeSafety.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNSVG.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNTAztecView.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CoreModules.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTActionSheet.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTAnimation.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTBlob.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTImage.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTLinking.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTNetwork.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTSettings.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTText.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTVibration.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cxxreact.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsi.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsireact.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsinspector.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactCommon.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactNativeDarkMode.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Aztec.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_get_random_values.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_keyboard_aware_scroll_view.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_safe_area.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_slider.framework",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-gutenberg/Pods-gutenberg-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Bundle React Native Code And Images";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
+ };
+ 70B839CE7B6A174DC4DE8FB6 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-gutenbergTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ 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;
+ };
+ 74E4D376F06BC61DB863CCC7 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-gutenberg-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ 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;
+ };
+ 944E2FEABB650B8AB00B7918 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-gutenberg-tvOSTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ 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;
+ };
+ EAFF01B6A058BE3235FB054C /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-gutenberg-tvOS-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ 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;
+ buildActionMask = 2147483647;
+ files = (
+ 00E356F31AD99517003FC87E /* gutenbergTests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 13B07F871A680F5B00A75B9A /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F151983C2100DC3D000F6E97 /* AppDelegate.swift in Sources */,
+ FF83DAA92226905A00A34C93 /* CustomImageLoader.swift in Sources */,
+ FF9A6F4121FA8E2500D36D14 /* MediaPickCoordinator.swift in Sources */,
+ F151983D2100DC3D000F6E97 /* MediaProvider.swift in Sources */,
+ 1E4F2E752459E6F200EB73E7 /* WebViewController.swift in Sources */,
+ FF6836C822035EAB00A0C562 /* MediaUploadCoordinator.swift in Sources */,
+ 7EC7328F21907E3F00FED2E6 /* GutenbergViewController.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2D02E4771E0B4A5D006451C7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2D02E48C1E0B4A5D006451C7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2DCD954D1E0B4F2C00145EB5 /* gutenbergTests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 13B07F861A680F5B00A75B9A /* gutenberg */;
+ targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
+ };
+ 2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 2D02E47A1E0B4A5D006451C7 /* gutenberg-tvOS */;
+ targetProxy = 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 13B07FB21A68108700A75B9A /* Base */,
+ );
+ name = LaunchScreen.xib;
+ path = gutenberg;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 00E356F61AD99517003FC87E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 034874811302E030BA1637A1 /* Pods-gutenbergTests.debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../react-native-aztec/example/iOS/example",
+ "$(SRCROOT)/../node_modules/react-native-svg/ios/**",
+ "$(SRCROOT)/../node_modules/react-native-safe-area/ios/RNSafeArea",
+ "$(SRCROOT)/../node_modules/react-native-video/ios/**",
+ );
+ INFOPLIST_FILE = gutenbergTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-lc++",
+ "$(inherited)",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/gutenberg.app/gutenberg";
+ };
+ name = Debug;
+ };
+ 00E356F71AD99517003FC87E /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 6206F0B13B70AD60CA886558 /* Pods-gutenbergTests.release.xcconfig */;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ COPY_PHASE_STRIP = NO;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../react-native-aztec/example/iOS/example",
+ "$(SRCROOT)/../node_modules/react-native-svg/ios/**",
+ "$(SRCROOT)/../node_modules/react-native-safe-area/ios/RNSafeArea",
+ "$(SRCROOT)/../node_modules/react-native-video/ios/**",
+ );
+ INFOPLIST_FILE = gutenbergTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-lc++",
+ "$(inherited)",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/gutenberg.app/gutenberg";
+ };
+ name = Release;
+ };
+ 13B07F941A680F5B00A75B9A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = A6B9393B15FAEBA6A3C885F2 /* Pods-gutenberg.debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEAD_CODE_STRIPPING = NO;
+ DEVELOPMENT_TEAM = PZYM8XX95Q;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /usr/include/libxml2,
+ "$(SRCROOT)/../react-native-aztec/example/iOS/example",
+ "$(SRCROOT)/../node_modules/react-native-svg/ios/**",
+ "$(SRCROOT)/../react-native-gutenberg-bridge/ios/**",
+ "$(SRCROOT)/../react-native-aztec/ios/**",
+ "$(SRCROOT)/../node_modules/react-native-safe-area/ios/RNSafeArea",
+ "$(SRCROOT)/../node_modules/react-native-video/ios/**",
+ );
+ INFOPLIST_FILE = gutenberg/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)";
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = org.wordpress.gutenberg.development;
+ PRODUCT_NAME = GutenbergDemo;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OBJC_BRIDGING_HEADER = "gutenberg-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 13B07F951A680F5B00A75B9A /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 083D3CAD9B26701AE0659EEB /* Pods-gutenberg.release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = PZYM8XX95Q;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /usr/include/libxml2,
+ );
+ INFOPLIST_FILE = gutenberg/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)";
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = org.wordpress.gutenberg.development;
+ PRODUCT_NAME = GutenbergDemo;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OBJC_BRIDGING_HEADER = "gutenberg-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+ 2D02E4971E0B4A5E006451C7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = FE6E9E6AEF37DEEE897DAC75 /* Pods-gutenberg-tvOS.debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../react-native-aztec/example/iOS/example",
+ "$(SRCROOT)/../node_modules/react-native-svg/ios/**",
+ "$(SRCROOT)/../node_modules/react-native-safe-area/ios/RNSafeArea",
+ "$(SRCROOT)/../node_modules/react-native-video/ios/**",
+ );
+ INFOPLIST_FILE = "gutenberg-tvOS/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.gutenberg-tvOS";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ TVOS_DEPLOYMENT_TARGET = 9.2;
+ };
+ name = Debug;
+ };
+ 2D02E4981E0B4A5E006451C7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D742287512CBBB046F519E11 /* Pods-gutenberg-tvOS.release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_NO_COMMON_BLOCKS = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../react-native-aztec/example/iOS/example",
+ "$(SRCROOT)/../node_modules/react-native-svg/ios/**",
+ "$(SRCROOT)/../node_modules/react-native-safe-area/ios/RNSafeArea",
+ "$(SRCROOT)/../node_modules/react-native-video/ios/**",
+ );
+ INFOPLIST_FILE = "gutenberg-tvOS/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.gutenberg-tvOS";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ TVOS_DEPLOYMENT_TARGET = 9.2;
+ };
+ name = Release;
+ };
+ 2D02E4991E0B4A5E006451C7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = A7031126C4DE90D4D7AAACD5 /* Pods-gutenberg-tvOSTests.debug.xcconfig */;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../react-native-aztec/example/iOS/example",
+ "$(SRCROOT)/../node_modules/react-native-svg/ios/**",
+ "$(SRCROOT)/../node_modules/react-native-safe-area/ios/RNSafeArea",
+ "$(SRCROOT)/../node_modules/react-native-video/ios/**",
+ );
+ INFOPLIST_FILE = "gutenberg-tvOSTests/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.gutenberg-tvOSTests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = appletvos;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/gutenberg-tvOS.app/gutenberg-tvOS";
+ TVOS_DEPLOYMENT_TARGET = 10.1;
+ };
+ name = Debug;
+ };
+ 2D02E49A1E0B4A5E006451C7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 549A3E45719DB5BA2F7ECC95 /* Pods-gutenberg-tvOSTests.release.xcconfig */;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_NO_COMMON_BLOCKS = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../react-native-aztec/example/iOS/example",
+ "$(SRCROOT)/../node_modules/react-native-svg/ios/**",
+ "$(SRCROOT)/../node_modules/react-native-safe-area/ios/RNSafeArea",
+ "$(SRCROOT)/../node_modules/react-native-video/ios/**",
+ );
+ INFOPLIST_FILE = "gutenberg-tvOSTests/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ );
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.gutenberg-tvOSTests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = appletvos;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/gutenberg-tvOS.app/gutenberg-tvOS";
+ TVOS_DEPLOYMENT_TARGET = 10.1;
+ };
+ name = Release;
+ };
+ 83CBBA201A601CBA00E9B192 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 83CBBA211A601CBA00E9B192 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SWIFT_VERSION = 5.0;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "gutenbergTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 00E356F61AD99517003FC87E /* Debug */,
+ 00E356F71AD99517003FC87E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "gutenberg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 13B07F941A680F5B00A75B9A /* Debug */,
+ 13B07F951A680F5B00A75B9A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "gutenberg-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2D02E4971E0B4A5E006451C7 /* Debug */,
+ 2D02E4981E0B4A5E006451C7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "gutenberg-tvOSTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2D02E4991E0B4A5E006451C7 /* Debug */,
+ 2D02E49A1E0B4A5E006451C7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "gutenberg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 83CBBA201A601CBA00E9B192 /* Debug */,
+ 83CBBA211A601CBA00E9B192 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
+}
diff --git a/packages/react-native-editor/ios/gutenberg.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000000000..919434a6254f0e
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000000000..18d981003d68d0
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg-tvOS.xcscheme b/packages/react-native-editor/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg-tvOS.xcscheme
new file mode 100644
index 00000000000000..6f7879ba8657f8
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg-tvOS.xcscheme
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg.xcscheme b/packages/react-native-editor/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg.xcscheme
new file mode 100644
index 00000000000000..8c6a40ffb9c923
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg.xcscheme
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg.xcworkspace/contents.xcworkspacedata b/packages/react-native-editor/ios/gutenberg.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000000000..6b9e6f57aaaccb
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/react-native-editor/ios/gutenberg.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000000000..18d981003d68d0
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/react-native-editor/ios/gutenberg.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000000000..f9b0d7c5ea15f1
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg/AppDelegate.swift b/packages/react-native-editor/ios/gutenberg/AppDelegate.swift
new file mode 100644
index 00000000000000..8338adc0a435f8
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/AppDelegate.swift
@@ -0,0 +1,33 @@
+import Foundation
+import UIKit
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ var window: UIWindow?
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+
+ AppDelegate.setupUITest()
+
+ window = UIWindow(frame: UIScreen.main.bounds)
+
+ let rootViewController = GutenbergViewController()
+
+ window?.rootViewController = UINavigationController(rootViewController: rootViewController)
+ window?.makeKeyAndVisible()
+
+ return true
+ }
+
+ static func setupUITest() {
+ if ( isUITesting() ) {
+ UIApplication.shared.keyWindow?.layer.speed = 100;
+ UIView.setAnimationsEnabled(false);
+ }
+ }
+
+ static func isUITesting() -> Bool {
+ return ProcessInfo.processInfo.arguments.contains("uitesting")
+ }
+}
diff --git a/packages/react-native-editor/ios/gutenberg/Base.lproj/LaunchScreen.xib b/packages/react-native-editor/ios/gutenberg/Base.lproj/LaunchScreen.xib
new file mode 100644
index 00000000000000..16f37cd9324e06
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/Base.lproj/LaunchScreen.xib
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg/GutenbergViewController.swift b/packages/react-native-editor/ios/gutenberg/GutenbergViewController.swift
new file mode 100644
index 00000000000000..1a28d073245431
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/GutenbergViewController.swift
@@ -0,0 +1,354 @@
+
+import UIKit
+import Gutenberg
+import Aztec
+
+class GutenbergViewController: UIViewController {
+
+ fileprivate lazy var gutenberg = Gutenberg(dataSource: self, extraModules: [CustomImageLoader()])
+ fileprivate var htmlMode = false
+ fileprivate var mediaPickCoordinator: MediaPickCoordinator?
+ fileprivate lazy var mediaUploadCoordinator: MediaUploadCoordinator = {
+ let mediaUploadCoordinator = MediaUploadCoordinator(gutenberg: self.gutenberg)
+ return mediaUploadCoordinator
+ }()
+ fileprivate var longPressGesture: UILongPressGestureRecognizer!
+ fileprivate var contentInfo: ContentInfo?
+
+ override func loadView() {
+ view = gutenberg.rootView
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ configureNavigationBar()
+ gutenberg.delegate = self
+ navigationController?.navigationBar.isTranslucent = false
+ registerLongPressGestureRecognizer()
+
+ _ = try! FallbackJavascriptInjection(blockHTML: "Hello", userId: "1")
+ }
+
+ @objc func moreButtonPressed(sender: UIBarButtonItem) {
+ showMoreSheet()
+ }
+
+ @objc func saveButtonPressed(sender: UIBarButtonItem) {
+ gutenberg.requestHTML()
+ }
+
+ func registerLongPressGestureRecognizer() {
+ longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
+ view.addGestureRecognizer(longPressGesture)
+ }
+
+ @objc func handleLongPress() {
+ NotificationCenter.default.post(Notification(name: MediaUploadCoordinator.failUpload ))
+ }
+}
+
+extension GutenbergViewController: GutenbergBridgeDelegate {
+
+ func gutenbergDidRequestFetch(path: String, completion: @escaping (Result) -> Void) {
+ completion(Result.success([:]))
+ }
+
+ func editorDidAutosave() {
+ print("➡️ Editor Did Autosave")
+ }
+
+ func gutenbergDidLoad() {
+ gutenberg.setFocusOnTitle()
+ }
+
+ func gutenbergDidMount(unsupportedBlockNames: [String]) {
+ print("gutenbergDidMount(unsupportedBlockNames: \(unsupportedBlockNames))")
+ gutenberg.requestHTML()
+ }
+
+ func gutenbergDidProvideHTML(title: String, html: String, changed: Bool, contentInfo: ContentInfo?) {
+ print("didProvideHTML:")
+ print("↳ Content changed: \(changed)")
+ print("↳ Title: \(title)")
+ print("↳ HTML: \(html)")
+ print("↳ Content Info: \(contentInfo)")
+ self.contentInfo = contentInfo
+ }
+
+ func gutenbergDidRequestMedia(from source: Gutenberg.MediaSource, filter: [Gutenberg.MediaType], allowMultipleSelection: Bool, with callback: @escaping MediaPickerDidPickMediaCallback) {
+ guard let currentFilter = filter.first else {
+ return
+ }
+ switch source {
+ case .mediaLibrary:
+ print("Gutenberg did request media picker, passing a sample url in callback")
+ switch currentFilter {
+ case .image:
+ if(allowMultipleSelection) {
+ callback([MediaInfo(id: 1, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image"),
+ MediaInfo(id: 3, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image", caption: "Mountain")])
+ } else {
+ callback([MediaInfo(id: 1, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image", caption: "Mountain")])
+ }
+ case .video:
+ if(allowMultipleSelection) {
+ callback([MediaInfo(id: 2, url: "https://i.cloudup.com/YtZFJbuQCE.mov", type: "video"),
+ MediaInfo(id: 4, url: "https://i.cloudup.com/YtZFJbuQCE.mov", type: "video")])
+ } else {
+ callback([MediaInfo(id: 2, url: "https://i.cloudup.com/YtZFJbuQCE.mov", type: "video", caption: "Cloudup")])
+ }
+ default:
+ break
+ }
+ case .deviceLibrary:
+ print("Gutenberg did request a device media picker, opening the device picker")
+ pickAndUpload(from: .savedPhotosAlbum, filter: currentFilter, callback: callback)
+ case .deviceCamera:
+ print("Gutenberg did request a device media picker, opening the camera picker")
+ pickAndUpload(from: .camera, filter: currentFilter, callback: callback)
+ default: break
+ }
+ }
+
+ func gutenbergDidRequestImport(from url: URL, with callback: @escaping MediaImportCallback) {
+ let id = mediaUploadCoordinator.upload(url: url)
+ callback(MediaInfo(id: id, url: url.absoluteString, type: "image"))
+ }
+
+ func pickAndUpload(from source: UIImagePickerController.SourceType, filter: Gutenberg.MediaType, callback: @escaping MediaPickerDidPickMediaCallback) {
+ mediaPickCoordinator = MediaPickCoordinator(presenter: self, filter: filter, callback: { (url) in
+ guard let url = url, let mediaID = self.mediaUploadCoordinator.upload(url: url) else {
+ callback([MediaInfo(id: nil, url: nil, type: nil)])
+ return
+ }
+ callback([MediaInfo(id: mediaID, url: url.absoluteString, type: "image")])
+ self.mediaPickCoordinator = nil
+ } )
+ mediaPickCoordinator?.pick(from: source)
+ }
+
+ func gutenbergDidRequestMediaUploadSync() {
+ print("Gutenberg request for media uploads to be resync")
+ }
+
+ func gutenbergDidRequestMediaUploadActionDialog(for mediaID: Int32) {
+ guard let progress = mediaUploadCoordinator.progressForUpload(mediaID: mediaID) else {
+ return
+ }
+
+ let title: String = "Media Options"
+ var message: String? = ""
+ let alertController = UIAlertController(title: title, message: nil, preferredStyle: .actionSheet)
+ let dismissAction = UIAlertAction(title: "Dismiss", style: .cancel) { (action) in
+
+ }
+ alertController.addAction(dismissAction)
+
+ if progress.fractionCompleted < 1 && mediaUploadCoordinator.successfullUpload {
+ let cancelUploadAction = UIAlertAction(title: "Cancel upload", style: .destructive) { (action) in
+ self.mediaUploadCoordinator.cancelUpload(with: mediaID)
+ }
+ alertController.addAction(cancelUploadAction)
+ } else if let error = progress.userInfo[.mediaError] as? String {
+ message = error
+ let retryUploadAction = UIAlertAction(title: "Retry upload", style: .default) { (action) in
+ self.mediaUploadCoordinator.retryUpload(with: mediaID)
+ }
+ alertController.addAction(retryUploadAction)
+ }
+
+ alertController.title = title
+ alertController.message = message
+ alertController.popoverPresentationController?.sourceView = view
+ alertController.popoverPresentationController?.sourceRect = view.frame
+ alertController.popoverPresentationController?.permittedArrowDirections = .any
+ present(alertController, animated: true, completion: nil)
+ }
+
+ /// Tells the delegate that an image block requested for the upload cancelation.
+ ///
+ func gutenbergDidRequestMediaUploadCancelation(for mediaID: Int32) {
+ guard let progress = mediaUploadCoordinator.progressForUpload(mediaID: mediaID) else {
+ return
+ }
+ progress.cancel()
+ }
+
+ func gutenbergDidEmitLog(message: String, logLevel: LogLevel) {
+ switch logLevel {
+ case .trace:
+ print("Debug: \(message)")
+ case .info:
+ print("Info: \(message)")
+ case .warn:
+ print("Warn: \(message)")
+ case .error:
+ print("Error: \(message)")
+ case .fatal:
+ print("Fatal: \(message)")
+ }
+ }
+
+ func gutenbergDidRequestImagePreview(with fullSizeUrl: URL, thumbUrl: URL?) {
+ print("Gutenberg requested fullscreen image preview for " + fullSizeUrl.absoluteString)
+ }
+
+ func gutenbergDidRequestMediaEditor(with mediaUrl: URL, callback: @escaping MediaPickerDidPickMediaCallback) {
+ print("Gutenberg requested media editor for " + mediaUrl.absoluteString)
+ callback([MediaInfo(id: 1, url: "https://cldup.com/Fz-ASbo2s3.jpg", type: "image")])
+ }
+
+ func gutenbergDidLogUserEvent(_ event: GutenbergUserEvent) {
+ print("Gutenberg loged user event")
+ }
+
+ func gutenbergDidRequestUnsupportedBlockFallback(for block: Block) {
+ print("Requesting Fallback for \(block)")
+ let controller = try! WebViewController(block: block, userId: "0")
+ controller.delegate = self
+ present(UINavigationController(rootViewController: controller), animated: true)
+ }
+
+ func gutenbergDidRequestMention(callback: @escaping (Result) -> Void) {
+ callback(.success("matt"))
+ }
+
+ func gutenbergDidRequestStarterPageTemplatesTooltipShown() -> Bool {
+ return false;
+ }
+
+ func gutenbergDidRequestSetStarterPageTemplatesTooltipShown(_ tooltipShown: Bool) {
+ print("Gutenberg requested setting tooltip flag")
+ }
+}
+
+extension GutenbergViewController: GutenbergWebDelegate {
+ func webController(controller: GutenbergWebSingleBlockViewController, didPressSave block: Block) {
+ gutenberg.replace(block: block)
+ dismiss(webController: controller)
+ }
+
+ func webControllerDidPressClose(controller: GutenbergWebSingleBlockViewController) {
+ dismiss(webController: controller)
+ }
+
+ func webController(controller: GutenbergWebSingleBlockViewController, didLog log: String) {
+ print("WebView: \(log)")
+ }
+
+ private func dismiss(webController: GutenbergWebSingleBlockViewController) {
+ webController.cleanUp()
+ dismiss(animated: true)
+ }
+}
+
+extension GutenbergViewController: GutenbergBridgeDataSource {
+ func gutenbergLocale() -> String? {
+ return Locale.preferredLanguages.first ?? "en"
+ }
+
+ func gutenbergTranslations() -> [String : [String]]? {
+ return nil
+ }
+
+ func gutenbergInitialContent() -> String? {
+ return nil
+ }
+
+ func gutenbergInitialTitle() -> String? {
+ return nil
+ }
+
+ func gutenbergCapabilities() -> [String : Bool]? {
+ return ["mentions": true]
+ }
+
+ func aztecAttachmentDelegate() -> TextViewAttachmentDelegate {
+ return ExampleAttachmentDelegate()
+ }
+
+ func gutenbergEditorTheme() -> GutenbergEditorTheme? {
+ return nil
+ }
+}
+
+//MARK: - Navigation bar
+
+extension GutenbergViewController {
+
+ func configureNavigationBar() {
+ addSaveButton()
+ addMoreButton()
+ }
+
+ func addSaveButton() {
+ navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save,
+ target: self,
+ action: #selector(saveButtonPressed(sender:)))
+ }
+
+ func addMoreButton() {
+ navigationItem.rightBarButtonItem = UIBarButtonItem(title: "...",
+ style: .plain,
+ target: self,
+ action: #selector(moreButtonPressed(sender:)))
+ }
+}
+
+//MARK: - More actions
+
+extension GutenbergViewController {
+
+ func showMoreSheet() {
+ let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
+ alert.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
+ if let contentInfo = contentInfo {
+ alert.title = "Content Structure\nBlocks: \(contentInfo.blockCount), Words: \(contentInfo.wordCount), Characters: \(contentInfo.characterCount)"
+ }
+ let cancelAction = UIAlertAction(title: "Keep Editing", style: .cancel)
+ alert.addAction(toggleHTMLModeAction)
+ alert.addAction(updateHtmlAction)
+ alert.addAction(cancelAction)
+
+ present(alert, animated: true)
+ }
+
+ var toggleHTMLModeAction: UIAlertAction {
+ return UIAlertAction(
+ title: htmlMode ? "Switch To Visual" : "Switch to HTML",
+ style: .default,
+ handler: { [unowned self] action in
+ self.toggleHTMLMode(action)
+ })
+ }
+
+ var updateHtmlAction: UIAlertAction {
+ return UIAlertAction(
+ title: "Update HTML",
+ style: .default,
+ handler: { [unowned self] action in
+ let alert = self.alertWithTextInput(using: { [unowned self] (htmlInput) in
+ if let input = htmlInput {
+ self.gutenberg.updateHtml(input)
+ }
+ })
+ self.present(alert, animated: true, completion: nil)
+ })
+ }
+
+ func alertWithTextInput(using handler: ((String?) -> Void)?) -> UIAlertController {
+ let alert = UIAlertController(title: "Enter HTML", message: nil, preferredStyle: .alert)
+ alert.addTextField()
+ let submitAction = UIAlertAction(title: "Submit", style: .default) { [unowned alert] (action) in
+ handler?(alert.textFields?.first?.text)
+ }
+ alert.addAction(submitAction)
+ alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
+ return alert
+ }
+
+ func toggleHTMLMode(_ action: UIAlertAction) {
+ htmlMode = !htmlMode
+ gutenberg.toggleHTMLMode()
+ }
+}
diff --git a/packages/react-native-editor/ios/gutenberg/Images.xcassets/AppIcon.appiconset/Contents.json b/packages/react-native-editor/ios/gutenberg/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000000000..19882d568afa3d
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,53 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/packages/react-native-editor/ios/gutenberg/Images.xcassets/Contents.json b/packages/react-native-editor/ios/gutenberg/Images.xcassets/Contents.json
new file mode 100644
index 00000000000000..da4a164c918651
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/packages/react-native-editor/ios/gutenberg/Images.xcassets/aztec.imageset/Contents.json b/packages/react-native-editor/ios/gutenberg/Images.xcassets/aztec.imageset/Contents.json
new file mode 100644
index 00000000000000..60b8cf92b7beda
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/Images.xcassets/aztec.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "aztec.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/packages/react-native-editor/ios/gutenberg/Images.xcassets/aztec.imageset/aztec.png b/packages/react-native-editor/ios/gutenberg/Images.xcassets/aztec.imageset/aztec.png
new file mode 100644
index 00000000000000..81b4e8d73e7e87
Binary files /dev/null and b/packages/react-native-editor/ios/gutenberg/Images.xcassets/aztec.imageset/aztec.png differ
diff --git a/packages/react-native-editor/ios/gutenberg/Info.plist b/packages/react-native-editor/ios/gutenberg/Info.plist
new file mode 100644
index 00000000000000..3929cb00cf60bf
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/Info.plist
@@ -0,0 +1,79 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ Gutenberg
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ NSAppTransportSecurity
+
+ NSExceptionDomains
+
+ localhost
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+
+
+
+ NSCameraUsageDescription
+ To take photos or videos to use in your posts.
+ NSLocationUsageDescription
+ The app would like to add your location to posts on sites where you have enabled geotagging.
+ NSLocationWhenInUseUsageDescription
+ The app would like to add your location to posts on sites where you have enabled geotagging.
+ NSMicrophoneUsageDescription
+ Enable microphone access to record sound in your videos.
+ NSPhotoLibraryAddUsageDescription
+ To add photos or videos to your posts.
+ NSPhotoLibraryUsageDescription
+ To add photos or videos to your posts.
+ UIAppFonts
+
+ NotoSerif-BoldItalic.ttf
+ NotoSerif-Regular.ttf
+ NotoSerif-Italic.ttf
+ NotoSerif-Bold.ttf
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationPortraitUpsideDown
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/packages/react-native-editor/ios/gutenberg/MediaPickCoordinator.swift b/packages/react-native-editor/ios/gutenberg/MediaPickCoordinator.swift
new file mode 100644
index 00000000000000..b6facdde82f36f
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/MediaPickCoordinator.swift
@@ -0,0 +1,89 @@
+
+import Foundation
+import UIKit
+import Gutenberg
+import CoreServices
+
+class MediaPickCoordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
+
+ private let presenter: UIViewController
+ private let callback: (URL?) -> Void
+ private let filter: Gutenberg.MediaType
+
+ init(presenter: UIViewController,
+ filter: Gutenberg.MediaType,
+ callback: @escaping (URL?) -> Void) {
+ self.presenter = presenter
+ self.callback = callback
+ self.filter = filter
+ }
+
+ private var mediaTypes: [ String ]? {
+ switch filter {
+ case .image:
+ return [ kUTTypeImage as String ]
+ case .video:
+ return [ kUTTypeVideo as String, kUTTypeMovie as String ]
+ default:
+ return nil
+ }
+ }
+
+ func pick(from source: UIImagePickerController.SourceType) {
+ guard UIImagePickerController.isSourceTypeAvailable(source) else {
+ // Camera not available, bound to happen in the simulator
+ callback(nil)
+ return
+ }
+ let pickerController = UIImagePickerController()
+ pickerController.sourceType = source
+ if let mediaTypes = mediaTypes {
+ pickerController.mediaTypes = mediaTypes
+ }
+ pickerController.delegate = self
+ presenter.show(pickerController, sender: nil)
+ }
+
+ func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
+ presenter.dismiss(animated: true, completion: nil)
+ callback(nil)
+ }
+
+ func save(image: UIImage, toTemporaryDirectoryUsingName name: String) -> URL? {
+ let url = URL(fileURLWithPath: NSTemporaryDirectory() + name + ".jpg")
+ guard let data = image.jpegData(compressionQuality: 1.0) else {
+ return nil
+ }
+ do {
+ try data.write(to: url)
+ return url
+ } catch {
+ return nil
+ }
+ }
+
+ func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
+ presenter.dismiss(animated: true, completion: nil)
+ let mediaID = UUID().uuidString
+ switch filter {
+ case .image:
+ guard
+ let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage,
+ let url = save(image: image, toTemporaryDirectoryUsingName: mediaID)
+ else {
+ callback(nil)
+ return
+ }
+ callback(url)
+ case .video:
+ guard let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL else {
+ callback(nil)
+ return
+ }
+ callback(url)
+ default:
+ callback(nil)
+ }
+ }
+
+}
diff --git a/packages/react-native-editor/ios/gutenberg/MediaProvider.swift b/packages/react-native-editor/ios/gutenberg/MediaProvider.swift
new file mode 100644
index 00000000000000..91f6d4f9c203ee
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/MediaProvider.swift
@@ -0,0 +1,58 @@
+import Aztec
+
+class ExampleAttachmentImageProvider: TextViewAttachmentImageProvider {
+ func textView(_ textView: TextView, shouldRender attachment: NSTextAttachment) -> Bool {
+ return true
+ }
+
+ func textView(_ textView: TextView, boundsFor attachment: NSTextAttachment, with lineFragment: CGRect) -> CGRect {
+ return CGRect(x: 0, y: 0, width: 20, height: 20)
+ }
+
+ func textView(_ textView: TextView, imageFor attachment: NSTextAttachment, with size: CGSize) -> UIImage? {
+ let image = UIImage(named: "aztec")!
+ return scale(image, to: size)
+ }
+
+ private func scale(_ image: UIImage, to newSize:CGSize) -> UIImage {
+ UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
+ image.draw(in: CGRect(origin: CGPoint.zero, size: CGSize(width: newSize.width, height: newSize.height)))
+ let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
+ UIGraphicsEndImageContext()
+ return newImage
+ }
+}
+
+class ExampleAttachmentDelegate: TextViewAttachmentDelegate {
+ func textView(_ textView: TextView, attachment: NSTextAttachment, imageAt url: URL, onSuccess success: @escaping (UIImage) -> Void, onFailure failure: @escaping () -> Void) {
+ URLSession.shared.dataTask(with: url) { (data, response, error) in
+ guard let data = data, let image = UIImage(data: data) else {
+ failure()
+ return
+ }
+ DispatchQueue.main.async {
+ success(image)
+ }
+ }.resume()
+ }
+
+ func textView(_ textView: TextView, urlFor imageAttachment: ImageAttachment) -> URL? {
+ return URL(string: "www.google.com")
+ }
+
+ func textView(_ textView: TextView, placeholderFor attachment: NSTextAttachment) -> UIImage {
+ return UIImage(named: "aztec")!
+ }
+
+ func textView(_ textView: TextView, deletedAttachment attachment: MediaAttachment) {
+
+ }
+
+ func textView(_ textView: TextView, selected attachment: NSTextAttachment, atPosition position: CGPoint) {
+
+ }
+
+ func textView(_ textView: TextView, deselected attachment: NSTextAttachment, atPosition position: CGPoint) {
+
+ }
+}
diff --git a/packages/react-native-editor/ios/gutenberg/MediaUploadCoordinator.swift b/packages/react-native-editor/ios/gutenberg/MediaUploadCoordinator.swift
new file mode 100644
index 00000000000000..9571d532d92c87
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/MediaUploadCoordinator.swift
@@ -0,0 +1,93 @@
+
+import Foundation
+import UIKit
+import Gutenberg
+
+class MediaUploadCoordinator: NSObject {
+
+ static let failUpload: Notification.Name = Notification.Name(rawValue: "Notification.FailUpload")
+
+ private let gutenberg: Gutenberg
+
+ private var activeUploads: [Int32: Progress] = [:]
+ private(set) var successfullUpload = true
+
+ init(gutenberg: Gutenberg) {
+ self.gutenberg = gutenberg
+ super.init()
+ NotificationCenter.default.addObserver(self, selector: #selector(failUpload), name: MediaUploadCoordinator.failUpload, object: nil)
+ }
+
+ func upload(url: URL) -> Int32? {
+ //Make sure the media is not larger than a 32 bits to number to avoid problems when bridging to JS
+ let mediaID = Int32(truncatingIfNeeded:UUID().uuidString.hash)
+ let progress = Progress(parent: nil, userInfo: [ProgressUserInfoKey.mediaID: mediaID, ProgressUserInfoKey.mediaURL: url])
+ progress.totalUnitCount = 100
+ activeUploads[mediaID] = progress
+ let timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(timerFireMethod(_:)), userInfo: progress, repeats: true)
+ progress.cancellationHandler = { () in
+ timer.invalidate()
+ self.gutenberg.mediaUploadUpdate(id: mediaID, state: .reset, progress: 0, url: nil, serverID: nil)
+ }
+ return mediaID
+ }
+
+ func progressForUpload(mediaID: Int32) -> Progress? {
+ return activeUploads[mediaID]
+ }
+
+ func retryUpload(with mediaID: Int32) {
+ guard let progress = activeUploads[mediaID] else {
+ return
+ }
+ progress.completedUnitCount = 0
+ successfullUpload = true
+ Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(timerFireMethod(_:)), userInfo: progress, repeats: true)
+ }
+
+ func cancelUpload(with mediaID: Int32) {
+ guard let progress = activeUploads[mediaID] else {
+ return
+ }
+ progress.cancel()
+ }
+
+ @objc func failUpload() {
+ successfullUpload = false
+ }
+
+ @objc func timerFireMethod(_ timer: Timer) {
+ guard let progress = timer.userInfo as? Progress,
+ let mediaID = progress.userInfo[.mediaID] as? Int32,
+ let mediaURL = progress.userInfo[.mediaURL] as? URL
+ else {
+ timer.invalidate()
+ return
+ }
+ progress.completedUnitCount += 1
+
+ if !successfullUpload {
+ timer.invalidate()
+ progress.setUserInfoObject("Network upload failed", forKey: .mediaError)
+ gutenberg.mediaUploadUpdate(id: mediaID, state: .failed, progress: 1, url: nil, serverID: nil)
+ successfullUpload = true
+ return
+ }
+
+ //Variable to switch upload final state from success to failure.
+ if progress.fractionCompleted < 1 {
+ gutenberg.mediaUploadUpdate(id: mediaID, state: .uploading, progress: Float(progress.fractionCompleted), url: nil, serverID: nil)
+ } else if progress.fractionCompleted >= 1 {
+ timer.invalidate()
+ gutenberg.mediaUploadUpdate(id: mediaID, state: .succeeded, progress: 1, url: mediaURL, serverID: mediaID)
+ activeUploads[mediaID] = nil
+ }
+ }
+
+}
+
+extension ProgressUserInfoKey {
+ static let mediaID = ProgressUserInfoKey("mediaID")
+ static let mediaURL = ProgressUserInfoKey("mediaURL")
+ static let mediaError = ProgressUserInfoKey("mediaError")
+}
diff --git a/packages/react-native-editor/ios/gutenberg/WebViewController.swift b/packages/react-native-editor/ios/gutenberg/WebViewController.swift
new file mode 100644
index 00000000000000..40f9c61c99900d
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenberg/WebViewController.swift
@@ -0,0 +1,5 @@
+import Gutenberg
+
+class WebViewController: GutenbergWebSingleBlockViewController {
+
+}
diff --git a/packages/react-native-editor/ios/gutenbergTests/Info.plist b/packages/react-native-editor/ios/gutenbergTests/Info.plist
new file mode 100644
index 00000000000000..886825ccc9bf0d
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenbergTests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/packages/react-native-editor/ios/gutenbergTests/gutenbergTests.m b/packages/react-native-editor/ios/gutenbergTests/gutenbergTests.m
new file mode 100644
index 00000000000000..a549f9a8783176
--- /dev/null
+++ b/packages/react-native-editor/ios/gutenbergTests/gutenbergTests.m
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#import
+#import
+
+#import
+#import
+
+#define TIMEOUT_SECONDS 600
+#define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
+
+@interface gutenbergTests : XCTestCase
+
+@end
+
+@implementation gutenbergTests
+
+- (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;
+ RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
+ if (level >= RCTLogLevelError) {
+ redboxError = message;
+ }
+ });
+
+ while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
+ [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
+ [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
+
+ foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
+ if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
+ return YES;
+ }
+ return NO;
+ }];
+ }
+
+ RCTSetLogFunction(RCTDefaultLogFunction);
+
+ XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
+ XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
+}
+
+
+@end
diff --git a/packages/react-native-editor/metro.config.js b/packages/react-native-editor/metro.config.js
new file mode 100644
index 00000000000000..b3b71d59566a23
--- /dev/null
+++ b/packages/react-native-editor/metro.config.js
@@ -0,0 +1,22 @@
+/**
+ * External dependencies
+ */
+const path = require( 'path' );
+
+module.exports = {
+ watchFolders: [ path.resolve( __dirname, '../..' ) ],
+ resolver: {
+ sourceExts: [ 'js', 'json', 'scss', 'sass', 'ts', 'tsx' ],
+ platforms: [ 'native', 'android', 'ios' ],
+ },
+ transformer: {
+ babelTransformerPath: require.resolve( './sass-transformer.js' ),
+ getTransformOptions: async () => ( {
+ transform: {
+ experimentalImportSupport: false,
+ inlineRequires: false,
+ },
+ } ),
+ },
+ maxWorkers: 2,
+};
diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json
new file mode 100644
index 00000000000000..24037e434c78b9
--- /dev/null
+++ b/packages/react-native-editor/package.json
@@ -0,0 +1,127 @@
+{
+ "name": "@wordpress/react-native-editor",
+ "version": "1.30.0",
+ "description": "Mobile WordPress gutenberg editor.",
+ "author": "The WordPress Contributors",
+ "license": "GPL-2.0-or-later",
+ "keywords": [
+ "wordpress",
+ "react-native"
+ ],
+ "private": true,
+ "config": {
+ "jsfiles": "./*.js src/*.js src/**/*.js src/**/**/*.js",
+ "scssfiles": "src/*.scss src/**/*.scss"
+ },
+ "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/react-native-editor/README.md",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/WordPress/gutenberg.git",
+ "directory": "packages/react-native-editor"
+ },
+ "bugs": {
+ "url": "https://github.com/WordPress/gutenberg/issues"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">=6.9"
+ },
+ "main": "src/index.js",
+ "react-native": "src/index",
+ "dependencies": {
+ "@babel/runtime": "^7.9.2",
+ "@react-native-community/slider": "git+https://github.com/wordpress-mobile/react-native-slider.git#5ad284d92b8d886e366445bf215be741ed53ddc6",
+ "@wordpress/api-fetch": "file:../api-fetch",
+ "@wordpress/block-editor": "file:../block-editor",
+ "@wordpress/block-library": "file:../block-library",
+ "@wordpress/blocks": "file:../blocks",
+ "@wordpress/components": "file:../components",
+ "@wordpress/data": "file:../data",
+ "@wordpress/edit-post": "file:../edit-post",
+ "@wordpress/element": "file:../element",
+ "@wordpress/hooks": "file:../hooks",
+ "@wordpress/i18n": "file:../i18n",
+ "@wordpress/react-native-aztec": "file:../react-native-aztec",
+ "@wordpress/react-native-bridge": "file:../react-native-bridge",
+ "fast-average-color": "^4.3.0",
+ "jed": "^1.1.1",
+ "jsc-android": "^241213.1.0",
+ "jsdom-jscore-rn": "git+https://github.com/iamcco/jsdom-jscore-rn.git#a562f3d57c27c13e5bfc8cf82d496e69a3ba2800",
+ "metro-react-native-babel-preset": "0.57.0",
+ "metro-react-native-babel-transformer": "0.56.0",
+ "node-fetch": "^2.3.0",
+ "react-native": "0.61.5",
+ "react-native-dark-mode": "git+https://github.com/wordpress-mobile/react-native-dark-mode.git#f09bf1480e7b34536413ab3300f29e4375edb2c6",
+ "react-native-get-random-values": "git+https://github.com/wordpress-mobile/react-native-get-random-values.git#f03f2c16414aff4ea76064dcd00a9e3c6efc838d",
+ "react-native-hr": "git+https://github.com/Riglerr/react-native-hr.git#2d01a5cf77212d100e8b99e0310cce5234f977b3",
+ "react-native-hsv-color-picker": "git+https://github.com/wordpress-mobile/react-native-hsv-color-picker",
+ "react-native-keyboard-aware-scroll-view": "git+https://github.com/wordpress-mobile/react-native-keyboard-aware-scroll-view.git#gb-v0.8.8",
+ "react-native-linear-gradient": "git+https://github.com/wordpress-mobile/react-native-linear-gradient.git#52bf43077171cff8714ce3e0155f3ebb7f55bc37",
+ "react-native-modal": "^6.5.0",
+ "react-native-safe-area": "^0.5.0",
+ "react-native-sass-transformer": "^1.1.1",
+ "react-native-svg": "git+https://github.com/wordpress-mobile/react-native-svg.git#a628e92990a2404e30a0086f168bd2b5b7b4ce96",
+ "react-native-url-polyfill": "^1.1.2",
+ "react-native-video": "git+https://github.com/wordpress-mobile/react-native-video.git#1b964b107863351ed744fc104d7952bbec3e2d4f"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "start": "react-native start",
+ "start:reset": "npm run clean:runtime && npm run start -- --reset-cache",
+ "start:debug": "node --inspect-brk node_modules/.bin/react-native start",
+ "patch-metro-no-file-watch": "cp ../../node_modules/metro/src/node-haste/DependencyGraph.js ./ && cp DependencyGraph.js.patched ../../node_modules/metro/src/node-haste/DependencyGraph.js",
+ "un-patch-metro-no-file-watch": "mv ./DependencyGraph.js ../../node_modules/metro/src/node-haste/DependencyGraph.js",
+ "prebundle": "npm run i18n-cache:force",
+ "prebundle:android": "npm run patch-metro-no-file-watch",
+ "postbundle:android": "npm run un-patch-metro-no-file-watch",
+ "bundle": "npm run bundle:android && npm run bundle:ios",
+ "bundle:android": "mkdir -p bundle/android && react-native bundle --platform android --dev false --entry-file index.js --assets-dest bundle/android --bundle-output bundle/android/App.js --sourcemap-output bundle/android/App.js.map",
+ "bundle:ios": "mkdir -p bundle/ios && react-native bundle --platform ios --dev false --entry-file index.js --assets-dest bundle/ios --bundle-output bundle/ios/App.js --sourcemap-output bundle/ios/App.js.map",
+ "i18n-cache": "node i18n-cache/index.js",
+ "i18n-cache:force": "cross-env REFRESH_I18N_CACHE=1 node i18n-cache/index.js",
+ "postinstall": "npm run i18n-cache",
+ "android": "react-native run-android",
+ "prewpandroid": "rm -Rf $TMPDIR/gbmobile-wpandroidfakernroot && mkdir $TMPDIR/gbmobile-wpandroidfakernroot && ln -s $(cd \"$(dirname \"../../../../../\")\"; pwd) $TMPDIR/gbmobile-wpandroidfakernroot/android",
+ "wpandroid": "npm run android -- --root $TMPDIR/gbmobile-wpandroidfakernroot --variant wasabiDebug --appIdSuffix beta --appFolder WordPress --main-activity=ui.WPLaunchActivity",
+ "preios": "cd ios && (bundle check --path=vendor/bundle > /dev/null || bundle install) && bundle exec pod install --repo-update",
+ "preios:carthage": "cd ../react-native-aztec && npm run install-aztec-ios",
+ "preios:carthage:update": "cd ../react-native-aztec && npm run update-aztec-ios",
+ "preios:xcode10": "cd ../../node_modules/react-native && ./scripts/ios-install-third-party.sh && cd third-party/glog-0.3.5 && [ -f libglog.pc ] || ../../scripts/ios-configure-glog.sh",
+ "ios": "react-native run-ios",
+ "ios:fast": "react-native run-ios",
+ "test": "cross-env NODE_ENV=test jest --verbose --config ../../test/native/jest.config.js",
+ "test:debug": "cross-env NODE_ENV=test node --inspect-brk jest --runInBand --verbose --config ../../test/native/jest.config.js",
+ "device-tests": "cross-env NODE_ENV=test jest --forceExit --detectOpenHandles --no-cache --maxWorkers=3 --reporters=default --reporters=jest-junit --verbose --config ../../test/native/jest_ui.config.js",
+ "device-tests-canary": "cross-env NODE_ENV=test jest --forceExit --detectOpenHandles --no-cache --maxWorkers=2 --testNamePattern=@canary --reporters=default --reporters=jest-junit --verbose --config ../../test/native/jest_ui.config.js",
+ "device-tests:local": "cross-env NODE_ENV=test jest --runInBand --reporters=default --reporters=jest-junit --detectOpenHandles --verbose --forceExit --config ../../test/native/jest_ui.config.js",
+ "device-tests:debug": "cross-env NODE_ENV=test node $NODE_DEBUG_OPTION --inspect-brk node_modules/jest/bin/jest --runInBand --reporters=default --reporters=jest-junit --detectOpenHandles --verbose --config ../../test/native/jest_ui.config.js",
+ "test:e2e": "npm run test:e2e:android && npm run test:e2e:ios",
+ "test:e2e:android": "TEST_RN_PLATFORM=android npm run device-tests",
+ "test:e2e:android:debug": "TEST_RN_PLATFORM=android npm run device-tests:debug",
+ "test:e2e:ios": "TEST_RN_PLATFORM=ios npm run device-tests",
+ "test:e2e:android:local": "npm run test:e2e:build-app:android && npm run test:e2e:install-app:android && TEST_RN_PLATFORM=android npm run device-tests:local",
+ "test:e2e:android:local:debug": "npm run test:e2e:build-app:android && npm run test:e2e:install-app:android && npm run test:e2e:android:debug",
+ "test:e2e:ios:local": "npm run test:e2e:bundle:ios && npm run test:e2e:build-app:ios && TEST_RN_PLATFORM=ios npm run device-tests:local",
+ "test:e2e:bundle:android": "mkdir -p android/app/src/main/assets && react-native bundle --reset-cache --platform android --dev false --minify false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
+ "test:e2e:build-app:android": "npm run test:e2e:bundle:android && cd android && ./gradlew clean && ./gradlew assembleDebug",
+ "test:e2e:install-app:android": "cd android && ./gradlew installDebug",
+ "test:e2e:bundle:ios": "mkdir -p ios/build/gutenberg/Build/Products/Release-iphonesimulator/GutenbergDemo.app && react-native bundle --reset-cache --platform=ios --dev=false --minify false --entry-file=index.js --bundle-output=./ios/build/gutenberg/Build/Products/Release-iphonesimulator/GutenbergDemo.app/main.jsbundle --assets-dest=./ios/build/gutenberg/Build/Products/Release-iphonesimulator/GutenbergDemo.app",
+ "test:e2e:build-app:ios": "npm run ios -- --configuration Release --no-packager --simulator 'iPhone 11 (13.4)'",
+ "build:gutenberg": "cd gutenberg && npm ci && npm run build",
+ "clean": "npm run clean:build-artifacts; npm run clean:aztec; npm run cache clean; npm run clean:haste; npm run clean:jest; npm run clean:metro; npm run clean:react; npm run clean:watchman",
+ "clean:runtime": "npm run clean:haste; npm run clean:react; npm run clean:metro; npm run clean:jest; npm run clean:watchman; npm run clean:babel-cache",
+ "clean:build-artifacts": "rm -rf ./ios/build && rm -rf ./ios/Pods",
+ "clean:aztec": "cd ../react-native-aztec && npm run clean",
+ "clean:haste": "rm -rf /tmp/haste-map-react-native-packager-*",
+ "clean:install": "npm run clean; npm install",
+ "clean:jest": "jest --clearCache --config ../../test/native/jest.config.js; rm -rf $TMPDIR/jest_*",
+ "clean:metro": "rm -rf $TMPDIR/metro-cache-*;",
+ "clean:react": "rm -rf $TMPDIR/react-*",
+ "clean:watchman": "command -v watchman >/dev/null 2>&1 && watchman watch-del-all; true",
+ "clean:babel-cache": "rm -rf ../../node_modules/.cache/babel-loader/*",
+ "clean:i18n-cache": "rm -rf ./i18n-cache/data/*.json && rm -f ./i18n-cache/index.native.js",
+ "version": "npm run bundle && git add -A bundle"
+ }
+}
diff --git a/packages/react-native-editor/resources/fonts/NotoSerif-Bold.ttf b/packages/react-native-editor/resources/fonts/NotoSerif-Bold.ttf
new file mode 100644
index 00000000000000..50b12d3f721392
Binary files /dev/null and b/packages/react-native-editor/resources/fonts/NotoSerif-Bold.ttf differ
diff --git a/packages/react-native-editor/resources/fonts/NotoSerif-BoldItalic.ttf b/packages/react-native-editor/resources/fonts/NotoSerif-BoldItalic.ttf
new file mode 100644
index 00000000000000..741402e9a97f66
Binary files /dev/null and b/packages/react-native-editor/resources/fonts/NotoSerif-BoldItalic.ttf differ
diff --git a/packages/react-native-editor/resources/fonts/NotoSerif-Italic.ttf b/packages/react-native-editor/resources/fonts/NotoSerif-Italic.ttf
new file mode 100644
index 00000000000000..84349fb19c9b7f
Binary files /dev/null and b/packages/react-native-editor/resources/fonts/NotoSerif-Italic.ttf differ
diff --git a/packages/react-native-editor/resources/fonts/NotoSerif-Regular.ttf b/packages/react-native-editor/resources/fonts/NotoSerif-Regular.ttf
new file mode 100644
index 00000000000000..ec8afe61f4508a
Binary files /dev/null and b/packages/react-native-editor/resources/fonts/NotoSerif-Regular.ttf differ
diff --git a/packages/react-native-editor/sass-transformer.js b/packages/react-native-editor/sass-transformer.js
new file mode 100644
index 00000000000000..978c645692b24c
--- /dev/null
+++ b/packages/react-native-editor/sass-transformer.js
@@ -0,0 +1,150 @@
+/**
+ * Parts of this source were derived and modified from react-native-sass-transformer,
+ * released under the MIT license.
+ *
+ * https://github.com/kristerkari/react-native-sass-transformer
+ *
+ * The MIT License (MIT)
+
+ * Copyright (c) 2018 Krister Kari
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+// TODO: create a new npm package with this transformer, or extend 'react-native-sass-transformer'
+
+/**
+ * External dependencies
+ */
+const fs = require( 'fs' );
+const path = require( 'path' );
+
+// eslint-disable-next-line import/no-extraneous-dependencies
+const sass = require( 'node-sass' );
+// eslint-disable-next-line import/no-extraneous-dependencies
+const css2rn = require( 'css-to-react-native-transform' ).default;
+
+const upstreamTransformer = require( 'metro-react-native-babel-transformer' );
+
+// TODO: need to find a way to pass the include paths and the default asset files via some config
+const autoImportIncludePaths = [
+ path.join( path.dirname( __filename ), 'src' ),
+ path.join( path.dirname( __filename ), '../base-styles' ),
+];
+const autoImportAssets = [
+ '_colors.scss',
+ '_breakpoints.scss',
+ '_variables.scss',
+ '_native.scss',
+ '_mixins.scss',
+ '_animations.scss',
+ '_z-index.scss',
+];
+const imports =
+ '@import "' + autoImportAssets.join( '";\n@import "' ) + '";\n\n';
+
+// Iterate through the include paths and extensions to find the file variant
+function findVariant( name, extensions, includePaths ) {
+ for ( let i = 0; i < includePaths.length; i++ ) {
+ const includePath = includePaths[ i ];
+
+ // try to find the file iterating through the extensions, in order.
+ const foundExtention = extensions.find( ( extension ) => {
+ const fname = includePath + '/' + name + extension;
+ const partialfname = includePath + '/_' + name + extension;
+ return fs.existsSync( fname ) || fs.existsSync( partialfname );
+ } );
+
+ if ( foundExtention ) {
+ return includePath + '/' + name + foundExtention;
+ }
+ }
+
+ return false;
+}
+
+// Transform function taken from react-native-sass-transformer but extended to have more include paths
+// and detect and use RN platform specific file variants
+function transform( src, filename, options ) {
+ if ( typeof src === 'object' ) {
+ // handle RN >= 0.46
+ ( { src, filename, options } = src );
+ }
+
+ const exts = [
+ // add the platform specific extension, first in the array to take precedence
+ options.platform === 'android' ? '.android.scss' : '.ios.scss',
+ '.native.scss',
+ '.scss',
+ ];
+
+ if ( filename.endsWith( '.scss' ) || filename.endsWith( '.sass' ) ) {
+ const result = sass.renderSync( {
+ data: src,
+ includePaths: [
+ path.dirname( filename ),
+ ...autoImportIncludePaths,
+ ],
+ importer( url /*, prev, done */ ) {
+ // url is the path in import as is, which LibSass encountered.
+ // prev is the previously resolved path.
+ // done is an optional callback, either consume it or return value synchronously.
+ // this.options contains this options hash, this.callback contains the node-style callback
+
+ const urlPath = path.parse( url );
+ const importerOptions = this.options;
+ const incPaths = importerOptions.includePaths
+ .slice( 0 )
+ .split( ':' );
+ if ( urlPath.dir.length > 0 ) {
+ incPaths.unshift(
+ path.resolve( path.dirname( filename ), urlPath.dir )
+ ); // add the file's dir to the search array
+ }
+ const f = findVariant( urlPath.name, exts, incPaths );
+
+ if ( f ) {
+ return { file: f };
+ }
+
+ return new Error(
+ url + ' could not be resolved in ' + incPaths
+ );
+ },
+ } );
+ const css = result.css.toString();
+ const cssObject = css2rn( css, { parseMediaQueries: true } );
+
+ return upstreamTransformer.transform( {
+ src: 'module.exports = ' + JSON.stringify( cssObject ),
+ filename,
+ options,
+ } );
+ }
+ return upstreamTransformer.transform( { src, filename, options } );
+}
+
+module.exports.transform = function ( { src, filename, options } ) {
+ if ( filename.endsWith( '.scss' ) || filename.endsWith( '.sass' ) ) {
+ // "auto-import" the stylesheets the GB webpack config imports
+ src = imports + src;
+ return transform( { src, filename, options } );
+ }
+ return upstreamTransformer.transform( { src, filename, options } );
+};
diff --git a/packages/react-native-editor/src/_native.android.scss b/packages/react-native-editor/src/_native.android.scss
new file mode 100644
index 00000000000000..3b90fe27810807
--- /dev/null
+++ b/packages/react-native-editor/src/_native.android.scss
@@ -0,0 +1,5 @@
+/** @format */
+
+// Fonts
+$default-monospace-font: monospace;
+$default-regular-font: serif;
diff --git a/packages/react-native-editor/src/_native.ios.scss b/packages/react-native-editor/src/_native.ios.scss
new file mode 100644
index 00000000000000..03c60c155da086
--- /dev/null
+++ b/packages/react-native-editor/src/_native.ios.scss
@@ -0,0 +1,5 @@
+/** @format */
+
+// Fonts
+$default-monospace-font: menlo;
+$default-regular-font: "Noto Serif";
diff --git a/packages/react-native-editor/src/api-fetch-setup.js b/packages/react-native-editor/src/api-fetch-setup.js
new file mode 100644
index 00000000000000..6a396732f49751
--- /dev/null
+++ b/packages/react-native-editor/src/api-fetch-setup.js
@@ -0,0 +1,53 @@
+/**
+ * External dependencies
+ */
+/**
+ * WordPress dependencies
+ */
+import { fetchRequest } from '@wordpress/react-native-bridge';
+
+/**
+ * WordPress dependencies
+ */
+import apiFetch from '@wordpress/api-fetch';
+
+const setTimeoutPromise = ( delay ) =>
+ new Promise( ( resolve ) => setTimeout( resolve, delay ) );
+
+const fetchHandler = ( { path }, retries = 20, retryCount = 1 ) => {
+ if ( ! isPathSupported( path ) ) {
+ return Promise.reject( `Unsupported path: ${ path }` );
+ }
+
+ const responsePromise = fetchRequest( path );
+
+ const parseResponse = ( response ) => {
+ if ( typeof response === 'string' ) {
+ response = JSON.parse( response );
+ }
+ return response;
+ };
+
+ return responsePromise.then( parseResponse ).catch( ( error ) => {
+ // eslint-disable-next-line no-console
+ console.warn( 'Network Error: ', JSON.stringify( error, null, 2 ) );
+ if ( error.code >= 400 && error.code < 600 ) {
+ return error;
+ } else if ( retries === 0 ) {
+ return Promise.reject( error );
+ }
+ return setTimeoutPromise( 1000 * retryCount ).then( () =>
+ fetchHandler( { path }, retries - 1, retryCount + 1 )
+ );
+ } );
+};
+
+export const isPathSupported = ( path ) =>
+ [
+ /wp\/v2\/(media|categories)\/?\d*?.*/i,
+ /wpcom\/v2\/gutenberg\/.*/i,
+ ].some( ( pattern ) => pattern.test( path ) );
+
+export default () => {
+ apiFetch.setFetchHandler( ( options ) => fetchHandler( options ) );
+};
diff --git a/packages/react-native-editor/src/globals.js b/packages/react-native-editor/src/globals.js
new file mode 100644
index 00000000000000..4cfebd0150f4f2
--- /dev/null
+++ b/packages/react-native-editor/src/globals.js
@@ -0,0 +1,59 @@
+/**
+ * External dependencies
+ */
+// This library works as a polyfill for the global crypto.getRandomValues which is needed by `uuid` version 7.0.0
+import 'react-native-get-random-values';
+import jsdom from 'jsdom-jscore-rn';
+import jsdomLevel1Core from 'jsdom-jscore-rn/lib/jsdom/level1/core';
+
+/**
+ * WordPress dependencies
+ */
+import { nativeLoggingHook } from '@wordpress/react-native-bridge';
+import { createElement } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+
+/**
+ * Import for side-effects: Patches for jsdom-jscore, mostly to implement
+ * functions that are called from Gutenberg code paths, where a more full DOM
+ * implementation is expected (in the browser environment).
+ *
+ * More details are available within the comments in the file.
+ */
+import './jsdom-patches';
+
+global.wp = {
+ element: {
+ createElement, // load the element creation function, needed by Gutenberg-web
+ },
+};
+
+const doc = jsdom.html( '', null, null );
+
+// inject a simple version of the missing createHTMLDocument method that `hpq` depends on
+doc.implementation.createHTMLDocument = function ( html ) {
+ return jsdom.html( html, null, null );
+};
+
+// `hpq` depends on `document` be available globally
+global.document = doc;
+
+if ( ! global.window.Node ) {
+ global.window.Node = jsdomLevel1Core.dom.level1.core.Node;
+}
+
+if ( ! global.window.matchMedia ) {
+ global.window.matchMedia = () => ( {
+ matches: false,
+ addListener: () => {},
+ removeListener: () => {},
+ } );
+}
+
+global.window.navigator.userAgent = [];
+
+// Leverages existing console polyfill from react-native
+global.nativeLoggingHook = nativeLoggingHook;
diff --git a/packages/react-native-editor/src/index.js b/packages/react-native-editor/src/index.js
new file mode 100644
index 00000000000000..bf2369b4a9d41f
--- /dev/null
+++ b/packages/react-native-editor/src/index.js
@@ -0,0 +1,110 @@
+/**
+ * External dependencies
+ */
+import { I18nManager } from 'react-native';
+
+/**
+ * Internal dependencies
+ */
+import './globals';
+import { getTranslation } from '../i18n-cache';
+import initialHtml from './initial-html';
+import setupApiFetch from './api-fetch-setup';
+
+const reactNativeSetup = () => {
+ // Disable warnings as they disrupt the user experience in dev mode
+ // eslint-disable-next-line no-console
+ console.disableYellowBox = true;
+
+ I18nManager.forceRTL( false ); // Change to `true` to debug RTL layout easily.
+};
+
+const gutenbergSetup = () => {
+ const wpData = require( '@wordpress/data' );
+
+ // wp-data
+ const userId = 1;
+ const storageKey = 'WP_DATA_USER_' + userId;
+ wpData.use( wpData.plugins.persistence, { storageKey } );
+
+ setupApiFetch();
+
+ const isHermes = () => global.HermesInternal !== null;
+ // eslint-disable-next-line no-console
+ console.log( 'Hermes is: ' + isHermes() );
+
+ setupInitHooks();
+
+ const initializeEditor = require( '@wordpress/edit-post' ).initializeEditor;
+ initializeEditor( 'gutenberg', 'post', 1 );
+};
+
+const setupInitHooks = () => {
+ const wpHooks = require( '@wordpress/hooks' );
+
+ wpHooks.addAction(
+ 'native.pre-render',
+ 'core/react-native-editor',
+ ( props ) => {
+ setupLocale( props.locale, props.translations );
+ }
+ );
+
+ // Map native props to Editor props
+ // TODO: normalize props in the bridge (So we don't have to map initialData to initialHtml)
+ wpHooks.addFilter(
+ 'native.block_editor_props',
+ 'core/react-native-editor',
+ ( props ) => {
+ const { capabilities = {} } = props;
+ let { initialData, initialTitle, postType } = props;
+
+ if ( initialData === undefined && __DEV__ ) {
+ initialData = initialHtml;
+ }
+ if ( initialTitle === undefined ) {
+ initialTitle = 'Welcome to Gutenberg!';
+ }
+ if ( postType === undefined ) {
+ postType = 'post';
+ }
+
+ return {
+ initialHtml: initialData,
+ initialHtmlModeEnabled: props.initialHtmlModeEnabled,
+ initialTitle,
+ postType,
+ capabilities,
+ colors: props.colors,
+ gradients: props.gradients,
+ };
+ }
+ );
+};
+
+const setupLocale = ( locale, extraTranslations ) => {
+ const setLocaleData = require( '@wordpress/i18n' ).setLocaleData;
+
+ I18nManager.forceRTL( false ); // Change to `true` to debug RTL layout easily.
+
+ let gutenbergTranslations = getTranslation( locale );
+ if ( locale && ! gutenbergTranslations ) {
+ // Try stripping out the regional
+ locale = locale.replace( /[-_][A-Za-z]+$/, '' );
+ gutenbergTranslations = getTranslation( locale );
+ }
+ const translations = Object.assign(
+ {},
+ gutenbergTranslations,
+ extraTranslations
+ );
+ // eslint-disable-next-line no-console
+ console.log( 'locale', locale, translations );
+ // Only change the locale if it's supported by gutenberg
+ if ( gutenbergTranslations || extraTranslations ) {
+ setLocaleData( translations );
+ }
+};
+
+reactNativeSetup();
+gutenbergSetup();
diff --git a/packages/react-native-editor/src/initial-html.js b/packages/react-native-editor/src/initial-html.js
new file mode 100644
index 00000000000000..88ce259eb670dd
--- /dev/null
+++ b/packages/react-native-editor/src/initial-html.js
@@ -0,0 +1,245 @@
+export default `
+
+Text Blocks
+
+
+
+What is Gutenberg?
+
+
+
+Bold Italic Striked Superscript(1) Subscript(2) Link
+
+
+
+List
+
+
+
+- First Item
- Second Item
- Third Item
+
+
+
+Quote
+
+
+
+"This will make running your own blog a viable alternative again."
— Adrian Zumbrunnen
+
+
+
+
+
+
+
+Style Paragraph
+
+
+
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer tempor tincidunt sapien, quis dictum orci sollicitudin quis. Proin sed elit id est pulvinar feugiat vitae eget dolor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+
+
+Pre formatted
+
+
+
+Some preformatted text...
And more!
+
+
+
+Code
+
+
+
+if name == "World":
+ return "Hello World"
+else:
+ return "Hello Pony"
+
+
+
+Verse
+
+
+
+Come
Home.
+
+
+
+Media
+
+
+
+Images
+
+
+
+
+
+
+
+
+
+
+
+Video
+
+
+
+
+
+
+
+Gallery
+
+
+
+
+
+
+
+Separators
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Layout
+
+
+
+Group
+
+
+
+
+
One.
+
+
+
+
Two
+
+
+
+
Three.
+
+
+
+
+Columns
+
+
+
+
+
+
Built with modern technology.
+
+
+
+
Gutenberg was developed on GitHub using the WordPress REST API, JavaScript, and React.
+
+
+
+
Learn more
+
+
+
+
+
+
Designed for compatibility.
+
+
+
+
We recommend migrating features to blocks, but support for existing WordPress functionality remains. There will be transition paths for shortcodes, meta-boxes, and Custom Post Types.
+
+
+
+
Learn more
+
+
+
+
+
+Media Text
+
+
+
+
+
+
+
+Cover
+
+
+
+
+
+
+
+Dynamic Blocks
+
+
+
+
+
+Buttons
+
+
+
+
+
+
+
+Legacy
+
+
+
+[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]
+
+
+
+Jetpack
+
+
+
+
+
+
+
+Unsupported
+
+
+
+`;
diff --git a/packages/react-native-editor/src/jsdom-patches.js b/packages/react-native-editor/src/jsdom-patches.js
new file mode 100644
index 00000000000000..3388a74488a44c
--- /dev/null
+++ b/packages/react-native-editor/src/jsdom-patches.js
@@ -0,0 +1,263 @@
+/**
+ * This file is used in src/globals.js to patch jsdom-jscore.
+ *
+ * Node.prototype.contains is implemented as a simple recursive function.
+ *
+ * Node.prototype.insertBefore is re-implemented (code copied) with the
+ * WrongDocumentError exception disabled.
+ *
+ * Element.prototype.matches is aliased to Element.prototype.matchesSelector.
+ *
+ * Getters are defined on the Node.prototype for the following properties:
+ * parentElement, previousElementSibling, nextElementSibling.
+ */
+
+/**
+ * External dependencies
+ */
+import jsdom from 'jsdom-jscore-rn';
+import jsdomLevel1Core from 'jsdom-jscore-rn/lib/jsdom/level1/core';
+
+// must be called to initialize jsdom before patching prototypes
+jsdom.html( '', null, null );
+
+const { core } = jsdomLevel1Core.dom.level1;
+const { Node, Element, CharacterData } = core;
+
+// Exception codes
+const {
+ NO_MODIFICATION_ALLOWED_ERR,
+ HIERARCHY_REQUEST_ERR,
+ NOT_FOUND_ERR,
+} = core;
+
+// Node types
+const { ATTRIBUTE_NODE, DOCUMENT_FRAGMENT_NODE } = Node;
+
+/**
+ * Simple recursive implementation of Node.contains method
+ *
+ * @param {number} otherNode Another node (may be the same node).
+ * @return {boolean} true if otherNode is a descendant of this node, or is this
+ * node, false otherwise.
+ *
+ * This function is necessary in the mobile environment, because there are code
+ * paths that make use of functions in the Gutenberg (web) project, which has
+ * expectation that this is implemented (as it is in the browser environment).
+ */
+Node.prototype.contains = function ( otherNode ) {
+ return (
+ this === otherNode ||
+ Array.prototype.some.call( this._childNodes, ( childNode ) => {
+ return childNode.contains( otherNode );
+ } )
+ );
+};
+
+/**
+ * Copy of insertBefore function from jsdom-jscore, WRONG_DOCUMENT_ERR exception
+ * disabled.
+ *
+ * @param {Object} newChild The node to be insterted.
+ * @param {Object} refChild The node before which newChild is inserted.
+ * @return {Object} the newly inserted child node
+ *
+ * This function is modified here to remove the WRONG_DOCUMENT_ERR exception
+ * that is no longer part of the DOM spec for this function.
+ * see: https://github.com/jsdom/jsdom/issues/717 for more information, * and:
+ * https://dom.spec.whatwg.org/#dom-node-insertbefore for the latest spec.
+ */
+Node.prototype.insertBefore = function (
+ /* Node */ newChild,
+ /* Node*/ refChild
+) {
+ if ( this._readonly === true ) {
+ throw new core.DOMException(
+ NO_MODIFICATION_ALLOWED_ERR,
+ 'Attempting to modify a read-only node'
+ );
+ }
+
+ // Adopt unowned children, for weird nodes like DocumentType
+ if ( ! newChild._ownerDocument ) {
+ newChild._ownerDocument = this._ownerDocument;
+ }
+
+ /*
+ * This is commented out to prevent WrongDocumentError
+ * see: https://github.com/jsdom/jsdom/issues/717
+ *
+ // TODO - if (!newChild) then?
+ if (newChild._ownerDocument !== this._ownerDocument) {
+ throw new core.DOMException(WRONG_DOCUMENT_ERR);
+ }
+ */
+
+ if ( newChild.nodeType && newChild.nodeType === ATTRIBUTE_NODE ) {
+ throw new core.DOMException( HIERARCHY_REQUEST_ERR );
+ }
+
+ // search for parents matching the newChild
+ let current = this;
+ do {
+ if ( current === newChild ) {
+ throw new core.DOMException( HIERARCHY_REQUEST_ERR );
+ }
+ } while ( ( current = current._parentNode ) );
+
+ // fragments are merged into the element
+ if ( newChild.nodeType === DOCUMENT_FRAGMENT_NODE ) {
+ let tmpNode,
+ i = newChild._childNodes.length;
+ while ( i-- > 0 ) {
+ tmpNode = newChild.removeChild( newChild.firstChild );
+ this.insertBefore( tmpNode, refChild );
+ }
+ } else if ( newChild === refChild ) {
+ return newChild;
+ } else {
+ // if the newChild is already in the tree elsewhere, remove it first
+ if ( newChild._parentNode ) {
+ newChild._parentNode.removeChild( newChild );
+ }
+
+ if ( refChild === null ) {
+ // eslint-disable-next-line no-var
+ var refChildIndex = this._childNodes.length;
+ } else {
+ // eslint-disable-next-line no-redeclare, no-var
+ var refChildIndex = this._indexOf( refChild );
+ if ( refChildIndex === -1 ) {
+ throw new core.DOMException( NOT_FOUND_ERR );
+ }
+ }
+
+ Array.prototype.splice.call(
+ this._childNodes,
+ refChildIndex,
+ 0,
+ newChild
+ );
+
+ newChild._parentNode = this;
+ if ( this._attached && newChild._attach ) {
+ newChild._attach();
+ }
+
+ this._modified();
+ }
+
+ return newChild;
+}; // raises(DOMException);
+
+/*
+ * This is merely an alias (polyfill not needed).
+ * see: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
+ *
+ * This function is necessary in the mobile environment, because there are code
+ * paths that make use of functions in the Gutenberg (web) project, which has
+ * expectation that this is implemented (as it is in the browser environment).
+ */
+Element.prototype.matches = Element.prototype.matchesSelector;
+
+/*
+ * Implementation of Element.prototype.closest that it's missing from the jsdom-jscore fork we're using.
+ * See https://github.com/wordpress-mobile/gutenberg-mobile/issues/1625
+ */
+Element.prototype.closest = function ( selector ) {
+ let el = this;
+ while ( el ) {
+ if ( el.matches( selector ) ) {
+ return el;
+ }
+ el = el.parentElement;
+ }
+ return null;
+};
+
+/**
+ * Helper function to check if a node implements the NonDocumentTypeChildNode
+ * interface
+ *
+ * @param {Object} node Node to check
+ * @return {boolean} true if node is a NonDocumentTypeChildNode, false otherwise
+ *
+ * This function is needed to implement the previousElementSibling and
+ * nextElementSibling properties.
+ * See: https://dom.spec.whatwg.org/#interface-nondocumenttypechildnode
+ */
+function isNonDocumentTypeChildNode( node ) {
+ return node instanceof Element || node instanceof CharacterData;
+}
+
+// $FlowFixMe
+Object.defineProperties( Node.prototype, {
+ /*
+ * This defines parentElement property on the Node prototype using a getter.
+ * See: https://dom.spec.whatwg.org/#parent-element
+ */
+ parentElement: {
+ get() {
+ const parent = this.parentNode;
+
+ if ( parent && parent.nodeType === Node.ELEMENT_NODE ) {
+ return parent;
+ }
+
+ return null;
+ },
+ },
+ /*
+ * This defines previousElementSibling property on the Node prototype using a
+ * getter.
+ * See: https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
+ */
+ previousElementSibling: {
+ get() {
+ // Property is undefined if node is not a NonDocumentTypeChildNode
+ if ( ! isNonDocumentTypeChildNode( this ) ) {
+ return;
+ }
+
+ let sibling = this.previousSibling;
+
+ while ( sibling && sibling.nodeType !== Node.ELEMENT_NODE ) {
+ sibling = sibling.previousSibling;
+ }
+
+ return sibling;
+ },
+ },
+ /*
+ * This defines nextElementSibling property on the Node prototype using a
+ * getter.
+ * See: https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
+ */
+ nextElementSibling: {
+ get() {
+ // Property is undefined if node is not a NonDocumentTypeChildNode
+ if ( ! isNonDocumentTypeChildNode( this ) ) {
+ return;
+ }
+
+ let sibling = this.nextSibling;
+
+ while ( sibling && sibling.nodeType !== Node.ELEMENT_NODE ) {
+ sibling = sibling.nextSibling;
+ }
+
+ return sibling;
+ },
+ },
+} );
+
+class DOMParser {
+ // This is required for the stripHTML function, but it doesn't necessarily
+ // conform to the DOM standard.
+ // See https://github.com/wordpress-mobile/gutenberg-mobile/pull/1771
+ parseFromString( string ) {
+ return jsdom.html( string );
+ }
+}
+
+global.DOMParser = DOMParser;
diff --git a/packages/react-native-editor/src/parser/block-parser-code.test.js b/packages/react-native-editor/src/parser/block-parser-code.test.js
new file mode 100644
index 00000000000000..276e73b6d7d5b7
--- /dev/null
+++ b/packages/react-native-editor/src/parser/block-parser-code.test.js
@@ -0,0 +1,43 @@
+/**
+ * Internal dependencies
+ */
+import '../globals';
+
+/**
+ * WordPress dependencies
+ */
+import { registerCoreBlocks } from '@wordpress/block-library';
+import { parse } from '@wordpress/blocks';
+
+registerCoreBlocks();
+
+describe( 'Parser', () => {
+ const codeContent = `
+ if name == "World":
+ return "Hello World"
+ else:
+ return "Hello Pony"`;
+
+ const originalCodeBlockHtml = `${ codeContent }
`;
+
+ const gbCodeBlockHtml = `
+
+ ${ originalCodeBlockHtml }
+ `;
+
+ it( 'parses the code block ok', () => {
+ const codeBlockInstance = parse( gbCodeBlockHtml )[ 0 ];
+ expect( codeBlockInstance ).toBeTruthy();
+ } );
+
+ it( 'parses the code block content ok', () => {
+ const codeBlockInstance = parse( gbCodeBlockHtml )[ 0 ];
+
+ expect( codeBlockInstance.isValid ).toEqual( true );
+ expect( codeBlockInstance.name ).toEqual( 'core/code' );
+ expect( codeBlockInstance.innerBlocks ).toHaveLength( 0 );
+ expect( codeBlockInstance.originalContent ).toEqual(
+ originalCodeBlockHtml
+ );
+ } );
+} );
diff --git a/packages/react-native-editor/src/parser/block-parser-more.test.js b/packages/react-native-editor/src/parser/block-parser-more.test.js
new file mode 100644
index 00000000000000..c2f2360fc64a2c
--- /dev/null
+++ b/packages/react-native-editor/src/parser/block-parser-more.test.js
@@ -0,0 +1,37 @@
+/**
+ * Internal dependencies
+ */
+import '../globals';
+
+/**
+ * WordPress dependencies
+ */
+import { registerCoreBlocks } from '@wordpress/block-library';
+import { parse } from '@wordpress/blocks';
+
+registerCoreBlocks();
+
+describe( 'Parser', () => {
+ const originalMoreBlockHtml = '';
+
+ const gbMoreBlockHtml = `
+
+ ${ originalMoreBlockHtml }
+ `;
+
+ it( 'parses the more block ok', () => {
+ const moreBlockInstance = parse( gbMoreBlockHtml )[ 0 ];
+ expect( moreBlockInstance ).toBeTruthy();
+ } );
+
+ it( 'parses the more block attributes ok', () => {
+ const moreBlockInstance = parse( gbMoreBlockHtml )[ 0 ];
+
+ expect( moreBlockInstance.isValid ).toEqual( true );
+ expect( moreBlockInstance.name ).toEqual( 'core/more' );
+ expect( moreBlockInstance.innerBlocks ).toHaveLength( 0 );
+ expect( moreBlockInstance.originalContent ).toEqual(
+ originalMoreBlockHtml
+ );
+ } );
+} );
diff --git a/packages/react-native-editor/src/parser/block-parser-paragraph.test.js b/packages/react-native-editor/src/parser/block-parser-paragraph.test.js
new file mode 100644
index 00000000000000..d9f451005901a4
--- /dev/null
+++ b/packages/react-native-editor/src/parser/block-parser-paragraph.test.js
@@ -0,0 +1,41 @@
+/**
+ * Internal dependencies
+ */
+import '../globals';
+
+/**
+ * WordPress dependencies
+ */
+import { registerCoreBlocks } from '@wordpress/block-library';
+import { parse } from '@wordpress/blocks';
+
+registerCoreBlocks();
+
+describe( 'Parser', () => {
+ const innerContent = `
+ if name == "World":
+ return "Hello World"
+ else:
+ return "Hello Pony"`;
+
+ const originalBlockHtml = `${ innerContent }
`;
+
+ const gbBlockHtml = `
+
+ ${ originalBlockHtml }
+ `;
+
+ it( 'parses the paragraph block ok', () => {
+ const blockInstance = parse( gbBlockHtml )[ 0 ];
+ expect( blockInstance ).toBeTruthy();
+ } );
+
+ it( 'parses the paragraph block content ok', () => {
+ const blockInstance = parse( gbBlockHtml )[ 0 ];
+
+ expect( blockInstance.isValid ).toEqual( true );
+ expect( blockInstance.name ).toEqual( 'core/paragraph' );
+ expect( blockInstance.innerBlocks ).toHaveLength( 0 );
+ expect( blockInstance.originalContent ).toEqual( originalBlockHtml );
+ } );
+} );
diff --git a/packages/react-native-editor/src/test/api-fetch-setup.test.js b/packages/react-native-editor/src/test/api-fetch-setup.test.js
new file mode 100644
index 00000000000000..c7d5b230fbf8fd
--- /dev/null
+++ b/packages/react-native-editor/src/test/api-fetch-setup.test.js
@@ -0,0 +1,31 @@
+/**
+ * Internal dependencies
+ */
+import { isPathSupported } from '../api-fetch-setup';
+
+const supportedPaths = [
+ 'wp/v2/media/54?context=edit&_locale=user',
+ 'wp/v2/media/5?context=edit',
+ 'wp/v2/media/54/',
+ 'wp/v2/media/',
+ 'wp/v2/media?context=edit&_locale=user',
+ 'wp/v2/categories/',
+];
+
+const unsupportedPaths = [
+ 'wp/v1/media/', // made up example
+];
+
+describe( 'isPathSupported', () => {
+ supportedPaths.forEach( ( path ) => {
+ it( `supports ${ path }`, () => {
+ expect( isPathSupported( path ) ).toBe( true );
+ } );
+ } );
+
+ unsupportedPaths.forEach( ( path ) => {
+ it( `does not support ${ path }`, () => {
+ expect( isPathSupported( path ) ).toBe( false );
+ } );
+ } );
+} );
diff --git a/packages/rich-text/src/component/index.native.js b/packages/rich-text/src/component/index.native.js
index 91fabd4cd2d4be..b3dfc7e1c482a6 100644
--- a/packages/rich-text/src/component/index.native.js
+++ b/packages/rich-text/src/component/index.native.js
@@ -3,9 +3,12 @@
/**
* External dependencies
*/
-import RCTAztecView from 'react-native-aztec';
+/**
+ * WordPress dependencies
+ */
+import RCTAztecView from '@wordpress/react-native-aztec';
import { View, Platform } from 'react-native';
-import { addMention } from 'react-native-gutenberg-bridge';
+import { addMention } from '@wordpress/react-native-bridge';
import { get, pickBy } from 'lodash';
import memize from 'memize';
diff --git a/packages/scripts/scripts/check-licenses.js b/packages/scripts/scripts/check-licenses.js
index d03e595b9dfc50..a7f6e1976a7888 100644
--- a/packages/scripts/scripts/check-licenses.js
+++ b/packages/scripts/scripts/check-licenses.js
@@ -80,6 +80,7 @@ const otherOssLicenses = [
'Apache License, Version 2.0',
'Apache version 2.0',
'CC-BY-3.0',
+ 'CC-BY-SA-2.0',
'LGPL',
];
diff --git a/test/native/jest.config.js b/test/native/jest.config.js
index f4c49f33a68fed..18ccbb421ea7fe 100644
--- a/test/native/jest.config.js
+++ b/test/native/jest.config.js
@@ -30,7 +30,10 @@ module.exports = {
'/' + configPath + '/enzyme.config.js',
],
testEnvironment: 'jsdom',
- testMatch: [ '**/test/*.native.[jt]s?(x)' ],
+ testMatch: [
+ '**/test/*.native.[jt]s?(x)',
+ '/packages/react-native-*/**/?(*.)+(spec|test).[jt]s?(x)',
+ ],
testPathIgnorePatterns: [
'/node_modules/',
'/wordpress/',
@@ -50,6 +53,9 @@ module.exports = {
'|'
) })$` ]: '/packages/$1/src',
},
+ modulePathIgnorePatterns: [
+ '/packages/react-native-editor/node_modules',
+ ],
haste: {
defaultPlatform: rnPlatform,
platforms: [ 'android', 'ios', 'native' ],
diff --git a/test/native/jest_ui.config.js b/test/native/jest_ui.config.js
new file mode 100644
index 00000000000000..15855a1a261e0b
--- /dev/null
+++ b/test/native/jest_ui.config.js
@@ -0,0 +1,24 @@
+const defaultPlatform = 'android';
+const rnPlatform = process.env.TEST_RN_PLATFORM || defaultPlatform;
+if ( process.env.TEST_RN_PLATFORM ) {
+ // eslint-disable-next-line no-console
+ console.log( 'Setting RN platform to: ' + rnPlatform );
+} else {
+ // eslint-disable-next-line no-console
+ console.log( 'Setting RN platform to: default (' + defaultPlatform + ')' );
+}
+
+module.exports = {
+ verbose: true,
+ rootDir: '../../',
+ haste: {
+ defaultPlatform: rnPlatform,
+ platforms: [ 'android', 'ios', 'native' ],
+ },
+ transform: {
+ '^.+\\.(js|ts|tsx)$': 'babel-jest',
+ },
+ timers: 'real',
+ setupFiles: [],
+ testMatch: [ '**/__device-tests__/**/*.test.[jt]s?(x)' ],
+};
diff --git a/test/native/setup.js b/test/native/setup.js
index cb2070555d4bcd..fe5bfe7a05f33c 100644
--- a/test/native/setup.js
+++ b/test/native/setup.js
@@ -3,7 +3,15 @@
*/
import { NativeModules } from 'react-native';
-jest.mock( 'react-native-gutenberg-bridge', () => {
+jest.mock( '@wordpress/element', () => {
+ return {
+ __esModule: true,
+ ...jest.requireActual( '@wordpress/element' ),
+ render: jest.fn(),
+ };
+} );
+
+jest.mock( '@wordpress/react-native-bridge', () => {
return {
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
@@ -70,8 +78,6 @@ jest.mock( 'react-native-safe-area', () => {
};
} );
-jest.mock( 'react-native-recyclerview-list' );
-
jest.mock( '@react-native-community/slider', () => () => 'Slider', {
virtual: true,
} );
diff --git a/test/unit/jest.config.js b/test/unit/jest.config.js
index 0a2624d639015d..c5023a5944366a 100644
--- a/test/unit/jest.config.js
+++ b/test/unit/jest.config.js
@@ -30,6 +30,7 @@ module.exports = {
'/.*/build/',
'/.*/build-module/',
'/.+.native.js$',
+ '/packages/react-native-*',
],
transform: {
'^.+\\.[jt]sx?$': '/test/unit/scripts/babel-transformer.js',
diff --git a/tsconfig.base.json b/tsconfig.base.json
index afabdbaf82e30d..08e7a57fab1e39 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -5,6 +5,7 @@
"allowSyntheticDefaultImports": true,
"jsx": "preserve",
"target": "esnext",
+ "types": ["react", "node", "requestidlecallback"],
"module": "esnext",
"lib": [ "dom", "esnext" ],
"declaration": true,
@@ -40,6 +41,7 @@
"**/build-*/**",
"**/*.android.js",
"**/*.ios.js",
- "**/*.native.js"
+ "**/*.native.js",
+ "./packages/**/react-native-*/**"
]
}
diff --git a/webpack.config.js b/webpack.config.js
index 84c93c9f4cf661..ec7a7ed42b0bd2 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -35,7 +35,8 @@ const gutenbergPackages = Object.keys( dependencies )
.filter(
( packageName ) =>
! BUNDLED_PACKAGES.includes( packageName ) &&
- packageName.startsWith( WORDPRESS_NAMESPACE )
+ packageName.startsWith( WORDPRESS_NAMESPACE ) &&
+ ! packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' )
)
.map( ( packageName ) => packageName.replace( WORDPRESS_NAMESPACE, '' ) );