Skip to content

Commit e3e0289

Browse files
authored
Add debug-only Post Types module for wordpress-rs integration (#22405)
* Add experimental Post Types feature flag 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 * Add Post Types screen UI skeleton 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 * Code cleanup for Post Types feature - 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) * Add flat post list screen skeleton 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 * Rename Post Types classes to use Cpt prefix 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` * Extract Post Types feature to isolated module 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 * Fix Post Types module UI issues and add composition pattern 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 * Fix detekt issues in Post Types module 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 hierarchical post list skeleton for Pages 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 * Fix Sonar security warnings in Post Types manifest Set explicit secure defaults for `allowBackup` and `usesCleartextTraffic` to satisfy static analysis. Main app values override during manifest merge. * Fix SiteItemsBuilderTest missing experimentalFeatures parameter Add mock for ExperimentalFeatures and pass it to SiteItemsBuilder constructor to fix compilation error after adding the dependency.
1 parent 9c55474 commit e3e0289

32 files changed

+1207
-3
lines changed

WordPress/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ dependencies {
395395
}
396396
}
397397
implementation project(":libs:login")
398+
implementation project(":libs:posttypes")
398399
implementation("$gradle.ext.aboutAutomatticBinaryPath:${libs.versions.automattic.about.get()}")
399400

400401
implementation("$gradle.ext.gutenbergKitBinaryPath:${libs.versions.gutenberg.kit.get()}")

WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@
9797
import org.wordpress.android.ui.posts.PostUtils.EntryPoint;
9898
import org.wordpress.android.ui.posts.PostsListActivity;
9999
import org.wordpress.android.ui.posts.RemotePreviewLogicHelper.RemotePreviewType;
100+
import org.wordpress.android.posttypes.CptPostTypesActivity;
101+
import org.wordpress.android.posttypes.bridge.SiteReference;
100102
import org.wordpress.android.ui.prefs.AccountSettingsActivity;
101103
import org.wordpress.android.ui.prefs.AppSettingsActivity;
102104
import org.wordpress.android.ui.prefs.BlogPreferencesActivity;
@@ -705,6 +707,16 @@ public static void viewCurrentBlogPages(@NonNull Context context, @NonNull SiteM
705707
AnalyticsUtils.trackWithSiteDetails(AnalyticsTracker.Stat.OPENED_PAGES, site);
706708
}
707709

710+
public static void viewPostTypes(@NonNull Context context, @NonNull SiteModel site) {
711+
SiteReference siteRef = SiteReference.Companion.create(
712+
site.getSiteId(),
713+
site.getName() != null ? site.getName() : "",
714+
site.getUrl() != null ? site.getUrl() : ""
715+
);
716+
Intent intent = CptPostTypesActivity.Companion.createIntent(context, siteRef);
717+
context.startActivity(intent);
718+
}
719+
708720
public static void viewCurrentBlogPagesOfType(Context context, SiteModel site, PageListType pageListType) {
709721
if (pageListType == null) {
710722
Intent intent = new Intent(context, PagesActivity.class);

WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,8 @@ class MySiteFragment : Fragment(R.layout.my_site_fragment),
616616
is SiteNavigationAction.OpenPlan -> ActivityLauncher.viewBlogPlans(activity, action.site)
617617
is SiteNavigationAction.OpenPosts -> ActivityLauncher.viewCurrentBlogPosts(requireActivity(), action.site)
618618
is SiteNavigationAction.OpenPages -> ActivityLauncher.viewCurrentBlogPages(requireActivity(), action.site)
619+
is SiteNavigationAction.OpenPostTypes ->
620+
ActivityLauncher.viewPostTypes(requireActivity(), action.site)
619621
is SiteNavigationAction.OpenHomepage -> ActivityLauncher.editLandingPageForResult(
620622
this,
621623
action.site,

WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ sealed class SiteNavigationAction {
2424
data class OpenPlan(val site: SiteModel) : SiteNavigationAction()
2525
data class OpenPosts(val site: SiteModel) : SiteNavigationAction()
2626
data class OpenPages(val site: SiteModel) : SiteNavigationAction()
27+
data class OpenPostTypes(val site: SiteModel) : SiteNavigationAction()
2728
data class OpenHomepage(
2829
val site: SiteModel,
2930
val homepageLocalId: Int,

WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/ListItemActionHandler.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class ListItemActionHandler @Inject constructor(
2828
ListItemAction.PLAN -> SiteNavigationAction.OpenPlan(selectedSite)
2929
ListItemAction.POSTS -> SiteNavigationAction.OpenPosts(selectedSite)
3030
ListItemAction.PAGES -> SiteNavigationAction.OpenPages(selectedSite)
31+
ListItemAction.POST_TYPES -> SiteNavigationAction.OpenPostTypes(selectedSite)
3132
ListItemAction.ADMIN -> SiteNavigationAction.OpenAdmin(selectedSite)
3233
ListItemAction.SUBSCRIBERS -> SiteNavigationAction.OpenSubscribers(selectedSite)
3334
ListItemAction.PEOPLE -> SiteNavigationAction.OpenPeople(selectedSite)

WordPress/src/main/java/org/wordpress/android/ui/mysite/items/listitem/ListItemAction.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ enum class ListItemAction (val trackingLabel: String) {
77
PLAN("plan"),
88
POSTS("posts"),
99
PAGES("pages"),
10+
POST_TYPES("post_types"),
1011
ADMIN("admin"),
1112
PEOPLE("people"),
1213
SUBSCRIBERS("subscribers"),

WordPress/src/main/java/org/wordpress/android/ui/mysite/items/listitem/SiteItemsBuilder.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import org.wordpress.android.ui.mysite.cards.quickstart.QuickStartRepository
1313
import org.wordpress.android.ui.mysite.items.listitem.ListItemAction.COMMENTS
1414
import org.wordpress.android.ui.mysite.items.listitem.ListItemAction.MEDIA
1515
import org.wordpress.android.ui.mysite.items.listitem.ListItemAction.POSTS
16+
import org.wordpress.android.ui.mysite.items.listitem.ListItemAction.POST_TYPES
17+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures
18+
import org.wordpress.android.ui.prefs.experimentalfeatures.ExperimentalFeatures.Feature
1619
import org.wordpress.android.ui.utils.ListItemInteraction
1720
import org.wordpress.android.ui.utils.UiString
1821
import org.wordpress.android.ui.utils.UiString.UiStringRes
@@ -21,7 +24,8 @@ import javax.inject.Inject
2124
class SiteItemsBuilder @Inject constructor(
2225
private val siteListItemBuilder: SiteListItemBuilder,
2326
private val quickStartRepository: QuickStartRepository,
24-
private val jetpackFeatureRemovalOverlayUtil: JetpackFeatureRemovalOverlayUtil
27+
private val jetpackFeatureRemovalOverlayUtil: JetpackFeatureRemovalOverlayUtil,
28+
private val experimentalFeatures: ExperimentalFeatures
2529
) {
2630
@Suppress("LongMethod")
2731
fun build(params: SiteItemsBuilderParams): List<MySiteCardAndItem> {
@@ -49,6 +53,7 @@ class SiteItemsBuilder @Inject constructor(
4953
listItemAction = POSTS
5054
),
5155
siteListItemBuilder.buildPagesItemIfAvailable(params.site, params.onClick, showPagesFocusPoint),
56+
buildPostTypesItemIfEnabled(params.onClick),
5257
ListItem(
5358
R.drawable.ic_media_white_24dp,
5459
UiStringRes(R.string.media),
@@ -65,6 +70,19 @@ class SiteItemsBuilder @Inject constructor(
6570
)
6671
}
6772

73+
private fun buildPostTypesItemIfEnabled(onClick: (ListItemAction) -> Unit): ListItem? {
74+
return if (experimentalFeatures.isEnabled(Feature.EXPERIMENTAL_POST_TYPES)) {
75+
ListItem(
76+
R.drawable.ic_posts_white_24dp,
77+
UiStringRes(R.string.post_types_screen_title),
78+
onClick = ListItemInteraction.create(POST_TYPES, onClick),
79+
listItemAction = POST_TYPES
80+
)
81+
} else {
82+
null
83+
}
84+
}
85+
6886
private fun getTrafficSiteItems(
6987
params: SiteItemsBuilderParams
7088
): List<MySiteCardAndItem> {

WordPress/src/main/java/org/wordpress/android/ui/mysite/menu/MenuActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class MenuActivity : BaseAppCompatActivity() {
133133
is SiteNavigationAction.OpenPlan -> ActivityLauncher.viewBlogPlans(this, action.site)
134134
is SiteNavigationAction.OpenPosts -> ActivityLauncher.viewCurrentBlogPosts(this, action.site)
135135
is SiteNavigationAction.OpenPages -> ActivityLauncher.viewCurrentBlogPages(this, action.site)
136+
is SiteNavigationAction.OpenPostTypes -> ActivityLauncher.viewPostTypes(this, action.site)
136137
is SiteNavigationAction.OpenAdmin -> ActivityLauncher.viewBlogAdmin(this, action.site)
137138
is SiteNavigationAction.OpenPeople -> ActivityLauncher.viewCurrentBlogPeople(this, action.site)
138139
is SiteNavigationAction.OpenSharing -> ActivityLauncher.viewBlogSharing(this, action.site)

WordPress/src/main/java/org/wordpress/android/ui/prefs/experimentalfeatures/ExperimentalFeatures.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ class ExperimentalFeatures @Inject constructor(
4444
"network_debugging",
4545
R.string.experimental_network_debugging,
4646
R.string.experimental_network_debugging_description
47+
),
48+
EXPERIMENTAL_POST_TYPES(
49+
"experimental_post_types",
50+
R.string.experimental_post_types,
51+
R.string.experimental_post_types_description
4752
);
4853
}
4954
}

WordPress/src/main/java/org/wordpress/android/ui/prefs/experimentalfeatures/ExperimentalFeaturesViewModel.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.StateFlow
88
import kotlinx.coroutines.flow.asStateFlow
99
import kotlinx.coroutines.flow.update
1010
import kotlinx.coroutines.launch
11+
import org.wordpress.android.BuildConfig
1112
import org.wordpress.android.analytics.AnalyticsTracker
1213
import org.wordpress.android.analytics.AnalyticsTracker.Stat
1314
import org.wordpress.android.fluxc.utils.AppLogWrapper
@@ -50,7 +51,10 @@ internal class ExperimentalFeaturesViewModel @Inject constructor(
5051
}
5152

5253
private fun shouldShowFeature(feature: Feature): Boolean {
53-
return if (gutenbergKitFeature.isEnabled()) {
54+
// Only show Post Types feature in debug builds
55+
return if (feature == Feature.EXPERIMENTAL_POST_TYPES) {
56+
BuildConfig.DEBUG
57+
} else if (gutenbergKitFeature.isEnabled()) {
5458
feature != Feature.EXPERIMENTAL_BLOCK_EDITOR
5559
} else {
5660
feature != Feature.DISABLE_EXPERIMENTAL_BLOCK_EDITOR

0 commit comments

Comments
 (0)