diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index 1f57611f38..626afab24d 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -201,7 +201,7 @@ + android:theme="@style/Theme.Acknowledgements" /> false false + + diff --git a/lawnchair/res/values/themes.xml b/lawnchair/res/values/themes.xml index a0ed6e7c99..ba40a1f23c 100644 --- a/lawnchair/res/values/themes.xml +++ b/lawnchair/res/values/themes.xml @@ -13,4 +13,16 @@ ?android:attr/colorBackground true - \ No newline at end of file + + + + + diff --git a/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt index 3f7f3053dc..5e03f60556 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt @@ -19,14 +19,26 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import androidx.navigation.NavGraphBuilder +import app.lawnchair.ui.preferences.components.PreferenceGroup +import app.lawnchair.ui.preferences.components.PreferenceLayout +import app.lawnchair.ui.preferences.components.SliderPreference +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 +@ExperimentalAnimationApi +fun NavGraphBuilder.appDrawerGraph(route: String) { + preferenceGraph(route, { AppDrawerPreferences() }) +} + @ExperimentalAnimationApi @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..793dc5b4a5 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt @@ -19,13 +19,25 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import androidx.navigation.NavGraphBuilder +import app.lawnchair.ui.preferences.components.PreferenceGroup +import app.lawnchair.ui.preferences.components.PreferenceLayout +import app.lawnchair.ui.preferences.components.SliderPreference +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 +@ExperimentalAnimationApi +fun NavGraphBuilder.dockGraph(route: String) { + preferenceGraph(route, { DockPreferences() }) +} + @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..0a105346ff 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt @@ -19,13 +19,25 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import androidx.navigation.NavGraphBuilder +import app.lawnchair.ui.preferences.components.PreferenceGroup +import app.lawnchair.ui.preferences.components.PreferenceLayout +import app.lawnchair.ui.preferences.components.SliderPreference +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 +@ExperimentalAnimationApi +fun NavGraphBuilder.folderGraph(route: String) { + preferenceGraph(route, { FolderPreferences() }) +} + @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..0025851987 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt @@ -20,14 +20,34 @@ import android.os.Build import androidx.compose.animation.* import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import app.lawnchair.ui.preferences.components.NavigationActionPreference +import app.lawnchair.ui.preferences.components.NotificationDotsPreference +import app.lawnchair.ui.preferences.components.PreferenceGroup +import app.lawnchair.ui.preferences.components.PreferenceLayout +import app.lawnchair.ui.preferences.components.SliderPreference +import app.lawnchair.ui.preferences.components.SwitchPreference +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.* import com.android.launcher3.R +object GeneralRoutes { + const val ICON_PACK = "iconPack" +} + +@ExperimentalAnimationApi +fun NavGraphBuilder.generalGraph(route: String) { + preferenceGraph(route, { GeneralPreferences() }) { subRoute -> + iconPackGraph(route = subRoute(GeneralRoutes.ICON_PACK)) + } +} + @ExperimentalAnimationApi @Composable -fun GeneralPreferences(navController: NavController, interactor: PreferenceInteractor) { +fun GeneralPreferences() { val prefs = preferenceManager() + pageMeta.provide(Meta(title = stringResource(id = R.string.general_label))) PreferenceLayout { PreferenceGroup(isFirstChild = true) { SwitchPreference( @@ -35,11 +55,10 @@ fun GeneralPreferences(navController: NavController, interactor: PreferenceInter label = stringResource(id = R.string.home_screen_rotation_label), description = stringResource(id = R.string.home_screen_rotaton_description) ) - NotificationDotsPreference(interactor) + NotificationDotsPreference() NavigationActionPreference( label = stringResource(id = R.string.icon_pack), - navController = navController, - destination = Routes.ICON_PACK, + destination = subRoute(name = GeneralRoutes.ICON_PACK), showDivider = false ) } diff --git a/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt index 3596b71c57..df4a733e52 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/HomeScreenPreferences.kt @@ -19,14 +19,27 @@ package app.lawnchair.ui.preferences import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import androidx.navigation.NavGraphBuilder +import app.lawnchair.ui.preferences.components.PreferenceGroup +import app.lawnchair.ui.preferences.components.PreferenceLayout +import app.lawnchair.ui.preferences.components.SliderPreference +import app.lawnchair.ui.preferences.components.SwitchPreference +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 +@ExperimentalAnimationApi +fun NavGraphBuilder.homeScreenGraph(route: String) { + preferenceGraph(route, { HomeScreenPreferences() }) +} + @ExperimentalAnimationApi @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..161ec13617 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/IconPackPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/IconPackPreferences.kt @@ -25,25 +25,40 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment 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 androidx.navigation.NavGraphBuilder +import app.lawnchair.ui.preferences.components.PreferenceGroup +import app.lawnchair.ui.preferences.components.PreferenceLayout +import app.lawnchair.ui.preferences.components.PreferenceTemplate +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 data class IconPackInfo(val name: String, val packageName: String, val icon: Drawable) +@ExperimentalAnimationApi +fun NavGraphBuilder.iconPackGraph(route: String) { + preferenceGraph(route, { IconPackPreferences() }) +} + @ExperimentalAnimationApi @Composable -fun IconPackPreferences(interactor: PreferenceInteractor) { - val iconPacks = interactor.getIconPacks().values.toList() +fun IconPackPreferences() { + val interactor = LocalPreferenceInteractor.current + val iconPacks = remember { interactor.getIconPacks() } 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/PreferenceInteractor.kt b/lawnchair/src/app/lawnchair/ui/preferences/PreferenceInteractor.kt index 8d173fecbd..4706c3cf60 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/PreferenceInteractor.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/PreferenceInteractor.kt @@ -21,5 +21,5 @@ import androidx.compose.runtime.State interface PreferenceInteractor { val notificationDotsEnabled: State - fun getIconPacks(): MutableMap + fun getIconPacks(): List } diff --git a/lawnchair/src/app/lawnchair/ui/preferences/PreferenceViewModel.kt b/lawnchair/src/app/lawnchair/ui/preferences/PreferenceViewModel.kt index e979e10b87..f09130e0f6 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/PreferenceViewModel.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/PreferenceViewModel.kt @@ -40,7 +40,7 @@ class PreferenceViewModel(application: Application) : AndroidViewModel(applicati override val notificationDotsEnabled: MutableState = mutableStateOf(enabledNotificationListeners?.contains(lawnchairNotificationListener.flattenToString()) == true) - override fun getIconPacks(): MutableMap { + override fun getIconPacks(): List { val pm = getApplication().packageManager val iconPacks: MutableMap = HashMap() val list: MutableList = pm.queryIntentActivities(Intent("com.novalauncher.THEME"), 0) @@ -51,9 +51,6 @@ class PreferenceViewModel(application: Application) : AndroidViewModel(applicati pm.queryIntentActivities(Intent("android.intent.action.MAIN").addCategory("com.anddoes.launcher.THEME"), 0) ) - iconPacks["system"] = - IconPackInfo("System Icons", "", AppCompatResources.getDrawable(getApplication(), R.drawable.ic_launcher_home)!!) - for (info in list) { iconPacks[info.activityInfo.packageName] = IconPackInfo( info.loadLabel(pm).toString(), @@ -62,6 +59,17 @@ class PreferenceViewModel(application: Application) : AndroidViewModel(applicati ) } - return iconPacks + val iconPackList = iconPacks.values.toMutableList() + iconPackList.sortBy { it.name } + iconPackList.add( + 0, + IconPackInfo( + "System Icons", + "", + AppCompatResources.getDrawable(getApplication(), R.drawable.ic_launcher_home)!! + ) + ) + + return iconPackList } } diff --git a/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt index 6021eb092a..ae8f7ede37 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/Preferences.kt @@ -25,11 +25,22 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.compositionLocalOf import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import app.lawnchair.ui.preferences.about.About +import app.lawnchair.ui.preferences.about.aboutGraph +import app.lawnchair.ui.preferences.components.PreferenceCategoryList +import app.lawnchair.ui.preferences.components.SystemUi +import app.lawnchair.ui.preferences.components.TopBar +import app.lawnchair.util.Meta +import app.lawnchair.util.pageMeta import app.lawnchair.util.preferences.getMajorVersion import com.android.launcher3.R @@ -41,21 +52,8 @@ object Routes { const val DOCK: String = "dock" const val APP_DRAWER: String = "appDrawer" const val FOLDERS: String = "folders" - 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 +61,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 @@ -114,6 +112,14 @@ fun getPreferenceCategories(context: Context) = listOf( PreferenceCategory.About(context) ) +val LocalNavController = compositionLocalOf { + error("CompositionLocal LocalNavController not present") +} + +val LocalPreferenceInteractor = compositionLocalOf { + error("CompositionLocal LocalPreferenceInteractor not present") +} + @ExperimentalAnimationApi @Composable fun Preferences(interactor: PreferenceInteractor = viewModel(), window: Window) { @@ -125,20 +131,22 @@ 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/ui/preferences/preferenceGraph.kt b/lawnchair/src/app/lawnchair/ui/preferences/preferenceGraph.kt new file mode 100644 index 0000000000..7e46287641 --- /dev/null +++ b/lawnchair/src/app/lawnchair/ui/preferences/preferenceGraph.kt @@ -0,0 +1,38 @@ +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 +import androidx.navigation.compose.navigation + +inline fun NavGraphBuilder.preferenceGraph( + route: String, + crossinline root: @Composable () -> Unit, + crossinline block: NavGraphBuilder.(subRoute: (String) -> String) -> Unit = { } +) { + val subRoute: (String) -> String = { name -> "$route/$name" } + val rootRoute = subRoute("root") + navigation(startDestination = rootRoute, route) { + composable(route = rootRoute) { + CompositionLocalProvider(LocalRoute provides route) { + root() + } + } + block(subRoute) + } +} + +inline fun NavGraphBuilder.root(crossinline content: @Composable () -> Unit) { + composable(route = "") { + content() + } +} + +val LocalRoute = compositionLocalOf { "" } + +@Composable +fun subRoute(name: String): String { + return "${LocalRoute.current}/$name" +} 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)) +} diff --git a/lawnchair/src/app/lawnchair/util/preferences/BasePreferenceManager.kt b/lawnchair/src/app/lawnchair/util/preferences/BasePreferenceManager.kt index 2852fdd156..cb101eba1f 100644 --- a/lawnchair/src/app/lawnchair/util/preferences/BasePreferenceManager.kt +++ b/lawnchair/src/app/lawnchair/util/preferences/BasePreferenceManager.kt @@ -2,8 +2,6 @@ package app.lawnchair.util.preferences import android.content.Context import android.content.SharedPreferences -import android.util.Log -import androidx.compose.runtime.currentComposer import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.Utilities import java.lang.ClassCastException @@ -26,16 +24,23 @@ abstract class BasePreferenceManager(context: Context) : SharedPreferences.OnSha } interface PreferenceChangeListener { - fun onPreferenceChange(pref: BasePref<*>) + fun onPreferenceChange(pref: PrefEntry<*>) } - abstract inner class BasePref(val key: String, private val primaryListener: ChangeListener?) { + interface PrefEntry { + val defaultValue: T + + fun get(): T + fun set(newValue: T) + + fun addListener(listener: PreferenceChangeListener) + fun removeListener(listener: PreferenceChangeListener) + } + + abstract inner class BasePref(val key: String, private val primaryListener: ChangeListener?) : PrefEntry { protected var loaded = false private val listeners = WeakHashMap() - abstract fun get(): T - abstract fun set(newValue: T) - fun onSharedPreferenceChange() { loaded = false primaryListener?.invoke() @@ -44,18 +49,18 @@ abstract class BasePreferenceManager(context: Context) : SharedPreferences.OnSha } } - fun addListener(listener: PreferenceChangeListener) { + override fun addListener(listener: PreferenceChangeListener) { listeners[listener] = true } - fun removeListener(listener: PreferenceChangeListener) { + override fun removeListener(listener: PreferenceChangeListener) { listeners.remove(listener) } } inner class StringPref( key: String, - private val defaultValue: String, + override val defaultValue: String, primaryListener: ChangeListener? = null ) : BasePref(key, primaryListener) { private var currentValue = "" @@ -80,7 +85,7 @@ abstract class BasePreferenceManager(context: Context) : SharedPreferences.OnSha inner class BoolPref( key: String, - private val defaultValue: Boolean, + override val defaultValue: Boolean, primaryListener: ChangeListener? = null ) : BasePref(key, primaryListener) { private var currentValue = false @@ -105,9 +110,10 @@ abstract class BasePreferenceManager(context: Context) : SharedPreferences.OnSha open inner class IntPref( key: String, - private val defaultValue: Int, + private val defaultValueInternal: Int, primaryListener: ChangeListener? = null ) : BasePref(key, primaryListener) { + override val defaultValue = defaultValueInternal private var currentValue = 0 init { @@ -117,9 +123,9 @@ abstract class BasePreferenceManager(context: Context) : SharedPreferences.OnSha override fun get(): Int { if (!loaded) { currentValue = try { - sp.getInt(key, defaultValue) + sp.getInt(key, defaultValueInternal) } catch (e: ClassCastException) { - sp.getFloat(key, defaultValue.toFloat()).toInt() + sp.getFloat(key, defaultValueInternal.toFloat()).toInt() } loaded = true } @@ -134,30 +140,45 @@ abstract class BasePreferenceManager(context: Context) : SharedPreferences.OnSha inner class IdpIntPref( key: String, - private val defaultValue: InvariantDeviceProfile.() -> Int, + private val selectDefaultValue: InvariantDeviceProfile.() -> Int, primaryListener: ChangeListener? = null ) : IntPref(key, -1, primaryListener) { + override val defaultValue: Int + get() = error("unsupported") + + override fun get(): Int { + error("unsupported") + } + + override fun set(newValue: Int) { + error("unsupported") + } + + fun defaultValue(idp: InvariantDeviceProfile): Int { + return selectDefaultValue(idp) + } + fun get(idp: InvariantDeviceProfile): Int { - val value = get() + val value = super.get() return if (value == -1) { - defaultValue(idp) + selectDefaultValue(idp) } else { value } } fun set(newValue: Int, idp: InvariantDeviceProfile) { - if (newValue == defaultValue(idp)) { - set(-1) + if (newValue == selectDefaultValue(idp)) { + super.set(-1) } else { - set(newValue) + super.set(newValue) } } } inner class FloatPref( key: String, - private val defaultValue: Float, + override val defaultValue: Float, primaryListener: ChangeListener? = null ) : BasePref(key, primaryListener) { private var currentValue = 0f diff --git a/lawnchair/src/app/lawnchair/util/preferences/PreferenceAdapter.kt b/lawnchair/src/app/lawnchair/util/preferences/PreferenceAdapter.kt index 18a079f303..e4f1de9fe2 100644 --- a/lawnchair/src/app/lawnchair/util/preferences/PreferenceAdapter.kt +++ b/lawnchair/src/app/lawnchair/util/preferences/PreferenceAdapter.kt @@ -16,7 +16,7 @@ class PreferenceAdapter( state.value = newValue } - override fun onPreferenceChange(pref: BasePreferenceManager.BasePref<*>) { + override fun onPreferenceChange(pref: BasePreferenceManager.PrefEntry<*>) { state.value = get() } } @@ -29,18 +29,18 @@ fun BasePreferenceManager.IdpIntPref.getAdapter(): PreferenceAdapter { } @Composable -fun BasePreferenceManager.BasePref.getAdapter(): PreferenceAdapter { +fun BasePreferenceManager.PrefEntry.getAdapter(): PreferenceAdapter { return getAdapter(this, ::get, ::set) } @Composable -fun BasePreferenceManager.BasePref.observeAsState(): State { +fun BasePreferenceManager.PrefEntry.observeAsState(): State { return getAdapter().state } @Composable private fun getAdapter( - pref: BasePreferenceManager.BasePref<*>, + pref: BasePreferenceManager.PrefEntry<*>, get: () -> T, set: (T) -> Unit ): PreferenceAdapter {