Flatten Navigation hiearchy (#4233)

* Simplify code of Preferences.kt

* Flatten navigation hierarchy

To make implementation of TwoPaneNav, this commit flattens the navigation hierarchy.

* Reorganize a bit

* Use nested NavGraphs for sub-destinations

Also add a dummy preference for TwoPane preparation

* Change highlight logic to use .contains()

* spotlessApply
This commit is contained in:
SuperDragonXD
2024-04-06 17:23:10 +08:00
committed by GitHub
parent 695eec1b12
commit 5b244bcddd
41 changed files with 354 additions and 499 deletions
@@ -38,7 +38,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder
import app.lawnchair.backup.LawnchairBackup
import app.lawnchair.preferences.PreferenceManager
import app.lawnchair.ui.preferences.LocalNavController
@@ -47,7 +46,6 @@ import app.lawnchair.ui.preferences.components.WallpaperPreview
import app.lawnchair.ui.preferences.components.controls.FlagSwitchPreference
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.util.BackHandler
import app.lawnchair.util.checkAndRequestFilesPermission
import app.lawnchair.util.filesAndStorageGranted
@@ -58,11 +56,6 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import kotlinx.coroutines.launch
fun NavGraphBuilder.createBackupGraph(route: String) {
preferenceGraph(route, { CreateBackupScreen(viewModel()) })
}
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun CreateBackupScreen(
@@ -49,7 +49,6 @@ import app.lawnchair.ui.preferences.components.DummyLauncherBox
import app.lawnchair.ui.preferences.components.controls.FlagSwitchPreference
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.util.BackHandler
import app.lawnchair.util.hasFlag
import app.lawnchair.util.restartLauncher
@@ -58,26 +57,24 @@ import java.util.Base64
import kotlinx.coroutines.launch
fun NavGraphBuilder.restoreBackupGraph(route: String) {
preferenceGraph(route, {}) { subRoute ->
composable(
route = subRoute("{base64Uri}"),
arguments = listOf(
navArgument("base64Uri") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val backupUri = remember {
val base64Uri = args.getString("base64Uri")!!
val backupUriString = String(Base64.getDecoder().decode(base64Uri))
Uri.parse(backupUriString)
}
val viewModel: RestoreBackupViewModel = viewModel()
DisposableEffect(key1 = null) {
viewModel.init(backupUri)
onDispose { }
}
RestoreBackupScreen()
composable(
route = "$route/{base64Uri}",
arguments = listOf(
navArgument("base64Uri") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val backupUri = remember {
val base64Uri = args.getString("base64Uri")!!
val backupUriString = String(Base64.getDecoder().decode(base64Uri))
Uri.parse(backupUriString)
}
val viewModel: RestoreBackupViewModel = viewModel()
DisposableEffect(key1 = null) {
viewModel.init(backupUri)
onDispose { }
}
RestoreBackupScreen()
}
}
@@ -224,7 +221,7 @@ fun restoreBackupOpener(): () -> Unit {
val uri = it.data?.data ?: return@rememberLauncherForActivityResult
val base64Uri = Base64.getEncoder().encodeToString(uri.toString().toByteArray())
navController.navigate("/${Routes.RESTORE_BACKUP}/$base64Uri/")
navController.navigate("${Routes.RESTORE_BACKUP}/$base64Uri")
}
return {
@@ -35,7 +35,7 @@ sealed class GestureHandlerOption(
GestureHandlerConfig.OpenApp::class.java,
) {
override suspend fun buildConfig(activity: Activity): GestureHandlerConfig? {
val intent = PreferenceActivity.createIntent(activity, "/${Routes.PICK_APP_FOR_GESTURE}/")
val intent = PreferenceActivity.createIntent(activity, "${Routes.PICK_APP_FOR_GESTURE}")
val result = BlankActivity.startBlankActivityForResult(activity, intent)
val configString = result.data?.getStringExtra("config") ?: return null
return kotlinxJson.decodeFromString(configString)
@@ -2,6 +2,7 @@ package app.lawnchair.override
import android.app.Activity
import android.graphics.drawable.Drawable
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
@@ -125,8 +126,10 @@ fun CustomizeAppDialog(
onClose()
}
Log.d("TEST", "${Routes.SELECT_ICON}/$componentKey")
val openIconPicker = {
val destination = "/${Routes.SELECT_ICON}/$componentKey/"
val destination = "${Routes.SELECT_ICON}/$componentKey/"
request.launch(PreferenceActivity.createIntent(context, destination))
}
@@ -143,6 +143,7 @@ class LawnchairAppSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm(c
}
searchTargets.add(generateSearchTarget.getHeaderTarget(SPACE))
searchTargets.add(generateSearchTarget.getStartPageSearchItem(query))
generateSearchTarget.getMarketSearchItem(query)?.let { searchTargets.add(it) }
@@ -9,7 +9,7 @@ class SmartspacePreferencesShortcut : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(PreferenceActivity.createIntent(this, "/${Routes.SMARTSPACE_WIDGET}/"))
startActivity(PreferenceActivity.createIntent(this, "${Routes.SMARTSPACE_WIDGET}"))
finish()
}
}
@@ -52,7 +52,7 @@ class SmartspaceViewContainer @JvmOverloads constructor(
R.drawable.ic_setting,
StatsLogManager.LauncherEvent.IGNORE,
) {
context.startActivity(PreferenceActivity.createIntent(context, "/${Routes.SMARTSPACE}/"))
context.startActivity(PreferenceActivity.createIntent(context, "${Routes.SMARTSPACE}"))
true
}
@@ -124,7 +124,7 @@ class SmartspacerView(context: Context, attrs: AttributeSet?) : BcSmartspaceView
R.drawable.ic_setting,
StatsLogManager.LauncherEvent.IGNORE,
) {
context.startActivity(PreferenceActivity.createIntent(context, "/${Routes.SMARTSPACE}/"))
context.startActivity(PreferenceActivity.createIntent(context, "${Routes.SMARTSPACE}"))
true
}
}
@@ -65,7 +65,7 @@ class NowPlayingProvider(context: Context) : SmartspaceDataSource(
notificationDotsEnabled(context = context).first().not()
override suspend fun startSetup(activity: Activity) {
val intent = PreferenceActivity.createIntent(activity, "/${Routes.GENERAL}/")
val intent = PreferenceActivity.createIntent(activity, "${Routes.GENERAL}")
val message = activity.getString(
R.string.event_provider_missing_notification_dots,
activity.getString(providerName),
@@ -47,7 +47,7 @@ class SmartspaceProvider private constructor(context: Context) {
headerAction = SmartspaceAction(
id = "smartspaceSetupAction",
title = context.getString(R.string.smartspace_requires_setup),
intent = PreferenceActivity.createIntent(context, "/${Routes.SMARTSPACE}/"),
intent = PreferenceActivity.createIntent(context, "${Routes.SMARTSPACE}"),
),
score = 999f,
featureType = SmartspaceTarget.FeatureType.FEATURE_TIPS,
@@ -1,26 +0,0 @@
package app.lawnchair.ui.preferences
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
inline fun NavGraphBuilder.preferenceGraph(
route: String,
crossinline root: @Composable () -> Unit,
crossinline block: NavGraphBuilder.(subRoute: (String) -> String) -> Unit = { },
) {
val subRoute: (String) -> String = { name -> "$route$name/" }
composable(route = route) {
CompositionLocalProvider(LocalRoute provides route) {
root()
}
}
block(subRoute)
}
val LocalRoute = compositionLocalOf { "" }
@Composable
fun subRoute(name: String) = "${LocalRoute.current}$name/"
@@ -24,35 +24,59 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.LayoutDirection
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import app.lawnchair.backup.ui.createBackupGraph
import androidx.navigation.navArgument
import androidx.navigation.navigation
import app.lawnchair.backup.ui.CreateBackupScreen
import app.lawnchair.backup.ui.restoreBackupGraph
import app.lawnchair.ui.preferences.about.aboutGraph
import app.lawnchair.ui.preferences.components.colorpreference.colorSelectionGraph
import app.lawnchair.preferences.BasePreferenceManager
import app.lawnchair.preferences.preferenceManager
import app.lawnchair.ui.preferences.about.About
import app.lawnchair.ui.preferences.about.AboutRoutes
import app.lawnchair.ui.preferences.about.acknowledgements.Acknowledgements
import app.lawnchair.ui.preferences.components.colorpreference.ColorPreferenceModelList
import app.lawnchair.ui.preferences.components.colorpreference.ColorSelection
import app.lawnchair.ui.preferences.destinations.AppDrawerPreferences
import app.lawnchair.ui.preferences.destinations.AppDrawerRoutes
import app.lawnchair.ui.preferences.destinations.CustomIconShapePreference
import app.lawnchair.ui.preferences.destinations.DebugMenuPreferences
import app.lawnchair.ui.preferences.destinations.DockPreferences
import app.lawnchair.ui.preferences.destinations.DockRoutes
import app.lawnchair.ui.preferences.destinations.DummyPreference
import app.lawnchair.ui.preferences.destinations.ExperimentalFeaturesPreferences
import app.lawnchair.ui.preferences.destinations.FolderPreferences
import app.lawnchair.ui.preferences.destinations.FontSelection
import app.lawnchair.ui.preferences.destinations.GeneralPreferences
import app.lawnchair.ui.preferences.destinations.GeneralRoutes
import app.lawnchair.ui.preferences.destinations.GesturePreferences
import app.lawnchair.ui.preferences.destinations.HiddenAppsPreferences
import app.lawnchair.ui.preferences.destinations.HomeScreenGridPreferences
import app.lawnchair.ui.preferences.destinations.HomeScreenPreferences
import app.lawnchair.ui.preferences.destinations.HomeScreenRoutes
import app.lawnchair.ui.preferences.destinations.IconPackPreferences
import app.lawnchair.ui.preferences.destinations.IconPickerPreference
import app.lawnchair.ui.preferences.destinations.IconShapePreference
import app.lawnchair.ui.preferences.destinations.IconShapeRoutes
import app.lawnchair.ui.preferences.destinations.PickAppForGesture
import app.lawnchair.ui.preferences.destinations.PreferencesDashboard
import app.lawnchair.ui.preferences.destinations.appDrawerGraph
import app.lawnchair.ui.preferences.destinations.debugMenuGraph
import app.lawnchair.ui.preferences.destinations.dockGraph
import app.lawnchair.ui.preferences.destinations.experimentalFeaturesGraph
import app.lawnchair.ui.preferences.destinations.folderGraph
import app.lawnchair.ui.preferences.destinations.fontSelectionGraph
import app.lawnchair.ui.preferences.destinations.generalGraph
import app.lawnchair.ui.preferences.destinations.gesturesGraph
import app.lawnchair.ui.preferences.destinations.homeScreenGraph
import app.lawnchair.ui.preferences.destinations.iconPickerGraph
import app.lawnchair.ui.preferences.destinations.pickAppForGestureGraph
import app.lawnchair.ui.preferences.destinations.quickstepGraph
import app.lawnchair.ui.preferences.destinations.searchGraph
import app.lawnchair.ui.preferences.destinations.selectIconGraph
import app.lawnchair.ui.preferences.destinations.smartspaceGraph
import app.lawnchair.ui.preferences.destinations.smartspaceWidgetGraph
import app.lawnchair.ui.preferences.destinations.QuickstepPreferences
import app.lawnchair.ui.preferences.destinations.SearchPreferences
import app.lawnchair.ui.preferences.destinations.SearchProviderPreferences
import app.lawnchair.ui.preferences.destinations.SelectIconPreference
import app.lawnchair.ui.preferences.destinations.SmartspacePreferences
import app.lawnchair.ui.util.ProvideBottomSheetHandler
import app.lawnchair.util.ProvideLifecycleState
import com.android.launcher3.util.ComponentKey
import soup.compose.material.motion.animation.materialSharedAxisXIn
import soup.compose.material.motion.animation.materialSharedAxisXOut
import soup.compose.material.motion.animation.rememberSlideDistance
@@ -88,6 +112,8 @@ val LocalPreferenceInteractor = staticCompositionLocalOf<PreferenceInteractor> {
error("CompositionLocal LocalPreferenceInteractor not present")
}
val LocalIsExpandedScreen = compositionLocalOf { false }
@Composable
fun Preferences(
windowSizeClass: WindowSizeClass,
@@ -97,65 +123,156 @@ fun Preferences(
val navController = rememberNavController()
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
val slideDistance = rememberSlideDistance()
val isExpandedScreen = windowSizeClass.widthSizeClass == WindowWidthSizeClass.Expanded
Providers(isExpandedScreen) {
Providers {
Surface(
modifier = modifier,
) {
CompositionLocalProvider(
LocalNavController provides navController,
LocalPreferenceInteractor provides interactor,
LocalIsExpandedScreen provides isExpandedScreen,
) {
NavHost(
navController = navController,
startDestination = "/",
enterTransition = { materialSharedAxisXIn(!isRtl, slideDistance) },
exitTransition = { materialSharedAxisXOut(!isRtl, slideDistance) },
popEnterTransition = { materialSharedAxisXIn(isRtl, slideDistance) },
popExitTransition = { materialSharedAxisXOut(isRtl, slideDistance) },
) {
preferenceGraph(route = "/", { PreferencesDashboard() }) { subRoute ->
generalGraph(route = subRoute(Routes.GENERAL))
homeScreenGraph(route = subRoute(Routes.HOME_SCREEN))
dockGraph(route = subRoute(Routes.DOCK))
appDrawerGraph(route = subRoute(Routes.APP_DRAWER))
folderGraph(route = subRoute(Routes.FOLDERS))
quickstepGraph(route = subRoute(Routes.QUICKSTEP))
aboutGraph(route = subRoute(Routes.ABOUT))
fontSelectionGraph(route = subRoute(Routes.FONT_SELECTION))
colorSelectionGraph(route = subRoute(Routes.COLOR_SELECTION))
debugMenuGraph(route = subRoute(Routes.DEBUG_MENU))
selectIconGraph(route = subRoute(Routes.SELECT_ICON))
iconPickerGraph(route = subRoute(Routes.ICON_PICKER))
experimentalFeaturesGraph(route = subRoute(Routes.EXPERIMENTAL_FEATURES))
smartspaceGraph(route = subRoute(Routes.SMARTSPACE))
smartspaceWidgetGraph(route = subRoute(Routes.SMARTSPACE_WIDGET))
createBackupGraph(route = subRoute(Routes.CREATE_BACKUP))
restoreBackupGraph(route = subRoute(Routes.RESTORE_BACKUP))
pickAppForGestureGraph(route = subRoute(Routes.PICK_APP_FOR_GESTURE))
gesturesGraph(route = subRoute(Routes.GESTURES))
searchGraph(route = subRoute(Routes.SEARCH))
}
}
InnerNavigation(navController, isRtl, slideDistance)
}
}
}
}
@Composable
private fun Providers(
isExpandedScreen: Boolean = false,
content: @Composable () -> Unit,
private fun InnerNavigation(
navController: NavHostController,
isRtl: Boolean,
slideDistance: Int,
) {
CompositionLocalProvider(LocalIsExpandedScreen provides isExpandedScreen) {
ProvideLifecycleState {
ProvideBottomSheetHandler {
content()
}
NavHost(
navController = navController,
startDestination = "/",
enterTransition = { materialSharedAxisXIn(!isRtl, slideDistance) },
exitTransition = { materialSharedAxisXOut(!isRtl, slideDistance) },
popEnterTransition = { materialSharedAxisXIn(isRtl, slideDistance) },
popExitTransition = { materialSharedAxisXOut(isRtl, slideDistance) },
) {
composable(route = "/") {
PreferencesDashboard(
currentRoute = navController.currentDestination?.route ?: "/",
onNavigate = {
navController.navigate(it)
},
)
}
composable(route = "dummy") {
DummyPreference()
}
navigation(route = Routes.GENERAL, startDestination = "main") {
composable(route = "main") {
GeneralPreferences()
}
composable(route = GeneralRoutes.ICON_PACK) { IconPackPreferences() }
composable(route = GeneralRoutes.ICON_SHAPE) { IconShapePreference() }
composable(route = IconShapeRoutes.CUSTOM_ICON_SHAPE_CREATOR) { CustomIconShapePreference() }
}
navigation(route = Routes.HOME_SCREEN, startDestination = "main") {
composable(route = "main") { HomeScreenPreferences() }
composable(route = HomeScreenRoutes.GRID) { HomeScreenGridPreferences() }
}
navigation(route = Routes.DOCK, startDestination = "main") {
composable(route = "main") { DockPreferences() }
composable(route = DockRoutes.SEARCH_PROVIDER) { SearchProviderPreferences() }
}
composable(route = Routes.SMARTSPACE) { SmartspacePreferences(fromWidget = false) }
composable(route = Routes.SMARTSPACE_WIDGET) { SmartspacePreferences(fromWidget = true) }
navigation(route = Routes.APP_DRAWER, startDestination = "main") {
composable(route = "main") { AppDrawerPreferences() }
composable(route = AppDrawerRoutes.HIDDEN_APPS) { HiddenAppsPreferences() }
}
composable(route = Routes.SEARCH) { SearchPreferences() }
composable(route = Routes.FOLDERS) { FolderPreferences() }
composable(route = Routes.GESTURES) { GesturePreferences() }
composable(route = Routes.PICK_APP_FOR_GESTURE) { PickAppForGesture() }
composable(route = Routes.QUICKSTEP) { QuickstepPreferences() }
composable(route = Routes.ABOUT) { About() }
composable(route = AboutRoutes.LICENSES) { Acknowledgements() }
composable(
route = "${Routes.FONT_SELECTION}/{prefKey}",
arguments = listOf(
navArgument("prefKey") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val prefKey = args.getString("prefKey")!!
val pref = preferenceManager().prefsMap[prefKey]
as? BasePreferenceManager.FontPref ?: return@composable
FontSelection(pref)
}
composable(route = Routes.DEBUG_MENU) { DebugMenuPreferences() }
composable(
route = "${Routes.SELECT_ICON}/{packageName}/{nameAndUser}/",
arguments = listOf(
navArgument("packageName") { type = NavType.StringType },
navArgument("nameAndUser") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val packageName = args.getString("packageName")
val nameAndUser = args.getString("nameAndUser")
val key = ComponentKey.fromString("$packageName/$nameAndUser")!!
SelectIconPreference(key)
}
composable(route = Routes.ICON_PICKER) { IconPickerPreference(packageName = "") }
composable(
route = "${Routes.ICON_PICKER}/{packageName}",
arguments = listOf(
navArgument("packageName") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val packageName = args.getString("packageName")!!
IconPickerPreference(packageName)
}
composable(route = Routes.EXPERIMENTAL_FEATURES) { ExperimentalFeaturesPreferences() }
composable(
route = "${Routes.COLOR_SELECTION}/{prefKey}",
arguments = listOf(
navArgument("prefKey") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val prefKey = args.getString("prefKey")!!
val modelList = ColorPreferenceModelList.INSTANCE.get(LocalContext.current)
val model = modelList[prefKey]
ColorSelection(
label = stringResource(id = model.labelRes),
preference = model.prefObject,
dynamicEntries = model.dynamicEntries,
)
}
composable(route = Routes.CREATE_BACKUP) { CreateBackupScreen(viewModel()) }
restoreBackupGraph(route = Routes.RESTORE_BACKUP)
}
}
val LocalIsExpandedScreen = compositionLocalOf { false }
@Composable
private fun Providers(
content: @Composable () -> Unit,
) {
ProvideLifecycleState {
ProvideBottomSheetHandler {
content()
}
}
}
@@ -43,14 +43,10 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.navigation.NavGraphBuilder
import app.lawnchair.ui.preferences.about.acknowledgements.licensesGraph
import app.lawnchair.ui.preferences.components.NavigationActionPreference
import app.lawnchair.ui.preferences.components.controls.ClickablePreference
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import com.android.launcher3.BuildConfig
import com.android.launcher3.R
@@ -209,12 +205,6 @@ object AboutRoutes {
const val LICENSES = "licenses"
}
fun NavGraphBuilder.aboutGraph(route: String) {
preferenceGraph(route, { About() }) { subRoute ->
licensesGraph(route = subRoute(AboutRoutes.LICENSES))
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun About(
@@ -294,7 +284,7 @@ fun About(
PreferenceGroup {
NavigationActionPreference(
label = stringResource(id = R.string.acknowledgements),
destination = subRoute(name = AboutRoutes.LICENSES),
destination = AboutRoutes.LICENSES,
)
ClickablePreference(
label = stringResource(id = R.string.translate),
@@ -19,6 +19,7 @@ package app.lawnchair.ui.preferences.about.acknowledgements
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
@@ -36,32 +37,15 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.ui.preferences.LocalNavController
import app.lawnchair.ui.ModalBottomSheetContent
import app.lawnchair.ui.preferences.LocalPreferenceInteractor
import app.lawnchair.ui.preferences.components.layout.LoadingScreen
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.components.layout.PreferenceLayoutLazyColumn
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
import app.lawnchair.ui.preferences.components.layout.preferenceGroupItems
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import app.lawnchair.ui.util.bottomSheetHandler
import com.android.launcher3.R
fun NavGraphBuilder.licensesGraph(route: String) {
preferenceGraph(route, { Acknowledgements() }) { subRoute ->
composable(
route = subRoute("{licenseIndex}"),
arguments = listOf(navArgument("licenseIndex") { type = NavType.IntType }),
) { backStackEntry ->
NoticePage(index = backStackEntry.arguments!!.getInt("licenseIndex"))
}
}
}
@Composable
fun Acknowledgements(
modifier: Modifier = Modifier,
@@ -90,8 +74,7 @@ fun OssLibraryItem(
index: Int,
modifier: Modifier = Modifier,
) {
val navController = LocalNavController.current
val destination = subRoute(name = "$index")
val bottomSheetHandler = bottomSheetHandler
PreferenceTemplate(
title = {
@@ -102,53 +85,60 @@ fun OssLibraryItem(
)
},
modifier = modifier
.clickable { navController.navigate(route = destination) },
.clickable {
bottomSheetHandler.show {
NoticePage(ossLibrary = ossLibrary)
}
},
)
}
@Composable
fun NoticePage(
index: Int,
ossLibrary: OssLibrary?,
modifier: Modifier = Modifier,
) {
val ossLibraries by LocalPreferenceInteractor.current.ossLibraries.collectAsState()
val ossLibrary = ossLibraries.getOrNull(index)
val dataState = ossLibrary?.let { loadNotice(ossLibrary = it) }
val data = dataState?.value
PreferenceLayout(
label = ossLibrary?.name ?: stringResource(id = R.string.loading),
ModalBottomSheetContent(
title = {
Text(text = ossLibrary?.name ?: stringResource(id = R.string.loading))
},
buttons = {},
modifier = modifier,
) {
Crossfade(targetState = data, label = "") { it ->
it ?: return@Crossfade
val uriHandler = LocalUriHandler.current
val layoutResult = remember { mutableStateOf<TextLayoutResult?>(null) }
val pressIndicator = Modifier.pointerInput(Unit) {
detectTapGestures { pos ->
layoutResult.value?.let { layoutResult ->
val position = layoutResult.getOffsetForPosition(pos)
val annotation =
it.notice.getStringAnnotations(position, position).firstOrNull()
if (annotation?.tag == "URL") {
uriHandler.openUri(annotation.item)
Column {
Crossfade(targetState = data, label = "") { it ->
it ?: return@Crossfade
val uriHandler = LocalUriHandler.current
val layoutResult = remember { mutableStateOf<TextLayoutResult?>(null) }
val pressIndicator = Modifier.pointerInput(Unit) {
detectTapGestures { pos ->
layoutResult.value?.let { layoutResult ->
val position = layoutResult.getOffsetForPosition(pos)
val annotation =
it.notice.getStringAnnotations(position, position).firstOrNull()
if (annotation?.tag == "URL") {
uriHandler.openUri(annotation.item)
}
}
}
}
}
Text(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 16.dp)
.then(pressIndicator),
text = it.notice,
fontFamily = FontFamily.Monospace,
fontSize = 14.sp,
onTextLayout = {
layoutResult.value = it
},
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 16.dp)
.then(pressIndicator),
text = it.notice,
fontFamily = FontFamily.Monospace,
fontSize = 14.sp,
onTextLayout = {
layoutResult.value = it
},
)
}
}
}
}
@@ -27,6 +27,6 @@ fun FontPreference(
)
},
modifier = modifier
.clickable { navController.navigate(route = "/fontSelection/${fontPref.key}/") },
.clickable { navController.navigate(route = "fontSelection/${fontPref.key}") },
)
}
@@ -53,6 +53,6 @@ fun ColorPreference(
description = {
Text(text = adapter.state.value.colorPreferenceEntry.label())
},
modifier = modifier.clickable { navController.navigate(route = "/colorSelection/${model.prefObject.key.name}/") },
modifier = modifier.clickable { navController.navigate(route = "colorSelection/${model.prefObject.key.name}") },
)
}
@@ -22,10 +22,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.preferences.getAdapter
import app.lawnchair.theme.color.ColorOption
import app.lawnchair.ui.preferences.components.colorpreference.pickers.CustomColorPicker
@@ -34,34 +30,11 @@ import app.lawnchair.ui.preferences.components.colorpreference.pickers.SwatchGri
import app.lawnchair.ui.preferences.components.layout.BottomSpacer
import app.lawnchair.ui.preferences.components.layout.Chip
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.R
import com.patrykmichalik.opto.domain.Preference
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.launch
fun NavGraphBuilder.colorSelectionGraph(route: String) {
preferenceGraph(route, {}) { subRoute ->
composable(
route = subRoute("{prefKey}"),
arguments = listOf(
navArgument("prefKey") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val prefKey = args.getString("prefKey")!!
val modelList = ColorPreferenceModelList.INSTANCE.get(LocalContext.current)
val model = modelList[prefKey]
ColorSelection(
label = stringResource(id = model.labelRes),
preference = model.prefObject,
dynamicEntries = model.dynamicEntries,
)
}
}
}
@Composable
fun ColorSelection(
label: String,
@@ -17,10 +17,10 @@
package app.lawnchair.ui.preferences.components.controls
import androidx.annotation.DrawableRes
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
@@ -32,78 +32,63 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import app.lawnchair.ui.preferences.LocalNavController
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
import app.lawnchair.ui.preferences.subRoute
import app.lawnchair.ui.theme.LawnchairTheme
import app.lawnchair.ui.util.PreviewLawnchair
import com.android.launcher3.R
@Composable
fun PreferenceCategory(
label: String,
@DrawableRes iconResource: Int,
route: String,
description: String? = null,
) {
val navController = LocalNavController.current
val resolvedRoute = subRoute(name = route)
PreferenceCategory(
label = label,
iconResource = iconResource,
onNavigate = { navController.navigate(resolvedRoute) },
description = description,
)
}
@Composable
private fun PreferenceCategory(
label: String,
@DrawableRes iconResource: Int,
onNavigate: () -> Unit,
modifier: Modifier = Modifier,
isSelected: Boolean = false,
description: String? = null,
) {
Row(
modifier = modifier.padding(horizontal = 16.dp),
) {
PreferenceTemplate(
modifier = Modifier
.clip(MaterialTheme.shapes.large)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(
bounded = true,
color = MaterialTheme.colorScheme.primaryContainer,
),
) { onNavigate() },
verticalPadding = 14.dp,
title = {
Text(text = label)
},
description = {
if (description != null) {
Text(text = description)
}
},
startWidget = {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.size(32.dp),
) {
Icon(
painter = painterResource(id = iconResource),
contentDescription = null,
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.primary,
)
}
},
)
}
PreferenceTemplate(
modifier = modifier
.padding(horizontal = 16.dp)
.clip(MaterialTheme.shapes.large)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(
bounded = true,
color = MaterialTheme.colorScheme.primaryContainer,
),
) { onNavigate() }
.background(
if (isSelected) MaterialTheme.colorScheme.surfaceVariant else Color.Transparent,
),
verticalPadding = 14.dp,
title = {
Text(
text = label,
color = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onBackground,
)
},
description = {
if (description != null) {
Text(text = description)
}
},
startWidget = {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.size(32.dp),
) {
Icon(
painter = painterResource(id = iconResource),
contentDescription = null,
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.primary,
)
}
},
)
}
@PreviewLawnchair
@@ -20,7 +20,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.not
import app.lawnchair.preferences.preferenceManager
@@ -32,20 +31,12 @@ import app.lawnchair.ui.preferences.components.controls.SwitchPreference
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import com.android.launcher3.R
object AppDrawerRoutes {
const val HIDDEN_APPS = "hiddenApps"
}
fun NavGraphBuilder.appDrawerGraph(route: String) {
preferenceGraph(route, { AppDrawerPreferences() }) { subRoute ->
hiddenAppsGraph(route = subRoute(AppDrawerRoutes.HIDDEN_APPS))
}
}
@Composable
fun AppDrawerPreferences(
modifier: Modifier = Modifier,
@@ -88,7 +79,7 @@ fun AppDrawerPreferences(
NavigationActionPreference(
label = stringResource(id = R.string.hidden_apps_label),
subtitle = resources.getQuantityString(R.plurals.apps_count, hiddenApps.size, hiddenApps.size),
destination = subRoute(name = AppDrawerRoutes.HIDDEN_APPS),
destination = AppDrawerRoutes.HIDDEN_APPS,
)
}
PreferenceGroup(heading = stringResource(id = R.string.grid)) {
@@ -38,13 +38,11 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavGraphBuilder
import app.lawnchair.icons.shape.IconCornerShape
import app.lawnchair.icons.shape.IconShape
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences2.preferenceManager2
import app.lawnchair.ui.ModalBottomSheetContent
import app.lawnchair.ui.preferences.components.IconShapePreview
import app.lawnchair.ui.preferences.components.controls.getSteps
import app.lawnchair.ui.preferences.components.controls.snapSliderValue
import app.lawnchair.ui.preferences.components.layout.BottomSpacer
@@ -52,19 +50,14 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceDivider
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.util.LocalBottomSheetHandler
import app.lawnchair.util.copyToClipboard
import app.lawnchair.util.getClipboardContent
import com.android.launcher3.R
import kotlin.math.roundToInt
fun NavGraphBuilder.customIconShapePreferenceGraph(route: String) {
preferenceGraph(route, { CustomIconShapePreference() })
}
@Composable
private fun CustomIconShapePreference(
fun CustomIconShapePreference(
modifier: Modifier = Modifier,
) {
val preferenceManager2 = preferenceManager2()
@@ -6,7 +6,6 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.datastore.preferences.core.Preferences
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.PreferenceManager
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
@@ -18,15 +17,10 @@ import app.lawnchair.ui.preferences.components.controls.SwitchPreference
import app.lawnchair.ui.preferences.components.controls.TextPreference
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.settings.SettingsActivity
import com.android.launcher3.uioverrides.flags.DeveloperOptionsFragment
import com.patrykmichalik.opto.domain.Preference
fun NavGraphBuilder.debugMenuGraph(route: String) {
preferenceGraph(route, { DebugMenuPreferences() })
}
/**
* A screen to house unfinished preferences and debug flags
*/
@@ -21,7 +21,6 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.hotseat.HotseatMode
import app.lawnchair.hotseat.LawnchairHotseat
import app.lawnchair.preferences.PreferenceAdapter
@@ -39,8 +38,6 @@ import app.lawnchair.ui.preferences.components.layout.DividerColumn
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import com.android.launcher3.R
import kotlinx.collections.immutable.toPersistentList
@@ -48,12 +45,6 @@ object DockRoutes {
const val SEARCH_PROVIDER = "searchProvider"
}
fun NavGraphBuilder.dockGraph(route: String) {
preferenceGraph(route, { DockPreferences() }) { subRoute ->
searchProviderGraph(subRoute(DockRoutes.SEARCH_PROVIDER))
}
}
@Composable
fun DockPreferences(
modifier: Modifier = Modifier,
@@ -87,7 +78,7 @@ fun DockPreferences(
val hotseatQsbProviderAdapter by preferenceManager2().hotseatQsbProvider.getAdapter()
NavigationActionPreference(
label = stringResource(R.string.search_provider),
destination = subRoute(DockRoutes.SEARCH_PROVIDER),
destination = DockRoutes.SEARCH_PROVIDER,
subtitle = stringResource(
id = QsbSearchProvider.values()
.first { it == hotseatQsbProviderAdapter }
@@ -0,0 +1,22 @@
package app.lawnchair.ui.preferences.destinations
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
@Composable
fun DummyPreference(
modifier: Modifier = Modifier,
) {
PreferenceLayout(
label = "",
backArrowVisible = false,
modifier = modifier,
) {
PreferenceTemplate(title = {
Text("Tap a preference in the left hand menu")
})
}
}
@@ -3,20 +3,14 @@ package app.lawnchair.ui.preferences.destinations
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
import app.lawnchair.preferences2.preferenceManager2
import app.lawnchair.ui.preferences.components.controls.SwitchPreference
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.R
fun NavGraphBuilder.experimentalFeaturesGraph(route: String) {
preferenceGraph(route, { ExperimentalFeaturesPreferences() })
}
@Composable
fun ExperimentalFeaturesPreferences(
modifier: Modifier = Modifier,
@@ -19,7 +19,6 @@ package app.lawnchair.ui.preferences.destinations
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
import app.lawnchair.preferences2.preferenceManager2
@@ -29,13 +28,8 @@ import app.lawnchair.ui.preferences.components.controls.SwitchPreference
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.R
fun NavGraphBuilder.folderGraph(route: String) {
preferenceGraph(route, { FolderPreferences() })
}
@Composable
fun FolderPreferences(
modifier: Modifier = Modifier,
@@ -42,16 +42,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.font.FontCache
import app.lawnchair.font.googlefonts.GoogleFontsListing
import app.lawnchair.preferences.BasePreferenceManager
import app.lawnchair.preferences.PreferenceAdapter
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
import app.lawnchair.ui.AndroidText
import app.lawnchair.ui.OverflowMenu
import app.lawnchair.ui.preferences.components.layout.PreferenceDivider
@@ -60,26 +55,8 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceLazyColumn
import app.lawnchair.ui.preferences.components.layout.PreferenceSearchScaffold
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
import app.lawnchair.ui.preferences.components.layout.preferenceGroupItems
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.R
fun NavGraphBuilder.fontSelectionGraph(route: String) {
preferenceGraph(route, {}) { subRoute ->
composable(
route = subRoute("{prefKey}"),
arguments = listOf(
navArgument("prefKey") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val prefKey = args.getString("prefKey")!!
val pref = preferenceManager().prefsMap[prefKey]
as? BasePreferenceManager.FontPref ?: return@composable
FontSelection(pref)
}
}
}
private enum class ContentType {
ADD_BUTTON,
FONT,
@@ -23,7 +23,6 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
import app.lawnchair.preferences2.asState
@@ -31,7 +30,6 @@ import app.lawnchair.preferences2.preferenceManager2
import app.lawnchair.theme.color.ColorOption
import app.lawnchair.ui.preferences.LocalPreferenceInteractor
import app.lawnchair.ui.preferences.components.FontPreference
import app.lawnchair.ui.preferences.components.IconShapePreview
import app.lawnchair.ui.preferences.components.NavigationActionPreference
import app.lawnchair.ui.preferences.components.NotificationDotsPreference
import app.lawnchair.ui.preferences.components.ThemePreference
@@ -40,16 +38,12 @@ import app.lawnchair.ui.preferences.components.colorpreference.ColorPreference
import app.lawnchair.ui.preferences.components.controls.SliderPreference
import app.lawnchair.ui.preferences.components.controls.SwitchPreference
import app.lawnchair.ui.preferences.components.controls.WarningPreference
import app.lawnchair.ui.preferences.components.iconShapeEntries
import app.lawnchair.ui.preferences.components.iconShapeGraph
import app.lawnchair.ui.preferences.components.layout.DividerColumn
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.components.notificationDotsEnabled
import app.lawnchair.ui.preferences.components.notificationServiceEnabled
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import com.android.launcher3.R
object GeneralRoutes {
@@ -57,13 +51,6 @@ object GeneralRoutes {
const val ICON_SHAPE = "iconShape"
}
fun NavGraphBuilder.generalGraph(route: String) {
preferenceGraph(route, { GeneralPreferences() }) { subRoute ->
iconPackGraph(route = subRoute(GeneralRoutes.ICON_PACK))
iconShapeGraph(route = subRoute(GeneralRoutes.ICON_SHAPE))
}
}
@Composable
fun GeneralPreferences() {
val context = LocalContext.current
@@ -136,7 +123,7 @@ fun GeneralPreferences() {
) {
NavigationActionPreference(
label = stringResource(id = R.string.icon_style),
destination = subRoute(name = GeneralRoutes.ICON_PACK),
destination = GeneralRoutes.ICON_PACK,
subtitle = iconStyleSubtitle,
)
ExpandAndShrink(visible = themedIconsEnabled) {
@@ -148,7 +135,7 @@ fun GeneralPreferences() {
}
NavigationActionPreference(
label = stringResource(id = R.string.icon_shape_label),
destination = subRoute(name = GeneralRoutes.ICON_SHAPE),
destination = GeneralRoutes.ICON_SHAPE,
subtitle = iconShapeSubtitle,
endWidget = {
IconShapePreview(iconShape = iconShapeAdapter.state.value)
@@ -3,19 +3,13 @@ package app.lawnchair.ui.preferences.destinations
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences2.preferenceManager2
import app.lawnchair.ui.preferences.components.GestureHandlerPreference
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.R
fun NavGraphBuilder.gesturesGraph(route: String) {
preferenceGraph(route, { GesturePreferences() })
}
@Composable
fun GesturePreferences(
modifier: Modifier = Modifier,
@@ -27,7 +27,6 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences2.preferenceManager2
import app.lawnchair.ui.preferences.LocalIsExpandedScreen
@@ -36,7 +35,6 @@ import app.lawnchair.ui.preferences.components.AppItemPlaceholder
import app.lawnchair.ui.preferences.components.layout.PreferenceLazyColumn
import app.lawnchair.ui.preferences.components.layout.PreferenceScaffold
import app.lawnchair.ui.preferences.components.layout.preferenceGroupItems
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.util.App
import app.lawnchair.util.appComparator
import app.lawnchair.util.appsState
@@ -45,10 +43,6 @@ import java.util.Comparator.comparing
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.toPersistentSet
fun NavGraphBuilder.hiddenAppsGraph(route: String) {
preferenceGraph(route, { HiddenAppsPreferences() })
}
@Composable
fun HiddenAppsPreferences(
modifier: Modifier = Modifier,
@@ -19,7 +19,6 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.asPreferenceAdapter
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
@@ -28,14 +27,9 @@ import app.lawnchair.ui.preferences.components.GridOverridesPreview
import app.lawnchair.ui.preferences.components.controls.SliderPreference
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.LauncherAppState
import com.android.launcher3.R
fun NavGraphBuilder.homeScreenGridGraph(route: String) {
preferenceGraph(route, { HomeScreenGridPreferences() })
}
@Composable
fun HomeScreenGridPreferences(
modifier: Modifier = Modifier,
@@ -23,7 +23,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.data.iconoverride.IconOverrideRepository
import app.lawnchair.nexuslauncher.OverlayCallbackImpl
import app.lawnchair.preferences.getAdapter
@@ -41,8 +40,6 @@ import app.lawnchair.ui.preferences.components.layout.DividerColumn
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import app.lawnchair.util.collectAsStateBlocking
import com.android.launcher3.R
import com.android.launcher3.Utilities
@@ -52,12 +49,6 @@ object HomeScreenRoutes {
const val GRID = "grid"
}
fun NavGraphBuilder.homeScreenGraph(route: String) {
preferenceGraph(route, { HomeScreenPreferences() }) { subRoute ->
homeScreenGridGraph(route = subRoute(HomeScreenRoutes.GRID))
}
}
@Composable
fun HomeScreenPreferences(
modifier: Modifier = Modifier,
@@ -120,7 +111,7 @@ fun HomeScreenPreferences(
val rows by prefs.workspaceRows.getAdapter()
NavigationActionPreference(
label = stringResource(id = R.string.home_screen_grid),
destination = subRoute(name = HomeScreenRoutes.GRID),
destination = HomeScreenRoutes.GRID,
subtitle = stringResource(id = R.string.x_by_y, columns, rows),
)
DividerColumn {
@@ -51,7 +51,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.PreferenceAdapter
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
@@ -66,7 +65,6 @@ import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.NestedScrollStretch
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.util.Constants
import app.lawnchair.util.getThemedIconPacksInstalled
import app.lawnchair.util.isPackageInstalled
@@ -103,10 +101,6 @@ enum class ThemedIconsState(
}
}
fun NavGraphBuilder.iconPackGraph(route: String) {
preferenceGraph(route, { IconPackPreferences() })
}
@Composable
fun IconPackPreferences(
modifier: Modifier = Modifier,
@@ -34,10 +34,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.icons.CustomIconPack
import app.lawnchair.icons.IconPack
import app.lawnchair.icons.IconPackProvider
@@ -48,7 +44,6 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceGroupDescription
import app.lawnchair.ui.preferences.components.layout.PreferenceLazyColumn
import app.lawnchair.ui.preferences.components.layout.PreferenceSearchScaffold
import app.lawnchair.ui.preferences.components.layout.verticalGridItems
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.util.LazyGridLayout
import app.lawnchair.ui.util.resultSender
import app.lawnchair.util.requireSystemService
@@ -58,23 +53,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
fun NavGraphBuilder.iconPickerGraph(route: String) {
preferenceGraph(route, {
IconPickerPreference(packageName = "")
}) { subRoute ->
composable(
route = subRoute("{packageName}"),
arguments = listOf(
navArgument("packageName") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val packageName = args.getString("packageName")!!
IconPickerPreference(packageName)
}
}
}
@Composable
fun IconPickerPreference(
packageName: String,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package app.lawnchair.ui.preferences.components
package app.lawnchair.ui.preferences.destinations
import android.content.Context
import androidx.compose.foundation.Canvas
@@ -47,7 +47,6 @@ import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import app.lawnchair.icons.shape.IconShape
import app.lawnchair.icons.shape.IconShapeManager
import app.lawnchair.preferences.PreferenceAdapter
@@ -59,21 +58,12 @@ import app.lawnchair.ui.preferences.components.controls.ListPreferenceEntry
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
import app.lawnchair.ui.preferences.destinations.customIconShapePreferenceGraph
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import com.android.launcher3.R
object IconShapeRoutes {
const val CUSTOM_ICON_SHAPE_CREATOR = "customIconShapeCreator"
}
fun NavGraphBuilder.iconShapeGraph(route: String) {
preferenceGraph(route, { IconShapePreference() }) { subRoute ->
customIconShapePreferenceGraph(subRoute(IconShapeRoutes.CUSTOM_ICON_SHAPE_CREATOR))
}
}
/**
* @return The list of all [IconShape]s each wrapped inside a [ListPreferenceEntry].
*/
@@ -114,7 +104,7 @@ fun IconShapePreference(
PreferenceGroup(
heading = stringResource(id = R.string.custom),
) {
CustomIconShapePreference(
CustomIconShapePreferenceOption(
iconShapeAdapter = iconShapeAdapter,
)
ModifyCustomIconShapePreference(
@@ -148,7 +138,7 @@ fun IconShapePreference(
}
@Composable
private fun CustomIconShapePreference(
private fun CustomIconShapePreferenceOption(
iconShapeAdapter: PreferenceAdapter<IconShape>,
modifier: Modifier = Modifier,
) {
@@ -182,7 +172,7 @@ private fun ModifyCustomIconShapePreference(
modifier: Modifier = Modifier,
) {
val navController = LocalNavController.current
val route = subRoute(IconShapeRoutes.CUSTOM_ICON_SHAPE_CREATOR)
val route = IconShapeRoutes.CUSTOM_ICON_SHAPE_CREATOR
val created = customIconShape != null
@@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.gestures.config.GestureHandlerConfig
import app.lawnchair.gestures.handlers.OpenAppTarget
import app.lawnchair.ui.preferences.LocalIsExpandedScreen
@@ -17,17 +16,12 @@ import app.lawnchair.ui.preferences.components.AppItemPlaceholder
import app.lawnchair.ui.preferences.components.layout.PreferenceLazyColumn
import app.lawnchair.ui.preferences.components.layout.PreferenceScaffold
import app.lawnchair.ui.preferences.components.layout.preferenceGroupItems
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.util.App
import app.lawnchair.util.appsState
import app.lawnchair.util.kotlinxJson
import com.android.launcher3.R
import kotlinx.serialization.encodeToString
fun NavGraphBuilder.pickAppForGestureGraph(route: String) {
preferenceGraph(route, { PickAppForGesture() })
}
@Composable
fun PickAppForGesture() {
val apps by appsState()
@@ -43,7 +43,6 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceDivider
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
import app.lawnchair.ui.preferences.data.liveinfo.SyncLiveInformation
import app.lawnchair.ui.preferences.subRoute
import app.lawnchair.util.isDefaultLauncher
import app.lawnchair.util.restartLauncher
import com.android.launcher3.BuildConfig
@@ -51,6 +50,8 @@ import com.android.launcher3.R
@Composable
fun PreferencesDashboard(
currentRoute: String,
onNavigate: (String) -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
@@ -76,56 +77,64 @@ fun PreferencesDashboard(
label = stringResource(R.string.general_label),
description = stringResource(R.string.general_description),
iconResource = R.drawable.ic_general,
route = Routes.GENERAL,
onNavigate = { onNavigate(Routes.GENERAL) },
isSelected = currentRoute.contains(Routes.GENERAL),
)
PreferenceCategory(
label = stringResource(R.string.home_screen_label),
description = stringResource(R.string.home_screen_description),
iconResource = R.drawable.ic_home_screen,
route = Routes.HOME_SCREEN,
onNavigate = { onNavigate(Routes.HOME_SCREEN) },
isSelected = currentRoute.contains(Routes.HOME_SCREEN),
)
PreferenceCategory(
label = stringResource(id = R.string.smartspace_widget),
description = stringResource(R.string.smartspace_widget_description),
iconResource = R.drawable.ic_smartspace,
route = Routes.SMARTSPACE,
onNavigate = { onNavigate(Routes.SMARTSPACE) },
isSelected = currentRoute.contains(Routes.SMARTSPACE),
)
PreferenceCategory(
label = stringResource(R.string.dock_label),
description = stringResource(R.string.dock_description),
iconResource = R.drawable.ic_dock,
route = Routes.DOCK,
onNavigate = { onNavigate(Routes.DOCK) },
isSelected = currentRoute.contains(Routes.DOCK),
)
PreferenceCategory(
label = stringResource(R.string.app_drawer_label),
description = stringResource(R.string.app_drawer_description),
iconResource = R.drawable.ic_app_drawer,
route = Routes.APP_DRAWER,
onNavigate = { onNavigate(Routes.APP_DRAWER) },
isSelected = currentRoute.contains(Routes.APP_DRAWER),
)
PreferenceCategory(
label = stringResource(R.string.drawer_search_label),
description = stringResource(R.string.drawer_search_description),
iconResource = R.drawable.ic_search,
route = Routes.SEARCH,
onNavigate = { onNavigate(Routes.SEARCH) },
isSelected = currentRoute.contains(Routes.SEARCH),
)
PreferenceCategory(
label = stringResource(R.string.folders_label),
description = stringResource(R.string.folders_description),
iconResource = R.drawable.ic_folder,
route = Routes.FOLDERS,
onNavigate = { onNavigate(Routes.FOLDERS) },
isSelected = currentRoute.contains(Routes.FOLDERS),
)
PreferenceCategory(
label = stringResource(id = R.string.gestures_label),
description = stringResource(R.string.gestures_description),
iconResource = R.drawable.ic_gestures,
route = Routes.GESTURES,
onNavigate = { onNavigate(Routes.GESTURES) },
isSelected = currentRoute.contains(Routes.GESTURES),
)
if (LawnchairApp.isRecentsEnabled || BuildConfig.DEBUG) {
@@ -133,7 +142,8 @@ fun PreferencesDashboard(
label = stringResource(id = R.string.quickstep_label),
description = stringResource(id = R.string.quickstep_description),
iconResource = R.drawable.ic_quickstep,
route = Routes.QUICKSTEP,
onNavigate = { onNavigate(Routes.QUICKSTEP) },
isSelected = currentRoute.contains(Routes.QUICKSTEP),
)
}
@@ -141,7 +151,8 @@ fun PreferencesDashboard(
label = stringResource(R.string.about_label),
description = "${context.getString(R.string.derived_app_name)} ${BuildConfig.MAJOR_VERSION}",
iconResource = R.drawable.ic_about,
route = Routes.ABOUT,
onNavigate = { onNavigate(Routes.ABOUT) },
isSelected = currentRoute.contains(Routes.ABOUT),
)
}
}
@@ -152,9 +163,9 @@ fun PreferencesOverflowMenu(
) {
val navController = LocalNavController.current
val enableDebug by preferenceManager().enableDebugMenu.observeAsState()
val experimentalFeaturesRoute = subRoute(name = Routes.EXPERIMENTAL_FEATURES)
val experimentalFeaturesRoute = Routes.EXPERIMENTAL_FEATURES
if (enableDebug) {
val resolvedRoute = subRoute(name = Routes.DEBUG_MENU)
val resolvedRoute = Routes.DEBUG_MENU
ClickableIcon(
imageVector = Icons.Rounded.Build,
onClick = { navController.navigate(resolvedRoute) },
@@ -185,7 +196,7 @@ fun PreferencesOverflowMenu(
})
PreferenceDivider(modifier = Modifier.padding(vertical = 8.dp))
DropdownMenuItem(onClick = {
navController.navigate("/${Routes.CREATE_BACKUP}/")
navController.navigate(Routes.CREATE_BACKUP)
hideMenu()
}, text = {
Text(text = stringResource(id = R.string.create_backup))
@@ -10,7 +10,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import app.lawnchair.LawnchairApp
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.observeAsState
@@ -22,15 +21,10 @@ import app.lawnchair.ui.preferences.components.controls.WarningPreference
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.util.isOnePlusStock
import com.android.launcher3.R
import com.android.launcher3.Utilities
fun NavGraphBuilder.quickstepGraph(route: String) {
preferenceGraph(route, { QuickstepPreferences() })
}
@Composable
fun QuickstepPreferences(
modifier: Modifier = Modifier,
@@ -3,7 +3,6 @@ package app.lawnchair.ui.preferences.destinations
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.not
import app.lawnchair.preferences.preferenceManager
@@ -16,17 +15,12 @@ import app.lawnchair.ui.preferences.components.controls.SwitchPreference
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.util.checkAndRequestFilesPermission
import app.lawnchair.util.contactPermissionGranted
import app.lawnchair.util.filesAndStorageGranted
import app.lawnchair.util.requestContactPermissionGranted
import com.android.launcher3.R
fun NavGraphBuilder.searchGraph(route: String) {
preferenceGraph(route, { SearchPreferences() })
}
@Composable
fun SearchPreferences() {
val prefs = preferenceManager()
@@ -17,7 +17,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences2.preferenceManager2
import app.lawnchair.qsb.providers.QsbSearchProvider
@@ -30,14 +29,9 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceDivider
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.util.LocalBottomSheetHandler
import com.android.launcher3.R
fun NavGraphBuilder.searchProviderGraph(route: String) {
preferenceGraph(route, { SearchProviderPreferences() })
}
@Composable
fun SearchProviderPreferences(
modifier: Modifier = Modifier,
@@ -11,10 +11,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.core.graphics.drawable.toBitmap
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.data.iconoverride.IconOverrideRepository
import app.lawnchair.icons.IconPickerItem
import app.lawnchair.ui.preferences.LocalNavController
@@ -24,31 +20,12 @@ import app.lawnchair.ui.preferences.components.AppItem
import app.lawnchair.ui.preferences.components.controls.ClickablePreference
import app.lawnchair.ui.preferences.components.layout.PreferenceLayoutLazyColumn
import app.lawnchair.ui.preferences.components.layout.preferenceGroupItems
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.util.OnResult
import app.lawnchair.util.requireSystemService
import com.android.launcher3.R
import com.android.launcher3.util.ComponentKey
import kotlinx.coroutines.launch
fun NavGraphBuilder.selectIconGraph(route: String) {
preferenceGraph(route, { }) { subRoute ->
composable(
route = subRoute("{packageName}/{nameAndUser}"),
arguments = listOf(
navArgument("packageName") { type = NavType.StringType },
navArgument("nameAndUser") { type = NavType.StringType },
),
) { backStackEntry ->
val args = backStackEntry.arguments!!
val packageName = args.getString("packageName")
val nameAndUser = args.getString("nameAndUser")
val key = ComponentKey.fromString("$packageName/$nameAndUser")!!
SelectIconPreference(key)
}
}
}
@Composable
fun SelectIconPreference(componentKey: ComponentKey) {
val context = LocalContext.current
@@ -103,9 +80,9 @@ fun SelectIconPreference(componentKey: ComponentKey) {
icon = remember(iconPack) { iconPack.icon.toBitmap() },
onClick = {
if (iconPack.packageName.isEmpty()) {
navController.navigate("/${Routes.ICON_PICKER}/")
navController.navigate(Routes.ICON_PICKER)
} else {
navController.navigate("/${Routes.ICON_PICKER}/${iconPack.packageName}/")
navController.navigate("${Routes.ICON_PICKER}/${iconPack.packageName}")
}
},
)
@@ -25,7 +25,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.PreferenceAdapter
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences2.preferenceManager2
@@ -44,20 +43,11 @@ import app.lawnchair.ui.preferences.components.layout.DividerColumn
import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.theme.isSelectedThemeDark
import com.android.launcher3.R
import com.kieronquinn.app.smartspacer.sdk.SmartspacerConstants
import kotlinx.collections.immutable.toPersistentList
fun NavGraphBuilder.smartspaceGraph(route: String) {
preferenceGraph(route, { SmartspacePreferences(fromWidget = false) })
}
fun NavGraphBuilder.smartspaceWidgetGraph(route: String) {
preferenceGraph(route, { SmartspacePreferences(fromWidget = true) })
}
@Composable
fun SmartspacePreferences(
fromWidget: Boolean,