From 77b718efa86305acd07da6d1d50c1893ad7a309a Mon Sep 17 00:00:00 2001 From: Zekan Qian Date: Mon, 5 Sep 2022 12:05:57 +0800 Subject: [PATCH] Add PageModel framework, and use it in ArgumentPageModel. Bug: 244122804 Test: manual - build Spa gallery Change-Id: I7079bfdcf84820a1d499be3efe65f9a046d7ab08 --- .../settingslib/spa/gallery/SpaEnvironment.kt | 12 +- .../spa/gallery/page/ArgumentPage.kt | 126 +++++++----------- .../spa/gallery/page/ArgumentPageModel.kt | 123 +++++++++++++++++ .../spa/framework/common/PageModel.kt | 33 +++++ .../common/SettingsEntryRepository.kt | 2 +- 5 files changed, 206 insertions(+), 90 deletions(-) create mode 100644 packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt create mode 100644 packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/PageModel.kt diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt index 43cfbb3f4f6d1..01ca74500bedf 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt @@ -47,16 +47,8 @@ object SpaEnvironment { FooterPageProvider, ), rootPageData = listOf( - SettingsPage(HomePageProvider.name), - SettingsPage( - ArgumentPageProvider.name, - ArgumentPageProvider.buildArgument("foo") - ), - SettingsPage( - ArgumentPageProvider.name, - ArgumentPageProvider.buildArgument("bar") - ), - ) + SettingsPage(HomePageProvider.name) + ) + ArgumentPageProvider.buildRootPages() ) } diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt index 028de7dd8d0fc..dd5cd2d3dd052 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt @@ -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 { - if (!parameter.isValid(arguments)) return emptyList() + if (!ArgumentPageModel.isValidArgument(arguments)) return emptyList() val owner = SettingsPage(name, parameter.normalize(arguments)) val entryList = mutableListOf() - 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 + if (!ArgumentPageModel.isValidArgument(arguments)) return null - val seBuilder = - SettingsEntryBuilder.createInject(name, parameter.normalize(arguments)) - seBuilder.setIsAllowSearch(false) + return SettingsEntryBuilder.createInject(name, parameter.normalize(arguments)) + // Set attributes + .setIsAllowSearch(false) + .setUiLayoutFn { + // Set ui rendering + Preference(ArgumentPageModel.create(arguments).genInjectPreferenceModel()) + } + } - 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)) - }) - } - - return seBuilder + fun buildRootPages(): List { + 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.isValid(arguments: Bundle?): Boolean { - val stringParam = getStringArg(STRING_PARAM_NAME, arguments) - return (stringParam != null && listOf("foo", "bar").contains(stringParam)) -} diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt new file mode 100644 index 0000000000000..8b94342cf0827 --- /dev/null +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt @@ -0,0 +1,123 @@ +/* + * 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) +} diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/PageModel.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/PageModel.kt new file mode 100644 index 0000000000000..ee12f02e5a7a3 --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/PageModel.kt @@ -0,0 +1,33 @@ +/* + * 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?) {} +} diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt index 588df5bbf247e..7c9225de13d8c 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt @@ -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