Skip to content

Conversation

@oguzkocer
Copy link
Contributor

Summary

Adds a debug-only Custom Post Types browser as the Android foundation for wordpress-rs service layer integration. The feature is behind an experimental flag and uses mock data - real data will come from wordpress-rs once the CPT service/repository layer is implemented.

Key decisions:

  • Isolated module (libs/posttypes) - Intentionally decoupled from FluxC to force clean wordpress-rs integration
  • Bridge pattern - SiteReference bridges app authentication to the module without FluxC dependency
  • Composition over inheritance - Activities use CptActivity interface instead of extending BaseAppCompatActivity

Changes

  • Add POST_TYPES experimental feature flag (debug builds only)
  • Add "Post Types" entry in MySite menu when flag is enabled
  • Create libs/posttypes module with:
    • Post types list screen (Posts, Pages)
    • Flat post list screen (for Posts)
    • Hierarchical post list screen (for Pages with indent-based hierarchy)
    • Bridge package with migration documentation

Demo

custom.post.types.webm

@dangermattic
Copy link
Collaborator

dangermattic commented Dec 8, 2025

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
Contributor

wpmobilebot commented Dec 8, 2025

Project manifest changes for WordPress

The following changes in the WordPress's merged AndroidManifest.xml file were detected (build variant: wordpressVanillaRelease):

--- ./build/reports/diff_manifest/WordPress/wordpressVanillaRelease/base_manifest.txt	2025-12-12 16:07:38.723568121 +0000
+++ ./build/reports/diff_manifest/WordPress/wordpressVanillaRelease/head_manifest.txt	2025-12-12 16:07:51.473568992 +0000
@@ -132,7 +132,8 @@
         android:preserveLegacyExternalStorage="true"
         android:requestLegacyExternalStorage="true"
         android:supportsRtl="true"
-        android:theme="@style/WordPress" >
+        android:theme="@style/WordPress"
+        android:usesCleartextTraffic="false" >
         <provider
             android:name="org.wordpress.android.localcontentmigration.LocalMigrationContentProvider"
             android:authorities="org.wordpress.android.LocalMigrationContentProvider"
@@ -1349,6 +1350,18 @@
             android:name="org.wordpress.android.editor.WPGutenbergWebViewActivity"
             android:theme="@style/Base.GutenbergWebView" />
         <activity
+            android:name="org.wordpress.android.posttypes.CptPostTypesActivity"
+            android:exported="false"
+            android:theme="@style/Cpt.NoActionBar" />
+        <activity
+            android:name="org.wordpress.android.posttypes.CptFlatPostListActivity"
+            android:exported="false"
+            android:theme="@style/Cpt.NoActionBar" />
+        <activity
+            android:name="org.wordpress.android.posttypes.CptHierarchicalPostListActivity"
+            android:exported="false"
+            android:theme="@style/Cpt.NoActionBar" />
+        <activity
             android:name="com.gravatar.quickeditor.ui.GravatarQuickEditorActivity"
             android:exported="true"
             android:launchMode="singleTask"

Go to https://buildkite.com/automattic/wordpress-android/builds/24206/canvas?sid=019b134c-8b3d-431a-8a99-4598e5e33b75, click on the Artifacts tab and audit the files.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Dec 8, 2025

Project manifest changes for WordPress

The following changes in the WordPress's merged AndroidManifest.xml file were detected (build variant: jetpackVanillaRelease):

--- ./build/reports/diff_manifest/WordPress/jetpackVanillaRelease/base_manifest.txt	2025-12-12 16:07:11.643904307 +0000
+++ ./build/reports/diff_manifest/WordPress/jetpackVanillaRelease/head_manifest.txt	2025-12-12 16:07:21.833933776 +0000
@@ -131,7 +131,8 @@
         android:preserveLegacyExternalStorage="true"
         android:requestLegacyExternalStorage="true"
         android:supportsRtl="true"
-        android:theme="@style/WordPress" > <!-- Deep Linking Activity -->
+        android:theme="@style/WordPress"
+        android:usesCleartextTraffic="false" > <!-- Deep Linking Activity -->
         <activity
             android:name="org.wordpress.android.ui.deeplinks.DeepLinkingIntentReceiverActivity"
             android:excludeFromRecents="true"
@@ -1376,6 +1377,18 @@
             android:name="org.wordpress.android.editor.WPGutenbergWebViewActivity"
             android:theme="@style/Base.GutenbergWebView" />
         <activity
