Skip to content

Commit b8e8fe1

Browse files
authored
Feat: support of multiple selection in media upload (#1331)
* wip - ios multiple * update gutenberg ref * update bundle ios * update ref * update ref * update example app * fix methods parameters description and use constants for dictionary keys * add android support * update js bundle * add RNMedia interface and use it * add multiple upload functionality for android * support multiple selection of video from device * update ref * Update bundles * update bundle and fix ids in tuple * update ref * update ref * update bundle * update js
1 parent f942586 commit b8e8fe1

File tree

15 files changed

+1950
-1809
lines changed

15 files changed

+1950
-1809
lines changed

android/app/src/main/java/com/gutenberg/MainApplication.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ public void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCa
4545
}
4646

4747
@Override
48-
public void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback, MediaType mediaType) {
48+
public void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection, MediaType mediaType) {
4949
}
5050

5151
@Override
52-
public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, MediaType mediaType) {
52+
public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) {
5353
}
5454

5555

bundle/android/App.js

+872-864
Large diffs are not rendered by default.

bundle/android/App.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/ios/App.js

+880-872
Large diffs are not rendered by default.

bundle/ios/App.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ios/gutenberg/GutenbergViewController.swift

+14-6
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
6464
print("↳ HTML: \(html)")
6565
}
6666

