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

Commit 3e02c39f authored by Zekan Qian's avatar Zekan Qian Committed by Android (Google) Code Review
Browse files

Merge "Add PageModel framework, and use it in ArgumentPageModel."

parents 17e4dbdb 77b718ef
Loading
Loading
Loading
Loading
+2 −10
Original line number Diff line number Diff line
@@ -49,16 +49,8 @@ object SpaEnvironment {
                IllustrationPageProvider,
            ),
            rootPageData = listOf(
                SettingsPage(HomePageProvider.name),
                SettingsPage(
                    ArgumentPageProvider.name,
                    ArgumentPageProvider.buildArgument("foo")
                ),
                SettingsPage(
                    ArgumentPageProvider.name,
                    ArgumentPageProvider.buildArgument("bar")
                ),
            )
                SettingsPage(HomePageProvider.name)
            ) + ArgumentPageProvider.buildRootPages()
        )
    }

+48 −80
Original line number Diff line number Diff line
@@ -19,64 +19,47 @@ package com.android.settingslib.spa.gallery.page
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NamedNavArgument
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.android.settingslib.spa.framework.common.SettingsEntry
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.toState
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.framework.util.getIntArg
import com.android.settingslib.spa.framework.util.getStringArg
import com.android.settingslib.spa.framework.util.navLink
import com.android.settingslib.spa.framework.util.normalize
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.scaffold.RegularScaffold

private const val TITLE = "Sample page with arguments"
private const val STRING_PARAM_NAME = "stringParam"
private const val INT_PARAM_NAME = "intParam"

object ArgumentPageProvider : SettingsPageProvider {
    override val name = "Argument"
    override val name = ArgumentPageModel.name

    override val parameter = listOf(
        navArgument(STRING_PARAM_NAME) { type = NavType.StringType },
        navArgument(INT_PARAM_NAME) { type = NavType.IntType },
    )
    override val parameter = ArgumentPageModel.parameter

    override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
        if (!parameter.isValid(arguments)) return emptyList()
        if (!ArgumentPageModel.isValidArgument(arguments)) return emptyList()

        val owner = SettingsPage(name, parameter.normalize(arguments))
        val entryList = mutableListOf<SettingsEntry>()
        val stringParamEntry = SettingsEntryBuilder.create("string_param", owner)
        stringParamEntry.setUiLayoutFn {
            Preference(object : PreferenceModel {
                override val title = "String param value"
                override val summary =
                    parameter.getStringArg(STRING_PARAM_NAME, arguments)!!.toState()
            })
        }
        entryList.add(stringParamEntry.build())
        entryList.add(
            SettingsEntryBuilder.create("string_param", owner)
                // Set attributes
                .setIsAllowSearch(true)
                .setUiLayoutFn {
                    // Set ui rendering
                    Preference(ArgumentPageModel.create(arguments).genStringParamPreferenceModel())
                }.build()
        )

        val intParamEntry = SettingsEntryBuilder.create("int_param", owner)
        intParamEntry.setUiLayoutFn {
            Preference(object : PreferenceModel {
                override val title = "Int param value"
                override val summary =
                    parameter.getIntArg(INT_PARAM_NAME, arguments)!!.toString().toState()
            })
        }
        entryList.add(intParamEntry.build())
        entryList.add(
            SettingsEntryBuilder.create("int_param", owner)
                // Set attributes
                .setIsAllowSearch(true)
                .setUiLayoutFn {
                    // Set ui rendering
                    Preference(ArgumentPageModel.create(arguments).genIntParamPreferenceModel())
                }.build()
        )

        val intParam = parameter.getIntArg(INT_PARAM_NAME, arguments)
        val entryFoo = buildInjectEntry(buildNextArgument("foo", intParam))
        val entryBar = buildInjectEntry(buildNextArgument("bar", intParam))
        val entryFoo = buildInjectEntry(ArgumentPageModel.buildNextArgument("foo", arguments))
        val entryBar = buildInjectEntry(ArgumentPageModel.buildNextArgument("bar", arguments))
        if (entryFoo != null) entryList.add(entryFoo.setLink(fromPage = owner).build())
        if (entryBar != null) entryList.add(entryBar.setLink(fromPage = owner).build())

@@ -84,30 +67,33 @@ object ArgumentPageProvider : SettingsPageProvider {
    }

