diff --git a/src/com/android/settings/datausage/BillingCyclePreference.kt b/src/com/android/settings/datausage/BillingCyclePreference.kt index 619f7e96286..a6904bc4eb6 100644 --- a/src/com/android/settings/datausage/BillingCyclePreference.kt +++ b/src/com/android/settings/datausage/BillingCyclePreference.kt @@ -16,15 +16,21 @@ package com.android.settings.datausage import android.app.settings.SettingsEnums import android.content.Context -import android.content.Intent import android.net.NetworkTemplate import android.os.Bundle import android.util.AttributeSet -import androidx.preference.Preference +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.res.stringResource +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.core.SubSettingLauncher import com.android.settings.datausage.lib.BillingCycleRepository -import com.android.settings.network.MobileDataEnabledListener +import com.android.settings.network.mobileDataEnabledFlow +import com.android.settings.spa.preference.ComposePreference +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import kotlinx.coroutines.flow.map /** * Preference which displays billing cycle of subscription @@ -36,45 +42,31 @@ class BillingCyclePreference @JvmOverloads constructor( context: Context, attrs: AttributeSet?, private val repository: BillingCycleRepository = BillingCycleRepository(context), -) : Preference(context, attrs), TemplatePreference { - private lateinit var template: NetworkTemplate - private var subId = 0 - - private val listener = MobileDataEnabledListener(context) { - updateEnabled() - } +) : ComposePreference(context, attrs), TemplatePreference { override fun setTemplate(template: NetworkTemplate, subId: Int) { - this.template = template - this.subId = subId - summary = null - updateEnabled() - intent = intent + setContent { + val isModifiable by remember { + context.mobileDataEnabledFlow(subId).map { repository.isModifiable(subId) } + }.collectAsStateWithLifecycle(initialValue = false) + + Preference(object : PreferenceModel { + override val title = stringResource(R.string.billing_cycle) + override val enabled = { isModifiable } + override val onClick = { launchBillingCycleSettings(template) } + }) + } } - override fun onAttached() { - super.onAttached() - listener.start(subId) - } - - override fun onDetached() { - listener.stop() - super.onDetached() - } - - private fun updateEnabled() { - isEnabled = repository.isModifiable(subId) - } - - override fun getIntent(): Intent { + private fun launchBillingCycleSettings(template: NetworkTemplate) { val args = Bundle().apply { putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, template) } - return SubSettingLauncher(context).apply { + SubSettingLauncher(context).apply { setDestination(BillingCycleSettings::class.java.name) setArguments(args) setTitleRes(R.string.billing_cycle) setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN) - }.toIntent() + }.launch() } } diff --git a/src/com/android/settings/spa/preference/ComposePreference.kt b/src/com/android/settings/spa/preference/ComposePreference.kt index aec85a9b324..aa5c32c3380 100644 --- a/src/com/android/settings/spa/preference/ComposePreference.kt +++ b/src/com/android/settings/spa/preference/ComposePreference.kt @@ -18,6 +18,7 @@ package com.android.settings.spa.preference import android.content.Context import android.util.AttributeSet +import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy @@ -26,13 +27,23 @@ import androidx.preference.PreferenceViewHolder import com.android.settings.R import com.android.settingslib.spa.framework.theme.SettingsTheme -class ComposePreference @JvmOverloads constructor( +open class ComposePreference @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0, ) : Preference(context, attrs, defStyleAttr, defStyleRes) { - var content: @Composable () -> Unit = {} + private var content: @Composable () -> Unit = {} + + fun setContent(content: @Composable () -> Unit) { + this.content = content + } + + @VisibleForTesting + @Composable + fun Content() { + content() + } init { layoutResource = R.layout.preference_compose diff --git a/src/com/android/settings/spa/preference/ComposePreferenceController.kt b/src/com/android/settings/spa/preference/ComposePreferenceController.kt index 3ddb66bbefa..9dd82824fd9 100644 --- a/src/com/android/settings/spa/preference/ComposePreferenceController.kt +++ b/src/com/android/settings/spa/preference/ComposePreferenceController.kt @@ -29,7 +29,7 @@ abstract class ComposePreferenceController(context: Context, preferenceKey: Stri override fun displayPreference(screen: PreferenceScreen) { super.displayPreference(screen) preference = screen.findPreference(preferenceKey)!! - preference.content = { Content() } + preference.setContent { Content() } } @Composable diff --git a/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt index 2e2620bd3cc..4bf385169d3 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt @@ -18,40 +18,69 @@ package com.android.settings.datausage import android.content.Context import android.net.NetworkTemplate +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertIsEnabled +import androidx.compose.ui.test.assertIsNotEnabled +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.R import com.android.settings.datausage.lib.BillingCycleRepository -import com.google.common.truth.Truth.assertThat +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock +import org.mockito.kotlin.stub @RunWith(AndroidJUnit4::class) class BillingCyclePreferenceTest { + @get:Rule + val composeTestRule = createComposeRule() - private val mockBillingCycleRepository = mock { - on { isModifiable(SUB_ID) } doReturn false - } + private val mockBillingCycleRepository = mock() private val context: Context = ApplicationProvider.getApplicationContext() private val preference = BillingCyclePreference(context, null, mockBillingCycleRepository) @Test - fun isEnabled_initialState() { - val enabled = preference.isEnabled + fun setTemplate_titleDisplayed() { + setTemplate() - assertThat(enabled).isTrue() + composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle)) + .assertIsDisplayed() } @Test - fun isEnabled_afterSetTemplate_updated() { + fun setTemplate_modifiable_enabled() { + mockBillingCycleRepository.stub { + on { isModifiable(SUB_ID) } doReturn true + } + + setTemplate() + + composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle)).assertIsEnabled() + } + + @Test + fun setTemplate_notModifiable_notEnabled() { + mockBillingCycleRepository.stub { + on { isModifiable(SUB_ID) } doReturn false + } + + setTemplate() + + composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle)) + .assertIsNotEnabled() + } + + private fun setTemplate() { preference.setTemplate(mock(), SUB_ID) - - val enabled = preference.isEnabled - - assertThat(enabled).isFalse() + composeTestRule.setContent { + preference.Content() + } } private companion object { diff --git a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt index 36817d1d3c7..cdfa514413a 100644 --- a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt @@ -61,7 +61,7 @@ class ComposePreferenceControllerTest { controller.displayPreference(preferenceScreen) composeTestRule.setContent { - preference.content() + preference.Content() } composeTestRule.onNodeWithText(TEXT).assertIsDisplayed() } diff --git a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt index 28bde3ab3a0..a2fe752120f 100644 --- a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt @@ -43,7 +43,7 @@ class ComposePreferenceTest { @Test fun onBindViewHolder() { - preference.content = { + preference.setContent { Text(TEXT) }