+            android:name="org.wordpress.android.posttypes.CptPostTypesActivity"
+            android:exported="false"
+            android:theme="@style/Cpt.NoActionBar" />
+        <activity
+            android:name="org.wordpress.android.posttypes.CptFlatPostListActivity"
+            android:exported="false"
+            android:theme="@style/Cpt.NoActionBar" />
+        <activity
+            android:name="org.wordpress.android.posttypes.CptHierarchicalPostListActivity"
+            android:exported="false"
+            android:theme="@style/Cpt.NoActionBar" />
+        <activity
             android:name="com.gravatar.quickeditor.ui.GravatarQuickEditorActivity"
             android:exported="true"
             android:launchMode="singleTask"

Go to https://buildkite.com/automattic/wordpress-android/builds/24206/canvas?sid=019b134c-8b3e-4e77-a840-9fed06535a49, click on the Artifacts tab and audit the files.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Dec 8, 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
FlavorJalapeno
Build TypeDebug
Versionpr22405-f412acc
Commitf412acc
Direct Downloadwordpress-prototype-build-pr22405-f412acc.apk
Note: Google Login is not supported on these builds.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Dec 8, 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
FlavorJalapeno
Build TypeDebug
Versionpr22405-f412acc
Commitf412acc
Direct Downloadjetpack-prototype-build-pr22405-f412acc.apk
Note: Google Login is not supported on these builds.

@codecov
Copy link

codecov bot commented Dec 8, 2025

Codecov Report

❌ Patch coverage is 46.15385% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 39.09%. Comparing base (c85d649) to head (f412acc).
⚠️ Report is 18 commits behind head on trunk.

Files with missing lines Patch % Lines
...ava/org/wordpress/android/ui/ActivityLauncher.java 0.00% 6 Missing ⚠️
...droid/ui/mysite/items/listitem/SiteItemsBuilder.kt 40.00% 5 Missing and 1 partial ⚠️
...ordpress/android/ui/mysite/SiteNavigationAction.kt 0.00% 1 Missing ⚠️
...s/android/ui/mysite/cards/ListItemActionHandler.kt 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##            trunk   #22405   +/-   ##
=======================================
  Coverage   39.09%   39.09%           
=======================================
  Files        2207     2207           
  Lines      106869   106893   +24     
  Branches    15162    15166    +4     
=======================================
+ Hits        41780    41790   +10     
- Misses      61573    61586   +13     
- Partials     3516     3517    +1     

☔ 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.

@oguzkocer oguzkocer marked this pull request as ready for review December 9, 2025 16:04
@oguzkocer oguzkocer enabled auto-merge (squash) December 9, 2025 16:04
@oguzkocer oguzkocer requested a review from jkmassel December 9, 2025 16:04
@oguzkocer oguzkocer added this to the 26.5 milestone Dec 9, 2025
Added debug-only experimental flag to enable/disable the Post Types screen.
This flag will control visibility of the new post types functionality that
allows users to view and navigate different post types from a unified screen.

Changes:
- Added EXPERIMENTAL_POST_TYPES feature to ExperimentalFeatures enum
- Configured flag to only appear in debug builds via BuildConfig check
- Added UI strings for feature name and description
Implements the initial UI for the experimental Post Types feature:
- `PostTypesActivity` with Compose-based UI
- `PostTypesViewModel` with hardcoded post types (Posts, Pages)
- `PostTypesScreen` composable with list display
- Navigation wiring from My Site menu (when feature flag enabled)

The screen is accessible from My Site menu when the experimental
Post Types feature flag is enabled in debug builds.

Changes:
- Add `PostTypesActivity`, `PostTypesViewModel`, and `PostTypesScreen`
- Register activity in AndroidManifest
- Add `OpenPostTypes` navigation action and `POST_TYPES` list item action
- Wire up navigation in `MySiteFragment`, `MenuActivity`, and handlers
- Add `post_types_screen_title` string resource
- Add proper import for `PostTypesActivity` in `ActivityLauncher.java`
- Add `@Suppress("unused")` annotation for `site` property in
  `PostTypesViewModel` (will be used when API integration is added)
Introduces `CptFlatPostListActivity` - a Compose-based screen that
displays a flat list of posts for a given post type. This is a skeleton
implementation with mock data to establish the navigation flow.

The `Cpt` prefix is used for all new types in this feature to avoid
naming conflicts with existing types and to indicate WIP status.

Changes:
- Add `CptFlatPostListActivity` with Compose UI
- Add `CptFlatPostListViewModel` with mock post data
- Add `CptFlatPostListScreen` composable with title, excerpt, and status
- Add `CptPostListItem` and `CptFlatPostListUiState` data classes
- Add `PostTypesNavigationAction` sealed class for type-safe navigation
- Wire up navigation from `PostTypesActivity` using SharedFlow
- Register new activity in AndroidManifest
Renames all new types in the posttypes package to use the `Cpt` prefix
for consistency and to avoid naming conflicts with existing types.

