Skip to content

Migrate the Site Creation Domain Search to wordpress-rs - #23247

Open
oguzkocer wants to merge 10 commits into
trunkfrom
integrate-wordpress-rs-site-creation-domains
Open

Migrate the Site Creation Domain Search to wordpress-rs#23247
oguzkocer wants to merge 10 commits into
trunkfrom
integrate-wordpress-rs-site-creation-domains

Conversation

@oguzkocer

@oguzkocer oguzkocer commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description

Moves SiteCreationDomainsViewModel and FetchDomainsUseCase off FluxC and onto wordpress-rs. FetchDomainsUseCase calls WpComApiClient.domains().suggestions() directly instead of dispatching newSuggestDomainsAction and waiting for an OnSuggestedDomains event, so the EventBus subscription, the query-to-continuation pairing, and the ViewModel's dispatcher registration all go away.

Behaviour is meant to match trunk. The pieces worth checking:

  • empty_results is not a failure. The API reports "no domains for that search" as an HTTP error, and FluxC turned it back into a successful empty list. The migration does the same, so the screen shows the empty-list message rather than a red error with a retry button.
  • invalid_query keeps its own message. Same as trunk, and it is not tracked as an error.
  • The tracked error type survives. FetchDomainsResult.Error carries the API's error code and message through to trackErrorShown. SuggestDomainErrorType supplied that value before, derived from the same code, and the tracker lowercases whatever it is given, so the value reported for a known code is unchanged.

Three cleanups came out of reviewing the migration:

  • fetchDomains had a size parameter that was suppressed rather than read, since quantity is always FETCH_DOMAINS_SIZE. No caller passed it.
  • Every FetchDomainsResult echoed the query back, which the caller already held. That existed to match an EventBus result to its request and a suspend call needs no such thing.
  • The screen fetched the domain products list on start and stored it in a field nothing read. NewDomainsSearchRepository and DomainSuggestionsViewModel are the callers that read a product, both for combinedSaleCostDisplay, and neither is affected. The sale UI this screen kept for it — Cost.OnSale, Tag.Sale, the SalePrice composable — was only ever built by DomainItemPreview, so it rendered in Android Studio and nowhere else.

Dropping animateLayoutChanges on this screen

On trunk, typing the first character into the domain search stops you typing until that first request finishes — every keystroke in between is lost. The implicit layout animation that runs when the clear button and the spinner appear takes focus off the search field, and nothing gives it back until the results arrive.

Removing animateLayoutChanges from this screen's two layouts fixes it. The trade is that the views around the header snap into place rather than sliding. It reads as snappier to me and losing keystrokes was the worse of the two, but it is a visible change.

Testing instructions

Reach the screen: My Site → the site name dropdown → +Create WordPress.com site → skip or fill the two steps before Choose a domain.

Typing is not interrupted:

  1. Type a single character into the search field.
  • Verify you can keep typing straight away, without waiting for the spinner to stop or tapping the field again.

A query the API refuses:

  1. Search for .
  • Verify the empty-state message about the search being invalid, not an error with a retry button.

A query with no matches:

  1. Search for a long run of the same letter, e.g. 200 or so z characters.
  • Verify the ordinary empty-state message.

A normal search:

  1. Search for anything ordinary, e.g. coolsite.
  • Verify suggestions appear, the free .wordpress.com option among them.
  • Verify the first two paid suggestions are tagged Recommended and Best Alternative.
  • Verify selecting one enables the button at the bottom and its label matches free vs. paid.

No connection:

  1. Turn off networking and search.
  • Verify the no-network message with a retry button, and that retry works once networking is back.

Screenshots

Invalid query No matches Results No connection
Invalid query No matches Results No connection

… FluxC to wordpress-rs

Replace FluxC's dispatcher/EventBus domain suggestions with direct
wordpress-rs API calls:

- `FetchDomainsUseCase` now uses `WpComApiClient.domains().suggestions()`
  instead of FluxC's `Dispatcher` + `OnSuggestedDomains` event
- `SiteCreationDomainsViewModel` uses wordpress-rs for products fetch
  instead of `ProductsStore`
