Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
08dad53
Add Chucker integration research documentation
oguzkocer Nov 25, 2025
3b1973c
Add track network requests interceptor foundation for Chucker integra…
oguzkocer Nov 25, 2025
f666fd7
Integrate Chucker library into TrackNetworkRequestsInterceptor
oguzkocer Nov 25, 2025
d13bbce
Add View Network Requests button to launch Chucker UI
oguzkocer Nov 25, 2025
4f2f330
Add configurable retention period and dialog-based UX for network tra…
oguzkocer Nov 25, 2025
a8ab423
Add login request tracking and make preferences device-level
oguzkocer Nov 25, 2025
4db23a1
Add GutenbergKit network request logging to Chucker
oguzkocer Nov 26, 2025
d47c0a2
Remove debug logs from GutenbergKit network logging
oguzkocer Nov 26, 2025
f26609c
Add experimental feature flag for Network Debugging
oguzkocer Nov 26, 2025
82c062c
Fix detekt issues in Chucker integration code
oguzkocer Nov 26, 2025
43d181b
Add network debugging to new Support screen
oguzkocer Nov 26, 2025
74c9397
Integrate Chucker interceptor into wordpress-rs clients
oguzkocer Nov 27, 2025
8e01862
Update GutenbergKit to v0.11.0 and adapt to API changes
oguzkocer Dec 1, 2025
e6de212
Use OkHttpClientQualifiers.INTERCEPTORS constant for @Named annotations
oguzkocer Dec 1, 2025
5801102
Remove research documentation files
oguzkocer Dec 1, 2025
333d16b
Fix lint warnings and update tests for new constructor parameters
oguzkocer Dec 1, 2025
b9cc5f7
Refactor retention period display string into two methods Split getR…
oguzkocer Dec 2, 2025
6505f42
Migrate network tracking dialogs to Compose
oguzkocer Dec 2, 2025
f20cacc
Add tests for network tracking functionality in SupportViewModel
oguzkocer Dec 2, 2025
dc1e76f
Update GutenbergKit to v0.11.1
oguzkocer Dec 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions WordPress/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ dependencies {
implementation(libs.greenrobot.eventbus.main)
implementation(libs.greenrobot.eventbus.java)
implementation(libs.squareup.retrofit)
implementation(libs.chucker)
implementation(libs.apache.commons.text)
implementation(libs.airbnb.lottie.main)
implementation(libs.facebook.shimmer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.wordpress.android.util.config.InAppUpdatesFeatureConfig;
import org.wordpress.android.util.config.RemoteConfigWrapper;
import org.wordpress.android.util.wizard.WizardManager;
import org.wordpress.android.fluxc.network.TrackNetworkRequestsInterceptor;
import org.wordpress.android.viewmodel.helpers.ConnectionStatus;
import org.wordpress.android.viewmodel.helpers.ConnectionStatusLiveData;

Expand Down Expand Up @@ -153,7 +154,9 @@
}

@Provides
public static WpLoginClient provideWpLoginClient() {
return new WpLoginClient(Collections.emptyList());
public static WpLoginClient provideWpLoginClient(
TrackNetworkRequestsInterceptor trackNetworkRequestsInterceptor
) {
return new WpLoginClient(Collections.singletonList(trackNetworkRequestsInterceptor));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.wordpress.android.modules

import android.content.Context
import dagger.Module

Check warning on line 4 in WordPress/src/main/java/org/wordpress/android/modules/TrackNetworkRequestsModule.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import.

See more on https://sonarcloud.io/project/issues?id=wordpress-mobile_WordPress-Android&issues=AZrcBHr7u-mtKnwcDg0p&open=AZrcBHr7u-mtKnwcDg0p&pullRequest=22381
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoSet
import okhttp3.Interceptor
import org.wordpress.android.fluxc.module.OkHttpClientQualifiers
import org.wordpress.android.fluxc.network.NetworkRequestsRetentionPeriod
import org.wordpress.android.fluxc.network.TrackNetworkRequestsInterceptor
import org.wordpress.android.fluxc.network.TrackNetworkRequestsPreference
import org.wordpress.android.ui.posts.editor.GutenbergKitNetworkLogger
import org.wordpress.android.ui.prefs.AppPrefsWrapper
import javax.inject.Named
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
class TrackNetworkRequestsModule {
@Singleton
@Provides
fun provideTrackNetworkRequestsPreference(appPrefsWrapper: AppPrefsWrapper): TrackNetworkRequestsPreference {
return object : TrackNetworkRequestsPreference {
override fun isEnabled(): Boolean = appPrefsWrapper.isTrackNetworkRequestsEnabled
override fun getRetentionPeriod(): NetworkRequestsRetentionPeriod =
NetworkRequestsRetentionPeriod.fromInt(appPrefsWrapper.trackNetworkRequestsRetentionPeriod)
}
}

@Singleton
@Provides
fun provideTrackNetworkRequestsInterceptor(
@ApplicationContext context: Context,
preference: TrackNetworkRequestsPreference
): TrackNetworkRequestsInterceptor {
return TrackNetworkRequestsInterceptor(context, preference)
}

@Provides
@IntoSet
@Named(OkHttpClientQualifiers.INTERCEPTORS)
fun provideTrackNetworkRequestsInterceptorAsInterceptor(
interceptor: TrackNetworkRequestsInterceptor
): Interceptor = interceptor

@Singleton
@Provides
fun provideGutenbergKitNetworkLogger(
interceptor: TrackNetworkRequestsInterceptor
): GutenbergKitNetworkLogger {
return GutenbergKitNetworkLogger(interceptor)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.widget.TextView
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
Expand All @@ -14,11 +16,14 @@
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.chuckerteam.chucker.api.Chucker
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.wordpress.android.BuildConfig
import org.wordpress.android.R
import org.wordpress.android.analytics.AnalyticsTracker
import org.wordpress.android.analytics.AnalyticsTracker.Stat
import org.wordpress.android.fluxc.network.NetworkRequestsRetentionPeriod
import org.wordpress.android.WordPress
import org.wordpress.android.support.aibot.ui.AIBotSupportActivity
import org.wordpress.android.support.logs.ui.LogsActivity
Expand All @@ -36,6 +41,7 @@
super.onCreate(savedInstanceState)
viewModel.init()
observeNavigationEvents()
observeDialogEvents()
composeView = ComposeView(this)
setContentView(
composeView.apply {
Expand All @@ -47,6 +53,7 @@
val userInfo by viewModel.userInfo.collectAsState()
val optionsVisibility by viewModel.optionsVisibility.collectAsState()
val isLoggedIn by viewModel.isLoggedIn.collectAsState()
val networkTrackingState by viewModel.networkTrackingState.collectAsState()
AppThemeM3 {
SupportScreen(
userName = userInfo.userName,
Expand All @@ -55,20 +62,45 @@
isLoggedIn = isLoggedIn,
showAskTheBots = optionsVisibility.showAskTheBots,
showAskHappinessEngineers = optionsVisibility.showAskHappinessEngineers,
showNetworkDebugging = networkTrackingState.showNetworkDebugging,
isNetworkTrackingEnabled = networkTrackingState.isTrackingEnabled,
networkTrackingRetentionInfo = getRetentionInfoText(
networkTrackingState.retentionPeriod
),
versionName = WordPress.versionName,
onBackClick = { finish() },
onLoginClick = { viewModel.onLoginClick() },
onHelpCenterClick = { viewModel.onHelpCenterClick() },
onAskTheBotsClick = { viewModel.onAskTheBotsClick() },
onAskHappinessEngineersClick = { viewModel.onAskHappinessEngineersClick() },
onApplicationLogsClick = { viewModel.onApplicationLogsClick() }
onApplicationLogsClick = { viewModel.onApplicationLogsClick() },
onNetworkTrackingToggle = { viewModel.onNetworkTrackingToggle(it) },
onViewNetworkRequestsClick = { viewModel.onViewNetworkRequestsClick() },
)
}
}
}
)
}

private fun getRetentionInfoText(period: NetworkRequestsRetentionPeriod): String {
val periodString = getRetentionPeriodDisplayString(period)
return getString(R.string.network_requests_retention_info, periodString)
}

private fun getRetentionPeriodDisplayString(period: NetworkRequestsRetentionPeriod): String {
return when (period) {
NetworkRequestsRetentionPeriod.ONE_HOUR ->
getString(R.string.network_requests_retention_one_hour)
NetworkRequestsRetentionPeriod.ONE_DAY ->
getString(R.string.network_requests_retention_one_day)
NetworkRequestsRetentionPeriod.ONE_WEEK ->
getString(R.string.network_requests_retention_one_week)
NetworkRequestsRetentionPeriod.FOREVER ->
getString(R.string.network_requests_retention_until_cleared)
}
}

private fun observeNavigationEvents() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
Expand All @@ -81,12 +113,69 @@
is SupportViewModel.NavigationEvent.NavigateToAskHappinessEngineers -> {
navigateToAskTheHappinessEngineers()
}
is SupportViewModel.NavigationEvent.NavigateToNetworkRequests -> {
navigateToNetworkRequests()
}
}
}
}
}
}