Renames:
- `PostTypesActivity` → `CptPostTypesActivity`
- `PostTypesViewModel` → `CptPostTypesViewModel`
- `PostTypesScreen` → `CptPostTypesScreen`
- `PostTypesUiState` → `CptPostTypesUiState`
- `PostTypeItem` → `CptPostTypeItem`
- `PostTypesNavigationAction` → `CptNavigationAction`
Moves the Custom Post Types (CPT) feature to `libs/posttypes` module
to enforce clean boundaries and prevent accidental FluxC usage during
wordpress-rs integration.

The module is intentionally isolated with minimal dependencies. A
`bridge` package contains temporary coupling code (`SiteReference`,
`CptTheme`, `BridgeConstants`) that explicitly documents what needs
attention when integrating wordpress-rs or merging back.

Changes:
- Create `libs/posttypes` module with Compose, Hilt, and Parcelize
- Add `bridge` package with documented temporary bridging types
- Move CPT activities, ViewModels, and Compose screens to new module
- Update `ActivityLauncher` to convert `SiteModel` to `SiteReference`
- Add comprehensive README with migration instructions
Fixes navigation not working and removes green action bar header that
appeared due to inheriting the app's default theme.

Changes:
- Add `extraBufferCapacity = 1` to SharedFlow for reliable navigation
- Add `CptActivity` interface with `applyBaseSetup()` extension for
  composition over inheritance pattern
- Add `Cpt.NoActionBar` theme to prevent action bar from showing
- Update activities to use new composition pattern
- Document bridge components and migration notes in README
Resolve 8 detekt violations:
- Rename ActivitySetup.kt to CptActivity.kt to match top-level declaration
- Remove TODO markers from suppression comments
- Refactor mock data generation to use loop instead of hardcoded list
- Add @Suppress annotations for intentional violations (mock data, stub handler)
Add separate UI for hierarchical post types (like Pages) that displays
posts with visual indentation based on parent-child relationships.

Changes:
- Add `hierarchical` flag to `CptPostTypeItem` model
- Create `CptHierarchicalPostListActivity` and ViewModel with mock hierarchy
- Create `CptHierarchicalPostListScreen` with indent-based display
- Route Pages to hierarchical screen, Posts to flat screen
Set explicit secure defaults for `allowBackup` and `usesCleartextTraffic`
to satisfy static analysis. Main app values override during manifest merge.
Add mock for ExperimentalFeatures and pass it to SiteItemsBuilder
constructor to fix compilation error after adding the dependency.
@oguzkocer oguzkocer force-pushed the experimental/post-types-ui branch from 1676e98 to f412acc Compare December 12, 2025 16:02
@sonarqubecloud
Copy link

@oguzkocer oguzkocer requested review from adalpari and removed request for jkmassel December 17, 2025 20:21
}

// Basic color schemes - these approximate the WordPress/Jetpack themes
private val LightColorScheme = lightColorScheme(
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ Probably not something we want to work on right now, but duplicating themes could be a source of future misalignments.

@Suppress("unused") // Will be used to fetch posts from wordpress-rs
private val postTypeSlug: String = savedStateHandle.get<String>(
CptFlatPostListActivity.EXTRA_POST_TYPE_SLUG
) ?: ""
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
) ?: ""
).orEmpty()


private val postTypeLabel: String = savedStateHandle.get<String>(
CptFlatPostListActivity.EXTRA_POST_TYPE_LABEL
) ?: ""
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
) ?: ""
).orEmpty()

@Suppress("unused") // Will be used to fetch posts from wordpress-rs
private val postTypeSlug: String = savedStateHandle.get<String>(
CptHierarchicalPostListActivity.EXTRA_POST_TYPE_SLUG
) ?: ""
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
) ?: ""
).orEmpty()


private val postTypeLabel: String = savedStateHandle.get<String>(
CptHierarchicalPostListActivity.EXTRA_POST_TYPE_LABEL
) ?: ""
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
) ?: ""
).orEmpty()

val navigation: SharedFlow<CptNavigationAction> = _navigation.asSharedFlow()

fun onPostTypeClick(postType: CptPostTypeItem) {
site?.let {
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ If site is null, should we log an error?

Copy link
Contributor

@adalpari adalpari left a comment

Choose a reason for hiding this comment

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

LGTM!
Just left some minor comments, but don't want to block the PR

@oguzkocer oguzkocer merged commit e3e0289 into trunk Dec 19, 2025
23 checks passed
@oguzkocer oguzkocer deleted the experimental/post-types-ui branch December 19, 2025 11:59
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.

5 participants