Add preferences for layout
This commit is contained in:
parent
7cd1269c33
commit
64cc07bef9
@ -37,6 +37,8 @@ fun AssistantScaffold(
|
||||
modifier: Modifier = Modifier,
|
||||
darkStatusBarIcons: Boolean = false,
|
||||
darkNavBarIcons: Boolean = false,
|
||||
bottomSearchBar: Boolean = false,
|
||||
reverseSearchResults: Boolean = false,
|
||||
) {
|
||||
val viewModel: LauncherScaffoldVM = viewModel()
|
||||
|
||||
@ -54,15 +56,6 @@ fun AssistantScaffold(
|
||||
}
|
||||
}
|
||||
|
||||
val bottomSearchBar by remember {
|
||||
viewModel.dataStore.data.map { it.appearance.layout != Settings.AppearanceSettings.Layout.PullDown }
|
||||
}.collectAsState(null)
|
||||
|
||||
val reverseResults by remember {
|
||||
viewModel.dataStore.data.map { it.appearance.layout != Settings.AppearanceSettings.Layout.PullDown }
|
||||
}.collectAsState(null)
|
||||
|
||||
|
||||
val searchState = rememberLazyListState()
|
||||
|
||||
val isSearchAtStart by remember {
|
||||
@ -79,14 +72,11 @@ fun AssistantScaffold(
|
||||
}
|
||||
}
|
||||
|
||||
if (reverseResults == null || bottomSearchBar == null) return
|
||||
|
||||
|
||||
val searchBarLevel by remember {
|
||||
derivedStateOf {
|
||||
when {
|
||||
reverseResults == bottomSearchBar && isSearchAtStart -> SearchBarLevel.Active
|
||||
reverseResults != bottomSearchBar && isSearchAtEnd -> SearchBarLevel.Active
|
||||
reverseSearchResults == bottomSearchBar && isSearchAtStart -> SearchBarLevel.Active
|
||||
reverseSearchResults != bottomSearchBar && isSearchAtEnd -> SearchBarLevel.Active
|
||||
else -> SearchBarLevel.Raised
|
||||
}
|
||||
}
|
||||
@ -95,7 +85,7 @@ fun AssistantScaffold(
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val showStatusBarScrim by remember {
|
||||
derivedStateOf {
|
||||
if (reverseResults == true) {
|
||||
if (reverseSearchResults) {
|
||||
!isSearchAtEnd
|
||||
} else {
|
||||
!isSearchAtStart
|
||||
@ -104,7 +94,7 @@ fun AssistantScaffold(
|
||||
}
|
||||
val showNavBarScrim by remember {
|
||||
derivedStateOf {
|
||||
if (reverseResults == true) {
|
||||
if (reverseSearchResults) {
|
||||
!isSearchAtStart
|
||||
} else {
|
||||
!isSearchAtEnd
|
||||
@ -154,7 +144,7 @@ fun AssistantScaffold(
|
||||
val nestedScrollConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
val y = available.y * if (reverseResults == true) -1f else 1f
|
||||
val y = available.y * if (reverseSearchResults) -1f else 1f
|
||||
searchBarOffset = (searchBarOffset + y).coerceIn(-maxSearchBarOffset, 0f)
|
||||
return super.onPreScroll(available, source)
|
||||
}
|
||||
@ -175,10 +165,10 @@ fun AssistantScaffold(
|
||||
SearchColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
paddingValues = PaddingValues(
|
||||
top = (if (bottomSearchBar == true) 0.dp else 56.dp + webSearchPadding) + 4.dp + windowInsets.calculateTopPadding(),
|
||||
bottom = (if (bottomSearchBar == true) 56.dp + webSearchPadding else 0.dp) + 4.dp + windowInsets.calculateBottomPadding()
|
||||
top = (if (bottomSearchBar) 0.dp else 56.dp + webSearchPadding) + 4.dp + windowInsets.calculateTopPadding(),
|
||||
bottom = (if (bottomSearchBar) 56.dp + webSearchPadding else 0.dp) + 4.dp + windowInsets.calculateBottomPadding()
|
||||
),
|
||||
reverse = reverseResults == true,
|
||||
reverse = reverseSearchResults,
|
||||
state = searchState
|
||||
)
|
||||
|
||||
@ -191,14 +181,14 @@ fun AssistantScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.align(if (bottomSearchBar == true) Alignment.BottomCenter else Alignment.TopCenter)
|
||||
.align(if (bottomSearchBar) Alignment.BottomCenter else Alignment.TopCenter)
|
||||
.windowInsetsPadding(WindowInsets.safeDrawing)
|
||||
.padding(8.dp)
|
||||
.offset {
|
||||
if (searchBarFocused) IntOffset.Zero
|
||||
else IntOffset(
|
||||
0,
|
||||
searchBarOffset.toInt() * if (bottomSearchBar == true) -1 else 1
|
||||
searchBarOffset.toInt() * if (bottomSearchBar) -1 else 1
|
||||
)
|
||||
},
|
||||
level = { searchBarLevel },
|
||||
@ -213,7 +203,7 @@ fun AssistantScaffold(
|
||||
onValueChange = { searchVM.search(it) },
|
||||
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == Settings.SearchBarSettings.SearchBarColors.Auto || searchBarColor == Settings.SearchBarSettings.SearchBarColors.Dark,
|
||||
style = searchBarStyle,
|
||||
reverse = bottomSearchBar == true
|
||||
reverse = bottomSearchBar
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -37,5 +37,7 @@ class LauncherActivityVM : ViewModel(), KoinComponent {
|
||||
isSystemInDarkMode.value = darkMode
|
||||
}
|
||||
|
||||
val layout = dataStore.data.map { it.appearance.layout }.asLiveData()
|
||||
val baseLayout = dataStore.data.map { it.layout.baseLayout }.asLiveData()
|
||||
val bottomSearchBar = dataStore.data.map { it.layout.bottomSearchBar }.asLiveData()
|
||||
val reverseSearchResults = dataStore.data.map { it.layout.reverseSearchResults }.asLiveData()
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package de.mm20.launcher2.ui.launcher
|
||||
|
||||
import android.util.Log
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
@ -117,15 +116,13 @@ fun PagerScaffold(
|
||||
}
|
||||
|
||||
val isSearchAtTop by remember {
|
||||
if (reverseSearchResults) {
|
||||
derivedStateOf {
|
||||
derivedStateOf {
|
||||
if (reverseSearchResults) {
|
||||
val lastItem =
|
||||
searchState.layoutInfo.visibleItemsInfo.lastOrNull()
|
||||
?: return@derivedStateOf true
|
||||
lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding
|
||||
}
|
||||
} else {
|
||||
derivedStateOf {
|
||||
} else {
|
||||
searchState.firstVisibleItemIndex == 0 && searchState.firstVisibleItemScrollOffset == 0
|
||||
}
|
||||
}
|
||||
@ -255,8 +252,10 @@ fun PagerScaffold(
|
||||
source: NestedScrollSource
|
||||
): Offset {
|
||||
if (source == NestedScrollSource.Drag) gestureManager.dispatchDrag(available)
|
||||
val deltaSearchBarOffset = consumed.y * if (isSearchOpen && reverseSearchResults) 1 else -1
|
||||
searchBarOffset.value = (searchBarOffset.value + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset)
|
||||
val deltaSearchBarOffset =
|
||||
consumed.y * if (isSearchOpen && reverseSearchResults) 1 else -1
|
||||
searchBarOffset.value =
|
||||
(searchBarOffset.value + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset)
|
||||
return super.onPostScroll(consumed, available, source)
|
||||
}
|
||||
|
||||
@ -311,8 +310,9 @@ fun PagerScaffold(
|
||||
state = pagerState,
|
||||
userScrollEnabled = !isWidgetEditMode,
|
||||
) {
|
||||
val pagerProgress = pagerState.currentPage + pagerState.currentPageOffsetFraction
|
||||
when(it) {
|
||||
val pagerProgress =
|
||||
pagerState.currentPage + pagerState.currentPageOffsetFraction
|
||||
when (it) {
|
||||
0 -> {
|
||||
val editModePadding by animateDpAsState(if (isWidgetEditMode && bottomSearchBar) 56.dp else 0.dp)
|
||||
|
||||
@ -382,6 +382,7 @@ fun PagerScaffold(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
1 -> {
|
||||
val webSearchPadding by animateDpAsState(
|
||||
if (actions.isEmpty()) 0.dp else 48.dp
|
||||
@ -469,7 +470,12 @@ fun PagerScaffold(
|
||||
.padding(8.dp)
|
||||
.windowInsetsPadding(WindowInsets.safeDrawing)
|
||||
.imePadding()
|
||||
.offset { IntOffset(0, if (focusSearchBar) 0 else searchBarOffset.value.toInt() * if (bottomSearchBar) 1 else -1) }
|
||||
.offset {
|
||||
IntOffset(
|
||||
0,
|
||||
if (focusSearchBar) 0 else searchBarOffset.value.toInt() * if (bottomSearchBar) 1 else -1
|
||||
)
|
||||
}
|
||||
.offset(y = widgetEditModeOffset),
|
||||
level = { searchBarLevel },
|
||||
focused = focusSearchBar,
|
||||
|
||||
@ -18,6 +18,7 @@ import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@ -117,7 +118,9 @@ abstract class SharedLauncherActivity(
|
||||
|
||||
val hideStatus by viewModel.hideStatusBar.observeAsState(false)
|
||||
val hideNav by viewModel.hideNavBar.observeAsState(false)
|
||||
val layout by viewModel.layout.observeAsState(null)
|
||||
val layout by viewModel.baseLayout.observeAsState(null)
|
||||
val bottomSearchBar by viewModel.bottomSearchBar.observeAsState(false)
|
||||
val reverseSearchResults by viewModel.reverseSearchResults.observeAsState(false)
|
||||
|
||||
val systemUiController = rememberSystemUiController()
|
||||
|
||||
@ -167,44 +170,56 @@ abstract class SharedLauncherActivity(
|
||||
) {
|
||||
NavBarEffects(modifier = Modifier.fillMaxSize())
|
||||
if (mode == LauncherActivityMode.Assistant) {
|
||||
AssistantScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
darkStatusBarIcons = lightStatus,
|
||||
darkNavBarIcons = lightNav,
|
||||
)
|
||||
key(bottomSearchBar, reverseSearchResults) {
|
||||
AssistantScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
darkStatusBarIcons = lightStatus,
|
||||
darkNavBarIcons = lightNav,
|
||||
bottomSearchBar = bottomSearchBar,
|
||||
reverseSearchResults = reverseSearchResults,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
when (layout) {
|
||||
Settings.AppearanceSettings.Layout.PullDown -> {
|
||||
PullDownScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
scaleX =
|
||||
0.5f + enterTransitionProgress.value * 0.5f
|
||||
scaleY =
|
||||
0.5f + enterTransitionProgress.value * 0.5f
|
||||
alpha = enterTransitionProgress.value
|
||||
},
|
||||
darkStatusBarIcons = lightStatus,
|
||||
darkNavBarIcons = lightNav,
|
||||
)
|
||||
Settings.LayoutSettings.Layout.PullDown -> {
|
||||
key(bottomSearchBar, reverseSearchResults) {
|
||||
PullDownScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
scaleX =
|
||||
0.5f + enterTransitionProgress.value * 0.5f
|
||||
scaleY =
|
||||
0.5f + enterTransitionProgress.value * 0.5f
|
||||
alpha = enterTransitionProgress.value
|
||||
},
|
||||
darkStatusBarIcons = lightStatus,
|
||||
darkNavBarIcons = lightNav,
|
||||
bottomSearchBar = bottomSearchBar,
|
||||
reverseSearchResults = reverseSearchResults,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Settings.AppearanceSettings.Layout.Pager,
|
||||
Settings.AppearanceSettings.Layout.PagerReversed -> {
|
||||
PagerScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
scaleX = enterTransitionProgress.value
|
||||
scaleY = enterTransitionProgress.value
|
||||
alpha = enterTransitionProgress.value
|
||||
},
|
||||
darkStatusBarIcons = lightStatus,
|
||||
darkNavBarIcons = lightNav,
|
||||
reverse = layout == Settings.AppearanceSettings.Layout.PagerReversed
|
||||
)
|
||||
Settings.LayoutSettings.Layout.Pager,
|
||||
Settings.LayoutSettings.Layout.PagerReversed -> {
|
||||
key(bottomSearchBar, reverseSearchResults) {
|
||||
PagerScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
scaleX = enterTransitionProgress.value
|
||||
scaleY = enterTransitionProgress.value
|
||||
alpha = enterTransitionProgress.value
|
||||
},
|
||||
darkStatusBarIcons = lightStatus,
|
||||
darkNavBarIcons = lightNav,
|
||||
reverse = layout == Settings.LayoutSettings.Layout.PagerReversed,
|
||||
bottomSearchBar = bottomSearchBar,
|
||||
reverseSearchResults = reverseSearchResults,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
|
||||
@ -40,6 +40,7 @@ import de.mm20.launcher2.ui.settings.easteregg.EasterEggSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.favorites.FavoritesSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.filesearch.FileSearchSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.hiddenitems.HiddenItemsSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.layout.LayoutSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.license.LicenseScreen
|
||||
import de.mm20.launcher2.ui.settings.log.LogScreen
|
||||
import de.mm20.launcher2.ui.settings.main.MainSettingsScreen
|
||||
@ -99,6 +100,9 @@ class SettingsActivity : BaseActivity() {
|
||||
composable("settings/appearance") {
|
||||
AppearanceSettingsScreen()
|
||||
}
|
||||
composable("settings/appearance/layout") {
|
||||
LayoutSettingsScreen()
|
||||
}
|
||||
composable("settings/appearance/colorscheme") {
|
||||
ColorSchemeSettingsScreen()
|
||||
}
|
||||
|
||||
@ -54,13 +54,13 @@ fun AppearanceSettingsScreen() {
|
||||
PreferenceScreen(title = stringResource(id = R.string.preference_screen_appearance)) {
|
||||
item {
|
||||
PreferenceCategory {
|
||||
val layout by viewModel.layout.observeAsState()
|
||||
LayoutPreference(
|
||||
Preference(
|
||||
title = stringResource(id = R.string.preference_layout),
|
||||
summary = stringResource(id = R.string.preference_layout_summary),
|
||||
value = layout, onValueChanged = {
|
||||
viewModel.setLayout(it)
|
||||
})
|
||||
onClick = {
|
||||
navController?.navigate("settings/appearance/layout")
|
||||
}
|
||||
)
|
||||
val theme by viewModel.theme.observeAsState()
|
||||
ListPreference(
|
||||
title = stringResource(id = R.string.preference_theme),
|
||||
@ -483,128 +483,6 @@ fun IconShapePreference(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LayoutPreference(
|
||||
title: String,
|
||||
summary: String? = null,
|
||||
value: AppearanceSettings.Layout?,
|
||||
onValueChanged: (AppearanceSettings.Layout) -> Unit
|
||||
) {
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
Preference(title = title, summary = summary, onClick = { showDialog = true })
|
||||
|
||||
if (showDialog && value != null) {
|
||||
val layouts = remember {
|
||||
AppearanceSettings.Layout.values()
|
||||
.filter { it != AppearanceSettings.Layout.UNRECOGNIZED }
|
||||
}
|
||||
val pagerState = rememberPagerState(layouts.indexOf(value))
|
||||
AlertDialog(
|
||||
onDismissRequest = { showDialog = false },
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
showDialog = false
|
||||
onValueChanged(layouts[pagerState.currentPage])
|
||||
}) {
|
||||
Text(
|
||||
text = stringResource(android.R.string.ok),
|
||||
)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showDialog = false }) {
|
||||
Text(
|
||||
text = stringResource(android.R.string.cancel),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
text = {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
HorizontalPager(
|
||||
count = layouts.size,
|
||||
state = pagerState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 16.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(250.dp)
|
||||
.width(141.dp)
|
||||
.background(MaterialTheme.colorScheme.secondary)
|
||||
) {
|
||||
|
||||
val composition by rememberLottieComposition(
|
||||
LottieCompositionSpec.RawRes(
|
||||
when (layouts[it]) {
|
||||
AppearanceSettings.Layout.PullDown -> R.raw.lottie_scaffold_pulldown
|
||||
AppearanceSettings.Layout.Pager -> R.raw.lottie_scaffold_pager
|
||||
AppearanceSettings.Layout.PagerReversed -> R.raw.lottie_scaffold_pager_reverse
|
||||
else -> 0
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
val dynamicProperties = rememberLottieDynamicProperties(
|
||||
rememberLottieDynamicProperty(
|
||||
property = LottieProperty.COLOR,
|
||||
value = MaterialTheme.colorScheme.primaryContainer.toArgb(),
|
||||
keyPath = arrayOf("Pointer", "**")
|
||||
),
|
||||
rememberLottieDynamicProperty(
|
||||
property = LottieProperty.COLOR,
|
||||
value = MaterialTheme.colorScheme.surface.toArgb(),
|
||||
keyPath = arrayOf("SearchBar", "**")
|
||||
),
|
||||
rememberLottieDynamicProperty(
|
||||
property = LottieProperty.COLOR,
|
||||
value = MaterialTheme.colorScheme.surface.toArgb(),
|
||||
keyPath = arrayOf("Favorites", "**")
|
||||
),
|
||||
rememberLottieDynamicProperty(
|
||||
property = LottieProperty.COLOR,
|
||||
value = MaterialTheme.colorScheme.surface.toArgb(),
|
||||
keyPath = arrayOf("Apps", "**")
|
||||
),
|
||||
rememberLottieDynamicProperty(
|
||||
property = LottieProperty.COLOR,
|
||||
value = Color.White.toArgb(),
|
||||
keyPath = arrayOf("ClockWidget", "**")
|
||||
)
|
||||
)
|
||||
|
||||
/*LaunchedEffect(null) {
|
||||
val drw = LottieDrawable()
|
||||
drw.composition = composition
|
||||
val list = drw.resolveKeyPath(KeyPath("**"))
|
||||
list.forEach {
|
||||
Log.d("MM20", it.keysToString())
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
val progress by animateLottieCompositionAsState(
|
||||
composition,
|
||||
iterations = LottieConstants.IterateForever
|
||||
)
|
||||
|
||||
LottieAnimation(
|
||||
composition = composition,
|
||||
progress = progress,
|
||||
dynamicProperties = dynamicProperties
|
||||
)
|
||||
}
|
||||
}
|
||||
HorizontalPagerIndicator(pagerState = pagerState)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
private fun getShapeName(shape: IconSettings.IconShape?): String? {
|
||||
|
||||
@ -288,18 +288,4 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val layout = dataStore.data.map { it.appearance.layout }.asLiveData()
|
||||
fun setLayout(layout: Settings.AppearanceSettings.Layout) {
|
||||
viewModelScope.launch {
|
||||
dataStore.updateData {
|
||||
it.toBuilder()
|
||||
.setAppearance(
|
||||
it.appearance.toBuilder()
|
||||
.setLayout(layout)
|
||||
)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package de.mm20.launcher2.ui.settings.layout
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.preferences.Settings.LayoutSettings.Layout
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.preferences.ListPreference
|
||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||
|
||||
@Composable
|
||||
fun LayoutSettingsScreen() {
|
||||
val viewModel: LayoutSettingsScreenVM = viewModel()
|
||||
PreferenceScreen(
|
||||
title = stringResource(id = R.string.preference_layout)
|
||||
) {
|
||||
item {
|
||||
PreferenceCategory {
|
||||
val baseLayout by viewModel.baseLayout.observeAsState()
|
||||
ListPreference(title = stringResource(R.string.preference_layout_open_search),
|
||||
items = listOf(
|
||||
stringResource(R.string.open_search_pull_down) to Layout.PullDown,
|
||||
stringResource(R.string.open_search_swipe_left) to Layout.Pager,
|
||||
stringResource(R.string.open_search_swipe_right) to Layout.PagerReversed,
|
||||
),
|
||||
value = baseLayout,
|
||||
onValueChanged = {
|
||||
if (it != null) viewModel.setBaseLayout(it)
|
||||
},
|
||||
)
|
||||
val bottomSearchBar by viewModel.bottomSearchBar.observeAsState()
|
||||
ListPreference(
|
||||
title = stringResource(R.string.preference_layout_search_bar_position),
|
||||
items = listOf(
|
||||
stringResource(R.string.search_bar_position_top) to false,
|
||||
stringResource(R.string.search_bar_position_bottom) to true,
|
||||
),
|
||||
value = bottomSearchBar,
|
||||
onValueChanged = {
|
||||
if (it != null) viewModel.setBottomSearchBar(it)
|
||||
},
|
||||
)
|
||||
val reverseSearchResults by viewModel.reverseSearchResults.observeAsState()
|
||||
ListPreference(title = stringResource(R.string.preference_layout_search_results),
|
||||
items = listOf(
|
||||
stringResource(R.string.search_results_order_top_down) to false,
|
||||
stringResource(R.string.search_results_order_bottom_up) to true,
|
||||
),
|
||||
value = reverseSearchResults,
|
||||
onValueChanged = {
|
||||
if (it != null) viewModel.setReverseSearchResults(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package de.mm20.launcher2.ui.settings.layout
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.preferences.Settings.LayoutSettings.Layout
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class LayoutSettingsScreenVM: ViewModel(), KoinComponent {
|
||||
|
||||
private val dataStore : LauncherDataStore by inject()
|
||||
|
||||
val baseLayout = dataStore.data.map { it.layout.baseLayout }.asLiveData()
|
||||
fun setBaseLayout(baseLayout: Layout) {
|
||||
viewModelScope.launch {
|
||||
dataStore.updateData {
|
||||
it.toBuilder()
|
||||
.setLayout(it.layout.toBuilder().setBaseLayout(baseLayout))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val bottomSearchBar = dataStore.data.map { it.layout.bottomSearchBar }.asLiveData()
|
||||
fun setBottomSearchBar(bottomSearchBar: Boolean) {
|
||||
viewModelScope.launch {
|
||||
dataStore.updateData {
|
||||
it.toBuilder()
|
||||
.setLayout(it.layout.toBuilder().setBottomSearchBar(bottomSearchBar))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val reverseSearchResults = dataStore.data.map { it.layout.reverseSearchResults }.asLiveData()
|
||||
fun setReverseSearchResults(reverseSearchResults: Boolean) {
|
||||
viewModelScope.launch {
|
||||
dataStore.updateData {
|
||||
it.toBuilder()
|
||||
.setLayout(it.layout.toBuilder().setReverseSearchResults(reverseSearchResults))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -722,4 +722,14 @@
|
||||
<item quantity="one">%1$d item selected</item>
|
||||
<item quantity="other">%1$d items selected</item>
|
||||
</plurals>
|
||||
<string name="preference_layout_open_search">Search activation</string>
|
||||
<string name="open_search_pull_down">Swipe down</string>
|
||||
<string name="open_search_swipe_left">Swipe left</string>
|
||||
<string name="open_search_swipe_right">Swipe right</string>
|
||||
<string name="preference_layout_search_bar_position">Search bar position</string>
|
||||
<string name="search_bar_position_top">Top</string>
|
||||
<string name="search_bar_position_bottom">Bottom</string>
|
||||
<string name="preference_layout_search_results">Arrangement of search results</string>
|
||||
<string name="search_results_order_top_down">Top-down</string>
|
||||
<string name="search_results_order_bottom_up">Bottom-up</string>
|
||||
</resources>
|
||||
@ -22,7 +22,7 @@ internal val Context.dataStore: LauncherDataStore by dataStore(
|
||||
}
|
||||
)
|
||||
|
||||
internal const val SchemaVersion = 11
|
||||
internal const val SchemaVersion = 12
|
||||
|
||||
internal fun getMigrations(context: Context): List<DataMigration<Settings>> {
|
||||
return listOf(
|
||||
@ -37,5 +37,6 @@ internal fun getMigrations(context: Context): List<DataMigration<Settings>> {
|
||||
Migration_8_9(),
|
||||
Migration_9_10(),
|
||||
Migration_10_11(),
|
||||
Migration_11_12(),
|
||||
)
|
||||
}
|
||||
@ -162,6 +162,12 @@ fun createFactorySettings(context: Context): Settings {
|
||||
Settings.WidgetSettings.newBuilder()
|
||||
.setEditButton(true)
|
||||
)
|
||||
.setLayout(
|
||||
Settings.LayoutSettings.newBuilder()
|
||||
.setBaseLayout(Settings.LayoutSettings.Layout.PullDown)
|
||||
.setBottomSearchBar(false)
|
||||
.setReverseSearchResults(false)
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package de.mm20.launcher2.preferences.migrations
|
||||
|
||||
import de.mm20.launcher2.preferences.Settings
|
||||
import de.mm20.launcher2.preferences.Settings.LayoutSettings
|
||||
|
||||
class Migration_11_12: VersionedMigration(11, 12) {
|
||||
override suspend fun applyMigrations(builder: Settings.Builder): Settings.Builder {
|
||||
val oldLayout = builder.appearance.layout
|
||||
when(oldLayout) {
|
||||
LayoutSettings.Layout.Pager -> {
|
||||
builder.setLayout(
|
||||
LayoutSettings.newBuilder()
|
||||
.setBaseLayout(LayoutSettings.Layout.Pager)
|
||||
.setBottomSearchBar(true)
|
||||
.setReverseSearchResults(true)
|
||||
)
|
||||
}
|
||||
LayoutSettings.Layout.PagerReversed -> {
|
||||
builder.setLayout(
|
||||
LayoutSettings.newBuilder()
|
||||
.setBaseLayout(LayoutSettings.Layout.PagerReversed)
|
||||
.setBottomSearchBar(true)
|
||||
.setReverseSearchResults(true)
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
builder.setLayout(
|
||||
LayoutSettings.newBuilder()
|
||||
.setBaseLayout(LayoutSettings.Layout.PullDown)
|
||||
.setBottomSearchBar(false)
|
||||
.setReverseSearchResults(false)
|
||||
)
|
||||
}
|
||||
}
|
||||
return builder
|
||||
}
|
||||
}
|
||||
@ -68,12 +68,10 @@ message Settings {
|
||||
CustomColors custom_colors = 8;
|
||||
bool dim_wallpaper = 7;
|
||||
|
||||
enum Layout {
|
||||
PullDown = 0;
|
||||
Pager = 1;
|
||||
PagerReversed = 2;
|
||||
}
|
||||
Layout layout = 9;
|
||||
/**
|
||||
* Deprecated, use layout instead
|
||||
*/
|
||||
LayoutSettings.Layout layout = 9 [deprecated = true];
|
||||
|
||||
enum Font {
|
||||
Outfit = 0;
|
||||
@ -288,4 +286,17 @@ message Settings {
|
||||
bool edit_button = 1;
|
||||
}
|
||||
WidgetSettings widgets = 26;
|
||||
|
||||
message LayoutSettings {
|
||||
enum Layout {
|
||||
PullDown = 0;
|
||||
Pager = 1;
|
||||
PagerReversed = 2;
|
||||
}
|
||||
|
||||
Layout base_layout = 1;
|
||||
bool bottom_search_bar = 2;
|
||||
bool reverse_search_results = 3;
|
||||
}
|
||||
LayoutSettings layout = 27;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user