Skip to content

Convert GutenbergKitSettingsBuilder to injectable class#22836

Open
jkmassel wants to merge 3 commits into
trunkfrom
jkmassel/builder-injectable
Open

Convert GutenbergKitSettingsBuilder to injectable class#22836
jkmassel wants to merge 3 commits into
trunkfrom
jkmassel/builder-injectable

Conversation

@jkmassel
Copy link
Copy Markdown
Contributor

@jkmassel jkmassel commented May 4, 2026

Summary

  • Promotes GutenbergKitSettingsBuilder from a Kotlin object returning Map<String, Any> to a @Singleton class returning EditorConfiguration directly via buildPostConfiguration(site, post, accessToken).
  • The injectable form lets the builder constructor-inject EditorCapabilityResolver and consult theme-styles / third-party-blocks state itself, instead of every call site assembling a FeatureConfig.
  • EditorConfigurationBuilder (the intermediate Map → EditorConfiguration adapter) is now redundant and removed.
  • GutenbergKitActivity adopts the injected builder via a small buildEditorConfiguration helper that overlays the per-call locale, cookies, and network-logging pref the builder cannot know about, and drops its now-unused GutenbergKitPluginsFeature injection.

Capability-gating coverage already lives in EditorCapabilityResolverTest (#22812); settings-builder tests are rewritten to verify the builder threads its inputs and the resolver's result through to the EditorConfiguration.

Extracted from #22579 so the preloading PR can focus on the preloader itself.

Behavior changes

Not a pure refactor — two intentional changes worth flagging:

  • Third-party blocks default to off pending user opt-in. Old gating in the builder auto-enabled plugins for any WP.com or Jetpack-with-app-password site whenever GutenbergKitPluginsFeature was on. The new resolver-driven path also requires the per-site useThirdPartyBlocks toggle to be set. Roll-out continues to be controlled by the existing GutenbergKitPluginsFeature remote flag, so users only see the toggle once the flag reaches them.
  • editorAssetsEndpoint is now always populated. Previously it was unset for self-hosted sites (empty namespace). The endpoint is now set unconditionally — but GutenbergKit's EditorAssetsLibrary.fetchManifest short-circuits when plugins == false, so the URL is never dereferenced on sites that don't support it. Filed GutenbergKit#494 to tighten that API shape upstream.

Test plan

  • ./gradlew :WordPress:testJetpackDebugUnitTest --tests "org.wordpress.android.ui.posts.GutenbergKitSettingsBuilderTest" passes
  • On a WP.com simple site with the third-party blocks toggle enabled in site settings — editor opens, theme styles applied per pref, AI block appears in the inserter
  • On the same WP.com simple site with the third-party blocks toggle disabled — editor opens, AI block does NOT appear in the inserter
  • On a self-hosted site with an application password — editor opens, no wpcom/v2/editor-assets request fires (regardless of toggle state, since the endpoint short-circuits)
  • On a Jetpack-connected site with the third-party blocks toggle enabled — editor opens, AI block appears in the inserter
  • On a WP.com Atomic site with the third-party blocks toggle enabled — editor opens, AI block appears in the inserter

Related

@dangermattic
Copy link
Copy Markdown
Collaborator

dangermattic commented May 4, 2026

2 Warnings
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.
⚠️ This PR is assigned to the milestone 26.8. This milestone is due in less than 4 days.
Please make sure to get it merged by then or assign it to a milestone with a later deadline.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented May 4, 2026

App Icon📲 You can test the changes from this Pull Request in WordPress Android by scanning the QR code below to install the corresponding build.

App NameWordPress Android
Build TypeDebug
Versionpr22836-d851897
Build Number1488
Application IDorg.wordpress.android.prealpha
Commitd851897
Installation URL60imqmk0sgeig
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented May 4, 2026

App Icon📲 You can test the changes from this Pull Request in Jetpack Android by scanning the QR code below to install the corresponding build.

App NameJetpack Android
Build TypeDebug
Versionpr22836-d851897
Build Number1488
Application IDcom.jetpack.android.prealpha
Commitd851897
Installation URL5tf84p8eu1idg
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

jkmassel added a commit to wordpress-mobile/GutenbergKit that referenced this pull request May 5, 2026
…undles

Move locale resolution into the library so Android consumers stop having
to mirror the `SUPPORTED_LOCALES` table to avoid silently falling back
to English. WP-Android historically passes `Locale.getLanguage()` (ISO
639-1 only), which dropped Brazilian users to the language-only `pt`
bundle and Chinese users to English regardless of region — see
wordpress-mobile/WordPress-Android#22836.

The Vite build now emits `dist/supported-locales.json` from the
`src/translations/` directory, and `LocaleResolver.fromAssets(context)`
reads that manifest from the library's `assets/` to apply the chain
full-tag → language-only → `en`.

`EditorConfiguration.Builder.setLocale(context: Context, locale: Locale)`
is the new type-safe entry point; `setLocale(String?)` stays as the
existing power-user / test escape hatch and the wire format is
unchanged. A Context is required because the manifest lives in the
library's assets — consumers calling this from an editor activity
already have one in hand.

The shared JS pieces (manifest emission, JS-side resolver) also land in
the iOS PR; merging the second of the two will be a no-op for those
files.

Refs #490
jkmassel added a commit to wordpress-mobile/GutenbergKit that referenced this pull request May 5, 2026
…undles

Move locale resolution into the library so Android consumers stop having
to mirror the `SUPPORTED_LOCALES` table to avoid silently falling back
to English. WP-Android historically passes `Locale.getLanguage()` (ISO
639-1 only), which dropped Brazilian users to the language-only `pt`
bundle and Chinese users to English regardless of region — see
wordpress-mobile/WordPress-Android#22836.

The Vite build now emits `dist/supported-locales.json` from the
`src/translations/` directory, and `LocaleResolver.fromAssets(context)`
reads that manifest from the library's `assets/` to apply the chain
full-tag → language-only → `en`.

`EditorConfiguration.Builder.setLocale(context: Context, locale: Locale)`
is the new type-safe entry point; `setLocale(String?)` stays as the
existing power-user / test escape hatch and the wire format is
unchanged. A Context is required because the manifest lives in the
library's assets — consumers calling this from an editor activity
already have one in hand.

The shared JS pieces (manifest emission, JS-side resolver) also land in
the iOS PR; merging the second of the two will be a no-op for those
files.

Refs #490
@jkmassel jkmassel force-pushed the jkmassel/editor-capability-resolver branch from 34887ae to d5911f3 Compare May 5, 2026 23:23
@jkmassel jkmassel requested a review from a team as a code owner May 5, 2026 23:23
@jkmassel jkmassel requested review from nbradbury and removed request for a team May 5, 2026 23:23
@nbradbury
Copy link
Copy Markdown
Contributor

@jkmassel This has some CI failures and conflicts that need to be addressed. I had Claude create a PDF review which also uncovered some issues.

review-pr-22836-gutenbergkit-builder-2026-05-06.pdf

@jkmassel jkmassel force-pushed the jkmassel/builder-injectable branch from b984d31 to 3538ea9 Compare May 13, 2026 23:09
@jkmassel jkmassel added this to the 26.8 milestone May 15, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

❌ Patch coverage is 89.18919% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.27%. Comparing base (0d37e90) to head (d851897).

Files with missing lines Patch % Lines
...ss/android/ui/posts/GutenbergKitSettingsBuilder.kt 88.88% 4 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk   #22836      +/-   ##
==========================================
+ Coverage   37.24%   37.27%   +0.02%     
==========================================
  Files        2319     2318       -1     
  Lines      124604   124520      -84     
  Branches    16927    16914      -13     
==========================================
- Hits        46413    46411       -2     
+ Misses      74441    74355      -86     
- Partials     3750     3754       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jkmassel jkmassel force-pushed the jkmassel/editor-capability-resolver branch from d5911f3 to 15e2fdb Compare May 19, 2026 16:00
@jkmassel jkmassel marked this pull request as draft May 19, 2026 17:33
@jkmassel jkmassel force-pushed the jkmassel/editor-capability-resolver branch from 6687be2 to 0e21611 Compare May 19, 2026 20:16
Base automatically changed from jkmassel/editor-capability-resolver to trunk May 19, 2026 20:28
jkmassel added 2 commits May 19, 2026 14:31
Promotes `GutenbergKitSettingsBuilder` from a Kotlin `object` with
`buildSettings` returning a `Map<String, Any>` to a `@Singleton` class
that returns `EditorConfiguration` directly via
`buildPostConfiguration(site, post, accessToken)`.

The injectable form is needed so the builder can constructor-inject
`EditorCapabilityResolver` and consult per-site theme-styles and
third-party-blocks state itself, instead of relying on each call site
to assemble a `FeatureConfig`. `EditorConfigurationBuilder` (the
intermediate Map → `EditorConfiguration` adapter) is now redundant
and removed.

`GutenbergKitActivity` adopts the injected builder via a small
`buildEditorConfiguration` helper that overlays the per-call locale,
cookies, and account fields the builder cannot know about, and drops
its now-unused `GutenbergKitPluginsFeature` injection.

Settings-builder tests are rewritten against the new ctor and API;
capability-gating coverage already lives in `EditorCapabilityResolverTest`.
Three independent fixes surfaced while validating the converted
builder; each is small but distinct.

## Handle schemeless URLs in `extractHost`

`URI(url).host` returns null for hosts without a scheme
(e.g. `example.wordpress.com`), but the OLD `UrlUtils.removeScheme`
path that this PR replaced was lenient. `SiteModel.url` can be
schemeless (FluxC's `SiteStoreUnitTest.java:472,494` writes
`shieldeyesfromlight.wordpress.com` directly), which regressed
`siteApiNamespace` (missing the `sites/$host/` alias) and
`cachedAssetHosts` (missing the site host). Normalize by
prepending `https://` when no scheme is present, then let `URI`
parse. Pure JDK, no Android dependency.

Added regression tests covering schemeless hosts, ports,
userinfo, and integration through `buildSiteApiNamespace` and
`buildCachedHosts` (the latter uses the exact value
`shieldeyesfromlight.wordpress.com` to lock in the regression).

## Require per-call values explicitly in `buildPostConfiguration`

The builder previously hardcoded `locale="en"`,
`cookies=emptyMap()`, and `enableNetworkLogging=false`, relying
on `GutenbergKitActivity.buildEditorConfiguration` to overlay
them via `toBuilder()`. The stacked preloader (#22579) calls
`buildPostConfiguration` directly with no overlay, baking the
placeholder values into the preloaded `EditorDependencies`.

Promoted `locale`, `cookies`, and `isNetworkLoggingEnabled` to
required non-default parameters. The activity now passes them at
the call site; the `.toBuilder()` overlay is gone. The preloader
will fail to compile on rebase until it supplies the values —
exactly the failure mode we want.

## Gate `editorAssetsEndpoint` on capability and correct the route check

Two related bugs:

- `EditorSettingsRepository.fetchRouteSupport` was populating
  `SiteSupportsEditorAssets` from
  `/wp-block-editor/v1/assets` — a copy-paste from the line
  above. The URL we actually hit is `wpcom/v2/editor-assets`,
  which a vanilla self-hosted WP 6.7+ install doesn't expose.
  So `getSupportsEditorAssetsForSite` could be true on sites
  where the URL 404s.
- This PR set `editorAssetsEndpoint` unconditionally; the
  safety net was GutenbergKit's `plugins == false`
  short-circuit, which fails to protect when `plugins == true`
  on a site that lacks `wpcom/v2/editor-assets`.

Fixed both: the route check now queries
`/wpcom/v2, editor-assets`, and the URL is only set when
`resolveThirdPartyBlocks(site).isAvailable`. Both `plugins` and
`editorAssetsEndpoint` flow from the same resolver call and
cannot drift.

(Considered using `resolver.resolve(...)` to canonicalise the URL,
but the concrete uniffi resolver classes load JNA on
instantiation and the unit-test classpath doesn't include the
native lib. The string-concat output is byte-identical to the
resolver output for both WP.com and self-hosted shapes, so the
resolver was purely cosmetic here.)
@jkmassel jkmassel force-pushed the jkmassel/builder-injectable branch from bf8eba5 to e7e5d52 Compare May 19, 2026 20:37
@jkmassel jkmassel force-pushed the jkmassel/builder-injectable branch from e7e5d52 to d851897 Compare May 19, 2026 20:53
@jkmassel jkmassel marked this pull request as ready for review May 19, 2026 22:35
@wordpress-mobile wordpress-mobile deleted a comment from wpmobilebot May 19, 2026
@jkmassel
Copy link
Copy Markdown
Contributor Author

@nbradbury, this is rebased now that #22812 landed. It's ready for review now!

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. Tech Debt

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants