Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…rg-mobile into issue/372-move-title-to-rich-text

* 'develop' of https://github.com/wordpress-mobile/gutenberg-mobile:
  Added missing react method signature (#523)
  passing mediaId in onMediaSelected (#521)
  v0.3.4
  Update GB bundle.
  Refactor name of MediaSource to avoid name collision on the main app.
  Update Gutenberg reference.
  refactor media upload methods to be inline with JS and iOS
  Refactor names of helper methods.
  Change media upload sync method.
  Implement enum using strings to simplify conversion logic.
  Remove whitespace
  Refactor method name to make it more obvious the intent.
  Refactor bridge media protocol methods to a single method.
  Merge branch 'develop' into feature/media_upload_methods_refactor
  Refactor media upload names to more consistent names.
  Removes border from title and changes the placeholder text.
  passing null to onImageQueryReattach() on Android
  Implement reattach of events on iOS.
  Add the ability to set font family, weight, size, and style from RN
  Recommend using the gutenberg-mobile repo

# Conflicts:
#	gutenberg
  • Loading branch information
daniloercoli committed Jan 30, 2019
2 parents 042c372 + bc8fde1 commit c8738ff
Show file tree
Hide file tree
Showing 17 changed files with 395 additions and 301 deletions.
198 changes: 102 additions & 96 deletions bundle/android/App.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bundle/android/App.js.map

Large diffs are not rendered by default.

210 changes: 108 additions & 102 deletions bundle/ios/App.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bundle/ios/App.js.map

Large diffs are not rendered by default.

39 changes: 21 additions & 18 deletions ios/gutenberg/GutenbergViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,28 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
print("↳ HTML: \(html)")
}

func gutenbergDidRequestMediaPicker(with callback: @escaping MediaPickerDidPickMediaCallback) {
print("Gutenberg did request media picker, passing a sample url in callback")
callback(1, "https://cldup.com/cXyG__fTLN.jpg")
func gutenbergDidRequestMedia(from source: MediaPickerSource, with callback: @escaping MediaPickerDidPickMediaCallback) {
switch source {
case .mediaLibrary:
print("Gutenberg did request media picker, passing a sample url in callback")
callback(1, "https://cldup.com/cXyG__fTLN.jpg")
case .deviceLibrary:
print("Gutenberg did request a device media picker, opening the device picker")
mediaPickAndUploadCoordinator = MediaPickAndUploadCoordinator(presenter: self, gutenberg: gutenberg, mediaCallback: callback, finishCallback: {
self.mediaPickAndUploadCoordinator = nil
} )
mediaPickAndUploadCoordinator?.pickAndUpload(from: .savedPhotosAlbum)
case .deviceCamera:
print("Gutenberg did request a device media picker, opening the camera picker")
mediaPickAndUploadCoordinator = MediaPickAndUploadCoordinator(presenter: self, gutenberg: gutenberg, mediaCallback: callback, finishCallback: {
self.mediaPickAndUploadCoordinator = nil
} )
mediaPickAndUploadCoordinator?.pickAndUpload(from: .camera)
}
}

func gutenbergDidRequestMediaFromDevicePicker(with callback: @escaping MediaPickerDidPickMediaCallback) {
print("Gutenberg did request a device media picker, opening the device picker")
mediaPickAndUploadCoordinator = MediaPickAndUploadCoordinator(presenter: self, gutenberg: gutenberg, mediaCallback: callback, finishCallback: {
self.mediaPickAndUploadCoordinator = nil
} )
mediaPickAndUploadCoordinator?.pickAndUpload(from: .savedPhotosAlbum)
}

func gutenbergDidRequestMediaFromCameraPicker(with callback: @escaping MediaPickerDidPickMediaCallback) {
print("Gutenberg did request a device media picker, opening the camera picker")
mediaPickAndUploadCoordinator = MediaPickAndUploadCoordinator(presenter: self, gutenberg: gutenberg, mediaCallback: callback, finishCallback: {
self.mediaPickAndUploadCoordinator = nil
} )
mediaPickAndUploadCoordinator?.pickAndUpload(from: .camera)

func gutenbergDidRequestMediaUploadSync() {
print("Gutenberg request for media uploads to be resync")
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gutenberg-mobile",
"version": "0.3.3",
"version": "0.3.4",
"private": true,
"config": {
"jsfiles": "./*.js src/*.js src/**/*.js src/**/**/*.js",
Expand Down
2 changes: 2 additions & 0 deletions react-native-aztec/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## Notice: We have git subtree'd this repo into https://github.com/wordpress-mobile/gutenberg-mobile. It is recommended that any new development happens on that one instead. Thanks!

# react-native-aztec

Wrapping Aztec Android and Aztec iOS in a React Native component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@


import android.graphics.Color;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import com.facebook.infer.annotation.Assertions;
Expand All @@ -17,11 +19,14 @@
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewDefaults;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.scroll.ScrollEvent;
import com.facebook.react.views.scroll.ScrollEventType;
import com.facebook.react.views.text.DefaultStyleValuesUtil;
import com.facebook.react.views.text.ReactFontManager;
import com.facebook.react.views.textinput.ReactContentSizeChangedEvent;
import com.facebook.react.views.textinput.ReactTextChangedEvent;
import com.facebook.react.views.textinput.ReactTextInputEvent;
Expand All @@ -47,6 +52,7 @@ public class ReactAztecManager extends SimpleViewManager<ReactAztecText> {
private static final int FOCUS_TEXT_INPUT = 1;
private static final int BLUR_TEXT_INPUT = 2;
private static final int COMMAND_NOTIFY_APPLY_FORMAT = 100;
private static final int UNSET = -1;

// we define the same codes in ReactAztecText as they have for ReactNative's TextInput, so
// it's easier to handle focus between Aztec and TextInput instances on the same screen.
Expand Down Expand Up @@ -171,6 +177,92 @@ private void setTextfromJS(ReactAztecText view, String text) {
view.setIsSettingTextFromJS(false);
}


/*
The code below was taken from the class ReactTextInputManager
*/
@ReactProp(name = ViewProps.FONT_SIZE, defaultFloat = ViewDefaults.FONT_SIZE_SP)
public void setFontSize(ReactAztecText view, float fontSize) {
view.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
(int) Math.ceil(PixelUtil.toPixelFromSP(fontSize)));
}

@ReactProp(name = ViewProps.FONT_FAMILY)
public void setFontFamily(ReactAztecText view, String fontFamily) {
int style = Typeface.NORMAL;
if (view.getTypeface() != null) {
style = view.getTypeface().getStyle();
}
Typeface newTypeface = ReactFontManager.getInstance().getTypeface(
fontFamily,
style,
view.getContext().getAssets());
view.setTypeface(newTypeface);
}

/**
/* This code was taken from the method setFontWeight of the class ReactTextShadowNode
/* TODO: Factor into a common place they can both use
*/
@ReactProp(name = ViewProps.FONT_WEIGHT)
public void setFontWeight(ReactAztecText view, @Nullable String fontWeightString) {
int fontWeightNumeric = fontWeightString != null ?
parseNumericFontWeight(fontWeightString) : -1;
int fontWeight = UNSET;
if (fontWeightNumeric >= 500 || "bold".equals(fontWeightString)) {
fontWeight = Typeface.BOLD;
} else if ("normal".equals(fontWeightString) ||
(fontWeightNumeric != -1 && fontWeightNumeric < 500)) {
fontWeight = Typeface.NORMAL;
}
Typeface currentTypeface = view.getTypeface();
if (currentTypeface == null) {
currentTypeface = Typeface.DEFAULT;
}
if (fontWeight != currentTypeface.getStyle()) {
view.setTypeface(currentTypeface, fontWeight);
}
}

/**
/* This code was taken from the method setFontStyle of the class ReactTextShadowNode
/* TODO: Factor into a common place they can both use
*/
@ReactProp(name = ViewProps.FONT_STYLE)
public void setFontStyle(ReactAztecText view, @Nullable String fontStyleString) {
int fontStyle = UNSET;
if ("italic".equals(fontStyleString)) {
fontStyle = Typeface.ITALIC;
} else if ("normal".equals(fontStyleString)) {
fontStyle = Typeface.NORMAL;
}

Typeface currentTypeface = view.getTypeface();
if (currentTypeface == null) {
currentTypeface = Typeface.DEFAULT;
}
if (fontStyle != currentTypeface.getStyle()) {
view.setTypeface(currentTypeface, fontStyle);
}
}

/**
* This code was taken from the method parseNumericFontWeight of the class ReactTextShadowNode
* TODO: Factor into a common place they can both use
*
* Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
* return the weight.
*/
private static int parseNumericFontWeight(String fontWeightString) {
// This should be much faster than using regex to verify input and Integer.parseInt
return fontWeightString.length() == 3 && fontWeightString.endsWith("00")
&& fontWeightString.charAt(0) <= '9' && fontWeightString.charAt(0) >= '1' ?
100 * (fontWeightString.charAt(0) - '0') : -1;
}

/* End of the code taken from ReactTextInputManager */

@ReactProp(name = "color", customType = "Color")
public void setColor(ReactAztecText view, @Nullable Integer color) {
int newColor = Color.BLACK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public interface GutenbergBridgeJS2Parent {
void responseHtml(String title, String html, boolean changed);

interface MediaSelectedCallback {
void onMediaSelected(String mediaUrl);
void onMediaSelected(int mediaId, String mediaUrl);
}

interface MediaUploadCallback {
Expand All @@ -14,11 +14,11 @@ interface MediaUploadCallback {
void onMediaFileUploadFailed(int mediaId);
}

void onMediaLibraryPressed(MediaSelectedCallback mediaSelectedCallback);
void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback);

void onUploadMediaPressed(MediaUploadCallback mediaUploadCallback);
void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback);

void onCapturePhotoPressed(MediaUploadCallback mediaUploadCallback);
void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCallback);

void onImageQueryReattach(MediaUploadCallback mediaUploadCallback);
void mediaUploadSync(MediaUploadCallback mediaUploadCallback);
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModu

private static final int MEDIA_SERVER_ID_UNKNOWN = 0;

private static final String MEDIA_SOURCE_MEDIA_LIBRARY = "SITE_MEDIA_LIBRARY";
private static final String MEDIA_SOURCE_DEVICE_LIBRARY = "DEVICE_MEDIA_LIBRARY";
private static final String MEDIA_SOURCE_DEVICE_CAMERA = "DEVICE_CAMERA";


public RNReactNativeGutenbergBridgeModule(ReactApplicationContext reactContext,
GutenbergBridgeJS2Parent gutenbergBridgeJS2Parent) {
Expand Down Expand Up @@ -73,35 +77,38 @@ public void provideToNative_Html(String html, String title, boolean changed) {
mGutenbergBridgeJS2Parent.responseHtml(title, html, changed);
}

@ReactMethod
public void onMediaLibraryPressed(final Callback onMediaSelected) {
mGutenbergBridgeJS2Parent.onMediaLibraryPressed(new MediaSelectedCallback() {
@Override public void onMediaSelected(String mediaUrl) {
onMediaSelected.invoke(mediaUrl);
}
});
}

@ReactMethod
public void onImageQueryReattach(final Callback onImageQueryReattached) {
mGutenbergBridgeJS2Parent.onImageQueryReattach(getNewUploadMediaCallback(onImageQueryReattached));
public void requestMediaPickFrom(String mediaSource, final Callback onUploadMediaSelected) {
if (mediaSource.equals(MEDIA_SOURCE_MEDIA_LIBRARY)) {
mGutenbergBridgeJS2Parent.requestMediaPickFromMediaLibrary(getNewMediaSelectedCallback(onUploadMediaSelected));
} else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_LIBRARY)) {
mGutenbergBridgeJS2Parent.requestMediaPickFromDeviceLibrary(getNewUploadMediaCallback(onUploadMediaSelected));
} else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_CAMERA)) {
mGutenbergBridgeJS2Parent.requestMediaPickerFromDeviceCamera(getNewUploadMediaCallback(onUploadMediaSelected));
}
}

@ReactMethod
public void onUploadMediaPressed(final Callback onUploadMediaSelected) {
mGutenbergBridgeJS2Parent.onUploadMediaPressed(getNewUploadMediaCallback(onUploadMediaSelected));
public void mediaUploadSync() {
mGutenbergBridgeJS2Parent.mediaUploadSync(getNewUploadMediaCallback(null));
}

@ReactMethod
public void onCapturePhotoPressed(final Callback onPhotoCaptured) {
mGutenbergBridgeJS2Parent.onCapturePhotoPressed(getNewUploadMediaCallback(onPhotoCaptured));
private MediaSelectedCallback getNewMediaSelectedCallback(final Callback jsCallback) {
return new MediaSelectedCallback() {
@Override public void onMediaSelected(int mediaId, String mediaUrl) {
jsCallback.invoke(mediaId, mediaUrl);
}
};
}

private GutenbergBridgeJS2Parent.MediaUploadCallback getNewUploadMediaCallback(final Callback jsCallback) {
return new GutenbergBridgeJS2Parent.MediaUploadCallback() {
@Override
public void onUploadMediaFileSelected(int mediaId, String mediaUri) {
jsCallback.invoke(mediaId, mediaUri, 0);
if (jsCallback != null) {
jsCallback.invoke(mediaId, mediaUri, 0);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,27 +89,30 @@ public void responseHtml(String title, String html, boolean changed) {
mGetContentCountDownLatch.countDown();
}

@Override public void onMediaLibraryPressed(MediaSelectedCallback mediaSelectedCallback) {
@Override
public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback) {
mPendingMediaSelectedCallback = mediaSelectedCallback;
onMediaLibraryButtonListener.onMediaLibraryButtonClicked();
}

@Override
public void onUploadMediaPressed(MediaUploadCallback mediaUploadCallback) {
public void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback) {
mPendingMediaUploadCallback = mediaUploadCallback;
onMediaLibraryButtonListener.onUploadMediaButtonClicked();
}

@Override
public void onCapturePhotoPressed(MediaUploadCallback mediaUploadCallback) {
public void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCallback) {
mPendingMediaUploadCallback = mediaUploadCallback;
onMediaLibraryButtonListener.onCapturePhotoButtonClicked();
}

@Override public void onImageQueryReattach(MediaUploadCallback mediaUploadCallback) {
@Override
public void mediaUploadSync(MediaUploadCallback mediaUploadCallback) {
mPendingMediaUploadCallback = mediaUploadCallback;
onReattachQueryListener.onQueryCurrentProgressForUploadingMedia();
}

});
return Arrays.asList(
new MainReactPackage(),
Expand Down Expand Up @@ -313,9 +316,9 @@ public CharSequence getTitle(OnGetContentTimeout onGetContentTimeout) {
return "";
}

public void appendMediaFile(final String mediaUrl) {
public void appendMediaFile(int mediaId, final String mediaUrl) {
if (mPendingMediaSelectedCallback != null) {
mPendingMediaSelectedCallback.onMediaSelected(mediaUrl);
mPendingMediaSelectedCallback.onMediaSelected(mediaId, mediaUrl);
mPendingMediaSelectedCallback = null;
}
}
Expand Down
16 changes: 8 additions & 8 deletions react-native-gutenberg-bridge/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ export function subscribeMediaUpload( callback ) {
return gutenbergBridgeEvents.addListener( 'mediaUpload', callback );
}

export function onMediaLibraryPressed( callback ) {
return RNReactNativeGutenbergBridge.onMediaLibraryPressed( callback );
export function requestMediaPickFromMediaLibrary( callback ) {
return RNReactNativeGutenbergBridge.requestMediaPickFrom( 'SITE_MEDIA_LIBRARY', callback );
}

export function onUploadMediaPressed( callback ) {
return RNReactNativeGutenbergBridge.onUploadMediaPressed( callback );
export function requestMediaPickFromDeviceLibrary( callback ) {
return RNReactNativeGutenbergBridge.requestMediaPickFrom( 'DEVICE_MEDIA_LIBRARY', callback );
}

export function onCapturePhotoPressed( callback ) {
return RNReactNativeGutenbergBridge.onCapturePhotoPressed( callback );
export function requestMediaPickFromDeviceCamera( callback ) {
return RNReactNativeGutenbergBridge.requestMediaPickFrom( 'DEVICE_CAMERA', callback );
}

export function onImageQueryReattach( callback ) {
return RNReactNativeGutenbergBridge.onImageQueryReattach( callback );
export function mediaUploadSync() {
return RNReactNativeGutenbergBridge.mediaUploadSync();
}

export default RNReactNativeGutenbergBridge;
25 changes: 13 additions & 12 deletions react-native-gutenberg-bridge/ios/GutenbergBridgeDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
public typealias MediaPickerDidPickMediaCallback = (_ id: Int?, _ url: String?) -> Void

public enum MediaPickerSource: String {
case mediaLibrary = "SITE_MEDIA_LIBRARY"
case deviceLibrary = "DEVICE_MEDIA_LIBRARY"
case deviceCamera = "DEVICE_CAMERA"
}

public protocol GutenbergBridgeDelegate: class {
/// Tells the delegate that Gutenberg had returned the requested HTML content.
/// You can request HTML content by calling `requestHTML()` on a Gutenberg bridge instance.
Expand All @@ -12,21 +18,16 @@ public protocol GutenbergBridgeDelegate: class {

/// Tells the delegate that an image block requested an image from the media picker.
///
/// - Parameter callback: A callbak block to be called with the selected
/// image Url or nil to signal that the action was canceled.
func gutenbergDidRequestMediaPicker(with callback: @escaping MediaPickerDidPickMediaCallback)

/// Tells the delegate that an image block requested an image from the device media.
/// - Parameters:
/// - source: the source from where the picker will get the media
/// - callback: A callback block to be called with an upload mediaIdentifier and a placeholder image file url, use nil on both parameters to signal that the action was canceled.
///
/// - Parameter callback: A callbak block to be called with an upload mediaIdentifier and a placaholder image file url,
/// use nil on both parameters to signal that the action was canceled.
func gutenbergDidRequestMediaFromDevicePicker(with callback: @escaping MediaPickerDidPickMediaCallback)
func gutenbergDidRequestMedia(from source: MediaPickerSource, with callback: @escaping MediaPickerDidPickMediaCallback)


/// Tells the delegate that an image block requested an image from the device cameras.
/// Tells the delegate that an image block requested to reconnect with media uploads coordinator.
///
/// - Parameter callback: A callbak block to be called with and temporary
/// image file url and an mediaIdentifier or nil to signal that the action was canceled.
func gutenbergDidRequestMediaFromCameraPicker(with callback: @escaping MediaPickerDidPickMediaCallback)
func gutenbergDidRequestMediaUploadSync()

/// Tells the delegate that the Gutenberg module has finished loading.
///
Expand Down
Loading

0 comments on commit c8738ff

Please sign in to comment.