diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index d16a6b01d159..8092c890bbf2 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,5 +1,6 @@ 12.0 ----- +Faster opening of large posts * Updated Notifications with tabs 11.9 diff --git a/libs/editor/WordPressEditor/build.gradle b/libs/editor/WordPressEditor/build.gradle index 9984b0c6fe6f..e72f7c25e874 100644 --- a/libs/editor/WordPressEditor/build.gradle +++ b/libs/editor/WordPressEditor/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { - aztecVersion = 'v1.3.20' + aztecVersion = 'v1.3.21' } repositories { diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java index 351bb75ea634..90b3f09fbd16 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java @@ -154,6 +154,10 @@ public AztecLoggingException(Throwable originalException) { private static boolean mIsToolbarExpanded = false; + // 1-deep cache of html parsed to spans, as a speed optimization instead of parsing the same content again and again + private static int sPostContentHash; + private static Spanned sParsedContentCached; + private boolean mEditorWasPaused = false; private boolean mHideActionBarOnSoftKeyboardUp = false; @@ -1987,7 +1991,7 @@ private static SpannableStringBuilder getCalypsoCompatibleStringBuilder(Context AztecParser parser) { SpannableStringBuilder builder = new SpannableStringBuilder(); String cleanSource = Format.removeSourceEditorFormatting(postContent, true); - builder.append(parser.fromHtml(cleanSource, context)); + builder.append(parser.parseHtmlForInspection(cleanSource, context)); Format.preProcessSpannedText(builder, true); return builder; } @@ -2102,7 +2106,7 @@ public static boolean hasMediaItemsMarkedFailed(Context context, @NonNull String private static boolean hasMediaItemsMarkedWithTag(Context context, @NonNull String postContent, String tag) { // fill in Aztec with the post's content AztecParser parser = getAztecParserWithPlugins(); - Spanned content = parser.fromHtml(postContent, context); + Spanned content = parseContent(context, parser, postContent); // get all items with the class in the "tag" param AztecText.AttributePredicate uploadingPredicate = getPredicateWithClass(tag); @@ -2141,7 +2145,7 @@ private static List getMediaMarkedAsClassInPostContent(Context context, ArrayList mediaMarkedUploading = new ArrayList<>(); // fill in Aztec with the post's content AztecParser parser = getAztecParserWithPlugins(); - Spanned content = parser.fromHtml(postContent, context); + Spanned content = parseContent(context, parser, postContent); AztecText.AttributePredicate uploadingPredicate = getPredicateWithClass(classToUse); for (Attributes attrs : getAllElementAttributes(content, uploadingPredicate)) { String itemId = attrs.getValue(ATTR_ID_WP); @@ -2152,6 +2156,20 @@ private static List getMediaMarkedAsClassInPostContent(Context context, return mediaMarkedUploading; } + public static Spanned parseContent(Context context, AztecParser parser, @NonNull String postContent) { + // parsing is an expensive operation (especially if the content is big) so, return previous result if matching. + if (sParsedContentCached != null && postContent.hashCode() == sPostContentHash) { + return new SpannableString(sParsedContentCached); + } + + // cache the post's content hash to compare next time + sPostContentHash = postContent.hashCode(); + + // fill in Aztec with the post's content + sParsedContentCached = parser.parseHtmlForInspection(postContent, context); + return sParsedContentCached; + } + public void setMediaToFailed(@NonNull String mediaId) { AztecText.AttributePredicate localMediaIdPredicate = MediaPredicate.getLocalMediaIdPredicate(mediaId); // we should be obtaining just one span for this media Id predicate, but just in case something diff --git a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/GutenbergEditorFragment.java b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/GutenbergEditorFragment.java index 5da912661c4c..f5c87d4b4fd3 100644 --- a/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/GutenbergEditorFragment.java +++ b/libs/editor/WordPressEditor/src/main/java/org/wordpress/android/editor/GutenbergEditorFragment.java @@ -9,6 +9,7 @@ import android.content.res.Resources; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.support.annotation.NonNull; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -55,6 +56,7 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements EditorMediaUploadListener, IHistoryListener { private static final String KEY_HTML_MODE_ENABLED = "KEY_HTML_MODE_ENABLED"; + private static final String KEY_EDITOR_DID_MOUNT = "KEY_EDITOR_DID_MOUNT"; private static final String ARG_IS_NEW_POST = "param_is_new_post"; private static final String ARG_LOCALE_SLUG = "param_locale_slug"; @@ -77,6 +79,8 @@ public class GutenbergEditorFragment extends EditorFragmentAbstract implements private boolean mIsNewPost; + private boolean mEditorDidMount; + public static GutenbergEditorFragment newInstance(String title, String content, boolean isNewPost, @@ -193,6 +197,7 @@ public void onCreate(Bundle savedInstanceState) { if (savedInstanceState != null) { mHtmlModeEnabled = savedInstanceState.getBoolean(KEY_HTML_MODE_ENABLED); + mEditorDidMount = savedInstanceState.getBoolean(KEY_EDITOR_DID_MOUNT); } } @@ -239,7 +244,16 @@ public void onQueryCurrentProgressForUploadingMedia() { new OnEditorMountListener() { @Override public void onEditorDidMount(boolean hasUnsupportedBlocks) { + mEditorDidMount = true; mEditorFragmentListener.onEditorFragmentContentReady(hasUnsupportedBlocks); + + // Hide the progress bar when editor is ready + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + setEditorProgressBarVisibility(!mEditorDidMount); + } + }); } } ); @@ -273,6 +287,12 @@ public void run() { return view; } + @Override public void onResume() { + super.onResume(); + + setEditorProgressBarVisibility(!mEditorDidMount); + } + @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { @@ -281,6 +301,12 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis } } + private void setEditorProgressBarVisibility(boolean shown) { + if (isAdded() && getView() != null) { + getView().findViewById(R.id.editor_progress).setVisibility(shown ? View.VISIBLE : View.GONE); + } + } + public void resetUploadingMediaToFailed(Set failedMediaIds) { // get all media failed for this post, and represent it on tje UI if (failedMediaIds != null && !failedMediaIds.isEmpty()) { @@ -402,6 +428,7 @@ public void onAttach(Activity activity) { @Override public void onSaveInstanceState(Bundle outState) { outState.putBoolean(KEY_HTML_MODE_ENABLED, mHtmlModeEnabled); + outState.putBoolean(KEY_EDITOR_DID_MOUNT, mEditorDidMount); } @Override diff --git a/libs/editor/WordPressEditor/src/main/res/layout/fragment_gutenberg_editor.xml b/libs/editor/WordPressEditor/src/main/res/layout/fragment_gutenberg_editor.xml index 28cf1027e77c..b499d654daba 100644 --- a/libs/editor/WordPressEditor/src/main/res/layout/fragment_gutenberg_editor.xml +++ b/libs/editor/WordPressEditor/src/main/res/layout/fragment_gutenberg_editor.xml @@ -5,4 +5,12 @@ android:layout_width="match_parent" android:background="@color/white" android:focusable="false" - android:focusableInTouchMode="true"/> + android:focusableInTouchMode="true"> + + + diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 44f1d996f6a6..90cce4eb0171 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 44f1d996f6a679b9d6197763979eb0b65f7fbea4 +Subproject commit 90cce4eb0171c776b74a7989ffd04e769cc10bef