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/gutenberg b/gutenberg index 0889786466..563e2926a6 160000 --- a/gutenberg +++ b/gutenberg @@ -1 +1 @@ -Subproject commit 08897864660d68efb226c19b685699992598b791 +Subproject commit 563e2926a68b10e098b1387c9af1c35ee2446fb8 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 b59b67b754..fdcab83d8e 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,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", @@ -71,8 +72,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" }, @@ -93,13 +94,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-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/app/initial-html.js b/src/app/initial-html.js index d62f70b5be..4baf92aa38 100644 --- a/src/app/initial-html.js +++ b/src/app/initial-html.js @@ -24,6 +24,10 @@ Hello World

Hello World!

+ + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer tempor tincidunt sapien, quis dictum orci sollicitudin quis. Proin sed elit id est pulvinar feugiat vitae eget dolor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

diff --git a/src/block-management/block-manager.js b/src/block-management/block-manager.js index 717e556b61..7e0ccfc13f 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/symlinked-packages-in-parent/@wordpress/notices b/symlinked-packages-in-parent/@wordpress/notices new file mode 120000 index 0000000000..3065505666 --- /dev/null +++ b/symlinked-packages-in-parent/@wordpress/notices @@ -0,0 +1 @@ +../../../packages/notices/build/ \ No newline at end of file diff --git a/symlinked-packages/@wordpress/notices b/symlinked-packages/@wordpress/notices new file mode 120000 index 0000000000..a4f03de65a --- /dev/null +++ b/symlinked-packages/@wordpress/notices @@ -0,0 +1 @@ +../../gutenberg/packages/notices/src \ No newline at end of file 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"