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

Commit 4d2cf1b1 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Migrate PreferencePageProvider

Bug: 370360039
Flag: EXEMPT gallery only
Test: manual - with gallery
Change-Id: I917e04f5bcf9a271176310dd0b5e2a46a99ec181
parent d6ca3043
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
 */
enum class SettingsPageProviderEnum(val displayName: String) {
    HOME("home"),
    PREFERENCE("preference"),

    // Add your SPPs
}
+0 −112
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settingslib.spa.gallery.preference

import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.settingslib.spa.framework.common.PageModel
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

private const val TAG = "PreferencePageModel"

class PreferencePageModel : PageModel() {
    companion object {
        // Defines all the resources for this page.
        // In real Settings App, resources data is defined in xml, rather than SPP.
        const val PAGE_TITLE = "Sample Preference"
        const val SIMPLE_PREFERENCE_TITLE = "Preference"
        const val SIMPLE_PREFERENCE_SUMMARY = "Simple summary"
        const val DISABLE_PREFERENCE_TITLE = "Disabled"
        const val DISABLE_PREFERENCE_SUMMARY = "Disabled summary"
        const val ASYNC_PREFERENCE_TITLE = "Async Preference"
        const val ASYNC_PREFERENCE_SUMMARY = "Async summary"
        const val MANUAL_UPDATE_PREFERENCE_TITLE = "Manual Updater"
        const val AUTO_UPDATE_PREFERENCE_TITLE = "Auto Updater"
        val SIMPLE_PREFERENCE_KEYWORDS = listOf("simple keyword1", "simple keyword2")

        @Composable
        fun create(): PreferencePageModel {
            val pageModel: PreferencePageModel = viewModel()
            pageModel.initOnce()
            return pageModel
        }
    }

    private val spaLogger = SpaEnvironmentFactory.instance.logger

    val asyncSummary = mutableStateOf("(loading)")
    val asyncEnable = mutableStateOf(false)

    private val manualUpdater = mutableStateOf(0)

    private val autoUpdater = object : MutableLiveData<String>(" ") {
        private var tick = 0
        private var updateJob: Job? = null
        override fun onActive() {
            spaLogger.message(TAG, "autoUpdater.active")
            updateJob = viewModelScope.launch(Dispatchers.IO) {
                while (true) {
                    delay(1000L)
                    tick++
                    spaLogger.message(TAG, "autoUpdater.value $tick")
                    postValue(tick.toString())
                }
            }
        }

        override fun onInactive() {
            spaLogger.message(TAG, "autoUpdater.inactive")
            updateJob?.cancel()
        }
    }

    override fun initialize(arguments: Bundle?) {
        spaLogger.message(TAG, "initialize with args " + arguments.toString())
        viewModelScope.launch(Dispatchers.IO) {
            // Loading your data here.
            delay(2000L)
            asyncSummary.value = ASYNC_PREFERENCE_SUMMARY
            asyncEnable.value = true
        }
    }

    fun getManualUpdaterSummary(): State<String> {
        spaLogger.message(TAG, "getManualUpdaterSummary")
        return derivedStateOf { manualUpdater.value.toString() }
    }

    fun manualUpdaterOnClick() {
        spaLogger.message(TAG, "manualUpdaterOnClick")
        manualUpdater.value = manualUpdater.value + 1
    }

    fun getAutoUpdaterSummary(): LiveData<String> {
        spaLogger.message(TAG, "getAutoUpdaterSummary")
        return autoUpdater
    }
}
+68 −150
Original line number Diff line number Diff line
@@ -18,188 +18,106 @@ package com.android.settingslib.spa.gallery.preference

