Skip to content

Extract :libs:core-ui module from :WordPress#22759

Draft
jkmassel wants to merge 26 commits intotrunkfrom
jkmassel/modularize-features
Draft

Extract :libs:core-ui module from :WordPress#22759
jkmassel wants to merge 26 commits intotrunkfrom
jkmassel/modularize-features

Conversation

@jkmassel
Copy link
Copy Markdown
Contributor

@jkmassel jkmassel commented Apr 2, 2026

Summary

  • Extracts a new :libs:core-ui module containing foundational UI components, Compose theme, ViewModel base classes, and shared utilities
  • Makes core-ui the canonical owner of shared UI strings (close, cancel, uploading, etc.) with all 54 locale translations
  • Registers core-ui in the fastlane localization pipeline for GlotPress translation flow

This is the first step toward modularizing the codebase to improve compilation and linting speed. The goal is to establish a foundational UI layer that feature modules (reader, stats, posts, etc.) can depend on without pulling in the full :WordPress module.

What moved to core-ui

  • Compose theme: AppThemeM3, AppColor, JetpackColors
  • Compose components: buttons, cards, text, dialogs, empty content, top app bars
  • Compose utilities: ComposeUtils, MarkdownUtils, SpannedTextUtils, FadingEdgesModifier
  • UI utilities: UiHelpers, UiString, UiDimen, ListItemInteraction, ContinuationWrapper
  • ViewModel base classes: ScopedViewModel, Event, ResourceProvider, SingleLiveEvent
  • Coroutine dispatcher constants: APPLICATION_SCOPE, UI_THREAD, BG_THREAD, IO_THREAD

Notable changes

  • AppThemeM3 uses a new LocalIsJetpackApp CompositionLocal instead of BuildConfig.IS_JETPACK_APP
  • UiHelpers animation methods moved to UiHelpersExt.kt in :WordPress (depend on app-specific AniUtils)

Test plan

  • Verify assembleWordPressDebug builds successfully
  • Verify assembleJetpackDebug builds successfully
  • Compare detekt lint time before and after this change
  • Verify Compose previews still render in core-ui components
  • Spot-check translated strings appear correctly at runtime

🤖 Generated with Claude Code

@dangermattic
Copy link
Copy Markdown
Collaborator

dangermattic commented Apr 2, 2026

2 Warnings
⚠️ View files have been modified, but no screenshot or video is included in the pull request. Consider adding some for clarity.
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.
1 Message
📖 This PR is still a Draft: some checks will be skipped.

Generated by 🚫 Danger

@jkmassel jkmassel force-pushed the jkmassel/modularize-features branch from 3cfd6c4 to 7214c88 Compare April 2, 2026 02:43
jkmassel and others added 3 commits April 1, 2026 20:47
Pure file moves with no modifications, to preserve git history.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move foundational UI components, Compose theme, ViewModel base classes,
and shared utilities into the new core-ui library module. This is the
first step toward modularizing the codebase to improve compilation and
linting speed.

Moved to core-ui:
- Compose theme (AppThemeM3, AppColor, JetpackColors)
- Compose components (buttons, cards, text, dialogs, etc.)
- Compose utilities (ComposeUtils, MarkdownUtils, SpannedTextUtils, etc.)
- UI utilities (UiHelpers, UiString, UiDimen, ListItemInteraction, etc.)
- ViewModel base classes (ScopedViewModel, Event, ResourceProvider, etc.)
- Coroutine dispatcher constants (APPLICATION_SCOPE, UI_THREAD, etc.)

Notable changes:
- AppThemeM3 now uses `LocalIsJetpackApp` CompositionLocal instead of
  BuildConfig.IS_JETPACK_APP, decoupling it from the app module
- UiHelpers animation methods moved to UiHelpersExt.kt in :WordPress
  (they depend on app-specific AniUtils)
- WPSwitch preview simplified to remove WPSwitchCompat dependency
- ComposeUtils inlines locale/RTL helpers previously from util.extensions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Make core-ui the single source of truth for shared UI strings (close,
cancel, uploading, navigate_up_desc, close_desc). Move all existing
translations (54 locales) from :WordPress to core-ui and remove the
duplicates from the app module.

Register core-ui in the fastlane localization pipeline so GlotPress
translations flow directly to the library module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jkmassel jkmassel force-pushed the jkmassel/modularize-features branch from 7214c88 to cc084fc Compare April 2, 2026 02:48
Move colors_studio_palette.xml (the design system palette) and the
placeholder color to core-ui as the canonical source. Remove duplicate
palette colors from core-ui's colors.xml now that the palette file
provides them.

