Add preferences for layout

This commit is contained in:
MM20 2023-01-16 17:49:45 +01:00
parent 7cd1269c33
commit 64cc07bef9
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
14 changed files with 273 additions and 218 deletions

View File

@ -37,6 +37,8 @@ fun AssistantScaffold(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
darkStatusBarIcons: Boolean = false, darkStatusBarIcons: Boolean = false,
darkNavBarIcons: Boolean = false, darkNavBarIcons: Boolean = false,
bottomSearchBar: Boolean = false,
reverseSearchResults: Boolean = false,
) { ) {
val viewModel: LauncherScaffoldVM = viewModel() 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 searchState = rememberLazyListState()
val isSearchAtStart by remember { val isSearchAtStart by remember {
@ -79,14 +72,11 @@ fun AssistantScaffold(
} }
} }
if (reverseResults == null || bottomSearchBar == null) return
val searchBarLevel by remember { val searchBarLevel by remember {
derivedStateOf { derivedStateOf {
when { when {
reverseResults == bottomSearchBar && isSearchAtStart -> SearchBarLevel.Active reverseSearchResults == bottomSearchBar && isSearchAtStart -> SearchBarLevel.Active
reverseResults != bottomSearchBar && isSearchAtEnd -> SearchBarLevel.Active reverseSearchResults != bottomSearchBar && isSearchAtEnd -> SearchBarLevel.Active
else -> SearchBarLevel.Raised else -> SearchBarLevel.Raised
} }
} }
@ -95,7 +85,7 @@ fun AssistantScaffold(
val systemUiController = rememberSystemUiController() val systemUiController = rememberSystemUiController()
val showStatusBarScrim by remember { val showStatusBarScrim by remember {
derivedStateOf { derivedStateOf {
if (reverseResults == true) { if (reverseSearchResults) {
!isSearchAtEnd !isSearchAtEnd
} else { } else {
!isSearchAtStart !isSearchAtStart
@ -104,7 +94,7 @@ fun AssistantScaffold(
} }
val showNavBarScrim by remember { val showNavBarScrim by remember {
derivedStateOf { derivedStateOf {
if (reverseResults == true) { if (reverseSearchResults) {
!isSearchAtStart !isSearchAtStart
} else { } else {
!isSearchAtEnd !isSearchAtEnd
@ -154,7 +144,7 @@ fun AssistantScaffold(
val nestedScrollConnection = remember { val nestedScrollConnection = remember {
object : NestedScrollConnection { object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { 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) searchBarOffset = (searchBarOffset + y).coerceIn(-maxSearchBarOffset, 0f)
return super.onPreScroll(available, source) return super.onPreScroll(available, source)
} }
@ -175,10 +165,10 @@ fun AssistantScaffold(
SearchColumn( SearchColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
paddingValues = PaddingValues( paddingValues = PaddingValues(
top = (if (bottomSearchBar == true) 0.dp else 56.dp + webSearchPadding) + 4.dp + windowInsets.calculateTopPadding(), top = (if (bottomSearchBar) 0.dp else 56.dp + webSearchPadding) + 4.dp + windowInsets.calculateTopPadding(),
bottom = (if (bottomSearchBar == true) 56.dp + webSearchPadding else 0.dp) + 4.dp + windowInsets.calculateBottomPadding() bottom = (if (bottomSearchBar) 56.dp + webSearchPadding else 0.dp) + 4.dp + windowInsets.calculateBottomPadding()
), ),
reverse = reverseResults == true, reverse = reverseSearchResults,
state = searchState state = searchState
) )
@ -191,14 +181,14 @@ fun AssistantScaffold(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.wrapContentHeight() .wrapContentHeight()
.align(if (bottomSearchBar == true) Alignment.BottomCenter else Alignment.TopCenter) .align(if (bottomSearchBar) Alignment.BottomCenter else Alignment.TopCenter)
.windowInsetsPadding(WindowInsets.safeDrawing) .windowInsetsPadding(WindowInsets.safeDrawing)
.padding(8.dp) .padding(8.dp)
.offset { .offset {
if (searchBarFocused) IntOffset.Zero if (searchBarFocused) IntOffset.Zero
else IntOffset( else IntOffset(
0, 0,
searchBarOffset.toInt() * if (bottomSearchBar == true) -1 else 1 searchBarOffset.toInt() * if (bottomSearchBar) -1 else 1
) )
}, },
level = { searchBarLevel }, level = { searchBarLevel },
@ -213,7 +203,7 @@ fun AssistantScaffold(
onValueChange = { searchVM.search(it) }, onValueChange = { searchVM.search(it) },
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == Settings.SearchBarSettings.SearchBarColors.Auto || searchBarColor == Settings.SearchBarSettings.SearchBarColors.Dark, darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == Settings.SearchBarSettings.SearchBarColors.Auto || searchBarColor == Settings.SearchBarSettings.SearchBarColors.Dark,
style = searchBarStyle, style = searchBarStyle,
reverse = bottomSearchBar == true reverse = bottomSearchBar
) )
} }
} }

View File

@ -37,5 +37,7 @@ class LauncherActivityVM : ViewModel(), KoinComponent {
isSystemInDarkMode.value = darkMode 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()
} }

View File

@ -1,6 +1,5 @@
package de.mm20.launcher2.ui.launcher package de.mm20.launcher2.ui.launcher
import android.util.Log
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateDpAsState
@ -117,15 +116,13 @@ fun PagerScaffold(
} }
val isSearchAtTop by remember { val isSearchAtTop by remember {
if (reverseSearchResults) { derivedStateOf {
derivedStateOf { if (reverseSearchResults) {
val lastItem = val lastItem =
searchState.layoutInfo.visibleItemsInfo.lastOrNull() searchState.layoutInfo.visibleItemsInfo.lastOrNull()
?: return@derivedStateOf true ?: return@derivedStateOf true
lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding
} } else {
} else {
derivedStateOf {
searchState.firstVisibleItemIndex == 0 && searchState.firstVisibleItemScrollOffset == 0 searchState.firstVisibleItemIndex == 0 && searchState.firstVisibleItemScrollOffset == 0
} }
} }
@ -255,8 +252,10 @@ fun PagerScaffold(
source: NestedScrollSource source: NestedScrollSource
): Offset { ): Offset {
if (source == NestedScrollSource.Drag) gestureManager.dispatchDrag(available) if (source == NestedScrollSource.Drag) gestureManager.dispatchDrag(available)
val deltaSearchBarOffset = consumed.y * if (isSearchOpen && reverseSearchResults) 1 else -1 val deltaSearchBarOffset =
searchBarOffset.value = (searchBarOffset.value + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset) consumed.y * if (isSearchOpen && reverseSearchResults) 1 else -1
searchBarOffset.value =
(searchBarOffset.value + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset)
return super.onPostScroll(consumed, available, source) return super.onPostScroll(consumed, available, source)
} }
@ -311,8 +310,9 @@ fun PagerScaffold(
state = pagerState, state = pagerState,
userScrollEnabled = !isWidgetEditMode, userScrollEnabled = !isWidgetEditMode,
) { ) {
val pagerProgress = pagerState.currentPage + pagerState.currentPageOffsetFraction val pagerProgress =
when(it) { pagerState.currentPage + pagerState.currentPageOffsetFraction
when (it) {
0 -> { 0 -> {
val editModePadding by animateDpAsState(if (isWidgetEditMode && bottomSearchBar) 56.dp else 0.dp) val editModePadding by animateDpAsState(if (isWidgetEditMode && bottomSearchBar) 56.dp else 0.dp)
@ -382,6 +382,7 @@ fun PagerScaffold(
) )
} }
} }
1 -> { 1 -> {
val webSearchPadding by animateDpAsState( val webSearchPadding by animateDpAsState(
if (actions.isEmpty()) 0.dp else 48.dp if (actions.isEmpty()) 0.dp else 48.dp
@ -469,7 +470,12 @@ fun PagerScaffold(
.padding(8.dp) .padding(8.dp)
.windowInsetsPadding(WindowInsets.safeDrawing) .windowInsetsPadding(WindowInsets.safeDrawing)
.imePadding() .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), .offset(y = widgetEditModeOffset),
level = { searchBarLevel }, level = { searchBarLevel },
focused = focusSearchBar, focused = focusSearchBar,

View File

@ -18,6 +18,7 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -117,7 +118,9 @@ abstract class SharedLauncherActivity(
val hideStatus by viewModel.hideStatusBar.observeAsState(false) val hideStatus by viewModel.hideStatusBar.observeAsState(false)
val hideNav by viewModel.hideNavBar.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() val systemUiController = rememberSystemUiController()
@ -167,44 +170,56 @@ abstract class SharedLauncherActivity(
) { ) {
NavBarEffects(modifier = Modifier.fillMaxSize()) NavBarEffects(modifier = Modifier.fillMaxSize())
if (mode == LauncherActivityMode.Assistant) { if (mode == LauncherActivityMode.Assistant) {
AssistantScaffold( key(bottomSearchBar, reverseSearchResults) {
modifier = Modifier AssistantScaffold(
.fillMaxSize(), modifier = Modifier
darkStatusBarIcons = lightStatus, .fillMaxSize(),
darkNavBarIcons = lightNav, darkStatusBarIcons = lightStatus,
) darkNavBarIcons = lightNav,
bottomSearchBar = bottomSearchBar,
reverseSearchResults = reverseSearchResults,
)
}
} else { } else {
when (layout) { when (layout) {
Settings.AppearanceSettings.Layout.PullDown -> { Settings.LayoutSettings.Layout.PullDown -> {
PullDownScaffold( key(bottomSearchBar, reverseSearchResults) {
modifier = Modifier PullDownScaffold(
.fillMaxSize() modifier = Modifier
.graphicsLayer { .fillMaxSize()
scaleX = .graphicsLayer {
0.5f + enterTransitionProgress.value * 0.5f scaleX =
scaleY = 0.5f + enterTransitionProgress.value * 0.5f
0.5f + enterTransitionProgress.value * 0.5f scaleY =
alpha = enterTransitionProgress.value 0.5f + enterTransitionProgress.value * 0.5f
}, alpha = enterTransitionProgress.value
darkStatusBarIcons = lightStatus, },
darkNavBarIcons = lightNav, darkStatusBarIcons = lightStatus,
) darkNavBarIcons = lightNav,
bottomSearchBar = bottomSearchBar,
reverseSearchResults = reverseSearchResults,
)
}
} }
Settings.AppearanceSettings.Layout.Pager, Settings.LayoutSettings.Layout.Pager,
Settings.AppearanceSettings.Layout.PagerReversed -> { Settings.LayoutSettings.Layout.PagerReversed -> {
PagerScaffold( key(bottomSearchBar, reverseSearchResults) {
modifier = Modifier PagerScaffold(
.fillMaxSize() modifier = Modifier
.graphicsLayer { .fillMaxSize()
scaleX = enterTransitionProgress.value .graphicsLayer {
scaleY = enterTransitionProgress.value scaleX = enterTransitionProgress.value
alpha = enterTransitionProgress.value scaleY = enterTransitionProgress.value
}, alpha = enterTransitionProgress.value
darkStatusBarIcons = lightStatus, },
darkNavBarIcons = lightNav, darkStatusBarIcons = lightStatus,
reverse = layout == Settings.AppearanceSettings.Layout.PagerReversed darkNavBarIcons = lightNav,
) reverse = layout == Settings.LayoutSettings.Layout.PagerReversed,
bottomSearchBar = bottomSearchBar,
reverseSearchResults = reverseSearchResults,
)
}
} }
else -> {} else -> {}

View File

@ -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.favorites.FavoritesSettingsScreen
import de.mm20.launcher2.ui.settings.filesearch.FileSearchSettingsScreen import de.mm20.launcher2.ui.settings.filesearch.FileSearchSettingsScreen
import de.mm20.launcher2.ui.settings.hiddenitems.HiddenItemsSettingsScreen 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.license.LicenseScreen
import de.mm20.launcher2.ui.settings.log.LogScreen import de.mm20.launcher2.ui.settings.log.LogScreen
import de.mm20.launcher2.ui.settings.main.MainSettingsScreen import de.mm20.launcher2.ui.settings.main.MainSettingsScreen
@ -99,6 +100,9 @@ class SettingsActivity : BaseActivity() {
composable("settings/appearance") { composable("settings/appearance") {
AppearanceSettingsScreen() AppearanceSettingsScreen()
} }
composable("settings/appearance/layout") {
LayoutSettingsScreen()
}
composable("settings/appearance/colorscheme") { composable("settings/appearance/colorscheme") {
ColorSchemeSettingsScreen() ColorSchemeSettingsScreen()
} }

View File

@ -54,13 +54,13 @@ fun AppearanceSettingsScreen() {
PreferenceScreen(title = stringResource(id = R.string.preference_screen_appearance)) { PreferenceScreen(title = stringResource(id = R.string.preference_screen_appearance)) {
item { item {
PreferenceCategory { PreferenceCategory {
val layout by viewModel.layout.observeAsState() Preference(
LayoutPreference(
title = stringResource(id = R.string.preference_layout), title = stringResource(id = R.string.preference_layout),
summary = stringResource(id = R.string.preference_layout_summary), summary = stringResource(id = R.string.preference_layout_summary),
value = layout, onValueChanged = { onClick = {
viewModel.setLayout(it) navController?.navigate("settings/appearance/layout")
}) }
)
val theme by viewModel.theme.observeAsState() val theme by viewModel.theme.observeAsState()
ListPreference( ListPreference(
title = stringResource(id = R.string.preference_theme), 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 @Composable
private fun getShapeName(shape: IconSettings.IconShape?): String? { private fun getShapeName(shape: IconSettings.IconShape?): String? {

View File

@ -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()
}
}
}
} }

View File

@ -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)
},
)
}
}
}
}

View File

@ -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()
}
}
}
}

View File

@ -722,4 +722,14 @@
<item quantity="one">%1$d item selected</item> <item quantity="one">%1$d item selected</item>
<item quantity="other">%1$d items selected</item> <item quantity="other">%1$d items selected</item>
</plurals> </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> </resources>

View File

@ -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>> { internal fun getMigrations(context: Context): List<DataMigration<Settings>> {
return listOf( return listOf(
@ -37,5 +37,6 @@ internal fun getMigrations(context: Context): List<DataMigration<Settings>> {
Migration_8_9(), Migration_8_9(),
Migration_9_10(), Migration_9_10(),
Migration_10_11(), Migration_10_11(),
Migration_11_12(),
) )
} }

View File

@ -162,6 +162,12 @@ fun createFactorySettings(context: Context): Settings {
Settings.WidgetSettings.newBuilder() Settings.WidgetSettings.newBuilder()
.setEditButton(true) .setEditButton(true)
) )
.setLayout(
Settings.LayoutSettings.newBuilder()
.setBaseLayout(Settings.LayoutSettings.Layout.PullDown)
.setBottomSearchBar(false)
.setReverseSearchResults(false)
)
.build() .build()
} }

View File

@ -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
}
}

View File

@ -68,12 +68,10 @@ message Settings {
CustomColors custom_colors = 8; CustomColors custom_colors = 8;
bool dim_wallpaper = 7; bool dim_wallpaper = 7;
enum Layout { /**
PullDown = 0; * Deprecated, use layout instead
Pager = 1; */
PagerReversed = 2; LayoutSettings.Layout layout = 9 [deprecated = true];
}
Layout layout = 9;
enum Font { enum Font {
Outfit = 0; Outfit = 0;
@ -288,4 +286,17 @@ message Settings {
bool edit_button = 1; bool edit_button = 1;
} }
WidgetSettings widgets = 26; 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;
} }