diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index c5265fddde..7e4aadda74 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -2,6 +2,7 @@ ------ * [**] Add support for customizing gradient type and angle in Buttons and Cover blocks. * [*] Show content information (block, word and characters counts). +* [*] [Android] Fix handling of upload completion while re-opening the editor 1.30.0 ------ diff --git a/android/app/src/main/java/com/gutenberg/MainApplication.java b/android/app/src/main/java/com/gutenberg/MainApplication.java index 71ef563b67..3245621ee2 100644 --- a/android/app/src/main/java/com/gutenberg/MainApplication.java +++ b/android/app/src/main/java/com/gutenberg/MainApplication.java @@ -50,31 +50,31 @@ public void responseHtml(String title, String html, boolean changed, ReadableMap } @Override - public void requestMediaImport(String url, MediaUploadCallback mediaUploadCallback) { + public void requestMediaImport(String url, MediaSelectedCallback mediaSelectedCallback) { } @Override - public void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCallback, MediaType mediaType) { + public void requestMediaPickerFromDeviceCamera(MediaSelectedCallback mediaSelectedCallback, MediaType mediaType) { } @Override - public void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection, MediaType mediaType) { + public void requestMediaPickFromDeviceLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) { } @Override - public void requestMediaPickFromMediaLibrary(MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection, MediaType mediaType) { + public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) { List rnMediaList = new ArrayList<>(); if (mediaType == MediaType.IMAGE) { rnMediaList.add(new Media(1, "https://cldup.com/cXyG__fTLN.jpg", "image", "Mountain" )); } else if (mediaType == MediaType.VIDEO) { rnMediaList.add(new Media(2, "https://i.cloudup.com/YtZFJbuQCE.mov", "video", "Cloudup" )); } - mediaUploadCallback.onUploadMediaFileSelected(rnMediaList); + mediaSelectedCallback.onMediaFileSelected(rnMediaList); } @Override - public void mediaUploadSync(MediaUploadCallback mediaUploadCallback) { + public void mediaUploadSync(MediaSelectedCallback mediaSelectedCallback) { } @Override @@ -103,7 +103,7 @@ public void getOtherMediaPickerOptions(OtherMediaOptionsReceivedCallback otherMe } @Override - public void requestMediaPickFrom(String mediaSource, MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection) { + public void requestMediaPickFrom(String mediaSource, MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection) { } @@ -113,7 +113,7 @@ public void requestImageFullscreenPreview(String mediaUrl) { } @Override - public void requestMediaEditor(MediaUploadCallback mediaUploadCallback, String mediaUrl) { + public void requestMediaEditor(MediaSelectedCallback mediaSelectedCallback, String mediaUrl) { } 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 index 4c947eac44..77cbff9122 100644 --- 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 @@ -23,8 +23,11 @@ interface OtherMediaOptionsReceivedCallback { void onOtherMediaOptionsReceived(ArrayList mediaList); } - interface MediaUploadCallback { - void onUploadMediaFileSelected(List mediaList); + interface MediaSelectedCallback { + void onMediaFileSelected(List mediaList); + } + + interface MediaUploadEventEmitter { void onUploadMediaFileClear(int mediaId); void onMediaFileUploadProgress(int mediaId, float progress); void onMediaFileUploadSucceeded(int mediaId, String mediaUrl, int serverId); @@ -109,15 +112,15 @@ public static GutenbergUserEvent getEnum(String eventName) { } } - void requestMediaPickFromMediaLibrary(MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection, MediaType mediaType); + void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType); - void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection, MediaType mediaType); + void requestMediaPickFromDeviceLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType); - void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCallback, MediaType mediaType); + void requestMediaPickerFromDeviceCamera(MediaSelectedCallback mediaSelectedCallback, MediaType mediaType); - void requestMediaImport(String url, MediaUploadCallback mediaUploadCallback); + void requestMediaImport(String url, MediaSelectedCallback mediaSelectedCallback); - void mediaUploadSync(MediaUploadCallback mediaUploadCallback); + void mediaUploadSync(MediaSelectedCallback mediaSelectedCallback); void requestImageFailedRetryDialog(int mediaId); @@ -131,11 +134,11 @@ public static GutenbergUserEvent getEnum(String eventName) { void getOtherMediaPickerOptions(OtherMediaOptionsReceivedCallback otherMediaOptionsReceivedCallback, MediaType mediaType); - void requestMediaPickFrom(String mediaSource, MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection); + void requestMediaPickFrom(String mediaSource, MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection); void requestImageFullscreenPreview(String mediaUrl); - void requestMediaEditor(MediaUploadCallback mediaUploadCallback, String mediaUrl); + void requestMediaEditor(MediaSelectedCallback mediaSelectedCallback, String mediaUrl); void logUserEvent(GutenbergUserEvent gutenbergUserEvent, ReadableMap eventProperties); 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 index 9578619132..db1aabb82f 100644 --- 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 @@ -22,6 +22,7 @@ import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaType; import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.OtherMediaOptionsReceivedCallback; import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.StarterPageTemplatesTooltipShownCallback; +import org.wordpress.mobile.WPAndroidGlue.DeferredEventEmitter; import org.wordpress.mobile.WPAndroidGlue.MediaOption; import java.io.Serializable; @@ -30,7 +31,8 @@ import java.util.List; import java.util.Map; -public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModule { +public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModule implements + DeferredEventEmitter.JSEventEmitter { private final ReactApplicationContext mReactContext; private final GutenbergBridgeJS2Parent mGutenbergBridgeJS2Parent; @@ -38,7 +40,6 @@ public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModu private static final String EVENT_NAME_UPDATE_HTML = "updateHtml"; private static final String EVENT_NAME_UPDATE_TITLE = "setTitle"; private static final String EVENT_NAME_FOCUS_TITLE = "setFocusOnTitle"; - private static final String EVENT_NAME_MEDIA_UPLOAD = "mediaUpload"; private static final String EVENT_NAME_MEDIA_APPEND = "mediaAppend"; private static final String EVENT_NAME_TOGGLE_HTML_MODE = "toggleHTMLMode"; private static final String EVENT_NAME_NOTIFY_MODAL_CLOSED = "notifyModalClosed"; @@ -48,28 +49,17 @@ public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModu private static final String MAP_KEY_UPDATE_HTML = "html"; private static final String MAP_KEY_UPDATE_TITLE = "title"; - private static final String MAP_KEY_MEDIA_FILE_UPLOAD_STATE = "state"; - private static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID = "mediaId"; - private static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL = "mediaUrl"; - private static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_TYPE = "mediaType"; - private static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_PROGRESS = "progress"; - private static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_SERVER_ID = "mediaServerId"; + public static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID = "mediaId"; + public static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL = "mediaUrl"; + public static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_TYPE = "mediaType"; private static final String MAP_KEY_THEME_UPDATE_COLORS = "colors"; private static final String MAP_KEY_THEME_UPDATE_GRADIENTS = "gradients"; private static final String MAP_KEY_IS_PREFERRED_COLOR_SCHEME_DARK = "isPreferredColorSchemeDark"; - private static final int MEDIA_UPLOAD_STATE_UPLOADING = 1; - private static final int MEDIA_UPLOAD_STATE_SUCCEEDED = 2; - private static final int MEDIA_UPLOAD_STATE_FAILED = 3; - private static final int MEDIA_UPLOAD_STATE_RESET = 4; - - 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"; - private static final String MEDIA_SOURCE_MEDIA_EDITOR = "MEDIA_EDITOR"; private static final String MAP_KEY_REPLACE_BLOCK_HTML = "html"; private static final String MAP_KEY_REPLACE_BLOCK_BLOCK_ID = "clientId"; @@ -89,7 +79,6 @@ public String getName() { return "RNReactNativeGutenbergBridge"; } - @Override public Map getConstants() { final HashMap constants = new HashMap<>(); @@ -97,7 +86,8 @@ public Map getConstants() { return constants; } - private void emitToJS(String eventName, @Nullable WritableMap data) { + @Override + public void emitToJS(String eventName, @Nullable WritableMap data) { mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, data); } @@ -165,16 +155,16 @@ public void editorDidMount(ReadableArray unsupportedBlockNames) { } @ReactMethod - public void requestMediaPickFrom(String mediaSource, ReadableArray filter, Boolean allowMultipleSelection, final Callback onUploadMediaSelected) { + public void requestMediaPickFrom(String mediaSource, ReadableArray filter, Boolean allowMultipleSelection, final Callback onMediaSelected) { MediaType mediaType = getMediaTypeFromFilter(filter); if (mediaSource.equals(MEDIA_SOURCE_MEDIA_LIBRARY)) { - mGutenbergBridgeJS2Parent.requestMediaPickFromMediaLibrary(getNewUploadMediaCallback(allowMultipleSelection, onUploadMediaSelected), allowMultipleSelection, mediaType); + mGutenbergBridgeJS2Parent.requestMediaPickFromMediaLibrary(getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), allowMultipleSelection, mediaType); } else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_LIBRARY)) { - mGutenbergBridgeJS2Parent.requestMediaPickFromDeviceLibrary(getNewUploadMediaCallback(allowMultipleSelection, onUploadMediaSelected), allowMultipleSelection, mediaType); + mGutenbergBridgeJS2Parent.requestMediaPickFromDeviceLibrary(getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), allowMultipleSelection, mediaType); } else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_CAMERA)) { - mGutenbergBridgeJS2Parent.requestMediaPickerFromDeviceCamera(getNewUploadMediaCallback(allowMultipleSelection, onUploadMediaSelected), mediaType); + mGutenbergBridgeJS2Parent.requestMediaPickerFromDeviceCamera(getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), mediaType); } else { - mGutenbergBridgeJS2Parent.requestMediaPickFrom(mediaSource, getNewUploadMediaCallback(allowMultipleSelection, onUploadMediaSelected), allowMultipleSelection); + mGutenbergBridgeJS2Parent.requestMediaPickFrom(mediaSource, getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), allowMultipleSelection); } } @@ -197,12 +187,12 @@ private MediaType getMediaTypeFromFilter(ReadableArray filter) { @ReactMethod public void requestMediaImport(String url, final Callback onUploadMediaSelected) { - mGutenbergBridgeJS2Parent.requestMediaImport(url, getNewUploadMediaCallback(false, onUploadMediaSelected)); + mGutenbergBridgeJS2Parent.requestMediaImport(url, getNewMediaSelectedCallback(false, onUploadMediaSelected)); } @ReactMethod public void mediaUploadSync() { - mGutenbergBridgeJS2Parent.mediaUploadSync(getNewUploadMediaCallback(false,null)); + mGutenbergBridgeJS2Parent.mediaUploadSync(getNewMediaSelectedCallback(false,null)); } @ReactMethod @@ -227,7 +217,7 @@ public void requestImageFullscreenPreview(String mediaUrl) { @ReactMethod public void requestMediaEditor(String mediaUrl, final Callback onUploadMediaSelected) { - mGutenbergBridgeJS2Parent.requestMediaEditor(getNewUploadMediaCallback(false, onUploadMediaSelected), mediaUrl); + mGutenbergBridgeJS2Parent.requestMediaEditor(getNewMediaSelectedCallback(false, onUploadMediaSelected), mediaUrl); } @ReactMethod @@ -316,10 +306,10 @@ private StarterPageTemplatesTooltipShownCallback requestStarterPageTemplatesTool }; } - private GutenbergBridgeJS2Parent.MediaUploadCallback getNewUploadMediaCallback(final Boolean allowMultipleSelection, final Callback jsCallback) { - return new GutenbergBridgeJS2Parent.MediaUploadCallback() { + private GutenbergBridgeJS2Parent.MediaSelectedCallback getNewMediaSelectedCallback(final Boolean allowMultipleSelection, final Callback jsCallback) { + return new GutenbergBridgeJS2Parent.MediaSelectedCallback() { @Override - public void onUploadMediaFileSelected(List mediaList) { + public void onMediaFileSelected(List mediaList) { if (allowMultipleSelection) { WritableArray writableArray = new WritableNativeArray(); for (RNMedia media : mediaList) { @@ -335,42 +325,9 @@ public void onUploadMediaFileSelected(List mediaList) { } } - @Override public void onUploadMediaFileClear(int mediaId) { - setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_RESET, mediaId, null, 0); - } - - @Override - public void onMediaFileUploadProgress(int mediaId, float progress) { - setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_UPLOADING, mediaId, null, progress); - } - - @Override - public void onMediaFileUploadSucceeded(int mediaId, String mediaUrl, int mediaServerId) { - setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_SUCCEEDED, mediaId, mediaUrl, 1, mediaServerId); - } - - @Override - public void onMediaFileUploadFailed(int mediaId) { - setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_FAILED, mediaId, null, 0); - } }; } - private void setMediaFileUploadDataInJS(int state, int mediaId, String mediaUrl, float progress) { - setMediaFileUploadDataInJS(state, mediaId, mediaUrl, progress, MEDIA_SERVER_ID_UNKNOWN); - } - - private void setMediaFileUploadDataInJS(int state, int mediaId, String mediaUrl, float progress, int mediaServerId) { - WritableMap writableMap = new WritableNativeMap(); - writableMap.putInt(MAP_KEY_MEDIA_FILE_UPLOAD_STATE, state); - writableMap.putInt(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID, mediaId); - writableMap.putString(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL, mediaUrl); - writableMap.putDouble(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_PROGRESS, progress); - if (mediaServerId != MEDIA_SERVER_ID_UNKNOWN) { - writableMap.putInt(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_SERVER_ID, mediaServerId); - } - emitToJS(EVENT_NAME_MEDIA_UPLOAD, writableMap); - } public void toggleEditorMode() { emitToJS(EVENT_NAME_TOGGLE_HTML_MODE, null); diff --git a/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgeModule.java.orig b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgeModule.java.orig new file mode 100644 index 0000000000..a6619ebfcc --- /dev/null +++ b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgeModule.java.orig @@ -0,0 +1,340 @@ +package org.wordpress.mobile.ReactNativeGutenbergBridge; + +import android.os.Bundle; + +import androidx.annotation.Nullable; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.modules.core.DeviceEventManagerModule; + +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.GutenbergUserEvent; +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaType; +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.OtherMediaOptionsReceivedCallback; +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.StarterPageTemplatesTooltipShownCallback; +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.RNMedia; +import org.wordpress.mobile.WPAndroidGlue.DeferredEventEmitter; +import org.wordpress.mobile.WPAndroidGlue.MediaOption; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModule implements + DeferredEventEmitter.JSEventEmitter { + private final ReactApplicationContext mReactContext; + private final GutenbergBridgeJS2Parent mGutenbergBridgeJS2Parent; + + private static final String EVENT_NAME_REQUEST_GET_HTML = "requestGetHtml"; + private static final String EVENT_NAME_UPDATE_HTML = "updateHtml"; + private static final String EVENT_NAME_UPDATE_TITLE = "setTitle"; + private static final String EVENT_NAME_FOCUS_TITLE = "setFocusOnTitle"; + private static final String EVENT_NAME_MEDIA_APPEND = "mediaAppend"; + private static final String EVENT_NAME_TOGGLE_HTML_MODE = "toggleHTMLMode"; + private static final String EVENT_NAME_NOTIFY_MODAL_CLOSED = "notifyModalClosed"; + private static final String EVENT_NAME_PREFERRED_COLOR_SCHEME = "preferredColorScheme"; + private static final String EVENT_NAME_MEDIA_REPLACE_BLOCK = "replaceBlock"; + private static final String EVENT_NAME_UPDATE_THEME = "updateTheme"; + + private static final String MAP_KEY_UPDATE_HTML = "html"; + private static final String MAP_KEY_UPDATE_TITLE = "title"; + public static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID = "mediaId"; + public static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL = "mediaUrl"; + public static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_TYPE = "mediaType"; + private static final String MAP_KEY_THEME_UPDATE_COLORS = "colors"; + private static final String MAP_KEY_THEME_UPDATE_GRADIENTS = "gradients"; + + private static final String MAP_KEY_IS_PREFERRED_COLOR_SCHEME_DARK = "isPreferredColorSchemeDark"; + + 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"; + + private static final String MAP_KEY_REPLACE_BLOCK_HTML = "html"; + private static final String MAP_KEY_REPLACE_BLOCK_BLOCK_ID = "clientId"; + + private boolean mIsDarkMode; + + public RNReactNativeGutenbergBridgeModule(ReactApplicationContext reactContext, + GutenbergBridgeJS2Parent gutenbergBridgeJS2Parent, boolean isDarkMode) { + super(reactContext); + mIsDarkMode = isDarkMode; + mReactContext = reactContext; + mGutenbergBridgeJS2Parent = gutenbergBridgeJS2Parent; + } + + @Override + public String getName() { + return "RNReactNativeGutenbergBridge"; + } + + @Override + public Map getConstants() { + final HashMap constants = new HashMap<>(); + constants.put("isInitialColorSchemeDark", mIsDarkMode); + return constants; + } + + @Override + public void emitToJS(String eventName, @Nullable WritableMap data) { + mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, data); + } + + public void getHtmlFromJS() { + emitToJS(EVENT_NAME_REQUEST_GET_HTML, null); + } + + public void setHtmlInJS(String html) { + WritableMap writableMap = new WritableNativeMap(); + writableMap.putString(MAP_KEY_UPDATE_HTML, html); + emitToJS(EVENT_NAME_UPDATE_HTML, writableMap); + } + + public void setTitleInJS(String title) { + WritableMap writableMap = new WritableNativeMap(); + writableMap.putString(MAP_KEY_UPDATE_TITLE, title); + emitToJS(EVENT_NAME_UPDATE_TITLE, writableMap); + } + + public void setFocusOnTitleInJS() { + WritableMap writableMap = new WritableNativeMap(); + emitToJS(EVENT_NAME_FOCUS_TITLE, writableMap); + } + + public void appendNewMediaBlock(int mediaId, String mediaUri, String mediaType) { + WritableMap writableMap = new WritableNativeMap(); + writableMap.putString(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_TYPE, mediaType); + writableMap.putString(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL, mediaUri); + writableMap.putInt(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID, mediaId); + emitToJS(EVENT_NAME_MEDIA_APPEND, writableMap); + } + + public void setPreferredColorScheme(boolean isDarkMode) { + WritableMap writableMap = new WritableNativeMap(); + writableMap.putBoolean(MAP_KEY_IS_PREFERRED_COLOR_SCHEME_DARK, isDarkMode); + emitToJS(EVENT_NAME_PREFERRED_COLOR_SCHEME, writableMap); + } + + public void updateTheme(@Nullable Bundle editorTheme) { + if (editorTheme == null) return; + + WritableMap writableMap = new WritableNativeMap(); + Serializable colors = editorTheme.getSerializable(MAP_KEY_THEME_UPDATE_COLORS); + Serializable gradients = editorTheme.getSerializable(MAP_KEY_THEME_UPDATE_GRADIENTS); + + if (colors != null) { + writableMap.putArray(MAP_KEY_THEME_UPDATE_COLORS, Arguments.fromList((ArrayList)colors)); + } + + if (gradients != null) { + writableMap.putArray(MAP_KEY_THEME_UPDATE_GRADIENTS, Arguments.fromList((ArrayList)gradients)); + } + + emitToJS(EVENT_NAME_UPDATE_THEME, writableMap); + } + + @ReactMethod + public void provideToNative_Html(String html, String title, boolean changed) { + mGutenbergBridgeJS2Parent.responseHtml(title, html, changed); + } + + @ReactMethod + public void editorDidMount(ReadableArray unsupportedBlockNames) { + mGutenbergBridgeJS2Parent.editorDidMount(unsupportedBlockNames); + } + + @ReactMethod + public void requestMediaPickFrom(String mediaSource, ReadableArray filter, Boolean allowMultipleSelection, final Callback onMediaSelected) { + MediaType mediaType = getMediaTypeFromFilter(filter); + if (mediaSource.equals(MEDIA_SOURCE_MEDIA_LIBRARY)) { + mGutenbergBridgeJS2Parent.requestMediaPickFromMediaLibrary(getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), allowMultipleSelection, mediaType); + } else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_LIBRARY)) { + mGutenbergBridgeJS2Parent.requestMediaPickFromDeviceLibrary(getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), allowMultipleSelection, mediaType); + } else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_CAMERA)) { + mGutenbergBridgeJS2Parent.requestMediaPickerFromDeviceCamera(getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), mediaType); + } else { + mGutenbergBridgeJS2Parent.requestMediaPickFrom(mediaSource, getNewMediaSelectedCallback(allowMultipleSelection, onMediaSelected), allowMultipleSelection); + } + } + + private MediaType getMediaTypeFromFilter(ReadableArray filter) { + switch (filter.size()) { + case 1: + return MediaType.getEnum(filter.getString(0)); + case 2: + MediaType filter0 = MediaType.getEnum(filter.getString(0)); + MediaType filter1 = MediaType.getEnum(filter.getString(1)); + + if ((filter0.equals(MediaType.VIDEO) && filter1.equals(MediaType.IMAGE)) + || (filter0.equals(MediaType.IMAGE) && filter1.equals(MediaType.VIDEO))) { + return MediaType.MEDIA; + } + default: + return MediaType.OTHER; + } + } + + @ReactMethod + public void requestMediaImport(String url, final Callback onUploadMediaSelected) { + mGutenbergBridgeJS2Parent.requestMediaImport(url, getNewMediaSelectedCallback(false, onUploadMediaSelected)); + } + + @ReactMethod + public void mediaUploadSync() { + mGutenbergBridgeJS2Parent.mediaUploadSync(getNewMediaSelectedCallback(false,null)); + } + + @ReactMethod + public void requestImageFailedRetryDialog(final int mediaId) { + mGutenbergBridgeJS2Parent.requestImageFailedRetryDialog(mediaId); + } + + @ReactMethod + public void requestImageUploadCancelDialog(final int mediaId) { + mGutenbergBridgeJS2Parent.requestImageUploadCancelDialog(mediaId); + } + + @ReactMethod + public void requestImageUploadCancel(final int mediaId) { + mGutenbergBridgeJS2Parent.requestImageUploadCancel(mediaId); + } + + @ReactMethod + public void requestImageFullscreenPreview(String mediaUrl) { + mGutenbergBridgeJS2Parent.requestImageFullscreenPreview(mediaUrl); + } + + @ReactMethod + public void requestMediaEditor(String mediaUrl, final Callback onUploadMediaSelected) { + mGutenbergBridgeJS2Parent.requestMediaEditor(getNewMediaSelectedCallback(false, onUploadMediaSelected), mediaUrl); + } + + @ReactMethod + public void editorDidEmitLog(String message, int logLevel) { + mGutenbergBridgeJS2Parent.editorDidEmitLog(message, GutenbergBridgeJS2Parent.LogLevel.valueOf(logLevel)); + } + + @ReactMethod + public void editorDidAutosave() { + mGutenbergBridgeJS2Parent.editorDidAutosave(); + } + + @ReactMethod + public void getOtherMediaOptions(ReadableArray filter, final Callback jsCallback) { + OtherMediaOptionsReceivedCallback otherMediaOptionsReceivedCallback = getNewOtherMediaReceivedCallback(jsCallback); + MediaType mediaType = getMediaTypeFromFilter(filter); + mGutenbergBridgeJS2Parent.getOtherMediaPickerOptions(otherMediaOptionsReceivedCallback, mediaType); + } + + @ReactMethod + public void fetchRequest(String path, Promise promise) { + mGutenbergBridgeJS2Parent.performRequest(path, + promise::resolve, + errorBundle -> { + WritableMap writableMap = Arguments.makeNativeMap(errorBundle); + if (writableMap.hasKey("code")) { + String code = String.valueOf(writableMap.getInt("code")); + promise.reject(code, new Error(), writableMap); + } else { + promise.reject(new Error(), writableMap); + } + }); + } + + @ReactMethod + public void logUserEvent(String eventName, ReadableMap eventProperties) { + mGutenbergBridgeJS2Parent.logUserEvent(GutenbergUserEvent.getEnum(eventName), eventProperties); + } + + @ReactMethod + public void requestUnsupportedBlockFallback(String content, String blockId, String blockName) { + mGutenbergBridgeJS2Parent.gutenbergDidRequestUnsupportedBlockFallback((savedContent, savedBlockId) -> + replaceBlock(savedContent, savedBlockId), content, blockId, blockName); + } + + private void replaceBlock(String content, String blockId) { + WritableMap writableMap = new WritableNativeMap(); + writableMap.putString(MAP_KEY_REPLACE_BLOCK_HTML, content); + writableMap.putString(MAP_KEY_REPLACE_BLOCK_BLOCK_ID, blockId); + emitToJS(EVENT_NAME_MEDIA_REPLACE_BLOCK, writableMap); + } + + private OtherMediaOptionsReceivedCallback getNewOtherMediaReceivedCallback(final Callback jsCallback) { + return new OtherMediaOptionsReceivedCallback() { + @Override public void onOtherMediaOptionsReceived(ArrayList mediaOptions) { + WritableArray writableArray = new WritableNativeArray(); + for (MediaOption mediaOption : mediaOptions) { + writableArray.pushMap(mediaOption.toMap()); + } + jsCallback.invoke(writableArray); + } + }; + } + + @ReactMethod + public void addMention(Promise promise) { + mGutenbergBridgeJS2Parent.onAddMention(promise::resolve); + } + + @ReactMethod + public void setStarterPageTemplatesTooltipShown(boolean tooltipShown) { + mGutenbergBridgeJS2Parent.setStarterPageTemplatesTooltipShown(tooltipShown); + } + + @ReactMethod + public void requestStarterPageTemplatesTooltipShown(final Callback jsCallback) { + StarterPageTemplatesTooltipShownCallback starterPageTemplatesTooltipShownCallback = requestStarterPageTemplatesTooltipShownCallback(jsCallback); + mGutenbergBridgeJS2Parent.requestStarterPageTemplatesTooltipShown(starterPageTemplatesTooltipShownCallback); + } + + private StarterPageTemplatesTooltipShownCallback requestStarterPageTemplatesTooltipShownCallback(final Callback jsCallback) { + return new StarterPageTemplatesTooltipShownCallback() { + @Override public void onRequestStarterPageTemplatesTooltipShown(boolean tooltipShown) { + jsCallback.invoke(tooltipShown); + } + }; + } + + private GutenbergBridgeJS2Parent.MediaSelectedCallback getNewMediaSelectedCallback(final Boolean allowMultipleSelection, final Callback jsCallback) { + return new GutenbergBridgeJS2Parent.MediaSelectedCallback() { + @Override + public void onMediaFileSelected(List mediaList) { + if (allowMultipleSelection) { + WritableArray writableArray = new WritableNativeArray(); + for (RNMedia media : mediaList) { + writableArray.pushMap(media.toMap()); + } + jsCallback.invoke(writableArray); + } else if (!mediaList.isEmpty()) { + jsCallback.invoke(mediaList.get(0).toMap()); + } else { + // if we have no media (e.g. when a content provider throws an exception during file copy), invoke + // the js callback with no arguments + jsCallback.invoke(); + } + } + + }; + } + + + public void toggleEditorMode() { + emitToJS(EVENT_NAME_TOGGLE_HTML_MODE, null); + } + + public void notifyModalClosed() { + emitToJS(EVENT_NAME_NOTIFY_MODAL_CLOSED, null); + } +} diff --git a/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/DeferredEventEmitter.java b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/DeferredEventEmitter.java new file mode 100644 index 0000000000..5ef2523424 --- /dev/null +++ b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/DeferredEventEmitter.java @@ -0,0 +1,124 @@ +package org.wordpress.mobile.WPAndroidGlue; + +import android.util.Pair; + +import androidx.annotation.Nullable; + +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeMap; + +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaUploadEventEmitter; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule.MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID; +import static org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule.MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL; + +public class DeferredEventEmitter implements MediaUploadEventEmitter { + public interface JSEventEmitter { + void emitToJS(String eventName, @Nullable WritableMap data); + } + private static final int MEDIA_SERVER_ID_UNKNOWN = 0; + private static final int MEDIA_UPLOAD_STATE_UPLOADING = 1; + private static final int MEDIA_UPLOAD_STATE_SUCCEEDED = 2; + private static final int MEDIA_UPLOAD_STATE_FAILED = 3; + private static final int MEDIA_UPLOAD_STATE_RESET = 4; + + private static final String EVENT_NAME_MEDIA_UPLOAD = "mediaUpload"; + + private static final String MAP_KEY_MEDIA_FILE_UPLOAD_STATE = "state"; + private static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_PROGRESS = "progress"; + private static final String MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_SERVER_ID = "mediaServerId"; + + + /** + * Used for storing deferred actions prior to editor mounting + */ + private Queue> mPendingActions = new ConcurrentLinkedQueue<>(); + + private JSEventEmitter mJSEventEmitter; + + void setEmitter(JSEventEmitter emitter) { + mJSEventEmitter = emitter; + flushActionQueueToJS(); + } + + /** This will queue actions to JS when the editor has not yet mounted. When the editor mounts, the events will be + * flushed. If the editor has already mounted, this will directly call emitToJS. This is useful for critical + * messages that have required actions, such as upload completion events. + * + * @param eventName the name of the JS event + * @param data the JS event data (can be null) + */ + private void queueActionToJS(String eventName, @Nullable WritableMap data) { + if (mJSEventEmitter == null) { + mPendingActions.add(new Pair<>(eventName, data)); + } else { + mJSEventEmitter.emitToJS(eventName, data); + } + } + + /** This will optimistically emit events to JS (i.e. when the editor has mounted). If the editor has not mounted, + * this will silently drop the message. This is useful to send non-critical messages in a safe way. + * + * @param eventName the name of the JS event + * @param data the JS event data (can be null) + */ + private void emitOrDrop(String eventName, @Nullable WritableMap data) { + if (mJSEventEmitter != null) { + mJSEventEmitter.emitToJS(eventName, data); + } + } + + private void flushActionQueueToJS() { + while (0 < mPendingActions.size()) { + final Pair action = mPendingActions.remove(); + mJSEventEmitter.emitToJS(action.first, action.second); + } + } + + private void setMediaFileUploadDataInJS(int state, int mediaId, String mediaUrl, float progress) { + setMediaFileUploadDataInJS(state, mediaId, mediaUrl, progress, MEDIA_SERVER_ID_UNKNOWN); + } + + private void setMediaFileUploadDataInJS(int state, int mediaId, String mediaUrl, float progress, int mediaServerId) { + WritableMap writableMap = new WritableNativeMap(); + writableMap.putInt(MAP_KEY_MEDIA_FILE_UPLOAD_STATE, state); + writableMap.putInt(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID, mediaId); + writableMap.putString(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL, mediaUrl); + writableMap.putDouble(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_PROGRESS, progress); + if (mediaServerId != MEDIA_SERVER_ID_UNKNOWN) { + writableMap.putInt(MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_SERVER_ID, mediaServerId); + } + if (isCriticalMessage(state)) { + queueActionToJS(EVENT_NAME_MEDIA_UPLOAD, writableMap); + } else { + emitOrDrop(EVENT_NAME_MEDIA_UPLOAD, writableMap); + } + } + + private boolean isCriticalMessage(int state) { + return state == MEDIA_UPLOAD_STATE_SUCCEEDED || state == MEDIA_UPLOAD_STATE_FAILED; + } + + @Override + public void onUploadMediaFileClear(int mediaId) { + setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_RESET, mediaId, null, 0); + } + + @Override + public void onMediaFileUploadProgress(int mediaId, float progress) { + setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_UPLOADING, mediaId, null, progress); + } + + @Override + public void onMediaFileUploadSucceeded(int mediaId, String mediaUrl, int mediaServerId) { + setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_SUCCEEDED, mediaId, mediaUrl, 1, mediaServerId); + } + + @Override + public void onMediaFileUploadFailed(int mediaId) { + setMediaFileUploadDataInJS(MEDIA_UPLOAD_STATE_FAILED, mediaId, null, 0); + } +} diff --git a/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java index 9004213293..636e015de1 100644 --- a/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java +++ b/react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java @@ -41,7 +41,8 @@ import org.wordpress.mobile.ReactNativeAztec.ReactAztecPackage; import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent; import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.GutenbergUserEvent; -import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaUploadCallback; +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaSelectedCallback; +import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaUploadEventEmitter; import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.ReplaceUnsupportedBlockCallback; import org.wordpress.mobile.ReactNativeGutenbergBridge.RNMedia; import org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgePackage; @@ -66,7 +67,8 @@ public class WPAndroidGlueCode { private ReactInstanceManager mReactInstanceManager; private ReactContext mReactContext; private RNReactNativeGutenbergBridgePackage mRnReactNativeGutenbergBridgePackage; - private MediaUploadCallback mPendingMediaUploadCallback; + private MediaSelectedCallback mMediaSelectedCallback; + private DeferredEventEmitter mDeferredEventEmitter = new DeferredEventEmitter(); private boolean mMediaPickedByUserOnBlock; /** @@ -217,10 +219,10 @@ public void responseHtml(String title, String html, boolean changed, ReadableMap } @Override - public void requestMediaPickFromMediaLibrary(MediaUploadCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) { + public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) { mMediaPickedByUserOnBlock = true; mAppendsMultipleSelectedToSiblingBlocks = !allowMultipleSelection; - mPendingMediaUploadCallback = mediaSelectedCallback; + mMediaSelectedCallback = mediaSelectedCallback; if (mediaType == MediaType.IMAGE) { mOnMediaLibraryButtonListener.onMediaLibraryImageButtonClicked(allowMultipleSelection); } else if (mediaType == MediaType.VIDEO) { @@ -231,24 +233,24 @@ public void requestMediaPickFromMediaLibrary(MediaUploadCallback mediaSelectedCa } @Override - public void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection, MediaType mediaType) { + public void requestMediaPickFromDeviceLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) { mMediaPickedByUserOnBlock = true; mAppendsMultipleSelectedToSiblingBlocks = false; - mPendingMediaUploadCallback = mediaUploadCallback; + mMediaSelectedCallback = mediaSelectedCallback; if (mediaType == MediaType.IMAGE) { mOnMediaLibraryButtonListener.onUploadPhotoButtonClicked(allowMultipleSelection); } else if (mediaType == MediaType.VIDEO) { mOnMediaLibraryButtonListener.onUploadVideoButtonClicked(allowMultipleSelection); } else if (mediaType == MediaType.MEDIA) { - mOnMediaLibraryButtonListener.onUploadMediaButtonClicked(allowMultipleSelection); + mOnMediaLibraryButtonListener.onUploadMediaButtonClicked(allowMultipleSelection); + } } - } @Override - public void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCallback, MediaType mediaType) { + public void requestMediaPickerFromDeviceCamera(MediaSelectedCallback mediaSelectedCallback, MediaType mediaType) { mMediaPickedByUserOnBlock = true; mAppendsMultipleSelectedToSiblingBlocks = false; - mPendingMediaUploadCallback = mediaUploadCallback; + mMediaSelectedCallback = mediaSelectedCallback; if (mediaType == MediaType.IMAGE) { mOnMediaLibraryButtonListener.onCapturePhotoButtonClicked(); } else if (mediaType == MediaType.VIDEO) { @@ -257,14 +259,14 @@ public void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCa } @Override - public void requestMediaImport(String url, MediaUploadCallback mediaSelectedCallback) { + public void requestMediaImport(String url, MediaSelectedCallback mediaSelectedCallback) { // no op - we don't need to paste images on Android, but the method needs to exist // to match the iOS counterpart } @Override - public void mediaUploadSync(MediaUploadCallback mediaUploadCallback) { - mPendingMediaUploadCallback = mediaUploadCallback; + public void mediaUploadSync(MediaSelectedCallback mediaSelectedCallback) { + mMediaSelectedCallback = mediaSelectedCallback; mOnReattachQueryListener.onQueryCurrentProgressForUploadingMedia(); } @@ -286,6 +288,8 @@ public void requestImageUploadCancel(int mediaId) { @Override public void editorDidMount(ReadableArray unsupportedBlockNames) { mOnEditorMountListener.onEditorDidMount(unsupportedBlockNames.toArrayList()); + mDeferredEventEmitter.setEmitter(mRnReactNativeGutenbergBridgePackage + .getRNReactNativeGutenbergBridgeModule()); mIsEditorMounted = true; if (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mContentHtml)) { setFocusOnTitle(); @@ -334,9 +338,9 @@ public void getOtherMediaPickerOptions(OtherMediaOptionsReceivedCallback otherMe @Override public void requestMediaPickFrom(String mediaSource, - MediaUploadCallback mediaSelectedCallback, + MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection) { - mPendingMediaUploadCallback = mediaSelectedCallback; + mMediaSelectedCallback = mediaSelectedCallback; mMediaPickedByUserOnBlock = true; mAppendsMultipleSelectedToSiblingBlocks = false; mOnMediaLibraryButtonListener.onOtherMediaButtonClicked(mediaSource, allowMultipleSelection); @@ -353,9 +357,9 @@ public void requestImageFullscreenPreview(String mediaUrl) { } @Override - public void requestMediaEditor(MediaUploadCallback mediaUploadCallback, String mediaUrl) { + public void requestMediaEditor(MediaSelectedCallback mediaSelectedCallback, String mediaUrl) { mMediaPickedByUserOnBlock = true; - mPendingMediaUploadCallback = mediaUploadCallback; + mMediaSelectedCallback = mediaSelectedCallback; mOnMediaEditorListener.onMediaEditorClicked(mediaUrl); } @@ -789,8 +793,8 @@ public void toggleEditorMode(boolean htmlModeEnabled) { mRnReactNativeGutenbergBridgePackage.getRNReactNativeGutenbergBridgeModule().toggleEditorMode(); } - public void appendUploadMediaFiles(ArrayList mediaList) { - if (isMediaUploadCallbackRegistered() && mMediaPickedByUserOnBlock) { + public void appendMediaFiles(ArrayList mediaList) { + if (isMediaSelectedCallbackRegistered() && mMediaPickedByUserOnBlock) { mMediaPickedByUserOnBlock = false; List rnMediaList = new ArrayList<>(); @@ -805,14 +809,14 @@ public void appendUploadMediaFiles(ArrayList mediaList) { if (mAppendsMultipleSelectedToSiblingBlocks && 1 < mediaList.size()) { rnMediaList.add(mediaList.get(0)); - mPendingMediaUploadCallback.onUploadMediaFileSelected(rnMediaList); + mMediaSelectedCallback.onMediaFileSelected(rnMediaList); for (Media mediaToAppend : mediaList.subList(1, mediaList.size())) { sendOrDeferAppendMediaSignal(mediaToAppend); } } else { rnMediaList.addAll(mediaList); - mPendingMediaUploadCallback.onUploadMediaFileSelected(rnMediaList); + mMediaSelectedCallback.onMediaFileSelected(rnMediaList); } } else { // This case is for media that is shared from the device @@ -854,27 +858,19 @@ private synchronized void dispatchOneMediaToAddAtATimeIfAvailable() { } public void mediaFileUploadProgress(final int mediaId, final float progress) { - if (isMediaUploadCallbackRegistered()) { - mPendingMediaUploadCallback.onMediaFileUploadProgress(mediaId, progress); - } + mDeferredEventEmitter.onMediaFileUploadProgress(mediaId, progress); } public void mediaFileUploadFailed(final int mediaId) { - if (isMediaUploadCallbackRegistered()) { - mPendingMediaUploadCallback.onMediaFileUploadFailed(mediaId); - } + mDeferredEventEmitter.onMediaFileUploadFailed(mediaId); } public void mediaFileUploadSucceeded(final int mediaId, final String mediaUrl, final int serverMediaId) { - if (isMediaUploadCallbackRegistered()) { - mPendingMediaUploadCallback.onMediaFileUploadSucceeded(mediaId, mediaUrl, serverMediaId); - } + mDeferredEventEmitter.onMediaFileUploadSucceeded(mediaId, mediaUrl, serverMediaId); } public void clearMediaFileURL(final int mediaId) { - if (isMediaUploadCallbackRegistered()) { - mPendingMediaUploadCallback.onUploadMediaFileClear(mediaId); - } + mDeferredEventEmitter.onUploadMediaFileClear(mediaId); } public void replaceUnsupportedBlock(String content, String blockId) { @@ -884,8 +880,8 @@ public void replaceUnsupportedBlock(String content, String blockId) { } } - private boolean isMediaUploadCallbackRegistered() { - return mPendingMediaUploadCallback != null; + private boolean isMediaSelectedCallbackRegistered() { + return mMediaSelectedCallback != null; } }