WordPress's semantic colors (reader, site creation, etc.) stay in
:WordPress and continue to reference the palette via resource names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented Apr 2, 2026

🤖 Build Failure Analysis

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

jkmassel and others added 20 commits April 1, 2026 22:11
Move dependency-free utility classes from `:WordPress` to a new
`:libs:utils` module so they can be compiled and linted in parallel.

Files that depend on WordPress-only classes (AppConfig, ImageManager,
WPActivityUtils, Gravatar SDK, etc.) remain in `:WordPress` for now.

Also re-declares shared UI strings and the color studio palette in
WordPress's own resources — AGP 9 non-transitive R class means the
app module's compile-time R class no longer includes library resources.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moves 10 unit tests that have no WordPress-only dependencies to
libs/utils/src/test/. Three tests (LiveDataUtilsTest,
PercentFormatterTest, WizardManagerTest) remain in WordPress because
they extend BaseUnitTest. Three instrumented tests remain because
they require Hilt test configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moves BaseUnitTest and CoroutineTestRule to a new core-test module
so library modules can use them for unit testing. Both WordPress
(408 tests) and libs:utils consume this via testImplementation.

Also moves LiveDataUtilsTest and PercentFormatterTest to libs:utils
now that their only blocker (BaseUnitTest) is available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the SiteCreationStep dependency with a test-local TestStep
enum so the test is self-contained and can live alongside WizardManager
in the utils module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moves from androidTest to libs:utils/src/test and removes the
unnecessary @HiltAndroidTest annotation — the test only exercises
pure static methods and never needed DI or device runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both tests only exercise pure static methods and never use injected
dependencies. They remain as instrumented tests because the underlying
code uses android.net.Uri which requires Android runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These widgets have no app-module dependencies (only Android
framework, AndroidX, Material, and wordpress-utils), making
them safe to share across library modules.

Moved: CheckedLinearLayout, ColorUnderlineSpan, HeaderGridView,
NestedCoordinatorLayout, NoticonTextView, RecyclerItemDecoration,
TypefaceCache, WPNestedScrollView, WPScrollView, WPSnackbar,
WPViewPager, WPViewPager2Transformer, WPViewPagerTransformer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both are generic utility types with zero app-module dependencies.
DateProvider wraps java.util.Date; SiteAccessibilityInfo is a
pure data class with a SiteVisibility enum. Moving them to utils
prepares for Reader module extraction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Zero-dependency enum used by Reader models and other features.
Moving to core-ui makes it available to all library modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moves Reader models, datasets, constants, and pure utility functions
into a dedicated library module. This enables non-Reader features
(notifications, engagement, posts) to depend on Reader data types
without depending on the full Reader UI.

Moved 47 files:
- 16 Reader model classes (ReaderPost, ReaderTag, ReaderBlog, etc.)
- 17 dataset/table classes + 4 wrappers (ReaderPostTable, etc.)
- 5 reader model POJOs (ReaderBlogIdPostId, ReaderSimplePost, etc.)
- ReaderConstants, ReaderActions, ReaderHtmlUtils, ReaderImageScanner
- FilterCriteria interface

Key refactors:
- ReaderDatabase: replaced WordPress.getContext() singleton with
  init(Context) pattern called from AppInitializer
- Created ReaderSlugUtils with model-layer methods extracted from
  ReaderUtils (sanitizeWithDashes, getTagFromTagName,
  getResizedImageUrl, etc.)
- ReaderPostDiscoverData: getAttributionHtml() now takes Context param
- ReaderPostTable: hardcoded "View original" in rare fallback path
- ReaderUserTable: replaced WPAvatarUtils with PhotonUtils
- Split ReaderRepositoryEvent out of ReaderRepositoryEvents.kt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create the `:libs:reader` library module and move Reader source files
that have no WordPress app-layer dependencies. Also move
ReaderBlogTableWrapper and ReaderDiscoverCardsTableWrapper to
`:libs:reader-models` where they belong alongside their table classes.

Fix cross-module smart cast issues in ReaderCommentListActivity,
ReaderPostDetailFragment, and SubfilterPageFragment caused by data
classes now residing in a different module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move data classes, enums, and UI state files that only depend on
libs:core-ui (UiString, ImageType) and classes already in libs:reader.
Fix cross-module smart cast in ReaderPostDetailHeaderView.

