diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/MainActivity.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/MainActivity.kt index 6e6da520a3f0c..a063847623721 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/MainActivity.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/MainActivity.kt @@ -18,4 +18,4 @@ package com.android.settingslib.spa.gallery import com.android.settingslib.spa.framework.BrowseActivity -class MainActivity : BrowseActivity(galleryPageProviders) +class MainActivity : BrowseActivity(SpaEnvironment.PageProviderRepository) 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 0d947342c930f..43cfbb3f4f6d1 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 @@ -16,6 +16,8 @@ package com.android.settingslib.spa.gallery +import com.android.settingslib.spa.framework.common.SettingsEntryRepository +import com.android.settingslib.spa.framework.common.SettingsPage import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository import com.android.settingslib.spa.gallery.home.HomePageProvider import com.android.settingslib.spa.gallery.page.ArgumentPageProvider @@ -28,20 +30,39 @@ import com.android.settingslib.spa.gallery.preference.SwitchPreferencePageProvid import com.android.settingslib.spa.gallery.preference.TwoTargetSwitchPreferencePageProvider import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider -val galleryPageProviders = SettingsPageProviderRepository( - allPagesList = listOf( - HomePageProvider, - PreferenceMainPageProvider, - PreferencePageProvider, - SwitchPreferencePageProvider, - TwoTargetSwitchPreferencePageProvider, - ArgumentPageProvider, - SliderPageProvider, - SpinnerPageProvider, - SettingsPagerPageProvider, - FooterPageProvider, - ), - rootPages = listOf(HomePageProvider.name) -) +object SpaEnvironment { + val PageProviderRepository: SettingsPageProviderRepository by + lazy(LazyThreadSafetyMode.SYNCHRONIZED) { + SettingsPageProviderRepository( + allPagesList = listOf( + HomePageProvider, + PreferenceMainPageProvider, + PreferencePageProvider, + SwitchPreferencePageProvider, + TwoTargetSwitchPreferencePageProvider, + ArgumentPageProvider, + SliderPageProvider, + SpinnerPageProvider, + SettingsPagerPageProvider, + FooterPageProvider, + ), + rootPageData = listOf( + SettingsPage(HomePageProvider.name), + SettingsPage( + ArgumentPageProvider.name, + ArgumentPageProvider.buildArgument("foo") + ), + SettingsPage( + ArgumentPageProvider.name, + ArgumentPageProvider.buildArgument("bar") + ), + ) + ) + } -// TODO: add other environment setup here. + val EntryRepository: SettingsEntryRepository by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { + SettingsEntryRepository(PageProviderRepository) + } + + // TODO: add other environment setup here. +} diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt index fdcb1c2a58535..ad492a5bb161d 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt @@ -17,12 +17,15 @@ package com.android.settingslib.spa.gallery.home import android.os.Bundle +import androidx.compose.material3.Button +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.gallery.R +import com.android.settingslib.spa.gallery.SpaEnvironment import com.android.settingslib.spa.gallery.page.ArgumentPageProvider import com.android.settingslib.spa.gallery.page.FooterPageProvider import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider @@ -50,6 +53,17 @@ private fun HomePage() { SpinnerPageProvider.EntryItem() SettingsPagerPageProvider.EntryItem() FooterPageProvider.EntryItem() + + /** + * A test button to generate hierarchy. + * TODO: remove it once the content provider is ready. + */ + Button(onClick = { + SpaEnvironment.EntryRepository.printAllPages() + SpaEnvironment.EntryRepository.printAllEntries() + }) { + Text(text = "Generate Entry") + } } } 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 92b64fb42abf0..028de7dd8d0fc 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,16 +19,20 @@ 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.PageArguments import com.android.settingslib.spa.framework.common.SettingsEntry import com.android.settingslib.spa.framework.common.SettingsEntryBuilder -import com.android.settingslib.spa.framework.common.SettingsPageBuilder +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 @@ -40,22 +44,22 @@ private const val INT_PARAM_NAME = "intParam" object ArgumentPageProvider : SettingsPageProvider { override val name = "Argument" - override val arguments = listOf( + override val parameter = listOf( navArgument(STRING_PARAM_NAME) { type = NavType.StringType }, navArgument(INT_PARAM_NAME) { type = NavType.IntType }, ) override fun buildEntry(arguments: Bundle?): List { - val pageArgs = PageArguments(ArgumentPageProvider.arguments, arguments) - if (!pageArgs.isValid()) return emptyList() + if (!parameter.isValid(arguments)) return emptyList() - val owner = SettingsPageBuilder.create(name, pageArgs.normalize()).build() + 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 = pageArgs.getStringArg(STRING_PARAM_NAME)!!.toState() + override val summary = + parameter.getStringArg(STRING_PARAM_NAME, arguments)!!.toState() }) } entryList.add(stringParamEntry.build()) @@ -64,13 +68,15 @@ object ArgumentPageProvider : SettingsPageProvider { intParamEntry.setUiLayoutFn { Preference(object : PreferenceModel { override val title = "Int param value" - override val summary = pageArgs.getIntArg(INT_PARAM_NAME)!!.toString().toState() + override val summary = + parameter.getIntArg(INT_PARAM_NAME, arguments)!!.toString().toState() }) } entryList.add(intParamEntry.build()) - val entryFoo = buildInjectEntry(pageArgs.buildNextArg("foo")) - val entryBar = buildInjectEntry(pageArgs.buildNextArg("bar")) + val intParam = parameter.getIntArg(INT_PARAM_NAME, arguments) + val entryFoo = buildInjectEntry(buildNextArgument("foo", intParam)) + val entryBar = buildInjectEntry(buildNextArgument("bar", intParam)) if (entryFoo != null) entryList.add(entryFoo.setLink(fromPage = owner).build()) if (entryBar != null) entryList.add(entryBar.setLink(fromPage = owner).build()) @@ -78,21 +84,21 @@ object ArgumentPageProvider : SettingsPageProvider { } private fun buildInjectEntry(arguments: Bundle?): SettingsEntryBuilder? { - val pageArgs = PageArguments(ArgumentPageProvider.arguments, arguments) - if (!pageArgs.isValid()) return null + if (!parameter.isValid(arguments)) return null - val seBuilder = SettingsEntryBuilder.createLinkTo("injection", name, pageArgs.normalize()) + val seBuilder = + SettingsEntryBuilder.createInject(name, parameter.normalize(arguments)) seBuilder.setIsAllowSearch(false) seBuilder.setUiLayoutFn { val summaryArray = listOf( - "$STRING_PARAM_NAME=" + pageArgs.getStringArg(STRING_PARAM_NAME)!!, - "$INT_PARAM_NAME=" + pageArgs.getIntArg(INT_PARAM_NAME)!! + "$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 + pageArgs.navLink()) + override val onClick = navigator(name + parameter.navLink(arguments)) }) } @@ -112,32 +118,33 @@ object ArgumentPageProvider : SettingsPageProvider { 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) + } } @Preview(showBackground = true) @Composable private fun ArgumentPagePreview() { SettingsTheme { - ArgumentPageProvider.Page(buildArgument(stringParam = "foo", intParam = 0)) + ArgumentPageProvider.Page( + ArgumentPageProvider.buildArgument(stringParam = "foo", intParam = 0) + ) } } -private fun PageArguments.isValid(): Boolean { - val stringParam = getStringArg(STRING_PARAM_NAME) +private fun List.isValid(arguments: Bundle?): Boolean { + val stringParam = getStringArg(STRING_PARAM_NAME, arguments) return (stringParam != null && listOf("foo", "bar").contains(stringParam)) } - -private fun PageArguments.buildNextArg(stringParam: String): Bundle { - val intParam = getIntArg(INT_PARAM_NAME) - return if (intParam == null) - buildArgument(stringParam) - else - buildArgument(stringParam, intParam + 1) -} - -private 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 -} diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt index e8d1ea2c7680c..87d4f5a936f88 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt @@ -27,10 +27,10 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import com.android.settingslib.spa.R -import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository import com.android.settingslib.spa.framework.compose.localNavController import com.android.settingslib.spa.framework.theme.SettingsTheme +import com.android.settingslib.spa.framework.util.navRoute open class BrowseActivity( private val sppRepository: SettingsPageProviderRepository, @@ -55,8 +55,8 @@ open class BrowseActivity( NavHost(navController, sppRepository.getDefaultStartPageName()) { for (page in sppRepository.getAllProviders()) { composable( - route = page.route, - arguments = page.arguments, + route = page.name + page.parameter.navRoute(), + arguments = page.parameter, ) { navBackStackEntry -> page.Page(navBackStackEntry.arguments) } @@ -75,9 +75,6 @@ open class BrowseActivity( } } - private val SettingsPageProvider.route: String - get() = name + arguments.joinToString("") { argument -> "/{${argument.name}}" } - companion object { const val KEY_DESTINATION = "spa:SpaActivity:destination" } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/PageArguments.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/PageArguments.kt deleted file mode 100644 index c0f585ffa595b..0000000000000 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/PageArguments.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.navigation.NamedNavArgument -import androidx.navigation.NavType - -class PageArguments( - private val navArgsDef: List, - private val rawArgs: Bundle? -) { - fun normalize(): Bundle { - if (rawArgs == null) return Bundle.EMPTY - val normArgs = Bundle() - for (navArg in navArgsDef) { - when (navArg.argument.type) { - NavType.StringType -> { - val value = rawArgs.getString(navArg.name) - if (value != null) normArgs.putString(navArg.name, value) - } - NavType.IntType -> { - if (rawArgs.containsKey(navArg.name)) - normArgs.putInt(navArg.name, rawArgs.getInt(navArg.name)) - } - } - } - return normArgs - } - - fun navLink(): String{ - if (rawArgs == null) return "" - val argsArray = mutableListOf() - for (navArg in navArgsDef) { - when (navArg.argument.type) { - NavType.StringType -> { - argsArray.add(rawArgs.getString(navArg.name, "")) - } - NavType.IntType -> { - argsArray.add(rawArgs.getInt(navArg.name).toString()) - } - } - } - return argsArray.joinToString("") {arg -> "/$arg" } - } - - fun getStringArg(key: String): String? { - if (rawArgs != null && rawArgs.containsKey(key)) { - return rawArgs.getString(key) - } - return null - } - - fun getIntArg(key: String): Int? { - if (rawArgs != null && rawArgs.containsKey(key)) { - return rawArgs.getInt(key) - } - return null - } -} diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt index 6fcd555f0df69..a38f5ec1361fa 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt @@ -19,6 +19,9 @@ package com.android.settingslib.spa.framework.common import android.os.Bundle import androidx.compose.runtime.Composable +const val INJECT_ENTRY_NAME = "INJECT" +const val ROOT_ENTRY_NAME = "ROOT" + /** * Defines data of one Settings entry for Settings search. */ @@ -32,18 +35,22 @@ data class UiData(val title: String = "") /** * Defines data to identify a Settings page. */ -data class SettingsPage(val name: String = "", val args: Bundle = Bundle.EMPTY) +data class SettingsPage(val name: String = "", val args: Bundle? = null) { + override fun toString(): String { + return name + args?.toString() + } +} /** * Defines data of a Settings entry. */ data class SettingsEntry( + // The unique id of this entry + val id: String, + val name: String, val owner: SettingsPage, - // Generates the unique id of this entry - val uniqueId: String, - // Defines linking of Settings entries val fromPage: SettingsPage? = null, val toPage: SettingsPage? = null, @@ -80,39 +87,13 @@ data class SettingsEntry( * use each entries' UI rendering function in the page instead. */ val uiLayout: (@Composable () -> Unit) = {}, -) - -/** - * The helper to build a Settings Page instance. - */ -class SettingsPageBuilder(private val name: String) { - private val arguments = Bundle() - - fun pushArgs(args: Bundle?): SettingsPageBuilder { - if (args != null) arguments.putAll(args) - return this - } - - fun pushArg(argName: String, argValue: String?): SettingsPageBuilder { - if (argValue != null) this.arguments.putString(argName, argValue) - return this - } - - fun pushArg(argName: String, argValue: Int?): SettingsPageBuilder { - if (argValue != null) this.arguments.putInt(argName, argValue) - return this - } - - fun build(): SettingsPage { - return SettingsPage(name, arguments) - } - - companion object { - fun create(name: String, args: Bundle? = null): SettingsPageBuilder { - return SettingsPageBuilder(name).apply { - pushArgs(args) - } - } +) { + override fun toString(): String { + return listOf( + name, + owner.toString(), + "(${fromPage?.toString()}-${toPage?.toString()})" + ).joinToString("-") } } @@ -130,9 +111,9 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings fun build(): SettingsEntry { return SettingsEntry( + id = computeUniqueId(), name = name, owner = owner, - uniqueId = computeUniqueId(), // linking data fromPage = fromPage, @@ -171,22 +152,27 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings return this } - private fun computeUniqueId(): String = uniqueId ?: (name + owner.toString()) + private fun computeUniqueId(): String = + uniqueId ?: name + owner.toString() + fromPage?.toString() + toPage?.toString() private fun computeSearchable(): Boolean = isAllowSearch ?: false companion object { + fun create(entryName: String, owner: SettingsPage): SettingsEntryBuilder { + return SettingsEntryBuilder(entryName, owner) + } + fun create( entryName: String, ownerPageName: String, ownerPageArgs: Bundle? = null ): SettingsEntryBuilder { - val owner = SettingsPageBuilder.create(ownerPageName, ownerPageArgs) - return SettingsEntryBuilder(entryName, owner.build()) + val owner = SettingsPage(ownerPageName, ownerPageArgs) + return create(entryName, owner) } - fun create(entryName: String, owner: SettingsPage): SettingsEntryBuilder { - return SettingsEntryBuilder(entryName, owner) + fun createLinkTo(entryName: String, owner: SettingsPage): SettingsEntryBuilder { + return create(entryName, owner).setLink(toPage = owner) } fun createLinkTo( @@ -194,12 +180,19 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings ownerPageName: String, ownerPageArgs: Bundle? = null ): SettingsEntryBuilder { - val owner = SettingsPageBuilder.create(ownerPageName, ownerPageArgs) - return SettingsEntryBuilder(entryName, owner.build()).setLink(toPage = owner.build()) + val owner = SettingsPage(ownerPageName, ownerPageArgs) + return createLinkTo(entryName, owner) } - fun createLinkTo(entryName: String, owner: SettingsPage): SettingsEntryBuilder { - return SettingsEntryBuilder(entryName, owner).setLink(toPage = owner) + fun createInject( + ownerPageName: String, + ownerPageArgs: Bundle? = null + ): SettingsEntryBuilder { + return createLinkTo(INJECT_ENTRY_NAME, ownerPageName, ownerPageArgs) + } + + fun createRoot(page: SettingsPage): SettingsEntryBuilder { + return createLinkTo(ROOT_ENTRY_NAME, page) } } } 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 new file mode 100644 index 0000000000000..588df5bbf247e --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt @@ -0,0 +1,79 @@ +/* + * 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.util.Log +import java.util.LinkedList + +const val MAX_ENTRY_SIZE = 5000 + +/** + * The repository to maintain all Settings entries + */ +class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) { + // Map of entry unique Id to entry + private val entryMap: Map + + // Map of Settings page to its contained entries. + private val pageToEntryListMap: Map> + + init { + logMsg("Initialize") + entryMap = mutableMapOf() + pageToEntryListMap = mutableMapOf() + + val entryQueue = LinkedList() + for (page in sppRepository.getAllRootPages()) { + val rootEntry = SettingsEntryBuilder.createRoot(page).build() + if (!entryMap.containsKey(rootEntry.id)) { + entryQueue.push(rootEntry) + entryMap.put(rootEntry.id, rootEntry) + } + } + + while (entryQueue.isNotEmpty() && entryMap.size < MAX_ENTRY_SIZE) { + val entry = entryQueue.pop() + val page = entry.toPage + if (page == null || pageToEntryListMap.containsKey(page.toString())) continue + val spp = sppRepository.getProviderOrNull(page.name) ?: continue + val newEntries = spp.buildEntry(page.args) + pageToEntryListMap[page.toString()] = newEntries + for (newEntry in newEntries) { + if (!entryMap.containsKey(newEntry.id)) { + entryQueue.push(newEntry) + entryMap.put(newEntry.id, newEntry) + } + } + } + } + + fun printAllPages() { + for (entry in pageToEntryListMap.entries) { + logMsg("page: ${entry.key} with ${entry.value.size} entries") + } + } + + fun printAllEntries() { + for (entry in entryMap.values) { + logMsg("entry: $entry") + } + } +} + +private fun logMsg(message: String) { + Log.d("EntryRepo", message) +} diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt index a57c66e14c3aa..965c2b39f4db0 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt @@ -28,8 +28,8 @@ interface SettingsPageProvider { /** The page name without arguments. */ val name: String - /** The page arguments, default is no arguments. */ - val arguments: List + /** The page parameters, default is no parameters. */ + val parameter: List get() = emptyList() /** The [Composable] used to render this page. */ diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepository.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepository.kt index 0a32939b36a3d..d78604a1c2725 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepository.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepository.kt @@ -18,22 +18,33 @@ package com.android.settingslib.spa.framework.common class SettingsPageProviderRepository( allPagesList: List, - private val rootPages: List + private val rootPages: List = emptyList(), + // TODO: deprecate rootPages above + private val rootPageData: List = emptyList(), ) { - // Maintains all SPA page providers. - private val allPages: Map = allPagesList.associateBy { it.name } + // Map of page name to its provider. + private val pageProviderMap: Map = + allPagesList.associateBy { it.name } fun getDefaultStartPageName(): String { - return rootPages.getOrElse(0) { - return "" + if (rootPageData.isNotEmpty()) { + return rootPageData[0].name + } else { + return rootPages.getOrElse(0) { + return "" + } } } + fun getAllRootPages(): Collection { + return rootPageData + } + fun getAllProviders(): Collection { - return allPages.values + return pageProviderMap.values } fun getProviderOrNull(name: String): SettingsPageProvider? { - return allPages[name] + return pageProviderMap[name] } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt new file mode 100644 index 0000000000000..834a52e737a3d --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt @@ -0,0 +1,87 @@ +/* + * 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.util + +import android.os.Bundle +import androidx.navigation.NamedNavArgument +import androidx.navigation.NavType + +fun List.navRoute(): String { + return this.joinToString("") { argument -> "/{${argument.name}}" } +} + +fun List.navLink(arguments: Bundle? = null): String { + if (arguments == null) return "" + val argsArray = mutableListOf() + for (navArg in this) { + when (navArg.argument.type) { + NavType.StringType -> { + argsArray.add(arguments.getString(navArg.name, "")) + } + NavType.IntType -> { + argsArray.add(arguments.getInt(navArg.name).toString()) + } + } + } + return argsArray.joinToString("") { arg -> "/$arg" } +} + +fun List.normalize(arguments: Bundle? = null): Bundle { + if (arguments == null) return Bundle.EMPTY + val normArgs = Bundle() + for (navArg in this) { + when (navArg.argument.type) { + NavType.StringType -> { + val value = arguments.getString(navArg.name) + if (value != null) normArgs.putString(navArg.name, value) + } + NavType.IntType -> { + if (arguments.containsKey(navArg.name)) + normArgs.putInt(navArg.name, arguments.getInt(navArg.name)) + } + } + } + return normArgs +} + +fun List.getStringArg(name: String, arguments: Bundle? = null): String? { + if (this.containsStringArg(name) && arguments != null) { + return arguments.getString(name) + } + return null +} + +fun List.getIntArg(name: String, arguments: Bundle? = null): Int? { + if (this.containsIntArg(name) && arguments != null && arguments.containsKey(name)) { + return arguments.getInt(name) + } + return null +} + +fun List.containsStringArg(name: String): Boolean { + for (navArg in this) { + if (navArg.argument.type == NavType.StringType && navArg.name == name) return true + } + return false +} + +fun List.containsIntArg(name: String): Boolean { + for (navArg in this) { + if (navArg.argument.type == NavType.IntType && navArg.name == name) return true + } + return false +} diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt index eb9ce5e77c933..8282498725595 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt @@ -47,7 +47,7 @@ internal class TogglePermissionAppInfoPageProvider( ) : SettingsPageProvider { override val name = NAME - override val arguments = listOf( + override val parameter = listOf( navArgument(PERMISSION) { type = NavType.StringType }, navArgument(PACKAGE_NAME) { type = NavType.StringType }, navArgument(USER_ID) { type = NavType.IntType }, diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt index f2eb96277b9bc..ca6ba84185ec8 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt @@ -42,7 +42,7 @@ internal class TogglePermissionAppListPageProvider( ) : SettingsPageProvider { override val name = NAME - override val arguments = listOf( + override val parameter = listOf( navArgument(PERMISSION) { type = NavType.StringType }, ) @@ -81,6 +81,7 @@ internal class TogglePermissionAppListPageProvider( * Expose route to enable enter from non-SPA pages. */ internal fun getRoute(permissionType: String) = "$NAME/$permissionType" + @Composable internal fun navigator(permissionType: String) = navigator(route = getRoute(permissionType)) }