Add preferences for layout
This commit is contained in:
parent
7cd1269c33
commit
64cc07bef9
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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()
|
||||||
}
|
}
|
||||||
@ -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,
|
||||||
|
|||||||
@ -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 -> {}
|
||||||
|
|||||||
@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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? {
|
||||||
|
|||||||
@ -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="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>
|
||||||
@ -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(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
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;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user