Skip to content

Commit 108ed89

Browse files
committed
Squashed 'libs/editor/' changes from 50ddd25..7f3b589
7f3b589 Updated example app to use the modified onMediaUploadSucceeded call b203bf0 Fixed an outdated reference in the ZSSEditor f9dbe59 Editor 0.6 version bump 76711d6 Updated localized string calls in ZSSEditor video methods c0b804b Merge branch 'feature/visual-editor' into feature/visual-editor-insert-video b87b917 Escape quotes for URLs being passed to the JS editor d06f2e2 Use hasAttribute to null-check when parsing for failed media items d3dff92 Wrapped called to getThumbnailURL in notNullStr() in the editor fragment 951bb3d Removed unnecessary console.logs 11feabd Drop data-failed attribute from ZSSEditor.insertLocalVideo 3c54e44 Merge branch 'feature/visual-editor' into feature/visual-editor-insert-video 7feb0e9 Use API<19 compatibility upload UI for video (imported from images) d806115 Include videos in count of failed media uploads 2fc0151 Mark uploading videos as failed when opening a post containing them, so they can be retried c6ac1e9 Send VideoPress shortcode and poster URL to visual editor when video upload completes 8f74166 Stop adding unnecessary 'data-wpid' attributed to completed video uploads b16606a Merge branch 'feature/visual-editor' into feature/visual-editor-insert-video 916c025 Handle video upload failure and support retrying fe3e855 Support cancelling in-progress video uploads and removing the video from the UI 2b14632 Differentiate media types in OnJsEditorStateChangedListener.onMediaTapped() native-side 26032af Added handling for completed video uploads, using the new remote URL and clearing placeholder and container adebbff Add CSS for video_container in API<19 compatibility mode 282dbea Use appropriate JS methods for local video insertion and upload progress updates d6ca1c7 Use placeholder image instead of video tag for uploading videos 10ae531 Track media type along with id in current uploads 2c9380b s/photo/image/ in example activity demo menu 7486336 Added video upload demo options to example activity d923987 Merge branch 'feature/visual-editor' into feature/visual-editor-insert-video 7487a90 Add support for remote video insertion to visual editor 5497330 Merge branch 'feature/visual-editor' into feature/visual-editor-add-video 9594791 Append break tags when inserting video tags for non-VideoPress videos a8a7858 Remove unused fullscreen video functionality from ZSSEditor git-subtree-dir: libs/editor git-subtree-split: 7f3b589d033fea945b226ccd85f31fe7dd7f0832
1 parent 87b5e7c commit 108ed89

File tree

11 files changed

+324
-194
lines changed

11 files changed

+324
-194
lines changed

WordPressEditor/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ android {
2323
buildToolsVersion "23.0.2"
2424

2525
defaultConfig {
26-
versionCode 5
27-
versionName "0.5"
26+
versionCode 6
27+
versionName "0.6"
2828
minSdkVersion 14
2929
targetSdkVersion 23
3030
}

WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragment.java

Lines changed: 116 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.wordpress.android.util.AppLog.T;
3737
import org.wordpress.android.util.JSONUtils;
3838
import org.wordpress.android.util.ProfilingUtils;
39+
import org.wordpress.android.util.ShortcodeUtils;
3940
import org.wordpress.android.util.StringUtils;
4041
import org.wordpress.android.util.ToastUtils;
4142
import org.wordpress.android.util.UrlUtils;
@@ -93,7 +94,7 @@ public class EditorFragment extends EditorFragmentAbstract implements View.OnCli
9394

9495
private ConcurrentHashMap<String, MediaFile> mWaitingMediaFiles;
9596
private Set<MediaGallery> mWaitingGalleries;
96-
private Set<String> mUploadingMediaIds;
97+
private Map<String, MediaType> mUploadingMedia;
9798
private Set<String> mFailedMediaIds;
9899
private MediaGallery mUploadingMediaGallery;
99100

@@ -137,7 +138,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
137138

138139
mWaitingMediaFiles = new ConcurrentHashMap<>();
139140
mWaitingGalleries = Collections.newSetFromMap(new ConcurrentHashMap<MediaGallery, Boolean>());
140-
mUploadingMediaIds = new HashSet<>();
141+
mUploadingMedia = new HashMap<>();
141142
mFailedMediaIds = new HashSet<>();
142143

143144
// -- WebView configuration
@@ -234,7 +235,7 @@ public void onResume() {
234235
@Override
235236
public void onDetach() {
236237
// Soft cancel (delete flag off) all media uploads currently in progress
237-
for (String mediaId : mUploadingMediaIds) {
238+
for (String mediaId : mUploadingMedia.keySet()) {
238239
mEditorFragmentListener.onMediaUploadCancelClicked(mediaId, false);
239240
}
240241
super.onDetach();
@@ -411,7 +412,7 @@ public void onClick(View v) {
411412
mEditorFragmentListener.onTrackableEvent(TrackableEvent.HTML_BUTTON_TAPPED);
412413

413414
// Don't switch to HTML mode if currently uploading media
414-
if (!mUploadingMediaIds.isEmpty()) {
415+
if (!mUploadingMedia.isEmpty()) {
415416
((ToggleButton) v).setChecked(false);
416417

417418
if (isAdded()) {
@@ -753,17 +754,38 @@ public void appendMediaFile(final MediaFile mediaFile, final String mediaUrl, Im
753754
return;
754755
}
755756

757+
final String safeMediaUrl = Utils.escapeQuotes(mediaUrl);
758+
756759
mWebView.post(new Runnable() {
757760
@Override
758761
public void run() {
759762
if (URLUtil.isNetworkUrl(mediaUrl)) {
760763
String mediaId = mediaFile.getMediaId();
761-
mWebView.execJavaScriptFromString("ZSSEditor.insertImage('" + mediaUrl + "', '" + mediaId + "');");
764+
if (mediaFile.isVideo()) {
765+
String posterUrl = Utils.escapeQuotes(StringUtils.notNullStr(mediaFile.getThumbnailURL()));
766+
String videoPressId = ShortcodeUtils.getVideoPressIdFromShortCode(
767+
mediaFile.getVideoPressShortCode());
768+
769+
mWebView.execJavaScriptFromString("ZSSEditor.insertVideo('" + safeMediaUrl + "', '" +
770+
posterUrl + "', '" + videoPressId + "');");
771+
} else {
772+
mWebView.execJavaScriptFromString("ZSSEditor.insertImage('" + safeMediaUrl + "', '" + mediaId +
773+
"');");
774+
}
762775
} else {
763776
String id = mediaFile.getMediaId();
764-
mWebView.execJavaScriptFromString("ZSSEditor.insertLocalImage(" + id + ", '" + mediaUrl + "');");
765-
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnImage(" + id + ", " + 0 + ");");
766-
mUploadingMediaIds.add(id);
777+
if (mediaFile.isVideo()) {
778+
String posterUrl = Utils.escapeQuotes(StringUtils.notNullStr(mediaFile.getThumbnailURL()));
779+
mWebView.execJavaScriptFromString("ZSSEditor.insertLocalVideo(" + id + ", '" + posterUrl +
780+
"');");
781+
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnVideo(" + id + ", " + 0 + ");");
782+
mUploadingMedia.put(id, MediaType.VIDEO);
783+
} else {
784+
mWebView.execJavaScriptFromString("ZSSEditor.insertLocalImage(" + id + ", '" + safeMediaUrl +
785+
"');");
786+
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnImage(" + id + ", " + 0 + ");");
787+
mUploadingMedia.put(id, MediaType.IMAGE);
788+
}
767789
}
768790
}
769791
});
@@ -796,8 +818,8 @@ public void setUrlForVideoPressId(final String videoId, final String videoUrl, f
796818
mWebView.post(new Runnable() {
797819
@Override
798820
public void run() {
799-
mWebView.execJavaScriptFromString("ZSSEditor.setVideoPressLinks('" + videoId + "', '" +
800-
videoUrl + "', '" + posterUrl + "');");
821+
mWebView.execJavaScriptFromString("ZSSEditor.setVideoPressLinks('" + videoId + "', '" +
822+
Utils.escapeQuotes(videoUrl) + "', '" + Utils.escapeQuotes(posterUrl) + "');");
801823
}
802824
});
803825
}
@@ -823,38 +845,67 @@ public void setContentPlaceholder(CharSequence placeholderText) {
823845
}
824846

825847
@Override
826-
public void onMediaUploadSucceeded(final String mediaId, final String remoteId, final String remoteUrl) {
827-
mWebView.post(new Runnable() {
828-
@Override
829-
public void run() {
830-
mWebView.execJavaScriptFromString("ZSSEditor.replaceLocalImageWithRemoteImage(" + mediaId + ", '" +
831-
remoteId + "', '" + remoteUrl + "');");
832-
mUploadingMediaIds.remove(mediaId);
833-
}
834-
});
848+
public void onMediaUploadSucceeded(final String localMediaId, final MediaFile mediaFile) {
849+
final MediaType mediaType = mUploadingMedia.get(localMediaId);
850+
if (mediaType != null) {
851+
mWebView.post(new Runnable() {
852+
@Override
853+
public void run() {
854+
String remoteUrl = Utils.escapeQuotes(mediaFile.getFileURL());
855+
if (mediaType.equals(MediaType.IMAGE)) {
856+
String remoteMediaId = mediaFile.getMediaId();
857+
mWebView.execJavaScriptFromString("ZSSEditor.replaceLocalImageWithRemoteImage(" + localMediaId +
858+
", '" + remoteMediaId + "', '" + remoteUrl + "');");
859+
} else if (mediaType.equals(MediaType.VIDEO)) {
860+
String posterUrl = Utils.escapeQuotes(StringUtils.notNullStr(mediaFile.getThumbnailURL()));
861+
String videoPressId = ShortcodeUtils.getVideoPressIdFromShortCode(
862+
mediaFile.getVideoPressShortCode());
863+
mWebView.execJavaScriptFromString("ZSSEditor.replaceLocalVideoWithRemoteVideo(" + localMediaId +
864+
", '" + remoteUrl + "', '" + posterUrl + "', '" + videoPressId + "');");
865+
}
866+
mUploadingMedia.remove(localMediaId);
867+
}
868+
});
869+
}
835870
}
836871

837872
@Override
838873
public void onMediaUploadProgress(final String mediaId, final float progress) {
839-
mWebView.post(new Runnable() {
840-
@Override
841-
public void run() {
842-
String progressString = String.format(Locale.US, "%.1f", progress);
843-
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnImage(" + mediaId + ", " +
844-
progressString + ");");
845-
}
846-
});
874+
final MediaType mediaType = mUploadingMedia.get(mediaId);
875+
if (mediaType != null) {
876+
mWebView.post(new Runnable() {
877+
@Override
878+
public void run() {
879+
String progressString = String.format(Locale.US, "%.1f", progress);
880+
if (mediaType.equals(MediaType.IMAGE)) {
881+
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnImage(" + mediaId + ", " +
882+
progressString + ");");
883+
} else if (mediaType.equals(MediaType.VIDEO)) {
884+
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnVideo(" + mediaId + ", " +
885+
progressString + ");");
886+
}
887+
}
888+
});
889+
}
847890
}
848891

849892
@Override
850893
public void onMediaUploadFailed(final String mediaId, final String errorMessage) {
851894
mWebView.post(new Runnable() {
852895
@Override
853896
public void run() {
854-
mWebView.execJavaScriptFromString("ZSSEditor.markImageUploadFailed(" + mediaId + ", '"
855-
+ errorMessage.replace("'", "\\'").replace("\"", "\\\"") + "');");
897+
MediaType mediaType = mUploadingMedia.get(mediaId);
898+
switch (mediaType) {
899+
case IMAGE:
900+
mWebView.execJavaScriptFromString("ZSSEditor.markImageUploadFailed(" + mediaId + ", '"
901+
+ Utils.escapeQuotes(errorMessage) + "');");
902+
break;
903+
case VIDEO:
904+
mWebView.execJavaScriptFromString("ZSSEditor.markVideoUploadFailed(" + mediaId + ", '"
905+
+ Utils.escapeQuotes(errorMessage) + "');");
906+
}
856907
mFailedMediaIds.add(mediaId);
857-
mUploadingMediaIds.remove(mediaId);
908+
mUploadingMedia.remove(mediaId);
858909
}
859910
});
860911
}
@@ -900,11 +951,11 @@ public void run() {
900951

901952
// If there are images that are still in progress (because the editor exited before they completed),
902953
// set them to failed, so the user can restart them (otherwise they will stay stuck in 'uploading' mode)
903-
mWebView.execJavaScriptFromString("ZSSEditor.markAllUploadingImagesAsFailed('"
954+
mWebView.execJavaScriptFromString("ZSSEditor.markAllUploadingMediaAsFailed('"
904955
+ getString(R.string.tap_to_try_again) + "');");
905956

906957
// Update the list of failed media uploads
907-
mWebView.execJavaScriptFromString("ZSSEditor.getFailedImages();");
958+
mWebView.execJavaScriptFromString("ZSSEditor.getFailedMedia();");
908959

909960
hideActionBarIfNeeded();
910961

@@ -980,7 +1031,11 @@ public void run() {
9801031
});
9811032
}
9821033

983-
public void onMediaTapped(final String mediaId, String url, final JSONObject meta, String uploadStatus) {
1034+
public void onMediaTapped(final String mediaId, final MediaType mediaType, final JSONObject meta, String uploadStatus) {
1035+
if (mediaType == null) {
1036+
return;
1037+
}
1038+
9841039
switch (uploadStatus) {
9851040
case "uploading":
9861041
// Display 'cancel upload' dialog
@@ -993,8 +1048,14 @@ public void onClick(DialogInterface dialog, int id) {
9931048
mWebView.post(new Runnable() {
9941049
@Override
9951050
public void run() {
996-
mWebView.execJavaScriptFromString("ZSSEditor.removeImage(" + mediaId + ");");
997-
mUploadingMediaIds.remove(mediaId);
1051+
switch (mediaType) {
1052+
case IMAGE:
1053+
mWebView.execJavaScriptFromString("ZSSEditor.removeImage(" + mediaId + ");");
1054+
break;
1055+
case VIDEO:
1056+
mWebView.execJavaScriptFromString("ZSSEditor.removeVideo(" + mediaId + ");");
1057+
}
1058+
mUploadingMedia.remove(mediaId);
9981059
}
9991060
});
10001061
dialog.dismiss();
@@ -1017,15 +1078,30 @@ public void onClick(DialogInterface dialog, int id) {
10171078
mWebView.post(new Runnable() {
10181079
@Override
10191080
public void run() {
1020-
mWebView.execJavaScriptFromString("ZSSEditor.unmarkImageUploadFailed(" + mediaId + ");");
1021-
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnImage(" + mediaId + ", " + 0 + ");");
1081+
switch (mediaType) {
1082+
case IMAGE:
1083+
mWebView.execJavaScriptFromString("ZSSEditor.unmarkImageUploadFailed(" + mediaId
1084+
+ ");");
1085+
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnImage(" + mediaId + ", "
1086+
+ 0 + ");");
1087+
break;
1088+
case VIDEO:
1089+
mWebView.execJavaScriptFromString("ZSSEditor.unmarkVideoUploadFailed(" + mediaId
1090+
+ ");");
1091+
mWebView.execJavaScriptFromString("ZSSEditor.setProgressOnVideo(" + mediaId + ", "
1092+
+ 0 + ");");
1093+
}
10221094
mFailedMediaIds.remove(mediaId);
1023-
mUploadingMediaIds.add(mediaId);
1095+
mUploadingMedia.put(mediaId, mediaType);
10241096
}
10251097
});
10261098
break;
10271099
default:
1028-
// Show media options fragment
1100+
if (!mediaType.equals(MediaType.IMAGE)) {
1101+
return;
1102+
}
1103+
1104+
// Only show image options fragment for image taps
10291105
FragmentManager fragmentManager = getFragmentManager();
10301106

10311107
if (fragmentManager.findFragmentByTag(ImageSettingsDialogFragment.IMAGE_SETTINGS_DIALOG_TAG) != null) {
@@ -1125,7 +1201,7 @@ public void onGetHtmlResponse(Map<String, String> inputArgs) {
11251201
mJavaScriptResult = inputArgs.get("result");
11261202
mGetSelectedTextCountDownLatch.countDown();
11271203
break;
1128-
case "getFailedImages":
1204+
case "getFailedMedia":
11291205
String[] mediaIds = inputArgs.get("ids").split(",");
11301206
for (String mediaId : mediaIds) {
11311207
if (!mediaId.equals("")) {

WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ public abstract class EditorFragmentAbstract extends Fragment {
2727
// TODO: remove this as soon as we can (we'll need to drop the legacy editor or fix html2spanned translation)
2828
public abstract Spanned getSpannedContent();
2929

30+
public enum MediaType {
31+
IMAGE, VIDEO;
32+
33+
public static MediaType fromString(String value) {
34+
if (value != null) {
35+
for (MediaType mediaType : MediaType.values()) {
36+
if (value.equalsIgnoreCase(mediaType.toString())) {
37+
return mediaType;
38+
}
39+
}
40+
}
41+
return null;
42+
}
43+
}
44+
3045
private static final String FEATURED_IMAGE_SUPPORT_KEY = "featured-image-supported";
3146
private static final String FEATURED_IMAGE_WIDTH_KEY = "featured-image-width";
3247

WordPressEditor/src/main/java/org/wordpress/android/editor/EditorMediaUploadListener.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.wordpress.android.editor;
22

3+
import org.wordpress.android.util.helpers.MediaFile;
4+
35
public interface EditorMediaUploadListener {
4-
void onMediaUploadSucceeded(String localId, String remoteId, String remoteUrl);
6+
void onMediaUploadSucceeded(String localId, MediaFile mediaFile);
57
void onMediaUploadProgress(String localId, float progress);
68
void onMediaUploadFailed(String localId, String errorMessage);
79
void onGalleryMediaUploadSucceeded(long galleryId, String remoteId, int remaining);

WordPressEditor/src/main/java/org/wordpress/android/editor/JsCallbackReceiver.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import java.util.Map;
1414
import java.util.Set;
1515

16+
import static org.wordpress.android.editor.EditorFragmentAbstract.MediaType;
17+
1618
public class JsCallbackReceiver {
1719
private static final String JS_CALLBACK_DELIMITER = "~";
1820

@@ -103,6 +105,7 @@ public void executeCallback(String callbackId, String params) {
103105
mediaIds.add("id");
104106
mediaIds.add("url");
105107
mediaIds.add("meta");
108+
mediaIds.add("type");
106109

107110
Set<String> mediaDataSet = Utils.splitValuePairDelimitedString(params, JS_CALLBACK_DELIMITER, mediaIds);
108111
Map<String, String> mediaDataMap = Utils.buildMapFromKeyValuePairs(mediaDataSet);
@@ -114,6 +117,8 @@ public void executeCallback(String callbackId, String params) {
114117
mediaUrl = Utils.decodeHtml(mediaUrl);
115118
}
116119

120+
MediaType mediaType = MediaType.fromString(mediaDataMap.get("type"));
121+
117122
String mediaMeta = mediaDataMap.get("meta");
118123
JSONObject mediaMetaJson = new JSONObject();
119124

@@ -136,7 +141,7 @@ public void executeCallback(String callbackId, String params) {
136141
}
137142
}
138143

139-
mListener.onMediaTapped(mediaId, mediaUrl, mediaMetaJson, uploadStatus);
144+
mListener.onMediaTapped(mediaId, mediaType, mediaMetaJson, uploadStatus);
140145
break;
141146
case CALLBACK_LINK_TAP:
142147
// Extract and HTML-decode the link data from the callback params
@@ -188,7 +193,7 @@ public void executeCallback(String callbackId, String params) {
188193
case "getSelectedText":
189194
responseIds.add("result");
190195
break;
191-
case "getFailedImages":
196+
case "getFailedMedia":
192197
responseIds.add("ids");
193198
}
194199

WordPressEditor/src/main/java/org/wordpress/android/editor/OnJsEditorStateChangedListener.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
import java.util.Map;
66

7+
import static org.wordpress.android.editor.EditorFragmentAbstract.MediaType;
8+
79
public interface OnJsEditorStateChangedListener {
810
void onDomLoaded();
911
void onSelectionChanged(Map<String, String> selectionArgs);
1012
void onSelectionStyleChanged(Map<String, Boolean> changeSet);
11-
void onMediaTapped(String mediaId, String url, JSONObject meta, String uploadStatus);
13+
void onMediaTapped(String mediaId, MediaType mediaType, JSONObject meta, String uploadStatus);
1214
void onLinkTapped(String url, String title);
1315
void onVideoPressInfoRequested(String videoId);
1416
void onGetHtmlResponse(Map<String, String> responseArgs);

WordPressEditor/src/main/java/org/wordpress/android/editor/Utils.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ public static String decodeHtml(String html) {
7373
return html;
7474
}
7575

76+
public static String escapeQuotes(String text) {
77+
if (text != null) {
78+
text = text.replace("'", "\\'").replace("\"", "\\\"");
79+
}
80+
return text;
81+
}
82+
7683
/**
7784
* Splits a delimited string into a set of strings.
7885
* @param string the delimited string to split

0 commit comments

Comments
 (0)