diff options
8 files changed, 104 insertions, 20 deletions
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GalleryDebugActivity.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GalleryDebugActivity.kt index 52bbf75e4ac2..317346d26f89 100644 --- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GalleryDebugActivity.kt +++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GalleryDebugActivity.kt @@ -18,4 +18,4 @@ package com.android.settingslib.spa.gallery import com.android.settingslib.spa.framework.DebugActivity -class GalleryDebugActivity : DebugActivity(SpaEnvironment.EntryRepository) +class GalleryDebugActivity : DebugActivity(SpaEnvironment.EntryRepository, MainActivity::class.java) 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 5fe17e5de34c..5cce21577e43 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 @@ -68,7 +68,10 @@ object ArgumentPageProvider : SettingsPageProvider { private fun buildInjectEntry(arguments: Bundle?): SettingsEntryBuilder? { if (!ArgumentPageModel.isValidArgument(arguments)) return null - return SettingsEntryBuilder.createInject(SettingsPage.create(name, parameter, arguments)) + return SettingsEntryBuilder.createInject( + entryName = ArgumentPageModel.getInjectEntryName(arguments), + owner = SettingsPage.create(name, parameter, arguments) + ) // Set attributes .setIsAllowSearch(false) .setUiLayoutFn { 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 index 8b94342cf082..e27bf6dc5b33 100644 --- 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 @@ -22,6 +22,7 @@ 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.BrowseActivity import com.android.settingslib.spa.framework.common.PageModel import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.compose.stateOf @@ -63,6 +64,10 @@ class ArgumentPageModel : PageModel() { return (stringParam != null && listOf("foo", "bar").contains(stringParam)) } + fun getInjectEntryName(arguments: Bundle?): String { + return "${name}_${parameter.getStringArg(STRING_PARAM_NAME, arguments)}" + } + @Composable fun create(arguments: Bundle?): ArgumentPageModel { val pageModel: ArgumentPageModel = viewModel(key = arguments.toString()) @@ -75,12 +80,14 @@ class ArgumentPageModel : PageModel() { private var arguments: Bundle? = null private var stringParam: String? = null private var intParam: Int? = null + private var highlightName: String? = 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) + highlightName = arguments?.getString(BrowseActivity.HIGHLIGHT_ENTRY_PARAM_NAME) } @Composable 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 87d4f5a936f8..ae15da66d68b 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 @@ -26,7 +26,9 @@ import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument import com.android.settingslib.spa.R +import com.android.settingslib.spa.framework.common.ROOT_PAGE_NAME import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository import com.android.settingslib.spa.framework.compose.localNavController import com.android.settingslib.spa.framework.theme.SettingsTheme @@ -48,22 +50,28 @@ open class BrowseActivity( @Composable private fun MainContent() { - val destination = intent?.getStringExtra(KEY_DESTINATION) + val destination = + intent?.getStringExtra(KEY_DESTINATION) ?: sppRepository.getDefaultStartPageName() val navController = rememberNavController() CompositionLocalProvider(navController.localNavController()) { - NavHost(navController, sppRepository.getDefaultStartPageName()) { + NavHost(navController, ROOT_PAGE_NAME) { + composable(ROOT_PAGE_NAME) {} for (page in sppRepository.getAllProviders()) { composable( - route = page.name + page.parameter.navRoute(), - arguments = page.parameter, + route = page.name + page.parameter.navRoute() + + "?$HIGHLIGHT_ENTRY_PARAM_NAME={$HIGHLIGHT_ENTRY_PARAM_NAME}", + arguments = page.parameter + listOf( + // add optional parameters + navArgument(HIGHLIGHT_ENTRY_PARAM_NAME) { defaultValue = "null" } + ), ) { navBackStackEntry -> page.Page(navBackStackEntry.arguments) } } } - if (!destination.isNullOrEmpty()) { + if (destination.isNotEmpty()) { LaunchedEffect(Unit) { navController.navigate(destination) { popUpTo(navController.graph.findStartDestination().id) { @@ -77,5 +85,6 @@ open class BrowseActivity( companion object { const val KEY_DESTINATION = "spa:SpaActivity:destination" + const val HIGHLIGHT_ENTRY_PARAM_NAME = "highlightEntry" } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt index d1ec7d0e6172..095e6833b613 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt @@ -16,20 +16,25 @@ package com.android.settingslib.spa.framework +import android.content.Intent import android.os.Bundle +import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.platform.LocalContext import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.android.settingslib.spa.R +import com.android.settingslib.spa.framework.BrowseActivity.Companion.KEY_DESTINATION import com.android.settingslib.spa.framework.common.SettingsEntry import com.android.settingslib.spa.framework.common.SettingsEntryRepository +import com.android.settingslib.spa.framework.common.SettingsPage import com.android.settingslib.spa.framework.compose.localNavController import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.compose.toState @@ -48,7 +53,8 @@ private const val PARAM_NAME_PAGE_ID = "pid" private const val PARAM_NAME_ENTRY_ID = "eid" open class DebugActivity( - private val entryRepository: SettingsEntryRepository + private val entryRepository: SettingsEntryRepository, + private val browseActivityClass: Class<*>, ) : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { setTheme(R.style.Theme_SpaLib_DayNight) @@ -87,7 +93,7 @@ open class DebugActivity( @Composable fun RootPage() { - HomeScaffold(title = "Entry Debug") { + HomeScaffold(title = "Settings Debug") { Preference(object : PreferenceModel { override val title = "List All Pages" override val onClick = navigator(route = ROUTE_All_PAGES) @@ -128,6 +134,10 @@ open class DebugActivity( RegularScaffold(title = "Page ${pageWithEntry.page.displayName}") { Text(text = pageWithEntry.page.formatArguments()) Text(text = "Entry size: ${pageWithEntry.entries.size}") + Preference(model = object : PreferenceModel { + override val title = "open page" + override val onClick = openPage(pageWithEntry.page) + }) EntryList(pageWithEntry.entries) } } @@ -137,7 +147,11 @@ open class DebugActivity( val id = arguments!!.getInt(PARAM_NAME_ENTRY_ID) val entry = entryRepository.getEntry(id)!! RegularScaffold(title = "Entry ${entry.displayName}") { - Text (text = entry.formatAll()) + Preference(model = object : PreferenceModel { + override val title = "open entry" + override val onClick = openEntry(entry) + }) + Text(text = entry.formatAll()) } } @@ -152,4 +166,30 @@ open class DebugActivity( }) } } + + @Composable + private fun openPage(page: SettingsPage): () -> Unit { + val route = page.buildRoute() + val context = LocalContext.current + val intent = Intent(context, browseActivityClass).apply { + putExtra(KEY_DESTINATION, route) + } + return { + Log.d("DEBUG ACTIVITY", "Open page: $route") + context.startActivity(intent) + } + } + + @Composable + private fun openEntry(entry: SettingsEntry): () -> Unit { + val route = entry.buildRoute() + val context = LocalContext.current + val intent = Intent(context, browseActivityClass).apply { + putExtra(KEY_DESTINATION, route) + } + return { + Log.d("DEBUG ACTIVITY", "Open entry: $route") + context.startActivity(intent) + } + } } 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 4452b819c168..86e75f3d018c 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,10 +19,13 @@ package com.android.settingslib.spa.framework.common import android.os.Bundle import androidx.compose.runtime.Composable import androidx.navigation.NamedNavArgument +import com.android.settingslib.spa.framework.BrowseActivity +import com.android.settingslib.spa.framework.util.navLink import com.android.settingslib.spa.framework.util.normalize const val INJECT_ENTRY_NAME = "INJECT" const val ROOT_ENTRY_NAME = "ROOT" +const val ROOT_PAGE_NAME = "Root" /** * Defines data of one Settings entry for Settings search. @@ -38,7 +41,7 @@ data class UiData(val title: String = "") * Defines data to identify a Settings page. */ data class SettingsPage( - // The unique id of this page, which is computed by name + arguments + // The unique id of this page, which is computed by name + normalized(arguments) val id: Int, // The name of the page, which is used to compute the unique id, and need to be stable. @@ -48,6 +51,9 @@ data class SettingsPage( // By default, it is the same as name. val displayName: String, + // Defined parameters of this page. + val parameter: List<NamedNavArgument> = emptyList(), + // The arguments of this page. val arguments: Bundle? = null, ) { @@ -62,13 +68,23 @@ data class SettingsPage( } fun formatArguments(): String { - if (arguments == null || arguments.isEmpty) return "[No arguments]" - return arguments.toString().removeRange(0, 6) + val normalizedArguments = parameter.normalize(arguments) + if (normalizedArguments == null || normalizedArguments.isEmpty) return "[No arguments]" + return normalizedArguments.toString().removeRange(0, 6) } fun formatAll(): String { return "$displayName ${formatArguments()}" } + + fun buildRoute(highlightEntryName: String? = null): String { + val highlightParam = + if (highlightEntryName == null) + "" + else + "?${BrowseActivity.HIGHLIGHT_ENTRY_PARAM_NAME}=$highlightEntryName" + return name + parameter.navLink(arguments) + highlightParam + } } /** @@ -133,6 +149,12 @@ data class SettingsEntry( ) return content.joinToString("\n") } + + fun buildRoute(): String { + // Open entry in its fromPage. + val page = fromPage ?: owner + return page.buildRoute(name) + } } data class SettingsPageWithEntry( @@ -153,7 +175,8 @@ class SettingsPageBuilder( id = "$name:${normArguments?.toString()}".toUniqueId(), name = name, displayName = displayName ?: name, - arguments = normArguments, + parameter = parameter, + arguments = arguments, ) } @@ -234,12 +257,14 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings return create(entryName, owner).setLink(toPage = owner) } - fun createInject(owner: SettingsPage): SettingsEntryBuilder { - return createLinkTo(INJECT_ENTRY_NAME, owner) + fun createInject(owner: SettingsPage, entryName: String? = null): SettingsEntryBuilder { + val name = entryName ?: "${INJECT_ENTRY_NAME}_${owner.name}" + return createLinkTo(name, owner) } - fun createRoot(page: SettingsPage): SettingsEntryBuilder { - return createLinkTo(ROOT_ENTRY_NAME, page) + fun createRoot(owner: SettingsPage, entryName: String? = null): SettingsEntryBuilder { + val name = entryName ?: "${ROOT_ENTRY_NAME}_${owner.name}" + return createLinkTo(name, owner) } } } 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 c5f72c5e7b3b..a4e5a58246ff 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 @@ -38,7 +38,7 @@ class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) { val entryQueue = LinkedList<SettingsEntry>() for (page in sppRepository.getAllRootPages()) { - val rootEntry = SettingsEntryBuilder.createRoot(page).build() + val rootEntry = SettingsEntryBuilder.createRoot(owner = page).build() if (!entryMap.containsKey(rootEntry.id)) { entryQueue.push(rootEntry) entryMap.put(rootEntry.id, rootEntry) 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 de8a65e9aec5..65cc4f9a165c 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 @@ -110,7 +110,7 @@ internal class TogglePermissionAppListPageProvider( internal fun buildInjectEntry(permissionType: String): SettingsEntryBuilder { val appListPage = SettingsPage.create( PAGE_NAME, PAGE_PARAMETER, bundleOf(PERMISSION to permissionType)) - return SettingsEntryBuilder.createInject(appListPage).setIsAllowSearch(false) + return SettingsEntryBuilder.createInject(owner = appListPage).setIsAllowSearch(false) } } } |