diff --git a/.gitmodules b/.gitmodules index 062b5e5a05..bad407ef3d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "gutenberg"] path = gutenberg - url = ../../WordPress/gutenberg.git + url = https://github.com/kmdupr33/gutenberg [submodule "react-native-aztec"] path = react-native-aztec-old-submodule url = ../react-native-aztec.git diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 45937ac904..14d3a1f4b1 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,7 @@ 1.20.0 ------ * Fix bug where image placeholders would sometimes not be shown +* Add keyboard shortcuts for bold, italics, and insert/edit link 1.19.0 ------ diff --git a/android/app/src/main/java/com/gutenberg/MainActivity.java b/android/app/src/main/java/com/gutenberg/MainActivity.java index f5f8ff7b24..e241b0a647 100644 --- a/android/app/src/main/java/com/gutenberg/MainActivity.java +++ b/android/app/src/main/java/com/gutenberg/MainActivity.java @@ -1,6 +1,13 @@ package com.gutenberg; +import android.os.Bundle; +import android.view.KeyEvent; + import com.facebook.react.ReactActivity; +import com.facebook.react.ReactApplication; + +import org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule; +import org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule.Shortcut; public class MainActivity extends ReactActivity { @@ -12,4 +19,33 @@ public class MainActivity extends ReactActivity { protected String getMainComponentName() { return "gutenberg"; } + + private RNReactNativeGutenbergBridgeModule module; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ((ReactApplication) getApplication()).getReactNativeHost() + .getReactInstanceManager() + .addReactInstanceEventListener(context -> module = context.getNativeModule(RNReactNativeGutenbergBridgeModule.class)); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (!event.isCtrlPressed()) { + return super.onKeyUp(keyCode, event); + } + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_B: + module.emitShortcutEventToJs(Shortcut.Bold); + break; + case KeyEvent.KEYCODE_I: + module.emitShortcutEventToJs(Shortcut.Italic); + break; + case KeyEvent.KEYCODE_K: + module.emitShortcutEventToJs(Shortcut.AddEditLink); + break; + } + return super.onKeyUp(keyCode, event); + } } diff --git a/gutenberg b/gutenberg index 73994a8f83..c381dfadde 160000 --- a/gutenberg +++ b/gutenberg @@ -1 +1 @@ -Subproject commit 73994a8f83df09abd49e269ae234666d7237da9a +Subproject commit c381dfadde8f5a7ad7f494d7b6f6bcece6ab14af diff --git a/ios/gutenberg.xcodeproj/project.pbxproj b/ios/gutenberg.xcodeproj/project.pbxproj index c2a0f6f19b..0d5e23d998 100644 --- a/ios/gutenberg.xcodeproj/project.pbxproj +++ b/ios/gutenberg.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 16AEBAC87CB24520ADA106D7 /* libRNSafeArea.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69F3DF692A7C4E5994CD3CBB /* libRNSafeArea.a */; }; + 1EE61FB623C0E47F003727EC /* ShortcutCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EE61FB523C0E47F003727EC /* ShortcutCoordinator.swift */; }; 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; }; @@ -419,6 +420,7 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = gutenberg/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = gutenberg/Info.plist; sourceTree = ""; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 1EE61FB523C0E47F003727EC /* ShortcutCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ShortcutCoordinator.swift; path = gutenberg/ShortcutCoordinator.swift; sourceTree = ""; }; 24AEC4495B174D4C9E96E630 /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTVideo.xcodeproj; path = "../node_modules/react-native-video/ios/RCTVideo.xcodeproj"; sourceTree = ""; }; 2D02E47B1E0B4A5D006451C7 /* gutenberg-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "gutenberg-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E4901E0B4A5D006451C7 /* gutenberg-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "gutenberg-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -600,6 +602,7 @@ 7EC7328E21907E3F00FED2E6 /* GutenbergViewController.swift */, FF9A6F1621FA8E2500D36D14 /* MediaPickCoordinator.swift */, FF6836C722035EAB00A0C562 /* MediaUploadCoordinator.swift */, + 1EE61FB523C0E47F003727EC /* ShortcutCoordinator.swift */, F151983A2100DC3D000F6E97 /* MediaProvider.swift */, 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, @@ -921,6 +924,7 @@ TargetAttributes = { 00E356ED1AD99517003FC87E = { CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 1130; TestTargetID = 13B07F861A680F5B00A75B9A; }; 13B07F861A680F5B00A75B9A = { @@ -1434,6 +1438,7 @@ F151983C2100DC3D000F6E97 /* AppDelegate.swift in Sources */, FF83DAA92226905A00A34C93 /* CustomImageLoader.swift in Sources */, FF9A6F4121FA8E2500D36D14 /* MediaPickCoordinator.swift in Sources */, + 1EE61FB623C0E47F003727EC /* ShortcutCoordinator.swift in Sources */, F151983D2100DC3D000F6E97 /* MediaProvider.swift in Sources */, FF6836C822035EAB00A0C562 /* MediaUploadCoordinator.swift in Sources */, 7EC7328F21907E3F00FED2E6 /* GutenbergViewController.swift in Sources */, @@ -1493,6 +1498,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -1522,6 +1528,8 @@ "-lc++", ); PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/gutenberg.app/gutenberg"; }; name = Debug; @@ -1531,6 +1539,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; COPY_PHASE_STRIP = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1557,6 +1566,7 @@ "-lc++", ); PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/gutenberg.app/gutenberg"; }; name = Release; diff --git a/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg.xcscheme b/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg.xcscheme index 9f2d80e4dc..d1115f73be 100644 --- a/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg.xcscheme +++ b/ios/gutenberg.xcodeproj/xcshareddata/xcschemes/gutenberg.xcscheme @@ -55,6 +55,15 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + @@ -67,17 +76,6 @@ - - - - - - + + mediaOptions) { + @Override + public void onOtherMediaOptionsReceived(ArrayList mediaOptions) { WritableArray writableArray = new WritableNativeArray(); for (MediaOption mediaOption : mediaOptions) { writableArray.pushMap(mediaOption.toMap()); @@ -225,7 +259,8 @@ public void onUploadMediaFileSelected(List mediaList) { } } - @Override public void onUploadMediaFileClear(int mediaId) { + @Override + public void onUploadMediaFileClear(int mediaId) { setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_RESET, mediaId, null, 0); } 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 index 794b12c7f7..5c427e3f5b 100644 --- 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 @@ -5,6 +5,8 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; +import org.jetbrains.annotations.NotNull; + import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -21,15 +23,17 @@ public RNReactNativeGutenbergBridgePackage(GutenbergBridgeJS2Parent gutenbergBri mGutenbergBridgeJS2Parent = gutenbergBridgeJS2Parent; } + @NotNull @Override - public List createNativeModules(ReactApplicationContext reactContext) { + public List createNativeModules(@NotNull ReactApplicationContext reactContext) { mRNReactNativeGutenbergBridgeModule = new RNReactNativeGutenbergBridgeModule(reactContext, mGutenbergBridgeJS2Parent); - return Arrays.asList(mRNReactNativeGutenbergBridgeModule); + return Arrays.asList(mRNReactNativeGutenbergBridgeModule); } + @NotNull @Override - public List createViewManagers(ReactApplicationContext reactContext) { + public List createViewManagers(@NotNull ReactApplicationContext reactContext) { return Collections.emptyList(); } } diff --git a/react-native-gutenberg-bridge/ios/Gutenberg.swift b/react-native-gutenberg-bridge/ios/Gutenberg.swift index 8efe38b3fc..b0cc64fdeb 100644 --- a/react-native-gutenberg-bridge/ios/Gutenberg.swift +++ b/react-native-gutenberg-bridge/ios/Gutenberg.swift @@ -97,6 +97,11 @@ public class Gutenberg: NSObject { bridgeModule.sendEvent(withName: EventName.updateHtml, body: ["html": html]) } + public func sendShortcut(_ shortcut: Shortcut) { + let event = mapShortcutToEvent(shortcut) + bridgeModule.sendEvent(withName: event, body: nil) + } + public func mediaUploadUpdate(id: Int32, state: MediaUploadState, progress: Float, url: URL?, serverID: Int32?) { var data: [String: Any] = ["mediaId": id, "state": state.rawValue, "progress": progress]; if let url = url { @@ -125,6 +130,14 @@ public class Gutenberg: NSObject { let url = sourceURL(for: bridge) return !(url?.isFileURL ?? true) } + + private func mapShortcutToEvent(_ shortcut: Shortcut) -> String { + switch(shortcut) { + case .bold: return EventName.toggleBold + case .italic: return EventName.toggleItalic + case .addEditLink: return EventName.addEditLink + } + } } extension Gutenberg: RCTBridgeDelegate { @@ -150,6 +163,15 @@ extension Gutenberg { static let mediaUpload = "mediaUpload" static let setFocusOnTitle = "setFocusOnTitle" static let mediaAppend = "mediaAppend" + static let toggleBold = "toggleBold" + static let toggleItalic = "toggleItalic" + static let addEditLink = "addEditLink" + } + + public enum Shortcut { + case bold + case italic + case addEditLink } public enum MediaUploadState: Int { diff --git a/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.swift b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.swift index a4f3512fa9..78478fdd42 100644 --- a/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.swift +++ b/react-native-gutenberg-bridge/ios/RNReactNativeGutenbergBridge.swift @@ -200,7 +200,10 @@ extension RNReactNativeGutenbergBridge { Gutenberg.EventName.updateHtml, Gutenberg.EventName.mediaUpload, Gutenberg.EventName.setFocusOnTitle, - Gutenberg.EventName.mediaAppend + Gutenberg.EventName.mediaAppend, + Gutenberg.EventName.toggleBold, + Gutenberg.EventName.toggleItalic, + Gutenberg.EventName.addEditLink ] }