diff --git a/android/app/build.gradle b/android/app/build.gradle index cf06f314ac..27cc4fa62f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -94,8 +94,8 @@ def enableSeparateBuildPerCPUArchitecture = false def enableProguardInReleaseBuilds = false android { - compileSdkVersion 26 - buildToolsVersion "28.0.2" + compileSdkVersion 27 + buildToolsVersion "27.0.3" defaultConfig { applicationId "com.gutenberg" diff --git a/babel.config.js b/babel.config.js index c0f47e2bc9..6a9b3c2c29 100644 --- a/babel.config.js +++ b/babel.config.js @@ -6,7 +6,7 @@ module.exports = function( api ) { ], plugins: [ 'react-require', - '@babel/plugin-transform-async-to-generator', + /*'@babel/plugin-transform-async-to-generator',*/ /* <--- commented out to make the wpandroid release build work */ '@babel/plugin-proposal-async-generator-functions', '@babel/plugin-transform-runtime', 'react-native-classname-to-style', diff --git a/ios/gutenberg.xcodeproj/project.pbxproj b/ios/gutenberg.xcodeproj/project.pbxproj index c888546b1d..ac27c64755 100644 --- a/ios/gutenberg.xcodeproj/project.pbxproj +++ b/ios/gutenberg.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 2DCD954D1E0B4F2C00145EB5 /* gutenbergTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* gutenbergTests.m */; }; 2DF0FFEE2056DD460020B375 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; }; 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; + 7E4C21212187419000EC7F49 /* libRNReactNativeGutenbergBridge.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E4C211D2187417100EC7F49 /* libRNReactNativeGutenbergBridge.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 8C666FF0C9224FB88C2C0447 /* libRNSVG-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9BFAFEB337654221B2F14D03 /* libRNSVG-tvOS.a */; }; ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; @@ -304,6 +305,13 @@ remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTLinking; }; + 7E4C211C2187417100EC7F49 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7E4C20F32187417100EC7F49 /* RNReactNativeGutenbergBridge.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RNReactNativeGutenbergBridge; + }; 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; @@ -378,6 +386,7 @@ 3ADEFEC092CF4D00BEF1019E /* libRNTAztecView.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNTAztecView.a; sourceTree = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; + 7E4C20F32187417100EC7F49 /* RNReactNativeGutenbergBridge.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNReactNativeGutenbergBridge.xcodeproj; path = "../react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.xcodeproj"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; 9B18D59B9364468890D0E546 /* RNSVG.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSVG.xcodeproj; path = "../node_modules/react-native-svg/ios/RNSVG.xcodeproj"; sourceTree = ""; }; 9BFAFEB337654221B2F14D03 /* libRNSVG-tvOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = "libRNSVG-tvOS.a"; sourceTree = ""; }; @@ -404,6 +413,7 @@ buildActionMask = 2147483647; files = ( F1289ECB2100E4320091E81D /* Aztec.framework in Frameworks */, + 7E4C21212187419000EC7F49 /* libRNReactNativeGutenbergBridge.a in Frameworks */, ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */, 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, 146834051AC3E58100842450 /* libReact.a in Frameworks */, @@ -593,9 +603,18 @@ name = Products; sourceTree = ""; }; + 7E4C20F42187417100EC7F49 /* Products */ = { + isa = PBXGroup; + children = ( + 7E4C211D2187417100EC7F49 /* libRNReactNativeGutenbergBridge.a */, + ); + name = Products; + sourceTree = ""; + }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( + 7E4C20F32187417100EC7F49 /* RNReactNativeGutenbergBridge.xcodeproj */, 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */, 146833FF1AC3E56700842450 /* React.xcodeproj */, 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, @@ -849,6 +868,10 @@ ProductGroup = 146834001AC3E56700842450 /* Products */; ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; }, + { + ProductGroup = 7E4C20F42187417100EC7F49 /* Products */; + ProjectRef = 7E4C20F32187417100EC7F49 /* RNReactNativeGutenbergBridge.xcodeproj */; + }, { ProductGroup = FFEDF6EF21241BDF007FCC6D /* Products */; ProjectRef = 9B18D59B9364468890D0E546 /* RNSVG.xcodeproj */; @@ -1114,6 +1137,13 @@ remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 7E4C211D2187417100EC7F49 /* libRNReactNativeGutenbergBridge.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNReactNativeGutenbergBridge.a; + remoteRef = 7E4C211C2187417100EC7F49 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; diff --git a/jest.config.js b/jest.config.js index 5afb4a4e0d..860a4c33a7 100644 --- a/jest.config.js +++ b/jest.config.js @@ -14,6 +14,7 @@ if ( process.env.TEST_RN_PLATFORM ) { module.exports = { verbose: true, preset: 'react-native', + setupFiles: [ './jest/setup.js' ], testEnvironment: 'jsdom', testPathIgnorePatterns: [ '/node_modules/', diff --git a/jest/setup.js b/jest/setup.js new file mode 100644 index 0000000000..7f94c1d3d3 --- /dev/null +++ b/jest/setup.js @@ -0,0 +1,7 @@ +jest.mock( '../react-native-gutenberg-bridge', () => { + return { + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + subscribeParentGetHtml: jest.fn(), + }; +} ); diff --git a/package.json b/package.json index 6825759611..8aa78c9157 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "start:debug": "node --inspect-brk node_modules/.bin/react-native start", "start:inside-gb:debug": "node --inspect-brk node_modules/.bin/react-native start:inside-gb", "android": "react-native run-android", + "wpandroid": "yarn android --root wpandroidlink --variant wasabiDebug --appIdSuffix beta --appFolder WordPress --main-activity=ui.WPLaunchActivity", "preios": "yarn preios:carthage", "preios:carthage": "cd react-native-aztec && yarn install-aztec-ios", "ios": "react-native run-ios", @@ -72,8 +73,8 @@ "clean:metro": "rm -rf $TMPDIR/metro-cache-*;", "clean:react": "rm -rf $TMPDIR/react-*", "clean:node": "rm -rf node_modules", - "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:watchman": "command -v watchman >/dev/null 2>&1 && watchman watch-del-all; true", + "clean:babel-cache": "rm -rf ./node_modules/.cache/babel-loader/*", "lint": "eslint . --ext .js", "lint:fix": "yarn lint --fix" }, @@ -94,13 +95,15 @@ "react": "16.5.0", "react-native": "0.57.1", "react-native-modal": "^6.5.0", - "react-native-recyclerview-list": "git+https://github.com/wordpress-mobile/react-native-recyclerview-list.git#c073c0335ebe0398c85648ffeb11cbed4ee79229", + "react-native-recyclerview-list": "git+https://github.com/wordpress-mobile/react-native-recyclerview-list.git#336f7159eb6e7bad467c041b3f34667d485e7b58", "react-native-svg": "^6.5.2", + "react-native-hr": "git+https://github.com/Riglerr/react-native-hr.git#2d01a5cf77212d100e8b99e0310cce5234f977b3", "react-redux": "^5.0.7", "redux": "^3.7.2", "rememo": "^3.0.0", "shallowequal": "^1.0.2", "simple-html-tokenizer": "^0.5.1", - "tinycolor2": "^1.4.1" + "tinycolor2": "^1.4.1", + "turbo-combine-reducers": "^1.0.2" } } diff --git a/react-native-aztec b/react-native-aztec index b7c28747e6..9d96ffff5d 160000 --- a/react-native-aztec +++ b/react-native-aztec @@ -1 +1 @@ -Subproject commit b7c28747e6ed6ec7f33a3e5dcfe8cc900ba706d6 +Subproject commit 9d96ffff5df55bc2aaf01aa7843cb1365ee1fc89 diff --git a/react-native-gutenberg-bridge/.gitattributes b/react-native-gutenberg-bridge/.gitattributes new file mode 100644 index 0000000000..eb3959108e --- /dev/null +++ b/react-native-gutenberg-bridge/.gitattributes @@ -0,0 +1 @@ +*.pbxproj -text \ No newline at end of file diff --git a/react-native-gutenberg-bridge/.gitignore b/react-native-gutenberg-bridge/.gitignore new file mode 100644 index 0000000000..9cadbfedcb --- /dev/null +++ b/react-native-gutenberg-bridge/.gitignore @@ -0,0 +1,46 @@ + +# OSX +# +.DS_Store + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml + +# BUCK +buck-out/ +\.buckd/ +*.keystore + \ No newline at end of file diff --git a/react-native-gutenberg-bridge/README.md b/react-native-gutenberg-bridge/README.md new file mode 100644 index 0000000000..d746ac95cc --- /dev/null +++ b/react-native-gutenberg-bridge/README.md @@ -0,0 +1,44 @@ + +# react-native-gutenberg-bridge + +## Getting started + +`$ npm install react-native-gutenberg-bridge --save` + +### Mostly automatic installation + +`$ react-native link react-native-gutenberg-bridge` + +### Manual installation + + +#### iOS + +1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` +2. Go to `node_modules` ➜ `react-native-gutenberg-bridge` and add `RNReactNativeGutenbergBridge.xcodeproj` +3. In XCode, in the project navigator, select your project. Add `libRNReactNativeGutenbergBridge.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` +4. Run your project (`Cmd+R`)< + +#### Android + +1. Open up `android/app/src/main/java/[...]/MainActivity.java` + - Add `import com.reactlibrary.RNReactNativeGutenbergBridgePackage;` to the imports at the top of the file + - Add `new RNReactNativeGutenbergBridgePackage()` to the list returned by the `getPackages()` method +2. Append the following lines to `android/settings.gradle`: + ``` + include ':react-native-gutenberg-bridge' + project(':react-native-gutenberg-bridge').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gutenberg-bridge/android') + ``` +3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: + ``` + compile project(':react-native-gutenberg-bridge') + ``` + +## Usage +```javascript +import RNReactNativeGutenbergBridge from 'react-native-gutenberg-bridge'; + +// TODO: What to do with the module? +RNReactNativeGutenbergBridge; +``` + \ No newline at end of file diff --git a/react-native-gutenberg-bridge/android/build.gradle b/react-native-gutenberg-bridge/android/build.gradle new file mode 100644 index 0000000000..e9d4097607 --- /dev/null +++ b/react-native-gutenberg-bridge/android/build.gradle @@ -0,0 +1,36 @@ + +buildscript { + repositories { + jcenter() + google() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.1.4' + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 27 + buildToolsVersion "27.0.3" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + } + lintOptions { + abortOnError false + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.facebook.react:react-native:+' +} diff --git a/react-native-gutenberg-bridge/android/src/main/AndroidManifest.xml b/react-native-gutenberg-bridge/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..29beea618d --- /dev/null +++ b/react-native-gutenberg-bridge/android/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + diff --git a/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/GutenbergBridgeJS2Parent.java b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/GutenbergBridgeJS2Parent.java new file mode 100644 index 0000000000..5cd32287a1 --- /dev/null +++ b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/GutenbergBridgeJS2Parent.java @@ -0,0 +1,5 @@ +package org.wordpress.mobile.ReactNativeGutenbergBridge; + +public interface GutenbergBridgeJS2Parent { + void responseHtml(String html); +} diff --git a/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgeModule.java b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgeModule.java new file mode 100644 index 0000000000..6d9711204e --- /dev/null +++ b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgeModule.java @@ -0,0 +1,39 @@ +package org.wordpress.mobile.ReactNativeGutenbergBridge; + +import android.support.annotation.Nullable; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.modules.core.DeviceEventManagerModule; + +public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModule { + private final ReactApplicationContext mReactContext; + private final GutenbergBridgeJS2Parent mGutenbergBridgeJS2Parent; + + public RNReactNativeGutenbergBridgeModule(ReactApplicationContext reactContext, + GutenbergBridgeJS2Parent gutenbergBridgeJS2Parent) { + super(reactContext); + mReactContext = reactContext; + mGutenbergBridgeJS2Parent = gutenbergBridgeJS2Parent; + } + + @Override + public String getName() { + return "RNReactNativeGutenbergBridge"; + } + + private void emitToJS(String eventName, @Nullable WritableMap data) { + mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, data); + } + + public void getHtmlFromJS() { + emitToJS("requestGetHtml", null); + } + + @ReactMethod + public void provideToNative_Html(String html) { + mGutenbergBridgeJS2Parent.responseHtml(html); + } +} diff --git a/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgePackage.java b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgePackage.java new file mode 100644 index 0000000000..794b12c7f7 --- /dev/null +++ b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgePackage.java @@ -0,0 +1,35 @@ +package org.wordpress.mobile.ReactNativeGutenbergBridge; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class RNReactNativeGutenbergBridgePackage implements ReactPackage { + private GutenbergBridgeJS2Parent mGutenbergBridgeJS2Parent; + private RNReactNativeGutenbergBridgeModule mRNReactNativeGutenbergBridgeModule; + + public RNReactNativeGutenbergBridgeModule getRNReactNativeGutenbergBridgeModule() { + return mRNReactNativeGutenbergBridgeModule; + } + + public RNReactNativeGutenbergBridgePackage(GutenbergBridgeJS2Parent gutenbergBridgeJS2Parent) { + mGutenbergBridgeJS2Parent = gutenbergBridgeJS2Parent; + } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + mRNReactNativeGutenbergBridgeModule = new RNReactNativeGutenbergBridgeModule(reactContext, + mGutenbergBridgeJS2Parent); + return Arrays.asList(mRNReactNativeGutenbergBridgeModule); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} diff --git a/react-native-gutenberg-bridge/index.js b/react-native-gutenberg-bridge/index.js new file mode 100644 index 0000000000..4f4e1c9cb7 --- /dev/null +++ b/react-native-gutenberg-bridge/index.js @@ -0,0 +1,13 @@ +/** @format */ + +import { NativeModules, NativeEventEmitter } from 'react-native'; + +const { RNReactNativeGutenbergBridge } = NativeModules; + +const gutenbergBridgeEvents = new NativeEventEmitter( RNReactNativeGutenbergBridge ); + +export function subscribeParentGetHtml( callback ) { + return gutenbergBridgeEvents.addListener( 'requestGetHtml', callback ); +} + +export default RNReactNativeGutenbergBridge; diff --git a/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.h b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.h new file mode 100644 index 0000000000..c0df8135d2 --- /dev/null +++ b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.h @@ -0,0 +1,12 @@ + +#if __has_include("RCTBridgeModule.h") +#import "RCTBridgeModule.h" +#else +#import +#import +#endif + +@interface RNReactNativeGutenbergBridge : RCTEventEmitter + +@end + \ No newline at end of file diff --git a/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.m b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.m new file mode 100644 index 0000000000..08e20e5fb4 --- /dev/null +++ b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.m @@ -0,0 +1,25 @@ + +#import "RNReactNativeGutenbergBridge.h" + +@implementation RNReactNativeGutenbergBridge + +- (dispatch_queue_t)methodQueue +{ + return dispatch_get_main_queue(); +} +RCT_EXPORT_MODULE() + +- (NSArray *)supportedEvents +{ + return @[@"requestGetHtml"]; +} + +//provideToNative_Html + +RCT_EXPORT_METHOD(provideToNative_Html:(NSString *)html) +{ + NSLog(@"provideToNative_Html called on IOS with:\n%@", html); +} + +@end + diff --git a/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.podspec b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.podspec new file mode 100644 index 0000000000..200fc8bfea --- /dev/null +++ b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.podspec @@ -0,0 +1,24 @@ + +Pod::Spec.new do |s| + s.name = "RNReactNativeGutenbergBridge" + s.version = "1.0.0" + s.summary = "RNReactNativeGutenbergBridge" + s.description = <<-DESC + RNReactNativeGutenbergBridge + DESC + s.homepage = "" + s.license = "MIT" + # s.license = { :type => "MIT", :file => "FILE_LICENSE" } + s.author = { "author" => "author@domain.cn" } + s.platform = :ios, "7.0" + s.source = { :git => "https://github.com/author/RNReactNativeGutenbergBridge.git", :tag => "master" } + s.source_files = "RNReactNativeGutenbergBridge/**/*.{h,m}" + s.requires_arc = true + + + s.dependency "React" + #s.dependency "others" + +end + + \ No newline at end of file diff --git a/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.xcodeproj/project.pbxproj b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..c0237a1322 --- /dev/null +++ b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.xcodeproj/project.pbxproj @@ -0,0 +1,259 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + B3E7B58A1CC2AC0600A0062D /* RNReactNativeGutenbergBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNReactNativeGutenbergBridge.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 58B511D91A9E6C8500147676 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 134814201AA4EA6300B7C361 /* libRNReactNativeGutenbergBridge.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNReactNativeGutenbergBridge.a; sourceTree = BUILT_PRODUCTS_DIR; }; + B3E7B5881CC2AC0600A0062D /* RNReactNativeGutenbergBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNReactNativeGutenbergBridge.h; sourceTree = ""; }; + B3E7B5891CC2AC0600A0062D /* RNReactNativeGutenbergBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNReactNativeGutenbergBridge.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 58B511D81A9E6C8500147676 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 134814211AA4EA7D00B7C361 /* Products */ = { + isa = PBXGroup; + children = ( + 134814201AA4EA6300B7C361 /* libRNReactNativeGutenbergBridge.a */, + ); + name = Products; + sourceTree = ""; + }; + 58B511D21A9E6C8500147676 = { + isa = PBXGroup; + children = ( + B3E7B5881CC2AC0600A0062D /* RNReactNativeGutenbergBridge.h */, + B3E7B5891CC2AC0600A0062D /* RNReactNativeGutenbergBridge.m */, + 134814211AA4EA7D00B7C361 /* Products */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 58B511DA1A9E6C8500147676 /* RNReactNativeGutenbergBridge */ = { + isa = PBXNativeTarget; + buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNReactNativeGutenbergBridge" */; + buildPhases = ( + 58B511D71A9E6C8500147676 /* Sources */, + 58B511D81A9E6C8500147676 /* Frameworks */, + 58B511D91A9E6C8500147676 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RNReactNativeGutenbergBridge; + productName = RCTDataManager; + productReference = 134814201AA4EA6300B7C361 /* libRNReactNativeGutenbergBridge.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 58B511D31A9E6C8500147676 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0830; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 58B511DA1A9E6C8500147676 = { + CreatedOnToolsVersion = 6.1.1; + }; + }; + }; + buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNReactNativeGutenbergBridge" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 58B511D21A9E6C8500147676; + productRefGroup = 58B511D21A9E6C8500147676; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 58B511DA1A9E6C8500147676 /* RNReactNativeGutenbergBridge */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 58B511D71A9E6C8500147676 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B3E7B58A1CC2AC0600A0062D /* RNReactNativeGutenbergBridge.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 58B511ED1A9E6C8500147676 /* 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_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + 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 = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 58B511EE1A9E6C8500147676 /* 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_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + 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 = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 58B511F01A9E6C8500147676 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../../React/**", + "$(SRCROOT)/../../react-native/React/**", + ); + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = RNReactNativeGutenbergBridge; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 58B511F11A9E6C8500147676 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../../React/**", + "$(SRCROOT)/../../react-native/React/**", + ); + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = RNReactNativeGutenbergBridge; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNReactNativeGutenbergBridge" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58B511ED1A9E6C8500147676 /* Debug */, + 58B511EE1A9E6C8500147676 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNReactNativeGutenbergBridge" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58B511F01A9E6C8500147676 /* Debug */, + 58B511F11A9E6C8500147676 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 58B511D31A9E6C8500147676 /* Project object */; +} diff --git a/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.xcworkspace/contents.xcworkspacedata b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..20563a73ca --- /dev/null +++ b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,9 @@ +// !$*UTF8*$! + + + + + + \ No newline at end of file diff --git a/react-native-gutenberg-bridge/package.json b/react-native-gutenberg-bridge/package.json new file mode 100644 index 0000000000..2b38f0f3fe --- /dev/null +++ b/react-native-gutenberg-bridge/package.json @@ -0,0 +1,20 @@ + +{ + "name": "react-native-gutenberg-bridge", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "react-native" + ], + "author": "", + "license": "", + "peerDependencies": { + "react-native": "^0.41.2", + "react-native-windows": "0.41.0-rc.1" + + } +} diff --git a/src/app/AppContainer.js b/src/app/AppContainer.js index 1689e6fbfd..6979c35773 100644 --- a/src/app/AppContainer.js +++ b/src/app/AppContainer.js @@ -10,6 +10,7 @@ import { deleteBlockAction, createBlockAction, parseBlocksAction, + serializeToNativeAction, mergeBlocksAction, } from '../store/actions'; import MainApp from './MainApp'; @@ -42,6 +43,9 @@ const mapDispatchToProps = ( dispatch, ownProps ) => { parseBlocksAction: ( html ) => { dispatch( parseBlocksAction( html ) ); }, + serializeToNativeAction: () => { + dispatch( serializeToNativeAction() ); + }, mergeBlocksAction: ( blockOneClientId, blockTwoClientId, block ) => { dispatch( mergeBlocksAction( blockOneClientId, blockTwoClientId, block ) ); }, diff --git a/src/app/MainApp.js b/src/app/MainApp.js index 487bbdd720..16636dc722 100644 --- a/src/app/MainApp.js +++ b/src/app/MainApp.js @@ -2,13 +2,30 @@ * @format */ import React from 'react'; +import { subscribeParentGetHtml } from 'react-native-gutenberg-bridge'; import BlockManager, { type BlockListType } from '../block-management/block-manager'; +import type { EmitterSubscription } from 'react-native'; + type PropsType = BlockListType; type StateType = {}; export default class MainScreen extends React.Component { + subscriptionParentGetHtml: ?EmitterSubscription; + + componentDidMount() { + this.subscriptionParentGetHtml = subscribeParentGetHtml( () => { + this.props.serializeToNativeAction(); + } ); + } + + componentWillUnmount() { + if ( this.subscriptionParentGetHtml ) { + this.subscriptionParentGetHtml.remove(); + } + } + render() { return ; } diff --git a/src/block-management/block-manager.js b/src/block-management/block-manager.js index c874159a06..eabba2d52b 100644 --- a/src/block-management/block-manager.js +++ b/src/block-management/block-manager.js @@ -24,6 +24,7 @@ export type BlockListType = { deleteBlockAction: string => mixed, createBlockAction: ( string, BlockType, string ) => mixed, parseBlocksAction: string => mixed, + serializeToNativeAction: void => void, mergeBlocksAction: ( string, string, BlockType ) => mixed, blocks: Array, aztechtml: string, diff --git a/src/store/actions/ActionTypes.js b/src/store/actions/ActionTypes.js index a01e0f25f9..478fb303b4 100644 --- a/src/store/actions/ActionTypes.js +++ b/src/store/actions/ActionTypes.js @@ -12,6 +12,7 @@ export default { DELETE: 'BLOCK_DELETE_ACTION', CREATE: 'BLOCK_CREATE_ACTION', PARSE: 'BLOCK_PARSE_ACTION', + SERIALIZE_ALL: 'SERIALIZE_ALL_BLOCKS_ACTION', MERGE: 'BLOCKS_MERGE_ACTION', }, }; diff --git a/src/store/actions/index.js b/src/store/actions/index.js index f0babe0539..586c4abe61 100644 --- a/src/store/actions/index.js +++ b/src/store/actions/index.js @@ -23,6 +23,10 @@ export type ParseActionType = string => { html: string, }; +export type serializeToNativeActionType = void => { + type: $Values, +}; + export type BlocksActionType = ( string, string, BlockType ) => { type: $Values, blockOneClientId: string, @@ -70,6 +74,10 @@ export const parseBlocksAction: ParseActionType = ( html ) => ( { html, } ); +export const serializeToNativeAction: serializeToNativeActionType = () => ( { + type: ActionTypes.BLOCK.SERIALIZE_ALL, +} ); + export const mergeBlocksAction: BlocksActionType = ( blockOneClientId, blockTwoClientId, block ) => ( { type: ActionTypes.BLOCK.MERGE, blockOneClientId, diff --git a/src/store/gutenbergBridgeMiddleware.js b/src/store/gutenbergBridgeMiddleware.js new file mode 100644 index 0000000000..2dea03e4af --- /dev/null +++ b/src/store/gutenbergBridgeMiddleware.js @@ -0,0 +1,27 @@ +/** + * @format + * @flow + */ + +// Gutenberg imports +import { serialize } from '@wordpress/blocks'; + +import type { Store, Dispatch } from 'redux'; + +import ActionTypes from './actions/ActionTypes'; +import type { BlockActionType } from './actions'; + +import RNReactNativeGutenbergBridge from 'react-native-gutenberg-bridge'; +export default ( store: Store ) => ( next: Dispatch ) => ( action: BlockActionType ) => { + switch ( action.type ) { + case ActionTypes.BLOCK.SERIALIZE_ALL: { + const html = store + .getState() + .blocks.map( serialize ) + .join( '\n\n' ); + RNReactNativeGutenbergBridge.provideToNative_Html( html ); + } + } + + return next( action ); +}; diff --git a/src/store/index.js b/src/store/index.js index 1c1c0051df..e8f331393d 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -11,11 +11,13 @@ import { setUnregisteredTypeHandlerName, } from '@wordpress/blocks'; -import { createStore } from 'redux'; +import { createStore, applyMiddleware } from 'redux'; import { reducer } from './reducers'; import * as UnsupportedBlock from '../block-types/unsupported-block/'; +import gutenbergBridgeMiddleware from './gutenbergBridgeMiddleware'; + export type BlockType = { clientId: string, name: string, @@ -45,11 +47,11 @@ export function html2State( html: string ) { return state; } -const devToolsEnhancer = - // ( 'development' === process.env.NODE_ENV && require( 'remote-redux-devtools' ).default ) || - () => {}; +// const devToolsEnhancer = +// // ( 'development' === process.env.NODE_ENV && require( 'remote-redux-devtools' ).default ) || +// () => {}; export function setupStore( state: StateType = html2State( '' ) ) { - const store = createStore( reducer, state, devToolsEnhancer() ); + const store = createStore( reducer, state, applyMiddleware( gutenbergBridgeMiddleware ) ); return store; } diff --git a/wpandroidlink/android b/wpandroidlink/android new file mode 120000 index 0000000000..1b20c9fb81 --- /dev/null +++ b/wpandroidlink/android @@ -0,0 +1 @@ +../../../ \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 05b0ec754f..dbe03068dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7236,6 +7236,10 @@ react-native-crypto@^2.0.1: pbkdf2 "3.0.8" public-encrypt "^4.0.0" +"react-native-hr@git+https://github.com/Riglerr/react-native-hr.git#2d01a5cf77212d100e8b99e0310cce5234f977b3": + version "1.1.3" + resolved "git+https://github.com/Riglerr/react-native-hr.git#2d01a5cf77212d100e8b99e0310cce5234f977b3" + react-native-modal@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/react-native-modal/-/react-native-modal-6.5.0.tgz#46220b2289a41597d344c1db17454611b426a758" @@ -7252,9 +7256,9 @@ react-native-randombytes@^2.2.0: buffer "^4.9.1" sjcl "^1.0.3" -"react-native-recyclerview-list@git+https://github.com/wordpress-mobile/react-native-recyclerview-list.git#c073c0335ebe0398c85648ffeb11cbed4ee79229": +"react-native-recyclerview-list@git+https://github.com/wordpress-mobile/react-native-recyclerview-list.git#336f7159eb6e7bad467c041b3f34667d485e7b58": version "0.3.2" - resolved "git+https://github.com/wordpress-mobile/react-native-recyclerview-list.git#c073c0335ebe0398c85648ffeb11cbed4ee79229" + resolved "git+https://github.com/wordpress-mobile/react-native-recyclerview-list.git#336f7159eb6e7bad467c041b3f34667d485e7b58" dependencies: prop-types "^15.6.0" @@ -8764,6 +8768,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +turbo-combine-reducers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/turbo-combine-reducers/-/turbo-combine-reducers-1.0.2.tgz#aa3650b3c63daa6804d35a4042014f6d31df1e47" + integrity sha512-gHbdMZlA6Ym6Ur5pSH/UWrNQMIM9IqTH6SoL1DbHpqEdQ8i+cFunSmSlFykPt0eGQwZ4d/XTHOl74H0/kFBVWw== + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"