private fun observeDialogEvents() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.dialogEvents.collect { event ->
when (event) {
is SupportViewModel.DialogEvent.ShowEnableTrackingDialog -> {
showEnableTrackingDialog(event.currentPeriod)
}
is SupportViewModel.DialogEvent.ShowDisableTrackingDialog -> {
showDisableTrackingDialog()
}
}
}
}
}
}

private fun showEnableTrackingDialog(currentPeriod: NetworkRequestsRetentionPeriod) {
val periods = NetworkRequestsRetentionPeriod.entries.toTypedArray()
val displayNames = periods.map { getRetentionPeriodDisplayString(it) }.toTypedArray()
var selectedIndex = periods.indexOf(currentPeriod)

val titleView = layoutInflater.inflate(R.layout.dialog_title_with_message, null).apply {
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ Feels a bit odd to inflate a layout and a dialog inside a Jetpack Compose activity. What about using a state instead of an event, and a composable AlertDialog?

Note: If we need to unblock this PR, I'm happy to approve it as it is, and work on the changes later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be addressed in 6505f42, let me know what you think!

findViewById<TextView>(R.id.dialog_title).setText(R.string.track_network_requests)
findViewById<TextView>(R.id.dialog_message)
.setText(R.string.network_requests_enable_dialog_description)
}

AlertDialog.Builder(this)
.setCustomTitle(titleView)
.setSingleChoiceItems(displayNames, selectedIndex) { _, which ->
selectedIndex = which
}
.setPositiveButton(R.string.network_requests_enable) { _, _ ->
val selectedPeriod = periods[selectedIndex]
viewModel.onEnableTrackingConfirmed(selectedPeriod)
}
// No action needed on cancel - UI state is driven by ViewModel
.setNegativeButton(R.string.cancel, null)
.show()
}

private fun showDisableTrackingDialog() {
AlertDialog.Builder(this)
.setTitle(R.string.network_requests_disable_tracking_title)
.setMessage(R.string.network_requests_disable_tracking_description)
.setPositiveButton(R.string.network_requests_disable) { _, _ ->
viewModel.onDisableTrackingConfirmed()
}
// No action needed on cancel - UI state is driven by ViewModel
.setNegativeButton(R.string.cancel, null)
.show()
}

private fun navigateToAskTheBots() {
startActivity(
AIBotSupportActivity.Companion.createIntent(this)
Expand Down Expand Up @@ -120,6 +209,10 @@
startActivity(LogsActivity.createIntent(this))
}

private fun navigateToNetworkRequests() {
startActivity(Chucker.getLaunchIntent(this))
}

companion object {
@JvmStatic
fun createIntent(context: Context): Intent = Intent(context, SupportActivity::class.java)
Expand Down
Loading