Loading packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/restricted/GalleryRestrictedRepository.kt +11 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settingslib.spa.gallery.restricted import android.content.Context import android.content.Intent import com.android.settingslib.spa.restricted.Blocked.SwitchPreferenceOverrides import com.android.settingslib.spa.restricted.BlockedWithDetails import com.android.settingslib.spa.restricted.NoRestricted import com.android.settingslib.spa.restricted.RestrictedMode Loading @@ -25,6 +26,7 @@ import com.android.settingslib.spa.restricted.RestrictedRepository import com.android.settingslib.spa.restricted.Restrictions import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map class GalleryRestrictedRepository(private val context: Context) : RestrictedRepository { Loading @@ -33,7 +35,13 @@ class GalleryRestrictedRepository(private val context: Context) : RestrictedRepo return enableRestrictionsFlow.map { enableRestrictions -> if (enableRestrictions && restrictions.isRestricted) { object : BlockedWithDetails { override val canOverrideSwitchChecked = true override val switchPreferenceOverridesFlow = combine(summaryOnFlow, summaryOffFlow) { summaryOn, summaryOff -> SwitchPreferenceOverrides( summaryOn = summaryOn, summaryOff = summaryOff, ) } override fun showDetails() { context.startActivity(Intent("android.settings.SHOW_ADMIN_SUPPORT_DETAILS")) Loading @@ -47,5 +55,7 @@ class GalleryRestrictedRepository(private val context: Context) : RestrictedRepo companion object { var enableRestrictionsFlow = MutableStateFlow(true) var summaryOnFlow = MutableStateFlow("Force on") var summaryOffFlow = MutableStateFlow("Force off") } } packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/restricted/RestrictedSwitchPreferencePageProvider.kt +15 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.restricted.RestrictedMainSwitchPreference import com.android.settingslib.spa.restricted.RestrictedSwitchPreference import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField import com.android.settingslib.spa.widget.preference.MainSwitchPreference import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel Loading @@ -42,7 +43,7 @@ object RestrictedSwitchPreferencePageProvider : SettingsPageProvider { @Composable override fun Page(arguments: Bundle?) { RegularScaffold(TITLE) { EnableRestrictionsSwitchPreference() Configs() SampleRestrictedMainSwitchPreference(ifBlockedOverrideCheckedTo = null) SampleRestrictedMainSwitchPreference(ifBlockedOverrideCheckedTo = true) Loading @@ -68,9 +69,11 @@ object RestrictedSwitchPreferencePageProvider : SettingsPageProvider { } @Composable private fun EnableRestrictionsSwitchPreference() { private fun Configs() { val enableRestrictions by GalleryRestrictedRepository.enableRestrictionsFlow.collectAsStateWithLifecycle() val summaryOn by GalleryRestrictedRepository.summaryOnFlow.collectAsStateWithLifecycle() val summaryOff by GalleryRestrictedRepository.summaryOffFlow.collectAsStateWithLifecycle() MainSwitchPreference( model = object : SwitchPreferenceModel { Loading @@ -81,6 +84,16 @@ private fun EnableRestrictionsSwitchPreference() { } } ) SettingsOutlinedTextField( value = summaryOn, label = "Override summary on", onTextChange = { GalleryRestrictedRepository.summaryOnFlow.value = it }, ) SettingsOutlinedTextField( value = summaryOff, label = "Override summary off", onTextChange = { GalleryRestrictedRepository.summaryOffFlow.value = it }, ) } @Composable Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/restricted/RestrictedBaseSwitchPreference.kt +51 −11 Original line number Diff line number Diff line Loading @@ -16,15 +16,24 @@ package com.android.settingslib.spa.restricted import androidx.compose.foundation.clickable import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.toggleableState import androidx.compose.ui.state.ToggleableState import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settingslib.spa.R import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.flowOn @Composable Loading Loading @@ -52,18 +61,49 @@ internal fun RestrictedBaseSwitchPreference( } val restrictedModeFlow = remember(restrictions) { repository.restrictedModeFlow(restrictions).flowOn(Dispatchers.Default) repository.restrictedModeFlow(restrictions).conflate().flowOn(Dispatchers.Default) } val restrictedMode by restrictedModeFlow.collectAsStateWithLifecycle(initialValue = NoRestricted) val restrictedSwitchPreferenceModel = remember(restrictedMode, model, ifBlockedOverrideCheckedTo) { RestrictedSwitchPreferenceModel( model = model, restrictedMode = restrictedMode, ifBlockedOverrideCheckedTo = ifBlockedOverrideCheckedTo, val restrictedMode by restrictedModeFlow.collectAsStateWithLifecycle(initialValue = null) val presenter = remember(model, ifBlockedOverrideCheckedTo) { RestrictedSwitchPreferencePresenter(model, ifBlockedOverrideCheckedTo) } val restrictedModel by remember(presenter, restrictedMode) { presenter.restrictedModelFlow(restrictedMode) } .collectAsStateWithLifecycle(initialValue = presenter.indeterminateModel) RestrictionWrapper(restrictedMode, restrictedModel, content) } @Composable private fun RestrictionWrapper( restrictedMode: RestrictedMode?, restrictedModel: SwitchPreferenceModel, content: @Composable (SwitchPreferenceModel, Modifier) -> Unit, ) { val modifier = when (restrictedMode) { is BlockedWithDetails -> { val statusDescription = stringResource(R.string.spa_unavailable) Modifier.clickable( onClickLabel = stringResource(R.string.spa_learn_more), role = Role.Switch, onClick = { restrictedMode.showDetails() }, ) .semantics { contentDescription = statusDescription toggleableState = toggleableState(restrictedModel.checked()) } } else -> Modifier } content(restrictedModel, modifier) } restrictedSwitchPreferenceModel.RestrictionWrapper(content) private fun toggleableState(value: Boolean?) = when (value) { true -> ToggleableState.On false -> ToggleableState.Off null -> ToggleableState.Indeterminate } packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/restricted/RestrictedMainSwitchPreference.kt +1 −2 Original line number Diff line number Diff line Loading @@ -25,8 +25,7 @@ import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel * Restricted version [MainSwitchPreference]. * * @param ifBlockedOverrideCheckedTo if this is not null and the current [RestrictedMode] is * [Blocked] and [Blocked.canOverrideSwitchChecked] is set to true, the switch's checked status * will be overridden to this value. * [Blocked], the switch's checked status will be overridden to this value. */ @Composable fun RestrictedMainSwitchPreference( Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/restricted/RestrictedMode.kt +25 −6 Original line number Diff line number Diff line Loading @@ -16,20 +16,39 @@ package com.android.settingslib.spa.restricted import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf sealed interface RestrictedMode data object NoRestricted : RestrictedMode sealed interface Blocked : RestrictedMode { /** * Determines if the [RestrictedSwitchPreference]'s checked state will be forced to its param * value of `ifBlockedOverrideCheckedTo` when the preference is blocked. * Represents the configuration for overriding a [RestrictedSwitchPreference] or * [RestrictedMainSwitchPreference] when it's in a blocked state. * * Requires [RestrictedSwitchPreference]'s param `ifBlockedOverrideCheckedTo` to be set to a * specific state (true or false). * This class allows specifying whether the checked state of the preference should be overridden * and provides custom summaries for the 'on' and 'off' states when blocked. */ val canOverrideSwitchChecked: Boolean get() = false data class SwitchPreferenceOverrides( /** * The summary to show when the preference is blocked and checked value is on. * * Note: Requires switch preference's param `ifBlockedOverrideCheckedTo` to be set to true. */ val summaryOn: String? = null, /** * The summary to show when the preference is blocked and checked value is off. * * Note: Requires switch preference's param `ifBlockedOverrideCheckedTo` to be set to false. */ val summaryOff: String? = null, ) val switchPreferenceOverridesFlow: Flow<SwitchPreferenceOverrides> get() = flowOf(SwitchPreferenceOverrides()) } interface BlockedWithDetails : Blocked { Loading Loading
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/restricted/GalleryRestrictedRepository.kt +11 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settingslib.spa.gallery.restricted import android.content.Context import android.content.Intent import com.android.settingslib.spa.restricted.Blocked.SwitchPreferenceOverrides import com.android.settingslib.spa.restricted.BlockedWithDetails import com.android.settingslib.spa.restricted.NoRestricted import com.android.settingslib.spa.restricted.RestrictedMode Loading @@ -25,6 +26,7 @@ import com.android.settingslib.spa.restricted.RestrictedRepository import com.android.settingslib.spa.restricted.Restrictions import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map class GalleryRestrictedRepository(private val context: Context) : RestrictedRepository { Loading @@ -33,7 +35,13 @@ class GalleryRestrictedRepository(private val context: Context) : RestrictedRepo return enableRestrictionsFlow.map { enableRestrictions -> if (enableRestrictions && restrictions.isRestricted) { object : BlockedWithDetails { override val canOverrideSwitchChecked = true override val switchPreferenceOverridesFlow = combine(summaryOnFlow, summaryOffFlow) { summaryOn, summaryOff -> SwitchPreferenceOverrides( summaryOn = summaryOn, summaryOff = summaryOff, ) } override fun showDetails() { context.startActivity(Intent("android.settings.SHOW_ADMIN_SUPPORT_DETAILS")) Loading @@ -47,5 +55,7 @@ class GalleryRestrictedRepository(private val context: Context) : RestrictedRepo companion object { var enableRestrictionsFlow = MutableStateFlow(true) var summaryOnFlow = MutableStateFlow("Force on") var summaryOffFlow = MutableStateFlow("Force off") } }
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/restricted/RestrictedSwitchPreferencePageProvider.kt +15 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.restricted.RestrictedMainSwitchPreference import com.android.settingslib.spa.restricted.RestrictedSwitchPreference import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField import com.android.settingslib.spa.widget.preference.MainSwitchPreference import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel Loading @@ -42,7 +43,7 @@ object RestrictedSwitchPreferencePageProvider : SettingsPageProvider { @Composable override fun Page(arguments: Bundle?) { RegularScaffold(TITLE) { EnableRestrictionsSwitchPreference() Configs() SampleRestrictedMainSwitchPreference(ifBlockedOverrideCheckedTo = null) SampleRestrictedMainSwitchPreference(ifBlockedOverrideCheckedTo = true) Loading @@ -68,9 +69,11 @@ object RestrictedSwitchPreferencePageProvider : SettingsPageProvider { } @Composable private fun EnableRestrictionsSwitchPreference() { private fun Configs() { val enableRestrictions by GalleryRestrictedRepository.enableRestrictionsFlow.collectAsStateWithLifecycle() val summaryOn by GalleryRestrictedRepository.summaryOnFlow.collectAsStateWithLifecycle() val summaryOff by GalleryRestrictedRepository.summaryOffFlow.collectAsStateWithLifecycle() MainSwitchPreference( model = object : SwitchPreferenceModel { Loading @@ -81,6 +84,16 @@ private fun EnableRestrictionsSwitchPreference() { } } ) SettingsOutlinedTextField( value = summaryOn, label = "Override summary on", onTextChange = { GalleryRestrictedRepository.summaryOnFlow.value = it }, ) SettingsOutlinedTextField( value = summaryOff, label = "Override summary off", onTextChange = { GalleryRestrictedRepository.summaryOffFlow.value = it }, ) } @Composable Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/restricted/RestrictedBaseSwitchPreference.kt +51 −11 Original line number Diff line number Diff line Loading @@ -16,15 +16,24 @@ package com.android.settingslib.spa.restricted import androidx.compose.foundation.clickable import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.toggleableState import androidx.compose.ui.state.ToggleableState import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settingslib.spa.R import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.flowOn @Composable Loading Loading @@ -52,18 +61,49 @@ internal fun RestrictedBaseSwitchPreference( } val restrictedModeFlow = remember(restrictions) { repository.restrictedModeFlow(restrictions).flowOn(Dispatchers.Default) repository.restrictedModeFlow(restrictions).conflate().flowOn(Dispatchers.Default) } val restrictedMode by restrictedModeFlow.collectAsStateWithLifecycle(initialValue = NoRestricted) val restrictedSwitchPreferenceModel = remember(restrictedMode, model, ifBlockedOverrideCheckedTo) { RestrictedSwitchPreferenceModel( model = model, restrictedMode = restrictedMode, ifBlockedOverrideCheckedTo = ifBlockedOverrideCheckedTo, val restrictedMode by restrictedModeFlow.collectAsStateWithLifecycle(initialValue = null) val presenter = remember(model, ifBlockedOverrideCheckedTo) { RestrictedSwitchPreferencePresenter(model, ifBlockedOverrideCheckedTo) } val restrictedModel by remember(presenter, restrictedMode) { presenter.restrictedModelFlow(restrictedMode) } .collectAsStateWithLifecycle(initialValue = presenter.indeterminateModel) RestrictionWrapper(restrictedMode, restrictedModel, content) } @Composable private fun RestrictionWrapper( restrictedMode: RestrictedMode?, restrictedModel: SwitchPreferenceModel, content: @Composable (SwitchPreferenceModel, Modifier) -> Unit, ) { val modifier = when (restrictedMode) { is BlockedWithDetails -> { val statusDescription = stringResource(R.string.spa_unavailable) Modifier.clickable( onClickLabel = stringResource(R.string.spa_learn_more), role = Role.Switch, onClick = { restrictedMode.showDetails() }, ) .semantics { contentDescription = statusDescription toggleableState = toggleableState(restrictedModel.checked()) } } else -> Modifier } content(restrictedModel, modifier) } restrictedSwitchPreferenceModel.RestrictionWrapper(content) private fun toggleableState(value: Boolean?) = when (value) { true -> ToggleableState.On false -> ToggleableState.Off null -> ToggleableState.Indeterminate }
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/restricted/RestrictedMainSwitchPreference.kt +1 −2 Original line number Diff line number Diff line Loading @@ -25,8 +25,7 @@ import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel * Restricted version [MainSwitchPreference]. * * @param ifBlockedOverrideCheckedTo if this is not null and the current [RestrictedMode] is * [Blocked] and [Blocked.canOverrideSwitchChecked] is set to true, the switch's checked status * will be overridden to this value. * [Blocked], the switch's checked status will be overridden to this value. */ @Composable fun RestrictedMainSwitchPreference( Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/restricted/RestrictedMode.kt +25 −6 Original line number Diff line number Diff line Loading @@ -16,20 +16,39 @@ package com.android.settingslib.spa.restricted import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf sealed interface RestrictedMode data object NoRestricted : RestrictedMode sealed interface Blocked : RestrictedMode { /** * Determines if the [RestrictedSwitchPreference]'s checked state will be forced to its param * value of `ifBlockedOverrideCheckedTo` when the preference is blocked. * Represents the configuration for overriding a [RestrictedSwitchPreference] or * [RestrictedMainSwitchPreference] when it's in a blocked state. * * Requires [RestrictedSwitchPreference]'s param `ifBlockedOverrideCheckedTo` to be set to a * specific state (true or false). * This class allows specifying whether the checked state of the preference should be overridden * and provides custom summaries for the 'on' and 'off' states when blocked. */ val canOverrideSwitchChecked: Boolean get() = false data class SwitchPreferenceOverrides( /** * The summary to show when the preference is blocked and checked value is on. * * Note: Requires switch preference's param `ifBlockedOverrideCheckedTo` to be set to true. */ val summaryOn: String? = null, /** * The summary to show when the preference is blocked and checked value is off. * * Note: Requires switch preference's param `ifBlockedOverrideCheckedTo` to be set to false. */ val summaryOff: String? = null, ) val switchPreferenceOverridesFlow: Flow<SwitchPreferenceOverrides> get() = flowOf(SwitchPreferenceOverrides()) } interface BlockedWithDetails : Blocked { Loading