diff --git a/lawnchair/src/app/lawnchair/ui/preferences/About.kt b/lawnchair/src/app/lawnchair/ui/preferences/About.kt index 4fc59de936..9f597030b5 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/About.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/About.kt @@ -34,6 +34,8 @@ 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 app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getFormattedVersionName import com.android.launcher3.R import com.google.android.gms.oss.licenses.OssLicensesMenuActivity @@ -114,6 +116,7 @@ val teamMembers = listOf( fun About() { val context = LocalContext.current + pageMeta.provide(Meta(title = stringResource(id = R.string.about_label))) Column( modifier = Modifier .fillMaxWidth() diff --git a/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt index 3f7f3053dc..3ec5f1dd6f 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt @@ -19,6 +19,8 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getAdapter import app.lawnchair.util.preferences.preferenceManager import com.android.launcher3.R @@ -27,6 +29,7 @@ import com.android.launcher3.R @Composable fun AppDrawerPreferences() { val prefs = preferenceManager() + pageMeta.provide(Meta(title = stringResource(id = R.string.app_drawer_label))) PreferenceLayout { PreferenceGroup(heading = stringResource(id = R.string.general_label), isFirstChild = true) { SliderPreference( diff --git a/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt index d5a226eafc..0959e4ba69 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt @@ -19,6 +19,8 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getAdapter import app.lawnchair.util.preferences.preferenceManager import com.android.launcher3.R @@ -26,6 +28,7 @@ import com.android.launcher3.R @ExperimentalAnimationApi @Composable fun DockPreferences() { + pageMeta.provide(Meta(title = stringResource(id = R.string.dock_label))) PreferenceLayout { PreferenceGroup(heading = stringResource(id = R.string.grid), isFirstChild = true) { SliderPreference( diff --git a/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt index b75069f241..cb0052ce84 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt @@ -19,6 +19,8 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getAdapter import app.lawnchair.util.preferences.preferenceManager import com.android.launcher3.R @@ -26,6 +28,7 @@ import com.android.launcher3.R @ExperimentalAnimationApi @Composable fun FolderPreferences() { + pageMeta.provide(Meta(title = stringResource(id = R.string.folders_label))) PreferenceLayout { val prefs = preferenceManager() PreferenceGroup(heading = stringResource(id = R.string.grid), isFirstChild = true) { diff --git a/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt index 038b725d2e..4097fccb5a 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt @@ -21,6 +21,8 @@ import androidx.compose.animation.* import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.navigation.NavController +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.* import com.android.launcher3.R @@ -28,6 +30,7 @@ import com.android.launcher3.R @Composable fun GeneralPreferences(navController: NavController, interactor: PreferenceInteractor) { val prefs = preferenceManager() + pageMeta.provide(Meta(title = stringResource(id = R.string.general_label))) PreferenceLayout { PreferenceGroup(isFirstChild = true) { SwitchPreference( diff --git a/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt index 3596b71c57..c4c411f6c8 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt @@ -19,6 +19,8 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getAdapter import app.lawnchair.util.preferences.preferenceManager import com.android.launcher3.R @@ -27,6 +29,7 @@ import com.android.launcher3.R @Composable fun HomeScreenPreferences() { val prefs = preferenceManager() + pageMeta.provide(Meta(title = stringResource(id = R.string.home_screen_label))) PreferenceLayout { PreferenceGroup(heading = "General", isFirstChild = true) { SwitchPreference( diff --git a/lawnchair/src/app/lawnchair/ui/preferences/IconPackPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/IconPackPreferences.kt index 39ef44c567..83b2edbec5 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/IconPackPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/IconPackPreferences.kt @@ -30,8 +30,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.graphics.drawable.toBitmap +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getAdapter import app.lawnchair.util.preferences.preferenceManager import com.android.launcher3.R @@ -44,6 +47,7 @@ fun IconPackPreferences(interactor: PreferenceInteractor) { val iconPacks = interactor.getIconPacks().values.toList() val iconPackPackage = preferenceManager().iconPackPackage.getAdapter() + pageMeta.provide(Meta(title = stringResource(id = R.string.icon_pack))) PreferenceLayout { PreferenceGroup(isFirstChild = true) { // TODO: Use `LazyColumn` if possible. diff --git a/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt index 6021eb092a..8351d1441f 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt @@ -26,10 +26,13 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getMajorVersion import com.android.launcher3.R @@ -44,18 +47,6 @@ object Routes { const val ICON_PACK: String = "iconPack" } -fun getRoutesToLabels(context: Context) = - mapOf( - Routes.PREFERENCES to context.getString(R.string.settings), - Routes.GENERAL to context.getString(R.string.general_label), - Routes.ABOUT to context.getString(R.string.about_label), - Routes.HOME_SCREEN to context.getString(R.string.home_screen_label), - Routes.DOCK to context.getString(R.string.dock_label), - Routes.APP_DRAWER to context.getString(R.string.app_drawer_label), - Routes.FOLDERS to context.getString(R.string.folders_label), - Routes.ICON_PACK to context.getString(R.string.icon_pack) - ) - sealed class PreferenceCategory( val label: String, val description: String, @@ -63,42 +54,42 @@ sealed class PreferenceCategory( val route: String ) { class General(context: Context) : PreferenceCategory( - label = getRoutesToLabels(context)[Routes.GENERAL]!!, + label = context.getString(R.string.settings), description = context.getString(R.string.general_description), iconResource = R.drawable.ic_general, route = Routes.GENERAL ) class HomeScreen(context: Context) : PreferenceCategory( - label = getRoutesToLabels(context)[Routes.HOME_SCREEN]!!, + label = context.getString(R.string.home_screen_label), description = context.getString(R.string.home_screen_description), iconResource = R.drawable.ic_home_screen, route = Routes.HOME_SCREEN ) class Dock(context: Context) : PreferenceCategory( - label = getRoutesToLabels(context)[Routes.DOCK]!!, + label = context.getString(R.string.dock_label), description = context.getString(R.string.dock_description), iconResource = R.drawable.ic_dock, route = Routes.DOCK ) class AppDrawer(context: Context) : PreferenceCategory( - label = getRoutesToLabels(context)[Routes.APP_DRAWER]!!, + label = context.getString(R.string.app_drawer_label), description = context.getString(R.string.app_drawer_description), iconResource = R.drawable.ic_app_drawer, route = Routes.APP_DRAWER ) class Folders(context: Context) : PreferenceCategory( - label = getRoutesToLabels(context)[Routes.FOLDERS]!!, + label = context.getString(R.string.folders_label), description = context.getString(R.string.folders_description), iconResource = R.drawable.ic_folder, route = Routes.FOLDERS ) class About(context: Context) : PreferenceCategory( - label = getRoutesToLabels(context)[Routes.ABOUT]!!, + label = context.getString(R.string.about_label), description = "${context.getString(R.string.derived_app_name)} ${getMajorVersion(context)}", iconResource = R.drawable.ic_about, route = Routes.ABOUT @@ -127,7 +118,10 @@ fun Preferences(interactor: PreferenceInteractor = viewModel + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .height(56.dp) + .background(MaterialTheme.colors.background) + ) { + AnimatedVisibility(visible = currentRoute != Routes.PREFERENCES && currentRoute != null) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .padding(start = 8.dp) + .height(40.dp) + .width(40.dp) + .clip(CircleShape) + .clickable { navController.popBackStack() } + ) { + Image( + painter = painterResource(id = R.drawable.ic_arrow_back), + contentDescription = null, + colorFilter = ColorFilter.tint(MaterialTheme.colors.onBackground) + ) + } } + Text( + text = state.title, + style = MaterialTheme.typography.h6, + modifier = Modifier.padding(start = 16.dp), + color = MaterialTheme.colors.onSurface, + ) } - Text( - text = title ?: "", - style = MaterialTheme.typography.h6, - modifier = Modifier.padding(start = 16.dp), - color = MaterialTheme.colors.onSurface, - ) } } \ No newline at end of file diff --git a/lawnchair/src/app/lawnchair/util/createSideEffect.kt b/lawnchair/src/app/lawnchair/util/createSideEffect.kt new file mode 100644 index 0000000000..4854f97151 --- /dev/null +++ b/lawnchair/src/app/lawnchair/util/createSideEffect.kt @@ -0,0 +1,46 @@ +package app.lawnchair.util + +import androidx.compose.runtime.* + +class PropsContainer

(var props: P) + +class SideEffect( + val consume: @Composable (@Composable (S) -> Unit) -> Unit, + val provide: @Composable (P) -> Unit) + +inline fun createSideEffect(crossinline reducePropsToState: (List

) -> S): SideEffect { + val mountedInstances = mutableListOf>() + var currentState = reducePropsToState(emptyList()) + var onChangeHandler: (() -> Unit)? = null + + val emitChange = { + currentState = reducePropsToState(mountedInstances.map { it.props }) + onChangeHandler?.invoke() + } + + return SideEffect( + consume = @Composable { block -> + val localState = remember { mutableStateOf(currentState) } + DisposableEffect(null) { + onChangeHandler = { localState.value = currentState } + onDispose { onChangeHandler = null } + } + block(localState.value) + }, + provide = @Composable { props -> + val currentProps = remember { PropsContainer(props) } + DisposableEffect(key1 = currentProps) { + mountedInstances.add(currentProps) + onDispose { + mountedInstances.remove(currentProps) + emitChange() + } + } + DisposableEffect(key1 = props) { + currentProps.props = props + emitChange() + onDispose { } + } + } + ) +} diff --git a/lawnchair/src/app/lawnchair/util/pageMeta.kt b/lawnchair/src/app/lawnchair/util/pageMeta.kt new file mode 100644 index 0000000000..045f8be470 --- /dev/null +++ b/lawnchair/src/app/lawnchair/util/pageMeta.kt @@ -0,0 +1,12 @@ +package app.lawnchair.util + +class MetaState(val title: String) +class Meta(val title: String?) + +private fun getTitleFromPropsList(propsList: List): String { + return propsList.lastOrNull()?.title ?: "" +} + +val pageMeta = createSideEffect { propsList -> + MetaState(title = getTitleFromPropsList(propsList)) +}