import android.os.Bundle
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Autorenew
import androidx.compose.material.icons.outlined.DisabledByDefault
import androidx.compose.material.icons.outlined.TouchApp
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.common.EntrySearchData
import com.android.settingslib.spa.framework.common.EntryStatusData
import com.android.settingslib.spa.framework.common.SettingsEntry
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
import com.android.settingslib.spa.framework.common.createSettingsPage
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.gallery.R
import com.android.settingslib.spa.gallery.SettingsPageProviderEnum
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.ASYNC_PREFERENCE_TITLE
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.AUTO_UPDATE_PREFERENCE_TITLE
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.DISABLE_PREFERENCE_SUMMARY
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.DISABLE_PREFERENCE_TITLE
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.MANUAL_UPDATE_PREFERENCE_TITLE
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.PAGE_TITLE
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.SIMPLE_PREFERENCE_KEYWORDS
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.SIMPLE_PREFERENCE_SUMMARY
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.SIMPLE_PREFERENCE_TITLE
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.preference.SimplePreferenceMacro
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category
import com.android.settingslib.spa.widget.ui.SettingsIcon

private const val TAG = "PreferencePage"
import kotlinx.coroutines.delay

object PreferencePageProvider : SettingsPageProvider {
    // Defines all entry name in this page.
    // Note that entry name would be used in log. DO NOT change it once it is set.
    // One can still change the display name for better readability if necessary.
    enum class EntryEnum(val displayName: String) {
        SIMPLE_PREFERENCE("preference"),
        SUMMARY_PREFERENCE("preference_with_summary"),
        SINGLE_LINE_SUMMARY_PREFERENCE("preference_with_single_line_summary"),
        DISABLED_PREFERENCE("preference_disable"),
        ASYNC_SUMMARY_PREFERENCE("preference_with_async_summary"),
        MANUAL_UPDATE_PREFERENCE("preference_actionable"),
        AUTO_UPDATE_PREFERENCE("preference_auto_update"),
    }

    override val name = SettingsPageProviderEnum.PREFERENCE.name
    override val displayName = SettingsPageProviderEnum.PREFERENCE.displayName
    private val spaLogger = SpaEnvironmentFactory.instance.logger
    override val name = "Preference"
    private const val PAGE_TITLE = "Sample Preference"
    private val owner = createSettingsPage()

    private fun createEntry(entry: EntryEnum): SettingsEntryBuilder {
        return SettingsEntryBuilder.create(owner, entry.name, entry.displayName)
    }

    override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
        val entryList = mutableListOf<SettingsEntry>()
        entryList.add(
            createEntry(EntryEnum.SIMPLE_PREFERENCE)
                .setMacro {
                    spaLogger.message(TAG, "create macro for ${EntryEnum.SIMPLE_PREFERENCE}")
                    SimplePreferenceMacro(title = SIMPLE_PREFERENCE_TITLE)
                }
                .setStatusDataFn { EntryStatusData(isDisabled = false) }
                .build()
        )
        entryList.add(
            createEntry(EntryEnum.SUMMARY_PREFERENCE)
                .setMacro {
                    spaLogger.message(TAG, "create macro for ${EntryEnum.SUMMARY_PREFERENCE}")
                    SimplePreferenceMacro(
                        title = SIMPLE_PREFERENCE_TITLE,
                        summary = SIMPLE_PREFERENCE_SUMMARY,
                        searchKeywords = SIMPLE_PREFERENCE_KEYWORDS,
                    )
                }
                .setStatusDataFn { EntryStatusData(isDisabled = true) }
                .build()
        )
        entryList.add(singleLineSummaryEntry())
        entryList.add(
            createEntry(EntryEnum.DISABLED_PREFERENCE)
                .setHasMutableStatus(true)
                .setMacro {
                    spaLogger.message(TAG, "create macro for ${EntryEnum.DISABLED_PREFERENCE}")
                    SimplePreferenceMacro(
                        title = DISABLE_PREFERENCE_TITLE,
                        summary = DISABLE_PREFERENCE_SUMMARY,
                        disabled = true,
                        icon = Icons.Outlined.DisabledByDefault,
                    )
                }
                .setStatusDataFn { EntryStatusData(isDisabled = true) }
                .build()
        )
        entryList.add(
            createEntry(EntryEnum.ASYNC_SUMMARY_PREFERENCE)
                .setHasMutableStatus(true)
                .setSearchDataFn {
                    EntrySearchData(title = ASYNC_PREFERENCE_TITLE)
                }
                .setStatusDataFn { EntryStatusData(isDisabled = false) }
                .setUiLayoutFn {
                    val model = PreferencePageModel.create()
                    Preference(
                        object : PreferenceModel {
                            override val title = ASYNC_PREFERENCE_TITLE
                            override val summary = { model.asyncSummary.value }
                            override val enabled = { model.asyncEnable.value }
                        }
                    )
                }.build()
        )
        entryList.add(
            createEntry(EntryEnum.MANUAL_UPDATE_PREFERENCE)
                .setUiLayoutFn {
                    val model = PreferencePageModel.create()
                    val manualUpdaterSummary = remember { model.getManualUpdaterSummary() }
                    Preference(
                        object : PreferenceModel {
                            override val title = MANUAL_UPDATE_PREFERENCE_TITLE
                            override val summary = { manualUpdaterSummary.value }
                            override val onClick = { model.manualUpdaterOnClick() }
                            override val icon = @Composable {
                                SettingsIcon(imageVector = Icons.Outlined.TouchApp)
                            }
                        }
                    )
                }.build()
        )
        entryList.add(
            createEntry(EntryEnum.AUTO_UPDATE_PREFERENCE)
                .setUiLayoutFn {
                    val model = PreferencePageModel.create()
                    val autoUpdaterSummary = remember {
                        model.getAutoUpdaterSummary()
                    }.observeAsState(" ")
                    Preference(
                        object : PreferenceModel {
                            override val title = AUTO_UPDATE_PREFERENCE_TITLE
                            override val summary = { autoUpdaterSummary.value }
                            override val icon = @Composable {
                                SettingsIcon(imageVector = Icons.Outlined.Autorenew)
                            }
                        }
                    )
                }.build()
        )