67-
func gutenbergDidRequestMedia(from source: MediaPickerSource, filter: [MediaFilter]?, with callback: @escaping MediaPickerDidPickMediaCallback) {
67+
func gutenbergDidRequestMedia(from source: MediaPickerSource, filter: [MediaFilter]?, allowMultipleSelection: Bool, with callback: @escaping MediaPickerDidPickMediaCallback) {
6868
guard let currentFilter = filter?.first else {
6969
return
7070
}
@@ -73,9 +73,17 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
7373
print("Gutenberg did request media picker, passing a sample url in callback")
7474
switch currentFilter {
7575
case .image:
76-
callback(1, "https://cldup.com/cXyG__fTLN.jpg")
76+
if(allowMultipleSelection) {
77+
callback([(1, "https://cldup.com/cXyG__fTLN.jpg"), (3, "https://cldup.com/cXyG__fTLN.jpg")])
78+
} else {
79+
callback([(1, "https://cldup.com/cXyG__fTLN.jpg")])
80+
}
7781
case .video:
78-
callback(2, "https://i.cloudup.com/YtZFJbuQCE.mov")
82+
if(allowMultipleSelection) {
83+
callback([(2, "https://i.cloudup.com/YtZFJbuQCE.mov"), (4, "https://i.cloudup.com/YtZFJbuQCE.mov")])
84+
} else {
85+
callback([(2, "https://i.cloudup.com/YtZFJbuQCE.mov")])
86+
}
7987
default:
8088
break
8189
}
@@ -90,16 +98,16 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
9098

9199
func gutenbergDidRequestImport(from url: URL, with callback: @escaping MediaPickerDidPickMediaCallback) {
92100
let id = mediaUploadCoordinator.upload(url: url)
93-
callback(id, url.absoluteString)
101+
callback([(id, url.absoluteString)])
94102
}
95103

96104
func pickAndUpload(from source: UIImagePickerController.SourceType, filter: MediaFilter, callback: @escaping MediaPickerDidPickMediaCallback) {
97105
mediaPickCoordinator = MediaPickCoordinator(presenter: self, filter: filter, callback: { (url) in
98106
guard let url = url, let mediaID = self.mediaUploadCoordinator.upload(url: url) else {
99-
callback(nil, nil)
107+
callback([(nil, nil)])
100108
return
101109
}
102-
callback(mediaID, url.absoluteString)
110+
callback([(mediaID, url.absoluteString)])
103111
self.mediaPickCoordinator = nil
104112
} )
105113
mediaPickCoordinator?.pick(from: source)

react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/GutenbergBridgeJS2Parent.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
package org.wordpress.mobile.ReactNativeGutenbergBridge;
22

33
import com.facebook.react.bridge.ReadableArray;
4+
import com.facebook.react.bridge.WritableMap;
5+
6+
import java.util.List;
47

58
public interface GutenbergBridgeJS2Parent {
9+
interface RNMedia {
10+
String getUrl();
11+
int getId();
12+
WritableMap toMap();
13+
}
14+
615
void responseHtml(String title, String html, boolean changed);
716

817
void editorDidMount(ReadableArray unsupportedBlockNames);
918

1019
interface MediaSelectedCallback {
11-
void onMediaSelected(int mediaId, String mediaUrl);
20+
void onMediaSelected(List<RNMedia> mediaList);
1221
}
1322

1423
interface MediaUploadCallback {
15-
void onUploadMediaFileSelected(int mediaId, String mediaUri);
24+
void onUploadMediaFileSelected(List<RNMedia> mediaList);
1625
void onUploadMediaFileClear(int mediaId);
1726
void onMediaFileUploadProgress(int mediaId, float progress);
1827
void onMediaFileUploadSucceeded(int mediaId, String mediaUrl, int serverId);
@@ -65,9 +74,9 @@ public static MediaType getEnum(String value) {
6574
}
6675
}
6776

68-
void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, MediaType mediaType);
77+
void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType);
6978

70-
void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback, MediaType mediaType);
79+
void requestMediaPickFromDeviceLibrary(MediaUploadCallback mediaUploadCallback, Boolean allowMultipleSelection, MediaType mediaType);
7180

7281
void requestMediaPickerFromDeviceCamera(MediaUploadCallback mediaUploadCallback, MediaType mediaType);
7382

react-native-gutenberg-bridge/android/src/main/java/org/wordpress/mobile/ReactNativeGutenbergBridge/RNReactNativeGutenbergBridgeModule.java

+32-13
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@
77
import com.facebook.react.bridge.ReactContextBaseJavaModule;
88
import com.facebook.react.bridge.ReactMethod;
99
import com.facebook.react.bridge.ReadableArray;
10+
import com.facebook.react.bridge.WritableArray;
1011
import com.facebook.react.bridge.WritableMap;
12+
import com.facebook.react.bridge.WritableNativeArray;
1113
import com.facebook.react.bridge.WritableNativeMap;
1214
import com.facebook.react.modules.core.DeviceEventManagerModule;
1315

1416
import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaSelectedCallback;
17+
import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.RNMedia;
18+
19+
import java.util.List;
1520

1621
public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModule {
1722
private final ReactApplicationContext mReactContext;
@@ -101,14 +106,14 @@ public void editorDidMount(ReadableArray unsupportedBlockNames) {
101106
}
102107

103108
@ReactMethod
104-
public void requestMediaPickFrom(String mediaSource, ReadableArray filter, final Callback onUploadMediaSelected) {
109+
public void requestMediaPickFrom(String mediaSource, ReadableArray filter, Boolean allowMultipleSelection, final Callback onUploadMediaSelected) {
105110
GutenbergBridgeJS2Parent.MediaType mediaType = getMediaTypeFromFilter(filter);
106111
if (mediaSource.equals(MEDIA_SOURCE_MEDIA_LIBRARY)) {
107-
mGutenbergBridgeJS2Parent.requestMediaPickFromMediaLibrary(getNewMediaSelectedCallback(onUploadMediaSelected), mediaType);
112+
mGutenbergBridgeJS2Parent.requestMediaPickFromMediaLibrary(getNewMediaSelectedCallback(allowMultipleSelection, onUploadMediaSelected), allowMultipleSelection, mediaType);
108113
} else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_LIBRARY)) {
109-
mGutenbergBridgeJS2Parent.requestMediaPickFromDeviceLibrary(getNewUploadMediaCallback(onUploadMediaSelected), mediaType);
114+
mGutenbergBridgeJS2Parent.requestMediaPickFromDeviceLibrary(getNewUploadMediaCallback(allowMultipleSelection, onUploadMediaSelected), allowMultipleSelection, mediaType);
110115
} else if (mediaSource.equals(MEDIA_SOURCE_DEVICE_CAMERA)) {
111-
mGutenbergBridgeJS2Parent.requestMediaPickerFromDeviceCamera(getNewUploadMediaCallback(onUploadMediaSelected), mediaType);
116+
mGutenbergBridgeJS2Parent.requestMediaPickerFromDeviceCamera(getNewUploadMediaCallback(false, onUploadMediaSelected), mediaType);
112117
}
113118
}
114119

@@ -123,12 +128,12 @@ private GutenbergBridgeJS2Parent.MediaType getMediaTypeFromFilter(ReadableArray
123128

124129
@ReactMethod
125130
public void requestMediaImport(String url, final Callback onUploadMediaSelected) {
126-
mGutenbergBridgeJS2Parent.requestMediaImport(url, getNewMediaSelectedCallback(onUploadMediaSelected));
131+
mGutenbergBridgeJS2Parent.requestMediaImport(url, getNewMediaSelectedCallback(false, onUploadMediaSelected));
127132
}
128133

129134
@ReactMethod
130135
public void mediaUploadSync() {
131-
mGutenbergBridgeJS2Parent.mediaUploadSync(getNewUploadMediaCallback(null));
136+
mGutenbergBridgeJS2Parent.mediaUploadSync(getNewUploadMediaCallback(false,null));
132137
}
133138

134139
@ReactMethod
@@ -156,20 +161,34 @@ public void editorDidAutosave() {
156161
mGutenbergBridgeJS2Parent.editorDidAutosave();
157162
}
158163

159-
private MediaSelectedCallback getNewMediaSelectedCallback(final Callback jsCallback) {
164+
private MediaSelectedCallback getNewMediaSelectedCallback(final Boolean allowMultipleSelection, final Callback jsCallback) {
160165
return new MediaSelectedCallback() {
161-
@Override public void onMediaSelected(int mediaId, String mediaUrl) {
162-
jsCallback.invoke(mediaId, mediaUrl);
166+
@Override public void onMediaSelected(List<RNMedia> mediaList) {
167+
if(allowMultipleSelection) {
168+
WritableArray writableArray = new WritableNativeArray();
169+
for (RNMedia media : mediaList) {
170+
writableArray.pushMap(media.toMap());
171+
}
172+
jsCallback.invoke(writableArray);
173+
} else {
174+
jsCallback.invoke(mediaList.get(0).toMap());
175+
}
163176
}
164177
};
165178
}
166179

167-
private GutenbergBridgeJS2Parent.MediaUploadCallback getNewUploadMediaCallback(final Callback jsCallback) {
180+
private GutenbergBridgeJS2Parent.MediaUploadCallback getNewUploadMediaCallback(final Boolean allowMultipleSelection, final Callback jsCallback) {
168181
return new GutenbergBridgeJS2Parent.MediaUploadCallback() {
169182
@Override
170-
public void onUploadMediaFileSelected(int mediaId, String mediaUri) {
171-
if (jsCallback != null) {
172-
jsCallback.invoke(mediaId, mediaUri, 0);
183+
public void onUploadMediaFileSelected(List<RNMedia> mediaList) {
184+
if(allowMultipleSelection) {
185+
WritableArray writableArray = new WritableNativeArray();
186+
for (RNMedia media : mediaList) {
187+
writableArray.pushMap(media.toMap());
188+
}
189+
jsCallback.invoke(writableArray);
190+
} else {
191+
jsCallback.invoke(mediaList.get(0).toMap());
173192
}
174193
}
175194

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.wordpress.mobile.WPAndroidGlue;
2+
3+
import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.RNMedia;
4+
import com.facebook.react.bridge.WritableMap;
5+
import com.facebook.react.bridge.WritableNativeMap;
6+
7+
public class Media implements RNMedia {
8+
private int mId;
9+
private String mUrl;
10+
private String mType;
11+
12+
public Media(int id, String url, String type) {
13+
this.mId = id;
14+
this.mUrl = url;
15+
this.mType = type;
16+
}
17+
18+
public Media(int id, String url) {
19+
this.mId = id;
20+
this.mUrl = url;
21+
this.mType = "";
22+
}
23+
24+
public int getId() {
25+
return mId;
26+
}
27+
28+
public void setId(int id) {
29+
this.mId = id;
30+
}
31+
32+
public String getUrl() {
33+
return mUrl;
34+
}
35+
36+
public void setUrl(String url) {
37+
this.mUrl = url;
38+
}
39+
40+
public String getType() {
41+
return mType;
42+
}
43+
44+
public void setType(String mediaType) {
45+
this.mType = mediaType;
46+
}
47+
48+
public WritableMap toMap() {
49+
WritableMap map = new WritableNativeMap();
50+
map.putInt("id", mId);
51+
map.putString("url", mUrl);
52+
return map;
53+
}
54+
}

0 commit comments

Comments
 (0)