Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40946801 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

[Spa] Add ifBlockedOverrideCheckedTo

If ifBlockedOverrideCheckedTo 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.

Also change the RestrictedRepository api to flow.

Bug: 422439682
Flag: EXEMPT new library
Test: unit test
Test: example usage in gallery
Change-Id: I38f833067ff8dd625c4a4c21e4dae2d4ab53e7a9
parent 8edb4eb8
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -23,16 +23,29 @@ import com.android.settingslib.spa.restricted.NoRestricted
import com.android.settingslib.spa.restricted.RestrictedMode
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.map

class GalleryRestrictedRepository(private val context: Context) : RestrictedRepository {
    override fun getRestrictedMode(restrictions: Restrictions): RestrictedMode {
    override fun restrictedModeFlow(restrictions: Restrictions): Flow<RestrictedMode> {
        check(restrictions is GalleryRestrictions)
        if (restrictions.isRestricted)
            return object : BlockedWithDetails {
        return enableRestrictionsFlow.map { enableRestrictions ->
            if (enableRestrictions && restrictions.isRestricted) {
                object : BlockedWithDetails {
                    override val canOverrideSwitchChecked = true

                    override fun showDetails() {
                        context.startActivity(Intent("android.settings.SHOW_ADMIN_SUPPORT_DETAILS"))
                    }
                }
        return NoRestricted
            } else {
                NoRestricted
            }
        }
    }

    companion object {
        var enableRestrictionsFlow = MutableStateFlow(true)
    }
}
+31 −2
Original line number Diff line number Diff line
@@ -22,11 +22,13 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.restricted.RestrictedSwitchPreference
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category
@@ -38,7 +40,14 @@ object RestrictedSwitchPreferencePageProvider : SettingsPageProvider {

    @Composable
    override fun Page(arguments: Bundle?) {
        RegularScaffold(TITLE) { Category { SampleRestrictedSwitchPreference() } }
        RegularScaffold(TITLE) {
            Category {
                EnableRestrictionsSwitchPreference()
                SampleRestrictedSwitchPreference(ifBlockedOverrideCheckedTo = null)
                SampleRestrictedSwitchPreference(ifBlockedOverrideCheckedTo = true)
                SampleRestrictedSwitchPreference(ifBlockedOverrideCheckedTo = false)
            }
        }
    }

    @Composable
@@ -53,15 +62,35 @@ object RestrictedSwitchPreferencePageProvider : SettingsPageProvider {
}

@Composable
private fun SampleRestrictedSwitchPreference() {
private fun EnableRestrictionsSwitchPreference() {
    val enableRestrictions by
        GalleryRestrictedRepository.enableRestrictionsFlow.collectAsStateWithLifecycle()
    SwitchPreference(
        model =
            object : SwitchPreferenceModel {
                override val title = "Enable restrictions"
                override val checked = { enableRestrictions }
                override val onCheckedChange = { newChecked: Boolean ->
                    GalleryRestrictedRepository.enableRestrictionsFlow.value = newChecked
                }
            }
    )
}

@Composable
private fun SampleRestrictedSwitchPreference(ifBlockedOverrideCheckedTo: Boolean?) {
    var checked by rememberSaveable { mutableStateOf(false) }
    RestrictedSwitchPreference(
        model =
            object : SwitchPreferenceModel {
                override val title = "RestrictedSwitchPreference"
                override val summary = {
                    "ifBlockedOverrideCheckedTo = $ifBlockedOverrideCheckedTo"
                }
                override val checked = { checked }
                override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
            },
        restrictions = GalleryRestrictions(isRestricted = true),
        ifBlockedOverrideCheckedTo = ifBlockedOverrideCheckedTo,
    )
}
+13 −1
Original line number Diff line number Diff line
@@ -20,7 +20,19 @@ sealed interface RestrictedMode

data object NoRestricted : RestrictedMode

interface BlockedWithDetails : 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.
     *
     * Requires [RestrictedSwitchPreference]'s param `ifBlockedOverrideCheckedTo` to be set to a
     * specific state (true or false).
     */
    val canOverrideSwitchChecked: Boolean
        get() = false
}

interface BlockedWithDetails : Blocked {
    /** Show the details of this restriction, usually a dialog will be displayed. */
    fun showDetails()
}
+3 −1
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.settingslib.spa.restricted

import kotlinx.coroutines.flow.Flow

interface RestrictedRepository {
    /** Gets the restricted mode. */
    fun getRestrictedMode(restrictions: Restrictions): RestrictedMode
    fun restrictedModeFlow(restrictions: Restrictions): Flow<RestrictedMode>
}
+21 −7
Original line number Diff line number Diff line
@@ -26,19 +26,28 @@ import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn

/** Restricted version [SwitchPreference]. */
/**
 * Restricted version [SwitchPreference].
 *
 * @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.
 */
@Composable
fun RestrictedSwitchPreference(model: SwitchPreferenceModel, restrictions: Restrictions) {
fun RestrictedSwitchPreference(
    model: SwitchPreferenceModel,
    restrictions: Restrictions,
    ifBlockedOverrideCheckedTo: Boolean? = null,
) {
    val context = LocalContext.current
    val repository = remember {
        checkNotNull(SpaEnvironmentFactory.instance.getRestrictedRepository(context)) {
            "RestrictedRepository not set"
        }
    }
    RestrictedSwitchPreference(model, restrictions, repository)
    RestrictedSwitchPreference(model, restrictions, repository, ifBlockedOverrideCheckedTo)
}

@VisibleForTesting
@@ -47,6 +56,7 @@ internal fun RestrictedSwitchPreference(
    model: SwitchPreferenceModel,
    restrictions: Restrictions,
    repository: RestrictedRepository,
    ifBlockedOverrideCheckedTo: Boolean? = null,
) {
    if (restrictions.isEmpty()) {
        SwitchPreference(model)
@@ -54,13 +64,17 @@ internal fun RestrictedSwitchPreference(
    }
    val restrictedModeFlow =
        remember(restrictions) {
            flow { emit(repository.getRestrictedMode(restrictions)) }.flowOn(Dispatchers.Default)
            repository.restrictedModeFlow(restrictions).flowOn(Dispatchers.Default)
        }
    val restrictedMode by
        restrictedModeFlow.collectAsStateWithLifecycle(initialValue = NoRestricted)
    val restrictedSwitchPreferenceModel =
        remember(restrictedMode, model) {
            RestrictedSwitchPreferenceModel(model = model, restrictedMode = restrictedMode)
        remember(restrictedMode, model, ifBlockedOverrideCheckedTo) {
            RestrictedSwitchPreferenceModel(
                model = model,
                restrictedMode = restrictedMode,
                ifBlockedOverrideCheckedTo = ifBlockedOverrideCheckedTo,
            )
        }

    restrictedSwitchPreferenceModel.RestrictionWrapper { SwitchPreference(it) }
Loading