        return entryList
    }

    private fun singleLineSummaryEntry() = createEntry(EntryEnum.SINGLE_LINE_SUMMARY_PREFERENCE)
        .setUiLayoutFn {
    @Composable
    override fun Page(arguments: Bundle?) {
        RegularScaffold(PAGE_TITLE) {
            Category {
                Preference(object : PreferenceModel {
                    override val title = "Preference"
                })
                Preference(object : PreferenceModel {
                    override val title = "Preference"
                    override val summary = { "Simple summary" }
                })
                val summary = stringResource(R.string.single_line_summary_preference_summary)
                Preference(
                    model = object : PreferenceModel {
                    override val title: String =
                        override val title =
                            stringResource(R.string.single_line_summary_preference_title)
                        override val summary = { summary }
                    },
                    singleLineSummary = true,
                )
            }
        .build()
            Category {
                Preference(object : PreferenceModel {
                    override val title = "Disabled"
                    override val summary = { "Disabled summary" }
                    override val enabled = { false }
                    override val icon = @Composable {
                        SettingsIcon(imageVector = Icons.Outlined.DisabledByDefault)
                    }
                })
            }
            Category {
                Preference(object : PreferenceModel {
                    override val title = "Preference"
                    val asyncSummary by produceState(initialValue = " ") {
                        delay(1000L)
                        value = "Async summary"
                    }
                    override val summary = { asyncSummary }
                })

                var count by remember { mutableIntStateOf(0) }
                Preference(object : PreferenceModel {
                    override val title = "Click me"
                    override val summary = { count.toString() }
                    override val onClick: (() -> Unit) = { count++ }
                })

                var ticks by remember { mutableIntStateOf(0) }
                LaunchedEffect(ticks) {
                    delay(1000L)
                    ticks++
                }
                Preference(object : PreferenceModel {
                    override val title = "Ticker"
                    override val summary = { ticks.toString() }
                })
            }
        }
    }

    fun buildInjectEntry(): SettingsEntryBuilder {
        return SettingsEntryBuilder.createInject(owner = owner)
            .setMacro {
                spaLogger.message(TAG, "create macro for INJECT entry")
                SimplePreferenceMacro(
                    title = PAGE_TITLE,
                    clickRoute = SettingsPageProviderEnum.PREFERENCE.name
                    clickRoute = name
                )
            }
    }

    override fun getTitle(arguments: Bundle?): String {
        return PAGE_TITLE
    }
}

@Preview(showBackground = true)