    private fun buildInjectEntry(arguments: Bundle?): SettingsEntryBuilder? {
        if (!parameter.isValid(arguments)) return null

        val seBuilder =
            SettingsEntryBuilder.createInject(name, parameter.normalize(arguments))
        seBuilder.setIsAllowSearch(false)

        seBuilder.setUiLayoutFn {
            val summaryArray = listOf(
                "$STRING_PARAM_NAME=" + parameter.getStringArg(STRING_PARAM_NAME, arguments)!!,
                "$INT_PARAM_NAME=" + parameter.getIntArg(INT_PARAM_NAME, arguments)!!
            )
            Preference(object : PreferenceModel {
                override val title = TITLE
                override val summary = summaryArray.joinToString(", ").toState()
                override val onClick = navigator(name + parameter.navLink(arguments))
            })
        if (!ArgumentPageModel.isValidArgument(arguments)) return null

        return SettingsEntryBuilder.createInject(name, parameter.normalize(arguments))
            // Set attributes
            .setIsAllowSearch(false)
            .setUiLayoutFn {
                // Set ui rendering
                Preference(ArgumentPageModel.create(arguments).genInjectPreferenceModel())
            }
    }

        return seBuilder
    fun buildRootPages(): List<SettingsPage> {
        return listOf(
            SettingsPage(
                ArgumentPageModel.name,
                ArgumentPageModel.buildArgument("foo")
            ),
            SettingsPage(
                ArgumentPageModel.name,
                ArgumentPageModel.buildArgument("bar")
            ),
        )
    }

    @Composable
    override fun Page(arguments: Bundle?) {
        RegularScaffold(title = TITLE) {
        RegularScaffold(title = ArgumentPageModel.create(arguments).genPageTitle()) {
            for (entry in buildEntry(arguments)) {
                entry.uiLayout()
            }
@@ -116,21 +102,8 @@ object ArgumentPageProvider : SettingsPageProvider {

    @Composable
    fun EntryItem(stringParam: String, intParam: Int) {
        buildInjectEntry(buildArgument(stringParam, intParam))?.build()?.uiLayout?.let { it() }
    }

    fun buildArgument(stringParam: String, intParam: Int? = null): Bundle {
        val args = Bundle()
        args.putString(STRING_PARAM_NAME, stringParam)
        if (intParam != null) args.putInt(INT_PARAM_NAME, intParam)
        return args
    }

    private fun buildNextArgument(stringParam: String, intParam: Int? = null): Bundle {
        return if (intParam == null)
            buildArgument(stringParam)
        else
            buildArgument(stringParam, intParam + 1)
        buildInjectEntry(ArgumentPageModel.buildArgument(stringParam, intParam))
            ?.build()?.uiLayout?.let { it() }
    }
}

@@ -139,12 +112,7 @@ object ArgumentPageProvider : SettingsPageProvider {
private fun ArgumentPagePreview() {
    SettingsTheme {
        ArgumentPageProvider.Page(
            ArgumentPageProvider.buildArgument(stringParam = "foo", intParam = 0)
            ArgumentPageModel.buildArgument(stringParam = "foo", intParam = 0)
        )
    }
}

private fun List<NamedNavArgument>.isValid(arguments: Bundle?): Boolean {
    val stringParam = getStringArg(STRING_PARAM_NAME, arguments)
    return (stringParam != null && listOf("foo", "bar").contains(stringParam))
}
+123 −0
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.page

import android.os.Bundle
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.android.settingslib.spa.framework.common.PageModel
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.framework.util.getIntArg
import com.android.settingslib.spa.framework.util.getStringArg
import com.android.settingslib.spa.framework.util.navLink
import com.android.settingslib.spa.widget.preference.PreferenceModel

private const val TITLE = "Sample page with arguments"
private const val STRING_PARAM_NAME = "stringParam"
private const val INT_PARAM_NAME = "intParam"

class ArgumentPageModel : PageModel() {

    companion object {
        const val name = "Argument"
        val parameter = listOf(
            navArgument(STRING_PARAM_NAME) { type = NavType.StringType },
            navArgument(INT_PARAM_NAME) { type = NavType.IntType },
        )

        fun buildArgument(stringParam: String, intParam: Int? = null): Bundle {
            val args = Bundle()
            args.putString(STRING_PARAM_NAME, stringParam)
            if (intParam != null) args.putInt(INT_PARAM_NAME, intParam)
            return args
        }

        fun buildNextArgument(newStringParam: String, arguments: Bundle? = null): Bundle {
            val intParam = parameter.getIntArg(INT_PARAM_NAME, arguments)
            return if (intParam == null)
                buildArgument(newStringParam)
            else
                buildArgument(newStringParam, intParam + 1)
        }

        fun isValidArgument(arguments: Bundle?): Boolean {
            val stringParam = parameter.getStringArg(STRING_PARAM_NAME, arguments)
            return (stringParam != null && listOf("foo", "bar").contains(stringParam))
        }

        @Composable
        fun create(arguments: Bundle?): ArgumentPageModel {
            val pageModel: ArgumentPageModel = viewModel(key = arguments.toString())
            pageModel.initOnce(arguments)
            return pageModel
        }
    }

    private val title = TITLE
    private var arguments: Bundle? = null
    private var stringParam: String? = null
    private var intParam: Int? = null

    override fun initialize(arguments: Bundle?) {
        logMsg("init with args " + arguments.toString())
        this.arguments = arguments
        stringParam = parameter.getStringArg(STRING_PARAM_NAME, arguments)
        intParam = parameter.getIntArg(INT_PARAM_NAME, arguments)
    }

    @Composable
    fun genPageTitle(): String {
        return title
    }

    @Composable
    fun genStringParamPreferenceModel(): PreferenceModel {
        return object : PreferenceModel {
            override val title = "String param value"
            override val summary = stateOf(stringParam!!)
        }
    }

    @Composable
    fun genIntParamPreferenceModel(): PreferenceModel {
        return object : PreferenceModel {
            override val title = "Int param value"
            override val summary = stateOf(intParam!!.toString())
        }
    }

    @Composable
    fun genInjectPreferenceModel(): PreferenceModel {
        val summaryArray = listOf(
            "$STRING_PARAM_NAME=" + stringParam!!,
            "$INT_PARAM_NAME=" + intParam!!
        )
        return object : PreferenceModel {
            override val title = genPageTitle()
            override val summary = stateOf(summaryArray.joinToString(", "))
            override val onClick = navigator(name + parameter.navLink(arguments))
        }
    }
}

private fun logMsg(message: String) {
    Log.d("ArgumentPageModel", message)
}
+33 −0
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.framework.common

import android.os.Bundle
import androidx.lifecycle.ViewModel

open class PageModel : ViewModel() {
    var initialized = false

    fun initOnce(arguments: Bundle?) {
        // Initialize only once
        if (initialized) return
        initialized = true
        initialize(arguments)
    }

    open fun initialize(arguments: Bundle?) {}
}
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.settingslib.spa.framework.common
import android.util.Log
import java.util.LinkedList

const val MAX_ENTRY_SIZE = 5000
private const val MAX_ENTRY_SIZE = 5000

/**
 * The repository to maintain all Settings entries