Moved files:
- subscription/ReaderSubscriptionSettingsUiState
- tracker/ReaderTrackerInfo
- views/uistates/FollowButtonUiState, CommentSnippetItemState,
  ReaderBlogSectionUiState, ReaderPostDetailsHeaderViewUiState,
  ReaderPostDetailsHeaderAction
- views/ReaderTagHeaderViewUiState
- adapters/CommentSnippetAdatperDiffCallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactor ReaderTracker from a concrete class to an interface in
libs:reader, enabling reader files that depend on it to eventually
move to the library module.

- Create ReaderTracker interface in libs:reader with all public methods
- Move SOURCE_* constants and static utilities to the interface companion
- Move ReaderTab enum to its own file in libs:reader
- Move ReaderTypes to libs:reader (depends on SOURCE_* constants)
- Rename concrete class to ReaderTrackerImpl implementing the interface
- Add Hilt @BINDS module (ReaderModule) to wire impl to interface
- Add libs:analytics dependency to libs:reader

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Now that ReaderTracker is an interface in libs:reader, files that
depended on it can move. Move use cases, view models, and helper
classes that are now fully resolved against library modules.

Moved files:
- comments/ThreadedCommentsActionSource
- viewmodels/ReaderModeInfo
- repository/usecases: GetPostsForTagUseCase, GetNumPostsForTagUseCase,
  ShouldAutoUpdateTagUseCase, GetPostsForTagWithCountUseCase
- repository/usecases/tags/GetFollowedTagsUseCase
- usecases/ReaderGetPostUseCase

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move SnackbarMessageHolder to `:libs:core-ui` and fix cross-module
  smart cast issues for buttonTitle in 20 call sites
- Create NetworkAvailability interface in `:libs:utils` and have
  NetworkUtilsWrapper implement it, wired via Hilt @BINDS
- Update 10 reader use cases to depend on the interface
- Move ReaderSiteNotificationsUseCase and ReaderBlogSubscriptionUseCase
  to `:libs:reader` (now unblocked by interface abstraction)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract reader-only strings from WordPress's strings.xml to
libs/reader/src/main/res/values/strings.xml. The 11 strings shared
with non-reader code stay in WordPress.

Update all 46 Kotlin files, 11 Java files, and 12 test files to
reference moved strings via `ReaderR.string.reader_*` (Kotlin) or
`org.wordpress.android.reader.R.string.reader_*` (Java).

XML layout references work unchanged via resource merging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract 27 reader-only colors (light + night modes) and 2 color state
list files from WordPress to libs:reader. The 5 colors shared with
non-reader code stay in WordPress.

Update R.color.reader_* references in Kotlin/Java files to use
ReaderR.color.reader_* or fully qualified references.

Inline semantic color aliases (neutral_*, primary, background_dark*)
that aren't available in the library module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract 66 reader-only dimens (plus overrides across 7 qualifier
directories) from WordPress to libs:reader. Update all R.dimen.reader_*
references in Kotlin files to ReaderR.dimen.reader_* and in Java files
to fully qualified references.

Inline @dimen/ aliases not available in the library module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move ReaderPostCardActionType enum from ReaderCardUiState.kt into its
own file in libs:reader, unblocking ReaderInterfaces.java which also
moves.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Creates a ReaderPreferences interface in libs:reader with the 22
reader-specific methods from AppPrefsWrapper. AppPrefsWrapper
implements the interface and is wired via Hilt @BINDS in ReaderModule.
This unblocks moving 9 more reader files to the libs:reader module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented Apr 2, 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
Versionpr22759-73d319e
Build Number1488
Application IDcom.jetpack.android.prealpha
Commit73d319e
Installation URL0num7tl5ac9cg
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

- ReaderCssProvider: swapped AppPrefsWrapper → ReaderPreferences,
  NetworkUtilsWrapper → NetworkAvailability
- SubfilterListItem: removed unused R import
- SubfilterCategory: extracted from SubfilterPageFragment to own file
- BottomSheetUiState: pure data class, no blockers
- JetpackMenuElementData: made NO_ICON public for cross-module access

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented Apr 2, 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
Versionpr22759-73d319e
Build Number1488
Application IDorg.wordpress.android.prealpha
Commit73d319e
Installation URL2l68g5ipc75h8
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

Remove unused `import org.wordpress.android.R` from files that now only
reference reader resources via `ReaderR`. Fix line length violations in
Java and Kotlin files. Add @Suppress annotations for pre-existing detekt
issues surfaced by moving files to new modules. Add missing base
`placeholder` color resource for lint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 3, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
E Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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