Skip to content

Conversation

@kean
Copy link
Contributor

@kean kean commented Oct 21, 2025

Changes

  • Fix an issues with editor cancelling loading if you open "Revisions"
  • Remove code handling non-existing error scenarios
  • Fix (potential) issue with RawBlockEditorSettingsService not proceeding with the request if cache read fails
  • Remove busy-waiting for editorState happening every 1 microsecond

Issue with "Revisions"

Prerequisites

  • Clean install
  • Add a delay when loading dependencies (using your preferred way)

Steps

  • Open the editor for the first time
  • Tap "More" / "Revisions"

Observed Results

  • Editor never gets loaded

RCA

viewWillDisappear is called not only when you close the screen, but also when it temporary gets covered by a different screen being presented as fullscreen modal or being pushed into the navigation stack.

@kean kean force-pushed the task/fix-loading-dependencies branch from 33356a5 to 7ad2ab0 Compare October 21, 2025 15:02
@kean kean marked this pull request as ready for review October 21, 2025 15:05
@kean kean added this to the 26.5 milestone Oct 21, 2025
/// the network.
func getSettings(allowingCachedResponse: Bool = true) async throws -> Data {
// Return cached settings if available
if allowingCachedResponse, let cachedSettings = try await BlockEditorCache.shared.getBlockSettings(for: blogID) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If local cache read using try Data(contentsOf: fileURL) were ever to fail, it would prevent fetchSettingsFromAPI from running. The cache lookup should not stop the request.

}

self.editorLoadingTask?.cancel()
if isBeingDismissedDirectlyOrByAncestor() {
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 easiest way to verify it works is by setting a breakpoint.

editorContentWasUpdated()
}

private func fetchEditorDependencies() async -> EditorDependencies {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This does not actually throw any errors – removing throws.

startEditor(dependencies: dependencies)
}

private func startEditor(dependencies: EditorDependencies) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved this with no changes.

@kean kean changed the title Fix editor cancelling loading Fix how editor handles dependencies loading Oct 21, 2025
@kean kean requested a review from dcalhoun October 21, 2025 15:10
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Oct 21, 2025

App Icon📲 You can test the changes from this Pull Request in WordPress by scanning the QR code below to install the corresponding build.
App NameWordPress
ConfigurationRelease-Alpha
Build Number29576
VersionPR #24956
Bundle IDorg.wordpress.alpha
Commitb0c6b7b
Installation URL54ucqnr1c4ve0
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Oct 21, 2025

App Icon📲 You can test the changes from this Pull Request in Jetpack by scanning the QR code below to install the corresponding build.
App NameJetpack
ConfigurationRelease-Alpha
Build Number29576
VersionPR #24956
Bundle IDcom.jetpack.alpha
Commitb0c6b7b
Installation URL5g0m9p2gnn9eg
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

Copy link
Contributor

@jkmassel jkmassel left a comment

Choose a reason for hiding this comment

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

You're no longer displaying an error if the editor fails to load dependencies. If the users requests site assets for the editor and we can't load them, we can't silently fail – we need to explain what's going on. Otherwise the editor looks broken and the user has no feedback about why.

One other thing you lose by dropping a state machine – it's far easier to deal with interactive plugin installation by having it. If a user doesn't have the plugins installed on their site to support the editor, we need to prompt them to install them. That can very quickly become difficult to follow without a more formal way to track state.

edit: for context, see: #24925

}

return try Data(contentsOf: fileURL)
return try? Data(contentsOf: fileURL)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we log the error then return nil instead of dropping it entirely?

That way we'll see something in Sentry if something's wrong – there's a performance implication here because loading performance will get way worse for anyone who has a cache miss.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I'll add wpAssert.

@kean
Copy link
Contributor Author

kean commented Oct 21, 2025

You're no longer displaying an error if the editor fails to load dependencies.

I'd be happy to add some kind of alert if we want it (in a separate PR?), but in the production version fetchEditorDependencies ignores all errors and showEditorError is not implemented, so I'm pretty sure it's not showing any errors.

    private func fetchEditorDependencies() async throws -> EditorDependencies {
        let settings: String?
        do {
            settings = try await blockEditorSettingsService.getSettingsString(allowingCachedResponse: true)
        } catch {
            DDLogError("Failed to fetch editor settings: \(error)")
            settings = nil
        }

        let loaded = await loadAuthenticationCookiesAsync()

        return EditorDependencies(settings: settings, didLoadCookies: loaded)
    }

    func showEditorError(_ error: Error) {
        // TODO: We should have a unified way to do this
    }

One other thing you lose by dropping a state machine – it's far easier to deal with interactive plugin installation by having it.

I didn't know about the other PRs. It seems like a sequential process, so would it work if you make recommendPlugin an async function (use withContinuation to indicate when the user is finished with the plugin installation? This way, the "start" sequence could look something like this:

   @MainActor
    private func actuallyLoadEditor() async {
        showActivityIndicator()
    
        do {
            let plugins = try await fetchPluginRecommendations()
            if "has recommendation" {
                await showRecommendedPlugin()
            }
        }
    
        let dependencies = await fetchEditorDependencies()
        startEditor(dependencies: dependencies)
    }

This way, it's clear what the steps are and in which order they are performed. I would use a state machine if it had more transitions between states, but again this does look a simple sequential process. I would lean into async/await for it.

@kean kean requested a review from jkmassel October 21, 2025 19:04
@sonarqubecloud
Copy link

@kean kean marked this pull request as draft October 23, 2025 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants