From cfa610399b48399d6f332dea0777fc37684f5a51 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Thu, 1 Feb 2024 11:54:12 +0100 Subject: [PATCH 01/10] Remove @react-native/gradle-plugin since it's included in the React Native package with support for AGP 8.2.1 --- package-lock.json | 12 ------------ packages/react-native-editor/package.json | 1 - 2 files changed, 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb12ab4fd70baf..9d9117f363777f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10601,11 +10601,6 @@ "node": ">=8" } }, - "node_modules/@react-native/gradle-plugin": { - "version": "0.72.11", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.72.11.tgz", - "integrity": "sha512-P9iRnxiR2w7EHcZ0mJ+fmbPzMby77ZzV6y9sJI3lVLJzF7TLSdbwcQyD3lwMsiL+q5lKUHoZJS4sYmih+P2HXw==" - }, "node_modules/@react-native/js-polyfills": { "version": "0.73.1", "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", @@ -56253,7 +56248,6 @@ "@react-native-community/blur": "4.2.0", "@react-native-community/slider": "https://raw.githubusercontent.com/wordpress-mobile/react-native-slider/v3.0.2-wp-4/react-native-community-slider-3.0.2-wp-4.tgz", "@react-native-masked-view/masked-view": "0.3.0", - "@react-native/gradle-plugin": "0.72.11", "@react-navigation/core": "5.12.0", "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", @@ -64183,11 +64177,6 @@ } } }, - "@react-native/gradle-plugin": { - "version": "0.72.11", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.72.11.tgz", - "integrity": "sha512-P9iRnxiR2w7EHcZ0mJ+fmbPzMby77ZzV6y9sJI3lVLJzF7TLSdbwcQyD3lwMsiL+q5lKUHoZJS4sYmih+P2HXw==" - }, "@react-native/js-polyfills": { "version": "0.73.1", "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", @@ -71612,7 +71601,6 @@ "@react-native-community/blur": "4.2.0", "@react-native-community/slider": "https://raw.githubusercontent.com/wordpress-mobile/react-native-slider/v3.0.2-wp-4/react-native-community-slider-3.0.2-wp-4.tgz", "@react-native-masked-view/masked-view": "0.3.0", - "@react-native/gradle-plugin": "0.72.11", "@react-navigation/core": "5.12.0", "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 48e3e9ddeced31..7e2d229e668b94 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -34,7 +34,6 @@ "@react-native-community/blur": "4.2.0", "@react-native-community/slider": "https://raw.githubusercontent.com/wordpress-mobile/react-native-slider/v3.0.2-wp-4/react-native-community-slider-3.0.2-wp-4.tgz", "@react-native-masked-view/masked-view": "0.3.0", - "@react-native/gradle-plugin": "0.72.11", "@react-navigation/core": "5.12.0", "@react-navigation/native": "6.0.14", "@react-navigation/routers": "5.4.9", From 2e2ec267abaeafeb732dd8721d87dbdaf966abb1 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Thu, 1 Feb 2024 11:57:07 +0100 Subject: [PATCH 02/10] Migrate java files to kotlin --- .../main/java/com/gutenberg/MainActivity.java | 233 ---------- .../main/java/com/gutenberg/MainActivity.kt | 207 +++++++++ .../java/com/gutenberg/MainApplication.java | 433 ------------------ .../java/com/gutenberg/MainApplication.kt | 309 +++++++++++++ 4 files changed, 516 insertions(+), 666 deletions(-) delete mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java create mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.kt delete mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java create mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.kt diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java deleted file mode 100644 index 3ea19fa97b3831..00000000000000 --- a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java +++ /dev/null @@ -1,233 +0,0 @@ -package com.gutenberg; - -import android.os.Bundle; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; - -import com.facebook.react.ReactActivity; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.ReactRootView; - -import org.json.JSONException; -import org.json.JSONObject; -import org.wordpress.mobile.WPAndroidGlue.GutenbergProps; - -import java.util.Locale; - -public class MainActivity extends ReactActivity { - private static MainActivity currentInstance; - - private ReactRootView mReactRootView; - private Menu mMenu; - - private static final String EXTRAS_INITIAL_PROPS = "initialProps"; - - private void openReactNativeDebugMenu() { - ReactInstanceManager devSettingsModule = getReactInstanceManager(); - if (devSettingsModule != null) { - devSettingsModule.showDevOptionsDialog(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - mMenu = menu; - getMenuInflater().inflate(R.menu.toolbar_menu, menu); - - // Set opacity for menu items - MenuItem undoItem = menu.findItem(R.id.menuUndo); - undoItem.getIcon().setAlpha(76); - undoItem.setEnabled(false); - - MenuItem redoItem = menu.findItem(R.id.menuRedo); - redoItem.getIcon().setAlpha(76); - redoItem.setEnabled(false); - return true; - } - - public void updateUndoItem(boolean isDisabled) { - if (mMenu != null) { - runOnUiThread(new Runnable() { - @Override - public void run() { - MenuItem undoItem = mMenu.findItem(R.id.menuUndo); - - undoItem.setEnabled(!isDisabled); - undoItem.getIcon().setAlpha(!isDisabled ? 255 : 76); - } - }); - } - } - - public void updateRedoItem(boolean isDisabled) { - if (mMenu != null) { - runOnUiThread(new Runnable() { - @Override - public void run() { - MenuItem redoItem = mMenu.findItem(R.id.menuRedo); - - redoItem.setEnabled(!isDisabled); - redoItem.getIcon().setAlpha(!isDisabled ? 255 : 76); - } - }); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - MainApplication mainApplication = (MainApplication) getApplication(); - - int itemId = item.getItemId(); - if (itemId == R.id.menuUndo) { - mainApplication.toggleUndo(); - return true; - } - if (itemId == R.id.menuRedo) { - mainApplication.toggleRedo(); - return true; - } - if (itemId == R.id.menuButton) { - openReactNativeDebugMenu(); - return true; - } - return super.onOptionsItemSelected(item); - } - - public static MainActivity getInstance() { - return currentInstance; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - currentInstance = this; - - // Create a LinearLayout that will hold both the toolbar and React Native content - LinearLayout linearLayout = new LinearLayout(this); - linearLayout.setOrientation(LinearLayout.VERTICAL); - linearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - linearLayout.setFocusable(false); - linearLayout.setFocusableInTouchMode(true); - - // Create a Toolbar instance - Toolbar toolbar = new Toolbar(this); - - // Set toolbar properties (you can customize this as you want) - toolbar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - - // Set the toolbar as the Activity's action bar - setSupportActionBar(toolbar); - - // Add the toolbar to the linear layout - linearLayout.addView(toolbar); - - // Create a View to be used as the border - View borderView = new View(this); - borderView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1)); - borderView.setBackgroundColor(ContextCompat.getColor(this, R.color.toolbarBorder)); - - // Add the border view to the linear layout - linearLayout.addView(borderView); - - // Create a ReactRootView and assign it to mReactRootView - mReactRootView = new ReactRootView(this); - LinearLayout.LayoutParams reactViewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1); - mReactRootView.setLayoutParams(reactViewParams); - - // Add ReactView to the linear layout - linearLayout.addView(mReactRootView); - - // Set the linear layout as the content view - setContentView(linearLayout); - - // Load the React application - mReactRootView.startReactApplication( - ((MainApplication) getApplication()).getReactNativeHost().getReactInstanceManager(), - getMainComponentName(), - getAppOptions() - ); - } - - /** - * Returns the name of the main component registered from JavaScript. - * This is used to schedule rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "gutenberg"; - } - - private Bundle getAppOptions() { - Bundle bundle = new Bundle(); - - // Parse initial props from launch arguments - String initialTitle = null; - String initialData = null; - String rawStyles = null; - String rawFeatures = null; - Bundle extrasBundle = getIntent().getExtras(); - - if(extrasBundle != null) { - String initialProps = extrasBundle.getString(EXTRAS_INITIAL_PROPS, "{}"); - try { - JSONObject jsonObject = new JSONObject(initialProps); - if (jsonObject.has(GutenbergProps.PROP_INITIAL_TITLE)) { - initialTitle = jsonObject.getString(GutenbergProps.PROP_INITIAL_TITLE); - } - if (jsonObject.has(GutenbergProps.PROP_INITIAL_DATA)) { - initialData = jsonObject.getString(GutenbergProps.PROP_INITIAL_DATA); - } - if (jsonObject.has(GutenbergProps.PROP_STYLES)) { - rawStyles = jsonObject.getString(GutenbergProps.PROP_STYLES); - } - if (jsonObject.has(GutenbergProps.PROP_FEATURES)) { - rawFeatures = jsonObject.getString(GutenbergProps.PROP_FEATURES); - } - } catch (final JSONException e) { - Log.e("MainActivity", "Json parsing error: " + e.getMessage()); - } - } - - // Add locale - String languageString = Locale.getDefault().toString(); - String localeSlug = languageString.replace("_", "-").toLowerCase(Locale.ENGLISH); - bundle.putString(GutenbergProps.PROP_LOCALE, localeSlug); - - // Add capabilities - Bundle capabilities = new Bundle(); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_MENTIONS, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_XPOSTS, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_UNSUPPORTED_BLOCK_EDITOR, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_REUSABLE_BLOCK, false); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_IS_AUDIO_BLOCK_MEDIA_UPLOAD_ENABLED, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_TILED_GALLERY_BLOCK, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_VIDEOPRESS_BLOCK, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_FACEBOOK_EMBED_BLOCK, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_INSTAGRAM_EMBED_BLOCK, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_LOOM_EMBED_BLOCK, true); - capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_SMARTFRAME_EMBED_BLOCK, true); - bundle.putBundle(GutenbergProps.PROP_CAPABILITIES, capabilities); - - if(initialTitle != null) { - bundle.putString(GutenbergProps.PROP_INITIAL_TITLE, initialTitle); - } - if(initialData != null) { - bundle.putString(GutenbergProps.PROP_INITIAL_DATA, initialData); - } - if(rawStyles != null) { - bundle.putString(GutenbergProps.PROP_STYLES, rawStyles); - } - if(rawFeatures != null) { - bundle.putString(GutenbergProps.PROP_FEATURES, rawFeatures); - } - - return bundle; - } -} diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.kt b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.kt new file mode 100644 index 00000000000000..29b047bf01f7d7 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.kt @@ -0,0 +1,207 @@ +package com.gutenberg + +import android.os.Bundle +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat +import com.facebook.react.ReactActivity +import com.facebook.react.ReactRootView +import org.json.JSONException +import org.json.JSONObject +import org.wordpress.mobile.WPAndroidGlue.GutenbergProps +import java.util.Locale + +class MainActivity : ReactActivity() { + private var mReactRootView: ReactRootView? = null + private var mMenu: Menu? = null + private fun openReactNativeDebugMenu() { + val devSettingsModule = reactInstanceManager + devSettingsModule?.showDevOptionsDialog() + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + mMenu = menu + menuInflater.inflate(R.menu.toolbar_menu, menu) + + // Set opacity for menu items + val undoItem = menu.findItem(R.id.menuUndo) + undoItem.icon!!.alpha = 76 + undoItem.setEnabled(false) + val redoItem = menu.findItem(R.id.menuRedo) + redoItem.icon!!.alpha = 76 + redoItem.setEnabled(false) + return true + } + + fun updateUndoItem(isDisabled: Boolean) { + if (mMenu != null) { + runOnUiThread { + val undoItem = mMenu!!.findItem(R.id.menuUndo) + undoItem.setEnabled(!isDisabled) + undoItem.icon!!.alpha = if (!isDisabled) 255 else 76 + } + } + } + + fun updateRedoItem(isDisabled: Boolean) { + if (mMenu != null) { + runOnUiThread { + val redoItem = mMenu!!.findItem(R.id.menuRedo) + redoItem.setEnabled(!isDisabled) + redoItem.icon!!.alpha = if (!isDisabled) 255 else 76 + } + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val mainApplication = application as MainApplication + val itemId = item.itemId + if (itemId == R.id.menuUndo) { + mainApplication.toggleUndo() + return true + } + if (itemId == R.id.menuRedo) { + mainApplication.toggleRedo() + return true + } + if (itemId == R.id.menuButton) { + openReactNativeDebugMenu() + return true + } + return super.onOptionsItemSelected(item) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + instance = this + + // Create a LinearLayout that will hold both the toolbar and React Native content + val linearLayout = LinearLayout(this) + linearLayout.orientation = LinearLayout.VERTICAL + linearLayout.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + linearLayout.isFocusable = false + linearLayout.isFocusableInTouchMode = true + + // Create a Toolbar instance + val toolbar = Toolbar(this) + + // Set toolbar properties (you can customize this as you want) + toolbar.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + + // Set the toolbar as the Activity's action bar + setSupportActionBar(toolbar) + + // Add the toolbar to the linear layout + linearLayout.addView(toolbar) + + // Create a View to be used as the border + val borderView = View(this) + borderView.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1) + borderView.setBackgroundColor(ContextCompat.getColor(this, R.color.toolbarBorder)) + + // Add the border view to the linear layout + linearLayout.addView(borderView) + + // Create a ReactRootView and assign it to mReactRootView + mReactRootView = ReactRootView(this) + val reactViewParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f) + mReactRootView!!.layoutParams = reactViewParams + + // Add ReactView to the linear layout + linearLayout.addView(mReactRootView) + + // Set the linear layout as the content view + setContentView(linearLayout) + + // Load the React application + mReactRootView!!.startReactApplication( + (application as MainApplication).reactNativeHost.reactInstanceManager, + mainComponentName, + appOptions + ) + } + + /** + * Returns the name of the main component registered from JavaScript. + * This is used to schedule rendering of the component. + */ + override fun getMainComponentName(): String { + return "gutenberg" + } + + private val appOptions: Bundle + get() { + val bundle = Bundle() + + // Parse initial props from launch arguments + var initialTitle: String? = null + var initialData: String? = null + var rawStyles: String? = null + var rawFeatures: String? = null + val extrasBundle = intent.extras + if (extrasBundle != null) { + val initialProps = extrasBundle.getString(EXTRAS_INITIAL_PROPS, "{}") + try { + val jsonObject = JSONObject(initialProps) + if (jsonObject.has(GutenbergProps.PROP_INITIAL_TITLE)) { + initialTitle = jsonObject.getString(GutenbergProps.PROP_INITIAL_TITLE) + } + if (jsonObject.has(GutenbergProps.PROP_INITIAL_DATA)) { + initialData = jsonObject.getString(GutenbergProps.PROP_INITIAL_DATA) + } + if (jsonObject.has(GutenbergProps.PROP_STYLES)) { + rawStyles = jsonObject.getString(GutenbergProps.PROP_STYLES) + } + if (jsonObject.has(GutenbergProps.PROP_FEATURES)) { + rawFeatures = jsonObject.getString(GutenbergProps.PROP_FEATURES) + } + } catch (e: JSONException) { + Log.e("MainActivity", "Json parsing error: " + e.message) + } + } + + // Add locale + val languageString = Locale.getDefault().toString() + val localeSlug = languageString.replace("_", "-").lowercase() + bundle.putString(GutenbergProps.PROP_LOCALE, localeSlug) + + // Add capabilities + val capabilities = Bundle() + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_MENTIONS, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_XPOSTS, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_UNSUPPORTED_BLOCK_EDITOR, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_REUSABLE_BLOCK, false) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_IS_AUDIO_BLOCK_MEDIA_UPLOAD_ENABLED, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_TILED_GALLERY_BLOCK, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_VIDEOPRESS_BLOCK, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_FACEBOOK_EMBED_BLOCK, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_INSTAGRAM_EMBED_BLOCK, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_LOOM_EMBED_BLOCK, true) + capabilities.putBoolean(GutenbergProps.PROP_CAPABILITIES_SMARTFRAME_EMBED_BLOCK, true) + bundle.putBundle(GutenbergProps.PROP_CAPABILITIES, capabilities) + if (initialTitle != null) { + bundle.putString(GutenbergProps.PROP_INITIAL_TITLE, initialTitle) + } + if (initialData != null) { + bundle.putString(GutenbergProps.PROP_INITIAL_DATA, initialData) + } + if (rawStyles != null) { + bundle.putString(GutenbergProps.PROP_STYLES, rawStyles) + } + if (rawFeatures != null) { + bundle.putString(GutenbergProps.PROP_FEATURES, rawFeatures) + } + return bundle + } + + companion object { + var instance: MainActivity? = null + private set + private const val EXTRAS_INITIAL_PROPS = "initialProps" + } +} diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java deleted file mode 100644 index 4477f1cc1d9f35..00000000000000 --- a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java +++ /dev/null @@ -1,433 +0,0 @@ -package com.gutenberg; - -import android.app.Application; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Bundle; -import android.util.Log; -import android.widget.Toast; - -import androidx.core.util.Consumer; - -import com.facebook.react.ReactApplication; -import com.BV.LinearGradient.LinearGradientPackage; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableNativeMap; -import com.reactnativecommunity.clipboard.ClipboardPackage; -import com.reactnativecommunity.slider.ReactSliderPackage; -import com.brentvatne.react.ReactVideoPackage; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.devsupport.interfaces.DevOptionHandler; -import com.facebook.react.devsupport.interfaces.DevSupportManager; -import com.horcrux.svg.SvgPackage; -import org.linusu.RNGetRandomValuesPackage; -import com.dylanvann.fastimage.FastImageViewPackage; - -import org.wordpress.mobile.ReactNativeAztec.ReactAztecPackage; -import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeInterface; -import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent; -import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergWebViewActivity; -import org.wordpress.mobile.ReactNativeGutenbergBridge.RNMedia; -import org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgePackage; - -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; -import com.facebook.react.defaults.DefaultReactNativeHost; -import com.facebook.react.shell.MainReactPackage; -import com.facebook.soloader.SoLoader; -import com.reactnativecommunity.webview.RNCWebViewPackage; -import com.swmansion.gesturehandler.RNGestureHandlerPackage; -import com.swmansion.reanimated.ReanimatedPackage; -import com.swmansion.rnscreens.RNScreensPackage; -import com.th3rdwave.safeareacontext.SafeAreaContextPackage; -import org.reactnative.maskedview.RNCMaskedViewPackage; -import org.wordpress.mobile.WPAndroidGlue.Media; -import org.wordpress.mobile.WPAndroidGlue.MediaOption; - -import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; -import java.util.List; -import java.util.ArrayList; - -public class MainApplication extends Application implements ReactApplication, GutenbergBridgeInterface { - - private static final String TAG = "MainApplication"; - - private ReactNativeHost mReactNativeHost; - private RNReactNativeGutenbergBridgePackage mRnReactNativeGutenbergBridgePackage; - private GutenbergBridgeJS2Parent.ReplaceUnsupportedBlockCallback mReplaceUnsupportedBlockCallback; - - private ReactNativeHost createReactNativeHost() { - mRnReactNativeGutenbergBridgePackage = new RNReactNativeGutenbergBridgePackage(new GutenbergBridgeJS2Parent() { - @Override - public void responseHtml(String title, String html, boolean changed, ReadableMap contentInfo) { - } - - @Override - public void requestMediaImport(String url, MediaSelectedCallback mediaSelectedCallback) { - } - - @Override - public void requestMediaPickerFromDeviceCamera(MediaSelectedCallback mediaSelectedCallback, MediaType mediaType) { - } - - @Override - public void requestMediaPickFromDeviceLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) { - } - - @Override - public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) { - List rnMediaList = new ArrayList<>(); - WritableNativeMap emptyMetadata = new WritableNativeMap(); - - switch (mediaType) { - case IMAGE: - Media image = new Media(1, "https://cldup.com/cXyG__fTLN.jpg", "image", "Mountain", "", "A snow-capped mountain top in a cloudy sky with red-leafed trees in the foreground", emptyMetadata); - rnMediaList.add(image); - break; - case VIDEO: - WritableNativeMap metadata = new WritableNativeMap(); - metadata.putString("extraID", "AbCdE"); - Media video = new Media(2, "https://i.cloudup.com/YtZFJbuQCE.mov", "video", "Cloudup", "", "", metadata); - rnMediaList.add(video); - break; - case ANY: - case OTHER: - Media other = new Media(3, "https://wordpress.org/latest.zip", "zip", "WordPress latest version", "WordPress.zip", "", emptyMetadata); - rnMediaList.add(other); - break; - case AUDIO: - Media audio = new Media(5, "https://cldup.com/59IrU0WJtq.mp3", "audio", "Summer presto", "", "", emptyMetadata); - rnMediaList.add(audio); - break; - } - mediaSelectedCallback.onMediaFileSelected(rnMediaList); - } - - - @Override - public void mediaUploadSync(MediaSelectedCallback mediaSelectedCallback) { - } - - @Override - public void mediaSaveSync(MediaSelectedCallback mediaSelectedCallback) { - } - - @Override - public void requestImageFailedRetryDialog(int mediaId) { - } - - @Override - public void requestImageUploadCancelDialog(int mediaId) { - } - - @Override - public void requestImageUploadCancel(int mediaId) { - } - - @Override - public void setFeaturedImage(int mediaId) { - } - - @Override - public void editorDidMount(ReadableArray unsupportedBlockNames) { - } - - @Override - public void editorDidAutosave() { - } - - @Override - public void getOtherMediaPickerOptions(OtherMediaOptionsReceivedCallback otherMediaOptionsReceivedCallback, MediaType mediaType) { - if (mediaType == MediaType.ANY) { - ArrayList mediaOptions = new ArrayList<>(); - mediaOptions.add(new MediaOption("1", "Choose from device")); - otherMediaOptionsReceivedCallback.onOtherMediaOptionsReceived(mediaOptions); - } - } - - @Override - public void requestMediaPickFrom(String mediaSource, MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection) { - if (mediaSource.equals("1")) { - List rnMediaList = new ArrayList<>(); - Media pdf = new Media(1, "https://grad.illinois.edu/sites/default/files/pdfs/cvsamples.pdf", "other", "","cvsamples.pdf", "", new WritableNativeMap()); - rnMediaList.add(pdf); - mediaSelectedCallback.onMediaFileSelected(rnMediaList); - } - } - - @Override - public void requestImageFullscreenPreview(String mediaUrl) { - - } - - @Override - public void requestEmbedFullscreenPreview(String content, String title) { - - } - - @Override - public void requestMediaEditor(MediaSelectedCallback mediaSelectedCallback, String mediaUrl) { - - } - - @Override - public void setFocalPointPickerTooltipShown(boolean tooltipShown) { - } - - @Override - public void requestFocalPointPickerTooltipShown(FocalPointPickerTooltipShownCallback focalPointPickerTooltipShownCallback) { - focalPointPickerTooltipShownCallback.onRequestFocalPointPickerTooltipShown(false); - } - - @Override - public void editorDidEmitLog(String message, LogLevel logLevel) { - switch (logLevel) { - case TRACE: - Log.d(TAG, message); - break; - case INFO: - Log.i(TAG, message); - break; - case WARN: - Log.w(TAG, message); - break; - case ERROR: - Log.e(TAG, message); - break; - } - } - - @Override - public void performGetRequest(String path, boolean enableCaching, Consumer onSuccess, Consumer onError) {} - - @Override - public void performPostRequest(String path, ReadableMap data, Consumer onSuccess, Consumer onError) {} - - @Override - public void gutenbergDidRequestUnsupportedBlockFallback(ReplaceUnsupportedBlockCallback replaceUnsupportedBlockCallback, - String content, - String blockId, - String blockName, - String blockTitle) { - mReplaceUnsupportedBlockCallback = replaceUnsupportedBlockCallback; - openGutenbergWebView(content, blockId, blockTitle); - } - - @Override - public void onShowUserSuggestions(Consumer onResult) { - onResult.accept("matt"); - } - - @Override - public void onShowXpostSuggestions(Consumer onResult) { - onResult.accept("ma.tt"); - } - - @Override - public void requestMediaFilesEditorLoad( - ReadableArray mediaFiles, - String blockId - ) { - Toast.makeText(MainApplication.this, "requestMediaFilesEditorLoad called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void requestMediaFilesFailedRetryDialog(ReadableArray mediaFiles) { - Toast.makeText(MainApplication.this, "requestMediaFilesFailedRetryDialog called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void requestMediaFilesUploadCancelDialog(ReadableArray mediaFiles) { - Toast.makeText(MainApplication.this, "requestMediaFilesUploadCancelDialog called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void requestMediaFilesSaveCancelDialog(ReadableArray mediaFiles) { - Toast.makeText(MainApplication.this, "requestMediaFilesSaveCancelDialog called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void mediaFilesBlockReplaceSync( - ReadableArray mediaFiles, - String blockId - ) { - Toast.makeText(MainApplication.this, "mediaFilesBlockReplaceSync called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void gutenbergDidSendButtonPressedAction(String buttonType) { - - } - - @Override - public void requestPreview() { - Toast.makeText(MainApplication.this, "requestPreview called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void requestBlockTypeImpressions(BlockTypeImpressionsCallback blockTypeImpressionsCallback) { - ReadableMap impressions = Arguments.createMap(); - blockTypeImpressionsCallback.onRequestBlockTypeImpressions(impressions); - } - - @Override - public void setBlockTypeImpressions(ReadableMap impressions) { - Log.d("BlockTypeImpressions", String.format("Gutenberg requested setting block type impression to %s.", impressions)); - } - - @Override - public void requestContactCustomerSupport() { - Toast.makeText(MainApplication.this, "requestContactCustomerSupport called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void requestGotoCustomerSupportOptions() { - Toast.makeText(MainApplication.this, "requestGotoCustomerSupportOptions called", Toast.LENGTH_SHORT).show(); - } - - @Override - public void sendEventToHost(final String eventName, final ReadableMap properties) { - Log.d("SendEventToHost", String.format("Gutenberg requested sending '%s' event to host with properties: %s", eventName, properties)); - } - - @Override - public void toggleUndoButton(boolean isDisabled) { - MainActivity mainActivity = MainActivity.getInstance(); - if (mainActivity != null) { - mainActivity.updateUndoItem(isDisabled); - } - } - - @Override - public void toggleRedoButton(boolean isDisabled) { - MainActivity mainActivity = MainActivity.getInstance(); - if (mainActivity != null) { - mainActivity.updateRedoItem(isDisabled); - } - } - - @Override - public void requestConnectionStatus(ConnectionStatusCallback connectionStatusCallback) { - connectionStatusCallback.onRequestConnectionStatus(true); - } - }, isDarkMode()); - - return new DefaultReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List 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(), - new RNCMaskedViewPackage(), - new RNGestureHandlerPackage(), - new ReanimatedPackage(), - new SafeAreaContextPackage(), - new RNScreensPackage(), - new RNCWebViewPackage(), - new ClipboardPackage(), - new FastImageViewPackage(), - mRnReactNativeGutenbergBridgePackage); - } - - @Override - protected String getJSMainModuleName() { - return "index"; - } - - @Override - protected boolean isNewArchEnabled() { - return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - } - @Override - protected Boolean isHermesEnabled() { - return BuildConfig.IS_HERMES_ENABLED; - } - }; - } - - private boolean isDarkMode() { - Configuration configuration = getResources().getConfiguration(); - int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK; - - return currentNightMode == Configuration.UI_MODE_NIGHT_YES; - } - - public void toggleUndo() { - mRnReactNativeGutenbergBridgePackage.getRNReactNativeGutenbergBridgeModule().onUndoPressed(); - } - - public void toggleRedo() { - mRnReactNativeGutenbergBridgePackage.getRNReactNativeGutenbergBridgeModule().onRedoPressed(); - } - - 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); - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - // If you opted-in for the New Architecture, we load the native entry point for this app. - DefaultNewArchitectureEntryPoint.load(); - } - ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - } - - private void createCustomDevOptions(ReactNativeHost reactNativeHost) { - DevSupportManager devSupportManager = reactNativeHost.getReactInstanceManager().getDevSupportManager(); - - devSupportManager.addCustomDevOption("Show html", new DevOptionHandler() { - @Override - public void onOptionSelected() { - mRnReactNativeGutenbergBridgePackage.getRNReactNativeGutenbergBridgeModule().toggleEditorMode(); - } - }); - - devSupportManager.addCustomDevOption("Help", new DevOptionHandler() { - @Override - public void onOptionSelected() { - mRnReactNativeGutenbergBridgePackage.getRNReactNativeGutenbergBridgeModule().showEditorHelp(); - } - }); - } - - @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/java/com/gutenberg/MainApplication.kt b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.kt new file mode 100644 index 00000000000000..f1a86917b23867 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.kt @@ -0,0 +1,309 @@ +package com.gutenberg + +import android.app.Application +import android.content.Intent +import android.content.res.Configuration +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.core.util.Consumer +import com.BV.LinearGradient.LinearGradientPackage +import com.brentvatne.react.ReactVideoPackage +import com.dylanvann.fastimage.FastImageViewPackage +import com.facebook.react.ReactApplication +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.PackageList +import com.facebook.react.ReactHost +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.ReadableArray +import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeMap +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader +import com.horcrux.svg.SvgPackage +import com.reactnativecommunity.clipboard.ClipboardPackage +import com.reactnativecommunity.slider.ReactSliderPackage +import com.reactnativecommunity.webview.RNCWebViewPackage +import com.swmansion.gesturehandler.RNGestureHandlerPackage +import com.swmansion.reanimated.ReanimatedPackage +import com.swmansion.rnscreens.RNScreensPackage +import com.th3rdwave.safeareacontext.SafeAreaContextPackage +import org.linusu.RNGetRandomValuesPackage +import org.reactnative.maskedview.RNCMaskedViewPackage +import org.wordpress.mobile.ReactNativeAztec.ReactAztecPackage +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeInterface +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.BlockTypeImpressionsCallback +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.ConnectionStatusCallback +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.FocalPointPickerTooltipShownCallback +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaSelectedCallback +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.OtherMediaOptionsReceivedCallback +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.ReplaceUnsupportedBlockCallback +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergWebViewActivity +import org.wordpress.mobile.ReactNativeGutenbergBridge.RNMedia +import org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgePackage +import org.wordpress.mobile.WPAndroidGlue.Media +import org.wordpress.mobile.WPAndroidGlue.MediaOption + +class MainApplication : Application(), ReactApplication, GutenbergBridgeInterface { + private var mRnReactNativeGutenbergBridgePackage: RNReactNativeGutenbergBridgePackage? = null + private var mReplaceUnsupportedBlockCallback: ReplaceUnsupportedBlockCallback? = null + + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + add(ReactSliderPackage()) + add(ReactVideoPackage()) + add(SvgPackage()) // passing null because we do not need log handlers in the demo ap)p + add(ReactAztecPackage(null, null)) + add(LinearGradientPackage()) + add(RNGetRandomValuesPackage()) + add(RNCMaskedViewPackage()) + add(RNGestureHandlerPackage()) + add(ReanimatedPackage()) + add(SafeAreaContextPackage()) + add(RNScreensPackage()) + add(RNCWebViewPackage()) + add(ClipboardPackage()) + add(FastImageViewPackage()) + add(mRnReactNativeGutenbergBridgePackage) + } + + override fun getJSMainModuleName(): String { + return "index" + } + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + private fun initializeGutenbergBridge() { + mRnReactNativeGutenbergBridgePackage = RNReactNativeGutenbergBridgePackage(object : GutenbergBridgeJS2Parent { + override fun responseHtml(title: String, html: String, changed: Boolean, contentInfo: ReadableMap) {} + override fun requestMediaImport(url: String, mediaSelectedCallback: MediaSelectedCallback) {} + override fun requestMediaPickerFromDeviceCamera(mediaSelectedCallback: MediaSelectedCallback, mediaType: GutenbergBridgeJS2Parent.MediaType) {} + override fun requestMediaPickFromDeviceLibrary(mediaSelectedCallback: MediaSelectedCallback, allowMultipleSelection: Boolean, mediaType: GutenbergBridgeJS2Parent.MediaType) {} + override fun requestMediaPickFromMediaLibrary(mediaSelectedCallback: MediaSelectedCallback, allowMultipleSelection: Boolean, mediaType: GutenbergBridgeJS2Parent.MediaType) { + val rnMediaList: MutableList = ArrayList() + val emptyMetadata = WritableNativeMap() + when (mediaType) { + GutenbergBridgeJS2Parent.MediaType.IMAGE -> { + val image = Media(1, "https://cldup.com/cXyG__fTLN.jpg", "image", "Mountain", "", "A snow-capped mountain top in a cloudy sky with red-leafed trees in the foreground", emptyMetadata) + rnMediaList.add(image) + } + + GutenbergBridgeJS2Parent.MediaType.VIDEO -> { + val metadata = WritableNativeMap() + metadata.putString("extraID", "AbCdE") + val video = Media(2, "https://i.cloudup.com/YtZFJbuQCE.mov", "video", "Cloudup", "", "", metadata) + rnMediaList.add(video) + } + + GutenbergBridgeJS2Parent.MediaType.ANY, GutenbergBridgeJS2Parent.MediaType.OTHER -> { + val other = Media(3, "https://wordpress.org/latest.zip", "zip", "WordPress latest version", "WordPress.zip", "", emptyMetadata) + rnMediaList.add(other) + } + + GutenbergBridgeJS2Parent.MediaType.AUDIO -> { + val audio = Media(5, "https://cldup.com/59IrU0WJtq.mp3", "audio", "Summer presto", "", "", emptyMetadata) + rnMediaList.add(audio) + } + + else -> {} + } + mediaSelectedCallback.onMediaFileSelected(rnMediaList) + } + + override fun mediaUploadSync(mediaSelectedCallback: MediaSelectedCallback) {} + override fun mediaSaveSync(mediaSelectedCallback: MediaSelectedCallback) {} + override fun requestImageFailedRetryDialog(mediaId: Int) {} + override fun requestImageUploadCancelDialog(mediaId: Int) {} + override fun requestImageUploadCancel(mediaId: Int) {} + override fun setFeaturedImage(mediaId: Int) {} + override fun editorDidMount(unsupportedBlockNames: ReadableArray) {} + override fun editorDidAutosave() {} + override fun getOtherMediaPickerOptions(otherMediaOptionsReceivedCallback: OtherMediaOptionsReceivedCallback, mediaType: GutenbergBridgeJS2Parent.MediaType) { + if (mediaType == GutenbergBridgeJS2Parent.MediaType.ANY) { + val mediaOptions = ArrayList() + mediaOptions.add(MediaOption("1", "Choose from device")) + otherMediaOptionsReceivedCallback.onOtherMediaOptionsReceived(mediaOptions) + } + } + + override fun requestMediaPickFrom(mediaSource: String, mediaSelectedCallback: MediaSelectedCallback, allowMultipleSelection: Boolean) { + if (mediaSource == "1") { + val rnMediaList: MutableList = ArrayList() + val pdf = Media(1, "https://grad.illinois.edu/sites/default/files/pdfs/cvsamples.pdf", "other", "", "cvsamples.pdf", "", WritableNativeMap()) + rnMediaList.add(pdf) + mediaSelectedCallback.onMediaFileSelected(rnMediaList) + } + } + + override fun requestImageFullscreenPreview(mediaUrl: String) {} + override fun requestEmbedFullscreenPreview(content: String, title: String) {} + override fun requestMediaEditor(mediaSelectedCallback: MediaSelectedCallback, mediaUrl: String) {} + override fun setFocalPointPickerTooltipShown(tooltipShown: Boolean) {} + override fun requestFocalPointPickerTooltipShown(focalPointPickerTooltipShownCallback: FocalPointPickerTooltipShownCallback) { + focalPointPickerTooltipShownCallback.onRequestFocalPointPickerTooltipShown(false) + } + + override fun editorDidEmitLog(message: String, logLevel: GutenbergBridgeJS2Parent.LogLevel) { + when (logLevel) { + GutenbergBridgeJS2Parent.LogLevel.TRACE -> Log.d(TAG, message) + GutenbergBridgeJS2Parent.LogLevel.INFO -> Log.i(TAG, message) + GutenbergBridgeJS2Parent.LogLevel.WARN -> Log.w(TAG, message) + GutenbergBridgeJS2Parent.LogLevel.ERROR -> Log.e(TAG, message) + } + } + + override fun performGetRequest(path: String, enableCaching: Boolean, onSuccess: Consumer, onError: Consumer) {} + override fun performPostRequest(path: String, data: ReadableMap, onSuccess: Consumer, onError: Consumer) {} + override fun gutenbergDidRequestUnsupportedBlockFallback(replaceUnsupportedBlockCallback: ReplaceUnsupportedBlockCallback, + content: String, + blockId: String, + blockName: String, + blockTitle: String) { + mReplaceUnsupportedBlockCallback = replaceUnsupportedBlockCallback + openGutenbergWebView(content, blockId, blockTitle) + } + + override fun onShowUserSuggestions(onResult: Consumer) { + onResult.accept("matt") + } + + override fun onShowXpostSuggestions(onResult: Consumer) { + onResult.accept("ma.tt") + } + + override fun requestMediaFilesEditorLoad( + mediaFiles: ReadableArray, + blockId: String + ) { + Toast.makeText(this@MainApplication, "requestMediaFilesEditorLoad called", Toast.LENGTH_SHORT).show() + } + + override fun requestMediaFilesFailedRetryDialog(mediaFiles: ReadableArray) { + Toast.makeText(this@MainApplication, "requestMediaFilesFailedRetryDialog called", Toast.LENGTH_SHORT).show() + } + + override fun requestMediaFilesUploadCancelDialog(mediaFiles: ReadableArray) { + Toast.makeText(this@MainApplication, "requestMediaFilesUploadCancelDialog called", Toast.LENGTH_SHORT).show() + } + + override fun requestMediaFilesSaveCancelDialog(mediaFiles: ReadableArray) { + Toast.makeText(this@MainApplication, "requestMediaFilesSaveCancelDialog called", Toast.LENGTH_SHORT).show() + } + + override fun mediaFilesBlockReplaceSync( + mediaFiles: ReadableArray, + blockId: String + ) { + Toast.makeText(this@MainApplication, "mediaFilesBlockReplaceSync called", Toast.LENGTH_SHORT).show() + } + + override fun gutenbergDidSendButtonPressedAction(buttonType: String) {} + override fun requestPreview() { + Toast.makeText(this@MainApplication, "requestPreview called", Toast.LENGTH_SHORT).show() + } + + override fun requestBlockTypeImpressions(blockTypeImpressionsCallback: BlockTypeImpressionsCallback) { + val impressions: ReadableMap = Arguments.createMap() + blockTypeImpressionsCallback.onRequestBlockTypeImpressions(impressions) + } + + override fun setBlockTypeImpressions(impressions: ReadableMap) { + Log.d("BlockTypeImpressions", String.format("Gutenberg requested setting block type impression to %s.", impressions)) + } + + override fun requestContactCustomerSupport() { + Toast.makeText(this@MainApplication, "requestContactCustomerSupport called", Toast.LENGTH_SHORT).show() + } + + override fun requestGotoCustomerSupportOptions() { + Toast.makeText(this@MainApplication, "requestGotoCustomerSupportOptions called", Toast.LENGTH_SHORT).show() + } + + override fun sendEventToHost(eventName: String, properties: ReadableMap) { + Log.d("SendEventToHost", String.format("Gutenberg requested sending '%s' event to host with properties: %s", eventName, properties)) + } + + override fun toggleUndoButton(isDisabled: Boolean) { + MainActivity.instance?.updateUndoItem(isDisabled) + } + + override fun toggleRedoButton(isDisabled: Boolean) { + MainActivity.instance?.updateRedoItem(isDisabled) + } + + override fun requestConnectionStatus(connectionStatusCallback: ConnectionStatusCallback) { + connectionStatusCallback.onRequestConnectionStatus(true) + } + }, isDarkMode) + } + + private val isDarkMode: Boolean + get() { + val configuration = resources.configuration + val currentNightMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK + return currentNightMode == Configuration.UI_MODE_NIGHT_YES + } + + fun toggleUndo() { + mRnReactNativeGutenbergBridgePackage!!.rnReactNativeGutenbergBridgeModule.onUndoPressed() + } + + fun toggleRedo() { + mRnReactNativeGutenbergBridgePackage!!.rnReactNativeGutenbergBridgeModule.onRedoPressed() + } + + private fun openGutenbergWebView(content: String, + blockId: String, + blockName: String) { + val intent = Intent(this, GutenbergWebViewActivity::class.java) + 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 val reactHost: ReactHost + get() = DefaultReactHost.getDefaultReactHost(this.applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, /* native exopackage */false) + + initializeGutenbergBridge() + + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + createCustomDevOptions(reactNativeHost) + } + + private fun createCustomDevOptions(reactNativeHost: ReactNativeHost?) { + val devSupportManager = reactNativeHost!!.reactInstanceManager.devSupportManager + devSupportManager.addCustomDevOption("Show html") { mRnReactNativeGutenbergBridgePackage!!.rnReactNativeGutenbergBridgeModule.toggleEditorMode() } + devSupportManager.addCustomDevOption("Help") { mRnReactNativeGutenbergBridgePackage!!.rnReactNativeGutenbergBridgeModule.showEditorHelp() } + } + + override fun saveContent(content: String, blockId: String) { + if (mReplaceUnsupportedBlockCallback != null) { + mReplaceUnsupportedBlockCallback!!.replaceUnsupportedBlock(content, blockId) + } + } + + companion object { + private const val TAG = "MainApplication" + } +} From 63bf83bfce60bd15c9959b56acbf6ea274884798 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Thu, 1 Feb 2024 11:57:49 +0100 Subject: [PATCH 03/10] Update build and gradle files --- .../react-native-aztec/android/build.gradle | 4 +- .../android/settings.gradle | 4 +- .../android/react-native-bridge/build.gradle | 6 +- .../android/settings.gradle | 4 +- .../android/app/build.gradle | 64 +++---------------- .../react-native-editor/android/build.gradle | 13 ++-- .../android/gradle.properties | 7 +- packages/react-native-editor/android/gradlew | 5 +- .../react-native-editor/android/gradlew.bat | 2 +- 9 files changed, 35 insertions(+), 74 deletions(-) diff --git a/packages/react-native-aztec/android/build.gradle b/packages/react-native-aztec/android/build.gradle index 6c1f4e5b02cce3..d1aa9fd77c91f8 100644 --- a/packages/react-native-aztec/android/build.gradle +++ b/packages/react-native-aztec/android/build.gradle @@ -57,8 +57,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } sourceSets { diff --git a/packages/react-native-aztec/android/settings.gradle b/packages/react-native-aztec/android/settings.gradle index 11cf7c1990544b..d0fdc88443ff71 100644 --- a/packages/react-native-aztec/android/settings.gradle +++ b/packages/react-native-aztec/android/settings.gradle @@ -1,6 +1,6 @@ pluginManagement { - gradle.ext.kotlinVersion = '1.6.10' - gradle.ext.agpVersion = '8.1.0' + gradle.ext.kotlinVersion = '1.8.0' + gradle.ext.agpVersion = '8.1.1' gradle.ext.automatticPublishToS3Version = '0.8.0' plugins { diff --git a/packages/react-native-bridge/android/react-native-bridge/build.gradle b/packages/react-native-bridge/android/react-native-bridge/build.gradle index c54e73b9a4b6a1..8f3fcd35a95ab6 100644 --- a/packages/react-native-bridge/android/react-native-bridge/build.gradle +++ b/packages/react-native-bridge/android/react-native-bridge/build.gradle @@ -48,8 +48,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } sourceSets { @@ -93,7 +93,7 @@ dependencies { // Published by `wordpress-mobile/react-native-libraries-publisher` // See the documentation for this value in `build.gradle.kts` of `wordpress-mobile/react-native-libraries-publisher` - def reactNativeLibrariesPublisherVersion = "v4" + def reactNativeLibrariesPublisherVersion = "v5" def reactNativeLibrariesGroupId = "org.wordpress.react-native-libraries.$reactNativeLibrariesPublisherVersion" implementation "$reactNativeLibrariesGroupId:react-native-get-random-values:${extractPackageVersion(packageJson, 'react-native-get-random-values', 'dependencies')}" implementation "$reactNativeLibrariesGroupId:react-native-safe-area-context:${extractPackageVersion(packageJson, 'react-native-safe-area-context', 'dependencies')}" diff --git a/packages/react-native-bridge/android/settings.gradle b/packages/react-native-bridge/android/settings.gradle index 32d592f7176160..0653b9c4ab64f2 100644 --- a/packages/react-native-bridge/android/settings.gradle +++ b/packages/react-native-bridge/android/settings.gradle @@ -1,6 +1,6 @@ pluginManagement { - gradle.ext.kotlinVersion = '1.6.10' - gradle.ext.agpVersion = '8.1.0' + gradle.ext.kotlinVersion = '1.8.0' + gradle.ext.agpVersion = '8.1.1' gradle.ext.automatticPublishToS3Version = '0.8.0' plugins { diff --git a/packages/react-native-editor/android/app/build.gradle b/packages/react-native-editor/android/app/build.gradle index 514c645354232d..6f2ed72318b13e 100644 --- a/packages/react-native-editor/android/app/build.gradle +++ b/packages/react-native-editor/android/app/build.gradle @@ -1,17 +1,16 @@ apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" apply from: "../../../react-native-bridge/android/extractPackageVersion.gradle" -import com.android.build.OutputFile - react { /* Folders */ // The root of your project, i.e. where "package.json" lives. Default is '..' root = file("../../../../") // The folder where the react-native NPM package is. Default is ../node_modules/react-native // reactNativeDir = file("../../../../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen - // codegenDir = file("../node_modules/react-native-codegen") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js // cliFile = file("../node_modules/react-native/cli.js") /* Variants */ @@ -46,29 +45,11 @@ react { // hermesFlags = ["-O", "-output-source-map"] } -/** - * Set this to true to create four separate APKs instead of one, - * one for each native architecture. This is useful if you don't - * use App Bundles (https://developer.android.com/guide/app-bundle/) - * and want to have separate APKs to upload to the Play Store. - */ -def enableSeparateBuildPerCPUArchitecture = false - /** * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ def enableProguardInReleaseBuilds = false -/** - * Private function to get the list of Native Architectures you want to build. - * This reads the value from reactNativeArchitectures in your gradle.properties - * file and works together with the --active-arch-only flag of react-native run-android. - */ -def reactNativeArchitectures() { - def value = project.getProperties().get("reactNativeArchitectures") - return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] -} - android { // IMPORTANT: Any updates to the namespace should be reflected in // the `package` attribute of the main `AndroidManifest.xml` file. @@ -76,11 +57,12 @@ android { namespace "com.gutenberg" ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion compileSdkVersion rootProject.ext.compileSdkVersion compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } buildFeatures { @@ -95,34 +77,12 @@ android { versionName "1.0" } - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include (*reactNativeArchitectures()) - } - } buildTypes { release { minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. - def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - defaultConfig.versionCode * 1000 + versionCodes.get(abi) - } - } - } packagingOptions { pickFirst 'META-INF/-no-jdk.kotlin_module' @@ -135,17 +95,17 @@ dependencies { implementation "org.wordpress.gutenberg-mobile:react-native-bridge" implementation 'androidx.appcompat:appcompat:1.2.0' implementation "com.google.android.material:material:1.9.0" + implementation "androidx.core:core-ktx:1.10.0" // The version of react-native is set by the React Native Gradle Plugin implementation "com.facebook.react:react-android" - - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + implementation("com.facebook.react:flipper-integration") implementation "com.github.wordpress-mobile:react-native-video:${extractPackageVersion(packageJson, 'react-native-video', 'dependencies')}" implementation "com.github.wordpress-mobile:react-native-slider:${extractPackageVersion(packageJson, '@react-native-community/slider', 'dependencies')}" // Published by `wordpress-mobile/react-native-libraries-publisher` // See the documentation for this value in `build.gradle.kts` of `wordpress-mobile/react-native-libraries-publisher` - def reactNativeLibrariesPublisherVersion = "v4" + def reactNativeLibrariesPublisherVersion = "v5" def reactNativeLibrariesGroupId = "org.wordpress.react-native-libraries.$reactNativeLibrariesPublisherVersion" implementation "$reactNativeLibrariesGroupId:react-native-get-random-values:${extractPackageVersion(packageJson, 'react-native-get-random-values', 'dependencies')}" implementation "$reactNativeLibrariesGroupId:react-native-safe-area-context:${extractPackageVersion(packageJson, 'react-native-safe-area-context', 'dependencies')}" @@ -161,13 +121,8 @@ dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation "com.facebook.react:hermes-android" - - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") - debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") - debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") } - // Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { @@ -175,3 +130,4 @@ task copyDownloadableDepsToLibs(type: Copy) { into 'libs' } +apply from: file("../../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) \ No newline at end of file diff --git a/packages/react-native-editor/android/build.gradle b/packages/react-native-editor/android/build.gradle index f08019a79c9007..4df6d1e90ea386 100644 --- a/packages/react-native-editor/android/build.gradle +++ b/packages/react-native-editor/android/build.gradle @@ -1,15 +1,14 @@ buildscript { ext { - gradlePluginVersion = '8.1.0' - kotlinVersion = '1.6.10' - buildToolsVersion = "33.0.0" + gradlePluginVersion = '8.1.1' + kotlinVersion = '1.8.0' + buildToolsVersion = "34.0.0" minSdkVersion = 24 compileSdkVersion = 34 - targetSdkVersion = 33 + targetSdkVersion = 34 supportLibVersion = '28.0.0' - // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. - ndkVersion = "23.1.7779620" + ndkVersion = "25.1.8937393" } repositories { google() @@ -38,3 +37,5 @@ allprojects { mavenLocal() } } + +apply plugin: "com.facebook.react.rootproject" diff --git a/packages/react-native-editor/android/gradle.properties b/packages/react-native-editor/android/gradle.properties index 0705a21e44f055..b91742df522ade 100644 --- a/packages/react-native-editor/android/gradle.properties +++ b/packages/react-native-editor/android/gradle.properties @@ -24,7 +24,6 @@ org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=false -FLIPPER_VERSION=0.177.0 # Use this property to specify which architecture you want to build. # You can also override it from the CLI using @@ -35,4 +34,8 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 # your application. You should enable this flag either if you want # to write custom TurboModules/Fabric components OR use libraries that # are providing them. -newArchEnabled=false \ No newline at end of file +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/packages/react-native-editor/android/gradlew b/packages/react-native-editor/android/gradlew index fcb6fca147c0cd..547ba0c2aa8ffc 100755 --- a/packages/react-native-editor/android/gradlew +++ b/packages/react-native-editor/android/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -245,4 +246,4 @@ eval "set -- $( tr '\n' ' ' )" '"$@"' -exec "$JAVACMD" "$@" +exec "$JAVACMD" "$@" \ No newline at end of file diff --git a/packages/react-native-editor/android/gradlew.bat b/packages/react-native-editor/android/gradlew.bat index 6689b85beecde6..c138ebb7fb1835 100644 --- a/packages/react-native-editor/android/gradlew.bat +++ b/packages/react-native-editor/android/gradlew.bat @@ -89,4 +89,4 @@ exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal -:omega +:omega \ No newline at end of file From dca54f406002295f559eddc64a438bec2fb3b471 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Thu, 1 Feb 2024 11:58:06 +0100 Subject: [PATCH 04/10] Remove Flipper java file --- .../com/gutenberg/ReactNativeFlipper.java | 74 ------------------- 1 file changed, 74 deletions(-) delete mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/ReactNativeFlipper.java diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/ReactNativeFlipper.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/ReactNativeFlipper.java deleted file mode 100644 index c3992d41c615c1..00000000000000 --- a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/ReactNativeFlipper.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.gutenberg; - -import android.content.Context; -import com.facebook.flipper.android.AndroidFlipperClient; -import com.facebook.flipper.android.utils.FlipperUtils; -import com.facebook.flipper.core.FlipperClient; -import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; -import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; -import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; -import com.facebook.flipper.plugins.inspector.DescriptorMapping; -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; -import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; -import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.modules.network.NetworkingModule; -import okhttp3.OkHttpClient; - -/** - * Class responsible of loading Flipper inside your React Native application. This is the debug - * flavor of it. Here you can add your own plugins and customize the Flipper setup. - */ -public class ReactNativeFlipper { - public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (FlipperUtils.shouldEnableFlipper(context)) { - final FlipperClient client = AndroidFlipperClient.getInstance(context); - - client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); - client.addPlugin(new DatabasesFlipperPlugin(context)); - client.addPlugin(new SharedPreferencesFlipperPlugin(context)); - client.addPlugin(CrashReporterPlugin.getInstance()); - - NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); - NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { - @Override - public void apply(OkHttpClient.Builder builder) { - builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); - } - }); - client.addPlugin(networkFlipperPlugin); - client.start(); - - // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized - // Hence we run if after all native modules have been initialized - ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); - if (reactContext == null) { - reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceManager.ReactInstanceEventListener() { - @Override - public void onReactContextInitialized(ReactContext reactContext) { - reactInstanceManager.removeReactInstanceEventListener(this); - reactContext.runOnNativeModulesQueueThread( - new Runnable() { - @Override - public void run() { - client.addPlugin(new FrescoFlipperPlugin()); - } - }); - } - }); - } else { - client.addPlugin(new FrescoFlipperPlugin()); - } - } - } -} From 98a80bd518ec8323ab8a1d562d6f910629c225ef Mon Sep 17 00:00:00 2001 From: Gerardo Date: Thu, 1 Feb 2024 11:58:16 +0100 Subject: [PATCH 05/10] Update debug AndroidManifest --- .../android/app/src/debug/AndroidManifest.xml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml b/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml index 150f7cd0cc14db..62d7d130c6b317 100644 --- a/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml +++ b/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,9 @@ - - - - - + + + + \ No newline at end of file From 42a43e158ee49261f0b4879f62539177fa29d93e Mon Sep 17 00:00:00 2001 From: Gerardo Date: Thu, 1 Feb 2024 11:59:30 +0100 Subject: [PATCH 06/10] Update react-native-config.js to include all packages that we are manually linking. This is needed to be able to use React Native's applyNativeModulesAppBuildGradle which includes needed configuration for other integration things. This auto links modules so we need to skip the ones we manually link. --- .../react-native.config.js | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/packages/react-native-editor/react-native.config.js b/packages/react-native-editor/react-native.config.js index eafa0b41ca9558..2b44fc2dc39325 100644 --- a/packages/react-native-editor/react-native.config.js +++ b/packages/react-native-editor/react-native.config.js @@ -3,13 +3,100 @@ */ const path = require( 'path' ); +// Currently all native libraries are linked manually for both platforms. module.exports = { dependencies: { '@wordpress/react-native-bridge': { root: path.resolve( __dirname, '../react-native-bridge' ), + platforms: { + android: null, + ios: null, + }, }, '@wordpress/react-native-aztec': { root: path.resolve( __dirname, '../react-native-aztec' ), + platforms: { + android: null, + ios: null, + }, + }, + '@react-native-clipboard/clipboard': { + platforms: { + android: null, + ios: null, + }, + }, + '@react-native-community/blur': { + platforms: { + android: null, + ios: null, + }, + }, + '@react-native-masked-view/masked-view': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-fast-image': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-gesture-handler': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-reanimated': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-get-random-values': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-linear-gradient': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-safe-area-context': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-screens': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-svg': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-video': { + platforms: { + android: null, + ios: null, + }, + }, + 'react-native-webview': { + platforms: { + android: null, + ios: null, + }, }, }, project: { From d1387fa4b3856a723bd5ddce4e8c04ca9ffac461 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Fri, 9 Feb 2024 17:31:34 +0100 Subject: [PATCH 07/10] Update react-native-gesture-handler and react-native-screens --- package-lock.json | 32 +++++++++++------------ packages/react-native-editor/package.json | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9d9117f363777f..80341b91f5d232 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45232,9 +45232,9 @@ } }, "node_modules/react-native-gesture-handler": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.14.0.tgz", - "integrity": "sha512-cOmdaqbpzjWrOLUpX3hdSjsMby5wq3PIEdMq7okJeg9DmCzanysHSrktw1cXWNc/B5MAgxAn9J7Km0/4UIqKAQ==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.14.1.tgz", + "integrity": "sha512-YiM1BApV4aKeuwsM6O4C2ufwewYEKk6VMXOt0YqEZFMwABBFWhXLySFZYjBSNRU2USGppJbfHP1q1DfFQpKhdA==", "dependencies": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", @@ -45356,9 +45356,9 @@ } }, "node_modules/react-native-screens": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.22.0.tgz", - "integrity": "sha512-csLypBSXIt/egh37YJmokETptZJCtZdoZBsZNLR9n31GesDyVogprT+MM22dEPDuxPxt/mFWq+lSpVwk7khuTw==", + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.29.0.tgz", + "integrity": "sha512-yB1GoAMamFAcYf4ku94uBPn0/ani9QG7NdI98beJ5cet2YFESYYzuEIuU+kt+CNRcO8qqKeugxlfgAa3HyTqlg==", "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" @@ -56272,7 +56272,7 @@ "node-fetch": "^2.6.0", "react-native": "0.73.3", "react-native-fast-image": "8.5.11", - "react-native-gesture-handler": "2.14.0", + "react-native-gesture-handler": "2.14.1", "react-native-get-random-values": "1.4.0", "react-native-linear-gradient": "2.7.3", "react-native-modal": "13.0.1", @@ -56280,7 +56280,7 @@ "react-native-safe-area": "^0.5.0", "react-native-safe-area-context": "4.8.2", "react-native-sass-transformer": "^1.1.1", - "react-native-screens": "3.22.0", + "react-native-screens": "3.29.0", "react-native-svg": "14.0.0", "react-native-url-polyfill": "1.3.0", "react-native-video": "https://raw.githubusercontent.com/wordpress-mobile/react-native-video/5.2.0-wp-6/react-native-video-5.2.0-wp-6.tgz", @@ -71625,7 +71625,7 @@ "node-fetch": "^2.6.0", "react-native": "0.73.3", "react-native-fast-image": "8.5.11", - "react-native-gesture-handler": "2.14.0", + "react-native-gesture-handler": "2.14.1", "react-native-get-random-values": "1.4.0", "react-native-linear-gradient": "2.7.3", "react-native-modal": "13.0.1", @@ -71633,7 +71633,7 @@ "react-native-safe-area": "^0.5.0", "react-native-safe-area-context": "4.8.2", "react-native-sass-transformer": "^1.1.1", - "react-native-screens": "3.22.0", + "react-native-screens": "3.29.0", "react-native-svg": "14.0.0", "react-native-url-polyfill": "1.3.0", "react-native-video": "https://raw.githubusercontent.com/wordpress-mobile/react-native-video/5.2.0-wp-6/react-native-video-5.2.0-wp-6.tgz", @@ -92095,9 +92095,9 @@ "integrity": "sha512-cNW4bIJg3nvKaheG8vGMfqCt5LMWX9MS5+wMudgKIHbGO51spRr4sgnlhVgwHLcZ5aeNOVJ8CPRxDIWKRq/0QA==" }, "react-native-gesture-handler": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.14.0.tgz", - "integrity": "sha512-cOmdaqbpzjWrOLUpX3hdSjsMby5wq3PIEdMq7okJeg9DmCzanysHSrktw1cXWNc/B5MAgxAn9J7Km0/4UIqKAQ==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.14.1.tgz", + "integrity": "sha512-YiM1BApV4aKeuwsM6O4C2ufwewYEKk6VMXOt0YqEZFMwABBFWhXLySFZYjBSNRU2USGppJbfHP1q1DfFQpKhdA==", "requires": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", @@ -92189,9 +92189,9 @@ } }, "react-native-screens": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.22.0.tgz", - "integrity": "sha512-csLypBSXIt/egh37YJmokETptZJCtZdoZBsZNLR9n31GesDyVogprT+MM22dEPDuxPxt/mFWq+lSpVwk7khuTw==", + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.29.0.tgz", + "integrity": "sha512-yB1GoAMamFAcYf4ku94uBPn0/ani9QG7NdI98beJ5cet2YFESYYzuEIuU+kt+CNRcO8qqKeugxlfgAa3HyTqlg==", "requires": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 7e2d229e668b94..62c9c4f897582d 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -58,7 +58,7 @@ "node-fetch": "^2.6.0", "react-native": "0.73.3", "react-native-fast-image": "8.5.11", - "react-native-gesture-handler": "2.14.0", + "react-native-gesture-handler": "2.14.1", "react-native-get-random-values": "1.4.0", "react-native-linear-gradient": "2.7.3", "react-native-modal": "13.0.1", @@ -66,7 +66,7 @@ "react-native-safe-area": "^0.5.0", "react-native-safe-area-context": "4.8.2", "react-native-sass-transformer": "^1.1.1", - "react-native-screens": "3.22.0", + "react-native-screens": "3.29.0", "react-native-svg": "14.0.0", "react-native-url-polyfill": "1.3.0", "react-native-video": "https://raw.githubusercontent.com/wordpress-mobile/react-native-video/5.2.0-wp-6/react-native-video-5.2.0-wp-6.tgz", From 93f5af4b083dffb5f9faf4b9f252dc7c862321d2 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Mon, 12 Feb 2024 16:17:50 +0100 Subject: [PATCH 08/10] Update package-lock.json --- package-lock.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 80341b91f5d232..b5139aad751e77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10601,6 +10601,14 @@ "node": ">=8" } }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", + "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==", + "engines": { + "node": ">=18" + } + }, "node_modules/@react-native/js-polyfills": { "version": "0.73.1", "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", @@ -45463,14 +45471,6 @@ "node": ">= 10.14.2" } }, - "node_modules/react-native/node_modules/@react-native/gradle-plugin": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", - "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==", - "engines": { - "node": ">=18" - } - }, "node_modules/react-native/node_modules/@types/yargs": { "version": "15.0.19", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", @@ -64177,6 +64177,11 @@ } } }, + "@react-native/gradle-plugin": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", + "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==" + }, "@react-native/js-polyfills": { "version": "0.73.1", "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", @@ -91952,11 +91957,6 @@ "chalk": "^4.0.0" } }, - "@react-native/gradle-plugin": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", - "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==" - }, "@types/yargs": { "version": "15.0.19", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", From 2af43c6e9ef8f535550a6155d2444206f54957f0 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Tue, 13 Feb 2024 17:58:52 +0100 Subject: [PATCH 09/10] Updates react-native.config to remove disabling iOS auto-linking --- .../react-native-editor/react-native.config.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/react-native-editor/react-native.config.js b/packages/react-native-editor/react-native.config.js index 2b44fc2dc39325..c83189dd4c34ce 100644 --- a/packages/react-native-editor/react-native.config.js +++ b/packages/react-native-editor/react-native.config.js @@ -10,92 +10,77 @@ module.exports = { root: path.resolve( __dirname, '../react-native-bridge' ), platforms: { android: null, - ios: null, }, }, '@wordpress/react-native-aztec': { root: path.resolve( __dirname, '../react-native-aztec' ), platforms: { android: null, - ios: null, }, }, '@react-native-clipboard/clipboard': { platforms: { android: null, - ios: null, }, }, '@react-native-community/blur': { platforms: { android: null, - ios: null, }, }, '@react-native-masked-view/masked-view': { platforms: { android: null, - ios: null, }, }, 'react-native-fast-image': { platforms: { android: null, - ios: null, }, }, 'react-native-gesture-handler': { platforms: { android: null, - ios: null, }, }, 'react-native-reanimated': { platforms: { android: null, - ios: null, }, }, 'react-native-get-random-values': { platforms: { android: null, - ios: null, }, }, 'react-native-linear-gradient': { platforms: { android: null, - ios: null, }, }, 'react-native-safe-area-context': { platforms: { android: null, - ios: null, }, }, 'react-native-screens': { platforms: { android: null, - ios: null, }, }, 'react-native-svg': { platforms: { android: null, - ios: null, }, }, 'react-native-video': { platforms: { android: null, - ios: null, }, }, 'react-native-webview': { platforms: { android: null, - ios: null, }, }, }, From ad4b747e0ddf509da818a81cca6c2caf9c0063e5 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Tue, 13 Feb 2024 18:06:56 +0100 Subject: [PATCH 10/10] Updates the comment explaning why auto-linking is disabled for Android in the react-native.config.js file --- packages/react-native-editor/react-native.config.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/react-native-editor/react-native.config.js b/packages/react-native-editor/react-native.config.js index c83189dd4c34ce..2496210957d66a 100644 --- a/packages/react-native-editor/react-native.config.js +++ b/packages/react-native-editor/react-native.config.js @@ -3,7 +3,12 @@ */ const path = require( 'path' ); -// Currently all native libraries are linked manually for both platforms. +/** + * The `null` value for the Android `platform` below disables auto-linking, as + * we manually link these library binaries to avoid a Node.js dependency + * using binaries from the React Native Libraries Publisher repository + * in the host WordPress Android app. + */ module.exports = { dependencies: { '@wordpress/react-native-bridge': {