Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance of Image and Gallery block processors to avoid long delay when saving a post #22896

Merged
merged 20 commits into from May 21, 2024

Conversation

fluiddot
Copy link
Contributor

@fluiddot fluiddot commented Mar 25, 2024

Fixes wordpress-mobile/gutenberg-mobile#6696.

Note

Uses the changes from #22886.

To test

Delay when saving a post

  1. Create a post.
  2. Add a Gallery block and insert multiple images.
  3. Wait until all uploads finish.
  4. Close the editor and save the post.
  5. Observe the editor closes quickly with no significant delay.
  6. Re-open the post.
  7. Add more images.
  8. Repeat steps 3, 4.
  9. Observe the editor closes quickly with no significant delay.

Block processors

Follow the testing instructions to cover the functionality related to the processors for each block:

Regression Notes

  1. Potential unintended areas of impact
    The block processors are only used when saving a post. No other area should be impacted.

  2. What I did to test those areas of impact (or what existing automated tests I relied on)
    Manually tested saving a post with different blocks. Additionally, each processor has its own unit test that has been verified.

  3. What automated tests I added (or what prevented me from doing so)
    N/A

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding unit tests for my changes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

Testing checklist:

  • WordPress.com sites and self-hosted Jetpack sites.
  • Portrait and landscape orientations.
  • Light and dark modes.
  • Fonts: Larger, smaller and bold text.
  • High contrast.
  • VoiceOver.
  • Languages with large words or with letters/accents not frequently used in English.
  • Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
  • iPhone and iPad.
  • Multi-tasking: Split view and Slide over. (iPad)

@fluiddot fluiddot added [Type] Bug Gutenberg Editing and display of Gutenberg blocks. labels Mar 25, 2024
@fluiddot fluiddot added this to the 24.6 milestone Mar 25, 2024
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Mar 25, 2024

WordPress Alpha📲 You can test the changes from this Pull Request in WordPress Alpha by scanning the QR code below to install the corresponding build.
App NameWordPress Alpha WordPress Alpha
ConfigurationRelease-Alpha
Build Numberpr22896-7694cb2
Version24.9
Bundle IDorg.wordpress.alpha
Commit7694cb2
App Center BuildWPiOS - One-Offs #9957
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@fluiddot fluiddot force-pushed the update/improve-image-blocks-processor branch from 6613f88 to af3c5ad Compare March 25, 2024 16:06
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Mar 25, 2024

Jetpack Alpha📲 You can test the changes from this Pull Request in Jetpack Alpha by scanning the QR code below to install the corresponding build.
App NameJetpack Alpha Jetpack Alpha
ConfigurationRelease-Alpha
Build Numberpr22896-7694cb2
Version24.9
Bundle IDcom.jetpack.alpha
Commit7694cb2
App Center Buildjetpack-installable-builds #9007
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@@ -188,26 +188,30 @@ class PostCoordinator: NSObject {
}

// Ensure that all synced media references are up to date
post.media.forEach { media in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be cautious about making changes to PostCoordinator because the large potion of it is or will be rewritten. prepareToSave is unchanged, so it's a safe change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kean for the call out 🙇 ! This PR mainly focuses on the logic related to processing blocks before saving a post, which requires touching up some bits of the PostCoordinator. I'm planning to modify only necessary here, so hopefully there won't be much conflict with ongoing changes. In any case, I'll be happy to contribute to the new version by applying the same updates.

@fluiddot fluiddot marked this pull request as ready for review March 26, 2024 09:58
Comment on lines +401 to +402
var gutenbergBlockProcessors: [GutenbergProcessor] = []
var gutenbergProcessors: [Processor] = []
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to update gradually the processors to adopt the new GutenbergContentParser. In the meantime, we'll have two different processors.

import Aztec
import SwiftSoup
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aztec was imported in this file to use HTMLProcessor. Now the HTML processing is performed by using SwiftSoup.

Comment on lines +77 to +79
<br />Asf fasd fas
<br />A sdfasdf sadf
<br /> Asdf</figcaption>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SwiftSoup always closes tags, so tags like br or hr will be converted.

@fluiddot fluiddot linked an issue Mar 26, 2024 that may be closed by this pull request
@irfano
Copy link
Member

irfano commented Apr 1, 2024

I'm moving this to the next milestone since this is not a blocker, and the code freeze will be completed today.

@irfano irfano modified the milestones: 24.6, 24.7 Apr 1, 2024
@twstokes twstokes self-requested a review April 3, 2024 18:27
@momo-ozawa momo-ozawa modified the milestones: 24.7, 24.8 Apr 15, 2024
@momo-ozawa
Copy link
Contributor

momo-ozawa commented Apr 15, 2024

👋 Hey @fluiddot, I'm bumping this PR to 24.8 since it's code freeze day. If this PR needs to target 24.7, please target the release branch once it's been cut. Thanks!

@dvdchr dvdchr removed this from the 24.8 milestone Apr 29, 2024
@dvdchr dvdchr added this to the 24.9 milestone Apr 29, 2024
@dvdchr
Copy link
Contributor

dvdchr commented Apr 29, 2024

Hi @fluiddot 👋 , I'm bumping this PR's milestone to 24.9 since I'm starting code freeze. Feel free to re-target this to the release branch if this is a blocker or intended for 24.8.

@salimbraksa
Copy link
Contributor

Hey @fluiddot, I'm bumping the milestone for this PR to 25.0 as I'm starting the code freeze. If this PR needs to go into 24.9, please go ahead and re-target it to the release branch.

@salimbraksa salimbraksa modified the milestones: 24.9, 25.0 May 13, 2024
Base automatically changed from add/gutenberg-content-parsing to trunk May 14, 2024 19:50
@twstokes
Copy link
Contributor

twstokes commented May 14, 2024

👋 Hey @fluiddot, I'd like to pull in trunk on this PR as some time has passed. I believe this patch resolves the conflict on PostCoordinator.swift but I'd like for you to verify if possible. Thanks!

diff --cc WordPress/Classes/Services/PostCoordinator.swift
index 7098c95cae,2ea04cc472..0000000000
--- a/WordPress/Classes/Services/PostCoordinator.swift
+++ b/WordPress/Classes/Services/PostCoordinator.swift
@@@ -203,15 -741,7 +736,16 @@@ class PostCoordinator: NSObject 
          completion(.success(post))
      }
  
 +    func updateMediaBlocksBeforeSave(in post: AbstractPost, with media: Set<Media>) {
 +        guard let postContent = post.content else {
 +            return
 +        }
 +        let contentParser = GutenbergContentParser(for: postContent)
 +        media.forEach { self.updateReferences(to: $0, in: contentParser.blocks, post: post) }
 +        post.content = contentParser.html()
 +    }
 +
+     // - warning: deprecated (kahu-offline-mode)
      func cancelAnyPendingSaveOf(post: AbstractPost) {
          removeObserver(for: post)
      }
@@@ -347,12 -879,18 +883,19 @@@
              switch state {
              case .ended:
                  let successHandler = {
 -                    self.updateReferences(to: media, in: post)
 +                    self.updateMediaBlocksBeforeSave(in: post, with: [media])
 +
-                     // Let's check if media uploading is still going, if all finished with success then we can upload the post
-                     if !self.mediaCoordinator.isUploadingMedia(for: post) && !post.hasFailedMedia {
-                         self.removeObserver(for: post)
-                         completion(.success(post))
+                     if self.isSyncPublishingEnabled {
+                         if post.media.allSatisfy({ $0.remoteStatus == .sync }) {
+                             self.removeObserver(for: post)
+                             completion(.success(post))
+                         }
+                     } else {
+                         // Let's check if media uploading is still going, if all finished with success then we can upload the post
+                         if !self.mediaCoordinator.isUploadingMedia(for: post) && !post.hasFailedMedia {
+                             self.removeObserver(for: post)
+                             completion(.success(post))
+                         }
                      }
                  }
                  switch media.mediaType {

# Conflicts:
#	WordPress/Classes/Services/PostCoordinator.swift
@fluiddot
Copy link
Contributor Author

👋 Hey @fluiddot, I'd like to pull in trunk on this PR as some time has passed. I believe this patch resolves the conflict on PostCoordinator.swift but I'd like for you to verify if possible. Thanks!

Yes @twstokes, your patch contains the same conflict resolution I have in mind. I've solved it in ccffe5b.

@twstokes
Copy link
Contributor

It looks like a unit test may be failing because the output changed. I'm only spotting a whitespace difference.

@fluiddot do you think we're good to just update the expected output?

@fluiddot
Copy link
Contributor Author

It looks like a unit test may be failing because the output changed. I'm only spotting a whitespace difference.

@fluiddot do you think we're good to just update the expected output?

@twstokes Yep, the difference is the extra whitespace at the end of the figure tag. The whitespace is only necessary to conform the xhtml specs for self-closing tags, which is not the case here as we are processing HTML. However, as commented in the parser's code (SwiftSoup), seems the same formatting is used to for compatibility. Hence, this extra whitespace is expected in the output. I've pushed a fix in 3a22f64.

Copy link
Contributor

@twstokes twstokes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM @fluiddot! Feel free to merge - I only shared some Swift styling thoughts. 🚀

}
_ = try? imgTag.attr("src", self.remoteURLString)
_ = try? imgTag.attr("class", newImgClassAttributes)
_ = try? imgTag.attr(ImageKeys.dataID, "\(self.serverMediaID)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional nit and more of a personal pref, but it may be more common to convert the Int -> String via String(self.serverMediaID) if you're not interpolating anything else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied this suggestion in 7694cb2.

return html
})
let dataLinkAttribute = try? imgTag.attr(ImageKeys.dataLink)
if dataLinkAttribute != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about adding an if let or guarding to remove the optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied this suggestion in d60c1d1.

let imgUploadID = Int32(imageIDString)
func processImgTags(_ block: GutenbergParsedBlock) {
let imgTags = try? block.elements.select("img")
imgTags?.forEach { img in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about adding an if let or guarding to remove the optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied this suggestion in d60c1d1.

return nil
}
func processLinkPostMediaUpload(_ block: GutenbergParsedBlock) {
let aTags = try? block.elements.select(LinkKeys.name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about adding an if let or guarding to remove the optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied this suggestion in d60c1d1.

}
func processImgPostMediaUpload(_ element: Element) {
let imgTags = try? element.select(ImageKeys.name)
imgTags?.forEach {imgTag in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional nit: Could be in an if let, or could guard and return early to remove the optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied this suggestion in d60c1d1.

@fluiddot fluiddot enabled auto-merge May 21, 2024 14:53
@fluiddot
Copy link
Contributor Author

fluiddot commented May 21, 2024

LGTM @fluiddot! Feel free to merge - I only shared some Swift styling thoughts. 🚀

Thanks @twstokes for reviewing and approving the PR 🙇 ! I've applied the suggestions you shared and enabled auto-merge.

@fluiddot fluiddot merged commit f46c4d9 into trunk May 21, 2024
23 of 24 checks passed
@fluiddot fluiddot deleted the update/improve-image-blocks-processor branch May 21, 2024 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Gutenberg Editing and display of Gutenberg blocks. [Type] Bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Long delay when saving a post
8 participants