Skip to content

Convert GutenbergKitSettingsBuilder to injectable class#22836

Open
jkmassel wants to merge 12 commits intojkmassel/editor-capability-resolverfrom
jkmassel/builder-injectable
Open

Convert GutenbergKitSettingsBuilder to injectable class#22836
jkmassel wants to merge 12 commits intojkmassel/editor-capability-resolverfrom
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
  • Open the editor on a WP.com simple site — opens, theme styles applied per pref
  • Open the editor on a self-hosted site with an application password — opens, Basic auth header set, no wpcom/v2/editor-assets request fires
  • Open the editor on a Jetpack site — opens, Bearer token used

Related

jkmassel and others added 12 commits April 22, 2026 09:06
Add a new "Use Third-Party Blocks" toggle in Site Settings, gated
behind GutenbergKit and editor assets support. Enhance the existing
"Use Theme Styles" toggle with contextual warnings when the site
lacks editor settings support or uses a non-block theme.

Includes SiteSettingsProvider interface for injectable access to
site settings from the local DB, replacing static SiteUtils calls
for block editor default detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gate the "Use Third-Party Blocks" toggle behind the remote
gutenberg_kit_plugins feature flag in addition to the existing
GutenbergKit and editor assets checks. Also simplify the summary
string by removing "and styles" per reviewer feedback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tion

Add ThemeRepository to fetch the active theme via WP API and determine
if it is a block theme. Add EditorSettingsRepository to discover
editor settings and editor assets route support via manifest/API root
queries. Wire SiteSettingsFragment to use EditorSettingsRepository for
gating theme styles and third-party blocks toggles.

Also adds manifest route fetching methods to WpApiClientProvider for
discovering available REST routes on WP.com and self-hosted sites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove fetchWpComManifestRoutes and fetchSiteManifestRoutes from
WpApiClientProvider. EditorSettingsRepository now uses the standard
WpApiClient.request { it.apiRoot().get() } for all site types,
which already handles WP.com vs self-hosted URL resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Call `EditorSettingsRepository.fetchEditorCapabilitiesForSite` when
the user lands on My Site so the route-discovery and theme-detection
results are available by the time they open Site Settings.

On failure, a snackbar is shown and cached prefs retain their previous
values so settings degrade to disabled rather than crashing.
12 tests covering pref delegation, route discovery persistence,
theme detection, API errors, transport-level error isolation
(one fetch failing doesn't block the other), and the both-fail
case. Also fix MySiteViewModelTest for new constructor param.
Points at Automattic/wordpress-rs#1285 which fixes route discovery
on WP.com simple sites so editor-assets and editor-settings routes
appear in the API root response.

Also adapts StatsDataSourceImpl to the new StatsUtmKeys API (String
replaced with List<StatsUtmKey>).
Switch from hasRoute (exact path match) to hasRouteForEndpoint
(namespace + endpoint) so that WP.com sites — whose route keys
include a sites/{site_id} prefix — are correctly detected.

Requires wordpress-rs PR #1285 which adds hasRouteForEndpoint
to WpApiDetails and the ApiUrlResolver parameter.
Call fetchEditorCapabilitiesForSite during pull-to-refresh so
editor settings prefs stay current without requiring a full
screen resume. Show snackbar on failure in both paths.
`SiteSettingsFragment` combined the top-level GutenbergKit feature
flag, the remote `gutenberg_kit_plugins` flag, the per-site capability
cache, and the user's toggle inline — a long conditional chain per
capability that's hard to share with other consumers and easy to drift
from when those consumers get added.

Introduces `EditorCapabilityResolver` as a single source of truth for
both theme styles and third-party blocks. Returns a `Resolved` sealed
result — `Hidden` / `Unsupported(reason)` / `Available(userEnabled,
advisory?)` — that UI callers branch on directly, and non-UI callers
collapse via `shouldApplyInEditor`. The theme-not-a-block-theme case
is modelled as an advisory, not a gate, matching today's behaviour
where the pref stays enabled with an informational summary.

Wires `SiteSettingsFragment` through the resolver. The editor-side
consumer (the GutenbergKit config builder) will land in a follow-up
alongside its refactor to an injectable class.
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`.
@dangermattic
Copy link
Copy Markdown
Collaborator

1 Error
🚫 PR requires at least one label.
1 Warning
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Copy Markdown
Contributor

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-b984d31
Build Number1488
Application IDorg.wordpress.android.prealpha
Commitb984d31
Installation URL4h2q6s3lsr20o
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

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-b984d31
Build Number1488
Application IDcom.jetpack.android.prealpha
Commitb984d31
Installation URL38dhi8hsdi0a8
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants