diff --git a/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragment.java b/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragment.java
index a2f3fc54d363..ad019edb4e84 100755
--- a/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragment.java
+++ b/WordPressEditor/src/main/java/org/wordpress/android/editor/EditorFragment.java
@@ -24,6 +24,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
+import android.webkit.JavascriptInterface;
import android.webkit.URLUtil;
import android.webkit.WebView;
import android.widget.ToggleButton;
@@ -59,6 +60,7 @@ public class EditorFragment extends EditorFragmentAbstract implements View.OnCli
private static final String ARG_PARAM_CONTENT = "param_content";
private static final String JS_CALLBACK_HANDLER = "nativeCallbackHandler";
+ private static final String JS_STATE_INTERFACE = "nativeState";
private static final String KEY_TITLE = "title";
private static final String KEY_CONTENT = "content";
@@ -366,13 +368,18 @@ private void setupFormatBarButtonMap(View view) {
}
protected void initJsEditor() {
- if(!isAdded()) {
+ if (!isAdded()) {
return;
}
String htmlEditor = Utils.getHtmlFromFile(getActivity(), "android-editor.html");
+ if (htmlEditor != null) {
+ htmlEditor = htmlEditor.replace("%%TITLE%%", getString(R.string.visual_editor));
+ }
mWebView.addJavascriptInterface(new JsCallbackReceiver(this), JS_CALLBACK_HANDLER);
+ mWebView.addJavascriptInterface(new NativeStateJsInterface(getActivity().getApplicationContext()),
+ JS_STATE_INTERFACE);
mWebView.loadDataWithBaseURL("file:///android_asset/", htmlEditor, "text/html", "utf-8", "");
@@ -1123,7 +1130,7 @@ private void updateVisualEditorFields() {
private void hideActionBarIfNeeded() {
ActionBar actionBar = getActionBar();
- if (getActionBar() != null
+ if (actionBar != null
&& !isHardwareKeyboardPresent()
&& mHideActionBarOnSoftKeyboardUp
&& mIsKeyboardOpen
@@ -1138,8 +1145,8 @@ private void hideActionBarIfNeeded() {
private void showActionBarIfNeeded() {
ActionBar actionBar = getActionBar();
- if (getActionBar() != null && !actionBar.isShowing()) {
- getActionBar().show();
+ if (actionBar != null && !actionBar.isShowing()) {
+ actionBar.show();
}
}
@@ -1261,4 +1268,37 @@ private void applyFormattingHtmlMode(ToggleButton toggleButton, String tag) {
mSourceViewContent.setSelection(selectionEnd + endTag.length());
}
}
+
+ private class NativeStateJsInterface {
+ Context mContext;
+
+ NativeStateJsInterface(Context context) {
+ mContext = context;
+ }
+
+ @JavascriptInterface
+ public String getStringEdit() {
+ return mContext.getString(R.string.edit);
+ }
+
+ @JavascriptInterface
+ public String getStringTapToRetry() {
+ return mContext.getString(R.string.tap_to_try_again);
+ }
+
+ @JavascriptInterface
+ public String getStringUploading() {
+ return mContext.getString(R.string.uploading);
+ }
+
+ @JavascriptInterface
+ public String getStringUploadingGallery() {
+ return mContext.getString(R.string.uploading_gallery_placeholder);
+ }
+
+ @JavascriptInterface
+ public int getAPILevel() {
+ return Build.VERSION.SDK_INT;
+ }
+ }
}
diff --git a/WordPressEditor/src/main/java/org/wordpress/android/editor/RippleToggleButton.java b/WordPressEditor/src/main/java/org/wordpress/android/editor/RippleToggleButton.java
index 4d932b322e0b..fd2ac6110142 100644
--- a/WordPressEditor/src/main/java/org/wordpress/android/editor/RippleToggleButton.java
+++ b/WordPressEditor/src/main/java/org/wordpress/android/editor/RippleToggleButton.java
@@ -21,12 +21,11 @@ public class RippleToggleButton extends ToggleButton {
private Paint mStrokePaint;
public RippleToggleButton(Context context) {
- super(context);
- }
+ this(context, null);
+ }
public RippleToggleButton(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
+ this(context, attrs, 0);
}
public RippleToggleButton(Context context, AttributeSet attrs, int defStyle) {
diff --git a/WordPressEditor/src/main/res/layout-w360dp/format_bar.xml b/WordPressEditor/src/main/res/layout-w360dp/format_bar.xml
index 6b498fe0baee..fc2eb283e5f0 100644
--- a/WordPressEditor/src/main/res/layout-w360dp/format_bar.xml
+++ b/WordPressEditor/src/main/res/layout-w360dp/format_bar.xml
@@ -37,6 +37,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_media"
android:background="@drawable/format_bar_button_media_selector"/>
@@ -52,6 +54,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_italic"
android:background="@drawable/format_bar_button_italic_selector"
android:tag="@string/format_bar_tag_italic"/>
@@ -60,6 +63,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_quote"
android:background="@drawable/format_bar_button_quote_selector"
android:tag="@string/format_bar_tag_blockquote"/>
@@ -68,6 +72,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_ul"
android:background="@drawable/format_bar_button_ul_selector"
android:tag="@string/format_bar_tag_unorderedList"/>
@@ -76,6 +81,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_ol"
android:background="@drawable/format_bar_button_ol_selector"
android:tag="@string/format_bar_tag_orderedList"/>
@@ -84,6 +90,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_link"
android:background="@drawable/format_bar_button_link_selector"
android:tag="@string/format_bar_tag_link"/>
@@ -100,6 +107,7 @@
style="@style/FormatBarHtmlButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_html"
android:background="@drawable/format_bar_button_html_selector"/>
-
\ No newline at end of file
+
diff --git a/WordPressEditor/src/main/res/layout-w380dp/format_bar.xml b/WordPressEditor/src/main/res/layout-w380dp/format_bar.xml
index bd8e1f900644..17d9f6d26358 100644
--- a/WordPressEditor/src/main/res/layout-w380dp/format_bar.xml
+++ b/WordPressEditor/src/main/res/layout-w380dp/format_bar.xml
@@ -31,6 +31,7 @@
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
+ android:contentDescription="@string/format_bar_description_media"
android:background="@drawable/format_bar_button_media_selector"/>
@@ -48,6 +50,7 @@
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
+ android:contentDescription="@string/format_bar_description_italic"
android:background="@drawable/format_bar_button_italic_selector"
android:tag="@string/format_bar_tag_italic"/>
@@ -57,6 +60,7 @@
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
+ android:contentDescription="@string/format_bar_description_quote"
android:background="@drawable/format_bar_button_quote_selector"
android:tag="@string/format_bar_tag_blockquote"/>
@@ -66,6 +70,7 @@
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
+ android:contentDescription="@string/format_bar_description_ul"
android:background="@drawable/format_bar_button_ul_selector"
android:tag="@string/format_bar_tag_unorderedList"/>
@@ -75,6 +80,7 @@
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
+ android:contentDescription="@string/format_bar_description_ol"
android:background="@drawable/format_bar_button_ol_selector"
android:tag="@string/format_bar_tag_orderedList"/>
@@ -84,6 +90,7 @@
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
+ android:contentDescription="@string/format_bar_description_link"
android:background="@drawable/format_bar_button_link_selector"
android:tag="@string/format_bar_tag_link"/>
@@ -99,6 +106,7 @@
style="@style/FormatBarHtmlButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_html"
android:background="@drawable/format_bar_button_html_selector"/>
-
\ No newline at end of file
+
diff --git a/WordPressEditor/src/main/res/layout-w600dp/format_bar.xml b/WordPressEditor/src/main/res/layout-w600dp/format_bar.xml
index dcceb2ea9321..58f907084759 100644
--- a/WordPressEditor/src/main/res/layout-w600dp/format_bar.xml
+++ b/WordPressEditor/src/main/res/layout-w600dp/format_bar.xml
@@ -34,6 +34,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_media"
android:background="@drawable/format_bar_button_media_selector"/>
@@ -47,6 +48,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_bold"
android:background="@drawable/format_bar_button_bold_selector"
android:tag="@string/format_bar_tag_bold"/>
@@ -55,6 +57,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_italic"
android:background="@drawable/format_bar_button_italic_selector"
android:tag="@string/format_bar_tag_italic"/>
@@ -77,6 +80,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_link"
android:background="@drawable/format_bar_button_link_selector"
android:tag="@string/format_bar_tag_link"/>
@@ -91,6 +95,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_ul"
android:background="@drawable/format_bar_button_ul_selector"
android:tag="@string/format_bar_tag_unorderedList"/>
@@ -99,6 +104,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_ol"
android:background="@drawable/format_bar_button_ol_selector"
android:tag="@string/format_bar_tag_orderedList"/>
@@ -107,6 +113,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_quote"
android:background="@drawable/format_bar_button_quote_selector"
android:tag="@string/format_bar_tag_blockquote"/>
@@ -121,6 +128,7 @@
style="@style/FormatBarButtonTablet"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_html"
android:background="@drawable/format_bar_button_html_selector"/>
diff --git a/WordPressEditor/src/main/res/layout/dialog_image_options.xml b/WordPressEditor/src/main/res/layout/dialog_image_options.xml
index 9b471f50832f..ead7e7653d37 100644
--- a/WordPressEditor/src/main/res/layout/dialog_image_options.xml
+++ b/WordPressEditor/src/main/res/layout/dialog_image_options.xml
@@ -21,6 +21,7 @@
-
\ No newline at end of file
+
diff --git a/WordPressEditor/src/main/res/layout/format_bar.xml b/WordPressEditor/src/main/res/layout/format_bar.xml
index a8e3e57a09af..5fb9c4fabe21 100644
--- a/WordPressEditor/src/main/res/layout/format_bar.xml
+++ b/WordPressEditor/src/main/res/layout/format_bar.xml
@@ -42,6 +42,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_media"
android:background="@drawable/format_bar_button_media_selector"/>
@@ -57,6 +59,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_italic"
android:background="@drawable/format_bar_button_italic_selector"
android:tag="@string/format_bar_tag_italic"/>
@@ -65,6 +68,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_quote"
android:background="@drawable/format_bar_button_quote_selector"
android:tag="@string/format_bar_tag_blockquote"/>
@@ -73,6 +77,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_ul"
android:background="@drawable/format_bar_button_ul_selector"
android:tag="@string/format_bar_tag_unorderedList"/>
@@ -81,6 +86,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_ol"
android:background="@drawable/format_bar_button_ol_selector"
android:tag="@string/format_bar_tag_orderedList"/>
@@ -89,6 +95,7 @@
style="@style/FormatBarButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_link"
android:background="@drawable/format_bar_button_link_selector"
android:tag="@string/format_bar_tag_link"/>
@@ -106,6 +113,7 @@
style="@style/FormatBarHtmlButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_html"
android:background="@drawable/format_bar_button_html_selector"/>
-
\ No newline at end of file
+
diff --git a/WordPressEditor/src/main/res/layout/fragment_edit_post_content.xml b/WordPressEditor/src/main/res/layout/fragment_edit_post_content.xml
index 76fa09b2caa3..c94a08e5e27e 100644
--- a/WordPressEditor/src/main/res/layout/fragment_edit_post_content.xml
+++ b/WordPressEditor/src/main/res/layout/fragment_edit_post_content.xml
@@ -100,6 +100,7 @@
style="@style/LegacyToggleButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
+ android:contentDescription="@string/format_bar_description_bold"
android:background="@drawable/legacy_format_bar_button_bold_selector" />
@@ -151,6 +158,7 @@
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:minWidth="@dimen/legacy_format_bar_height"
+ android:contentDescription="@string/format_bar_description_media"
android:background="@drawable/legacy_format_bar_button_media_selector" />
diff --git a/WordPressEditor/src/main/res/values/strings.xml b/WordPressEditor/src/main/res/values/strings.xml
index 88a5130a0669..5da604328659 100644
--- a/WordPressEditor/src/main/res/values/strings.xml
+++ b/WordPressEditor/src/main/res/values/strings.xml
@@ -9,6 +9,10 @@
Delete
Save
Discard
+ Edit
+ Tap to try again!
+ Uploading…
+ Uploading gallery…
Can\'t insert media directly in HTML mode. Please switch back to visual mode.
You are currently uploading media. Please wait until this completes.
@@ -61,4 +65,20 @@
- Full Size
+
+ Bold
+ Italic
+ Underline
+ Strikethrough
+ Block quote
+ Insert link
+ Insert more
+ Insert media
+ Unordered list
+ Ordered list
+ HTML mode
+ Visual editor
+ Image thumbnail
+
+
diff --git a/libs/editor-common/assets/ZSSRichTextEditor.js b/libs/editor-common/assets/ZSSRichTextEditor.js
index 511240a39aa2..3e8b3109f468 100755
--- a/libs/editor-common/assets/ZSSRichTextEditor.js
+++ b/libs/editor-common/assets/ZSSRichTextEditor.js
@@ -41,6 +41,9 @@ ZSSEditor.caretInfo = { y: 0, height: 0 };
// Is this device an iPad
ZSSEditor.isiPad;
+// The API level of the native host (Android)
+ZSSEditor.androidApiLevel;
+
// The current selection
ZSSEditor.currentSelection;
@@ -76,6 +79,8 @@ ZSSEditor.init = function() {
rangy.init();
+ ZSSEditor.androidApiLevel = nativeState.getAPILevel();
+
// Change a few CSS values if the device is an iPad
ZSSEditor.isiPad = (navigator.userAgent.match(/iPad/i) != null);
if (ZSSEditor.isiPad) {
@@ -850,11 +855,22 @@ ZSSEditor.insertImage = function(url, remoteId, alt) {
ZSSEditor.insertLocalImage = function(imageNodeIdentifier, localImageUrl) {
var progressIdentifier = this.getImageProgressIdentifier(imageNodeIdentifier);
var imageContainerIdentifier = this.getImageContainerIdentifier(imageNodeIdentifier);
- var imgContainerStart = '';
+
+ if (ZSSEditor.androidApiLevel > 18) {
+ var imgContainerClass = 'img_container';
+ var progressElement = '';
+ } else {
+ // Before API 19, the WebView didn't support progress tags. Use an upload overlay instead of a progress bar
+ var imgContainerClass = 'img_container compat';
+ var progressElement = '' + nativeState.getStringUploading()
+ + '';
+ }
+
+ var imgContainerStart = '';
var imgContainerEnd = '';
- var progress = '';
var image = '
';
- var html = imgContainerStart + progress+image + imgContainerEnd;
+ var html = imgContainerStart + progressElement + image + imgContainerEnd;
this.insertHTML(this.wrapInParagraphTags(html));
this.sendEnabledStyles();
@@ -941,6 +957,12 @@ ZSSEditor.setProgressOnImage = function(imageNodeIdentifier, progress) {
imageNode.addClass("uploading");
}
+ // Revert to non-compatibility image container once image upload has begun. This centers the overlays on the image
+ // (instead of the screen), while still circumventing the small container bug the compat class was added to fix
+ if (progress > 0) {
+ this.getImageContainerNodeWithIdentifier(imageNodeIdentifier).removeClass("compat");
+ }
+
var imageProgressNode = this.getImageProgressNodeWithIdentifier(imageNodeIdentifier);
if (imageProgressNode.length == 0){
return;
@@ -1023,6 +1045,9 @@ ZSSEditor.markImageUploadFailed = function(imageNodeIdentifier, message) {
if (imageProgressNode.length != 0){
imageProgressNode.addClass('failed');
}
+
+ // Delete the compatibility overlay if present
+ imageContainerNode.find("span.upload-overlay").addClass("failed");
};
/**
@@ -1046,6 +1071,9 @@ ZSSEditor.unmarkImageUploadFailed = function(imageNodeIdentifier, message) {
if (imageProgressNode.length != 0){
imageProgressNode.removeClass('failed');
}
+
+ // Display the compatibility overlay again if present
+ imageContainerNode.find("span.upload-overlay").removeClass("failed");
};
/**
@@ -1432,7 +1460,8 @@ ZSSEditor.applyVideoPressFormattingCallback = function( match ) {
var posterSVG = '"wpposter.svg"';
// The empty 'onclick' is important. It prevents the cursor jumping to the end
// of the content body when `-webkit-user-select: none` is set and the video is tapped.
- var out = '';
+ var out = '';
out = out + '
';
return out;
@@ -1552,7 +1581,8 @@ ZSSEditor.applyImageSelectionFormatting = function( imageNode ) {
sizeClass = " small";
}
- var overlay = 'Edit';
+ var overlay = ''
+ + nativeState.getStringEdit() + '';
if (document.body.style.filter == null) {
// CSS Filters (including blur) are not supported
@@ -1991,8 +2021,8 @@ ZSSEditor.insertGallery = function( imageIds, type, columns ) {
}
ZSSEditor.insertLocalGallery = function( placeholderId ) {
- var container = '[Uploading gallery...]';
-
+ var container = '['
+ + nativeState.getStringUploadingGallery() + ']';
this.insertHTML(this.wrapInParagraphTags(container));
}
@@ -2791,6 +2821,15 @@ ZSSField.prototype.handleTapEvent = function(e) {
return;
}
+ if (targetNode.className.indexOf('upload-overlay') != -1 ||
+ targetNode.className.indexOf('upload-overlay-bg') != -1 ) {
+ // Select the image node associated with the selected upload overlay
+ var imageNode = targetNode.parentNode.getElementsByTagName('img')[0];
+
+ this.sendImageTappedCallback( imageNode );
+ return;
+ }
+
if ( ZSSEditor.currentEditingImage ) {
ZSSEditor.removeImageSelectionFormatting( ZSSEditor.currentEditingImage );
ZSSEditor.currentEditingImage = null;
diff --git a/libs/editor-common/assets/android-editor.html b/libs/editor-common/assets/android-editor.html
index 13b6281d6603..b0bb0f5e99e1 100755
--- a/libs/editor-common/assets/android-editor.html
+++ b/libs/editor-common/assets/android-editor.html
@@ -1,7 +1,7 @@
- ZSSRichTextEditor
+ %%TITLE%%
diff --git a/libs/editor-common/assets/editor-android.css b/libs/editor-common/assets/editor-android.css
index ceed82213289..e3d0aef8701a 100644
--- a/libs/editor-common/assets/editor-android.css
+++ b/libs/editor-common/assets/editor-android.css
@@ -16,6 +16,8 @@ video::-webkit-media-controls-fullscreen-button {
display: none;
}
+/* --- API<19 workarounds --- */
+
/* Used only on older APIs (API<19), which don't support CSS filter effects (specifically, blur). */
.edit-container .edit-overlay-bg {
position: absolute;
@@ -25,4 +27,54 @@ video::-webkit-media-controls-fullscreen-button {
height: 100%;
display: block;
background-color: rgba(0, 0, 0, 0.5);
+}
+
+/* Used only on older APIs (API<19), where using inline-block is buggy and sometimes displays a very small container */
+span.img_container.compat {
+ display: block;
+}
+
+/* Used on API<19 to darken the image so that the 'uploading' and 'retry' overlays can still be seen when the image is
+light */
+.img_container .upload-overlay-bg {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ display: block;
+ background-color: rgba(0, 0, 0, 0.5);
+}
+
+/* When the upload-overlay-bg element is present (API<19), a bug is exposed where the img_container is slightly larger
+than its containing image. The upload-overlay-bg is larger as well, leaving a dark line below the image. By setting
+display:block on the image and setting a width limit we get around this issue. */
+
+.img_container .upload-overlay-bg ~ img.uploading {
+ display:block;
+ max-width:100%;
+}
+
+.img_container .upload-overlay-bg ~ img.failed {
+ display:block;
+ max-width:100%;
+}
+
+/* Used only on older APIs (API<19) instead of a progress bar for uploading images, since the WebView at those API
+ levels does not support the progress tag */
+.img_container .upload-overlay {
+ position: absolute;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ width:100%;
+ z-index: 100;
+ min-width: 60px;
+ font-family:OpenSans;
+ font-size:20px;
+ font-weight:600;
+ text-align: center;
+ text-shadow: 0px 1px 2px rgba(0,0,0,.06);
+ color: white;
+}
+
+.img_container .upload-overlay.failed {
+ visibility: hidden;
}
\ No newline at end of file