- Handle `invalid_query` API error via `WpErrorCode.CustomException`
  to preserve the empty-results UX (matching FluxC's `INVALID_QUERY`)
- Remove `Dispatcher` registration/unregistration from ViewModel
`quantity` is always `FETCH_DOMAINS_SIZE`, so the parameter was suppressed
rather than read. No caller passed it.

Changes:
- Remove `size` from `FetchDomainsUseCase.fetchDomains`
- Drop it from the stubs and verifications in `SiteCreationDomainsViewModelTest`
The caller passes the query in and holds it across the call, so it never
read the copy coming back. Echoing it was needed when the result arrived
over EventBus and had to be matched to its request.

Changes:
- Remove `query` from `FetchDomainsResult`, making `InvalidQuery` and
  `Error` data objects
- Update the ViewModel branches and both test classes
Every rejection reported as a generic error with no message, and
`empty_results` reached the user as a failure with a retry button rather
than the empty-list message it stands for.

`SuggestDomainErrorType` supplied the tracked type before, derived from the
same API code; the tracker lowercases what it is given, so the code goes
through as-is.

Changes:
- Carry the API error code and message on `FetchDomainsResult.Error` and
  track them instead of a hardcoded `GENERIC_ERROR`
- Map `empty_results` to an empty `Success`
- Log the product-fetch failure with `toLogErrorString()`
- Cover the `invalid_query`, `empty_results`, and other-code paths, and
  assert the tracked type and message
Changes:
- Sort the `rs.wordpress` and `uniffi` imports after the `org.wordpress`
  block in the ViewModel and its test, matching the other migrated classes
- Make `SALE_PRODUCTS_COUNT` a const and drop its `@Suppress("unused")`;
  both sale tests read it
- Drop an `@Suppress("UNCHECKED_CAST")` from a test with no cast, and a
  stray blank line
`SiteCreationDomainsViewModel` requested the products list on start and
stored it in a field nothing read, so the screen paid for a request it made
no use of.

`NewDomainsSearchRepository` and `DomainSuggestionsViewModel` are the callers
that read a product, both for `combinedSaleCostDisplay`, and neither is
affected.

Changes:
- Remove the products fetch, the cached field, and the API client it needed,
  along with the `WpComApiClientProvider` and `AccountStore` dependencies
- Remove the test asserting the fetch happened once, and the two `@Ignore`d
  sale tests it fed
`Cost.OnSale` and `Tag.Sale` were only ever built by `DomainItemPreview`, so
the sale price and its tag rendered in Android Studio and nowhere else.

Changes:
- Remove `Cost.OnSale`, `Tag.Sale`, the `SalePrice` composable, and the
  branch selecting it
- Remove them from the preview fixture
- Remove the `site_creation_domain_cost_sale` and
  `site_creation_domain_tag_sale` strings they used
Typing the first character made the clear button and the spinner appear,
and the `LayoutTransition` animated the neighbouring views' bounds through
zero height. The framework clears focus on a view animated to zero size, so
the field lost it, the toolbar's navigation button took it, and the input
connection stayed inactive until the results arrived and the field asked for
focus back. Every character typed in between was dropped.

Both layouts belong to this screen alone. The header still animates itself
in `updateHeader`; what is lost is the implicit animation of the views
around it.

Changes:
- Drop `android:animateLayoutChanges` from `site_creation_domains_screen`
  and `site_creation_search_input_item`
@dangermattic

dangermattic commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator
2 Warnings
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.
⚠️ PR is not assigned to a milestone.

Generated by 🚫 Danger

Checkstyle rejects an empty line before a closing brace, and removing
`Tag.Sale` and `Cost.OnSale` left one behind in each.

Changes:
- Drop the blank lines before the `Tag` and `Cost` closing braces
@wpmobilebot

wpmobilebot commented Aug 20, 2026

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
Versionpr23247-e21c17e
Build Number1498
Application IDcom.jetpack.android.prealpha
Commite21c17e
Installation URL2ircro5fp5248
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot

wpmobilebot commented Aug 20, 2026

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
Versionpr23247-e21c17e
Build Number1498
Application IDorg.wordpress.android.prealpha
Commite21c17e
Installation URL11e963qgpolo0
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

🤖 Build Failure Analysis

This build has failures. Claude has analyzed them - check the build annotations for details.

Lint's `ExtraTranslation` rejects a string that a locale translates but the
default locale does not define, and the two sale strings left the default
locale with the UI that used them.

Changes:
- Delete `site_creation_domain_tag_sale` and
  `site_creation_domain_cost_sale` from every `values-*/strings.xml`
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.85714% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.98%. Comparing base (d97e85a) to head (e21c17e).

Files with missing lines Patch % Lines
...id/ui/sitecreation/usecases/FetchDomainsUseCase.kt 85.29% 1 Missing and 4 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##            trunk   #23247   +/-   ##
=======================================
  Coverage   37.97%   37.98%           
=======================================
  Files        2336     2336           
  Lines      127220   127218    -2     
  Branches    17629    17632    +3     
=======================================
+ Hits        48312    48319    +7     
+ Misses      74960    74951    -9     
  Partials     3948     3948           

☔ View full report in Codecov by Harness.
📢 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.

@oguzkocer
oguzkocer marked this pull request as ready for review August 20, 2026 22:13
@oguzkocer
oguzkocer requested review from a team and adalpari and removed request for a team August 20, 2026 22:13
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