Merge "Add SettingsEntryRepository with some refactoring"
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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. */
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 },
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user