diff options
| author | 2022-09-02 16:36:19 +0800 | |
|---|---|---|
| committer | 2022-09-05 13:03:59 +0800 | |
| commit | dccbbc0b587effe57fff2ec2cccee9998a7d53c3 (patch) | |
| tree | 0e1a77363e88ad9caaf6d5e9932c658f2c9d7ab2 | |
| parent | 44622764d9420f27a2d7fc2dfd84d89be3273ca5 (diff) | |
Add SettingsEntryRepository with some refactoring
1. Refactor SpaEnvironment, lazy init sppRepo and entryRepo
2. Add SettingsArguments with helper functions for arguments build, which is going to replace arguments in SPP
3. Add rootSettingsPages in SppRepo, which is going to replace rootPageNames (TODO).
4. Add button in HomePage to print pages & entries
Bug: 244122804
Test: manual - build Spa gallery
Change-Id: Iccc66f0cb7156c8aa2d9793e296c2a1a2b0e277a
13 files changed, 325 insertions, 189 deletions
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 6e6da520a3f0..a06384762372 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 0d947342c930..43cfbb3f4f6d 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 fdcb1c2a5853..ad492a5bb161 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 92b64fb42abf..028de7dd8d0f 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<SettingsEntry> { - 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<SettingsEntry>() 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<NamedNavArgument>.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 e8d1ea2c7680..87d4f5a936f8 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 c0f585ffa595..000000000000 --- 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<NamedNavArgument>, - 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<String>() - 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 6fcd555f0df6..a38f5ec1361f 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 000000000000..588df5bbf247 --- /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<String, SettingsEntry> + + // Map of Settings page to its contained entries. + private val pageToEntryListMap: Map<String, List<SettingsEntry>> + + init { + logMsg("Initialize") + entryMap = mutableMapOf() + pageToEntryListMap = mutableMapOf() + + val entryQueue = LinkedList<SettingsEntry>() + 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 a57c66e14c3a..965c2b39f4db 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<NamedNavArgument> + /** The page parameters, default is no parameters. */ + val parameter: List<NamedNavArgument> 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 0a32939b36a3..d78604a1c272 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<SettingsPageProvider>, - private val rootPages: List<String> + private val rootPages: List<String> = emptyList(), + // TODO: deprecate rootPages above + private val rootPageData: List<SettingsPage> = emptyList(), ) { - // Maintains all SPA page providers. - private val allPages: Map<String, SettingsPageProvider> = allPagesList.associateBy { it.name } + // Map of page name to its provider. + private val pageProviderMap: Map<String, SettingsPageProvider> = + 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<SettingsPage> { + return rootPageData + } + fun getAllProviders(): Collection<SettingsPageProvider> { - 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 000000000000..834a52e737a3 --- /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<NamedNavArgument>.navRoute(): String { + return this.joinToString("") { argument -> "/{${argument.name}}" } +} + +fun List<NamedNavArgument>.navLink(arguments: Bundle? = null): String { + if (arguments == null) return "" + val argsArray = mutableListOf<String>() + 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<NamedNavArgument>.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<NamedNavArgument>.getStringArg(name: String, arguments: Bundle? = null): String? { + if (this.containsStringArg(name) && arguments != null) { + return arguments.getString(name) + } + return null +} + +fun List<NamedNavArgument>.getIntArg(name: String, arguments: Bundle? = null): Int? { + if (this.containsIntArg(name) && arguments != null && arguments.containsKey(name)) { + return arguments.getInt(name) + } + return null +} + +fun List<NamedNavArgument>.containsStringArg(name: String): Boolean { + for (navArg in this) { + if (navArg.argument.type == NavType.StringType && navArg.name == name) return true + } + return false +} + +fun List<NamedNavArgument>.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 eb9ce5e77c93..828249872559 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 f2eb96277b9b..ca6ba84185ec 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)) } |