From 960dd5159457181f139b76c1fdb48db838be2eed Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Fri, 19 Sep 2025 22:20:30 +0200 Subject: [PATCH] Fix search action bottom sheet button placement Fix #1584 --- .gitignore | 1 + .../ui/component/BottomSheetDialog.kt | 22 +-- .../searchactions/EditSearchActionSheet.kt | 139 ++++++++++-------- 3 files changed, 78 insertions(+), 84 deletions(-) diff --git a/.gitignore b/.gitignore index 198a321c8..3e8c0599b 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ captures/ .idea/modules.xml # Comment next line if keeping position of elements in Navigation Editor is relevant for you .idea/navEditor.xml +.idea/copilot.*.xml # Keystore files # Uncomment the following lines if you do not want to check your keystore files in. diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheetDialog.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheetDialog.kt index 5fda551dd..8581a298b 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheetDialog.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheetDialog.kt @@ -1,44 +1,28 @@ package de.mm20.launcher2.ui.component -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SheetState import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @Composable fun BottomSheetDialog( onDismissRequest: () -> Unit, - footerItems: @Composable (() -> Unit)? = null, bottomSheetState: SheetState = rememberModalBottomSheetState(), content: @Composable (paddingValues: PaddingValues) -> Unit, ) { ModalBottomSheet( - modifier = Modifier.statusBarsPadding().padding(top = 8.dp), + modifier = Modifier + .statusBarsPadding() + .padding(top = 8.dp), sheetState = bottomSheetState, onDismissRequest = onDismissRequest, ) { content(PaddingValues(horizontal = 24.dp, vertical = 8.dp)) - if (footerItems != null) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 24.dp, end = 24.dp, bottom = 8.dp), - horizontalArrangement = Arrangement.spacedBy( - space = 16.dp, - alignment = Alignment.End, - ) - ) { - footerItems() - } - } } } \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/searchactions/EditSearchActionSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/searchactions/EditSearchActionSheet.kt index 39bca9c41..fbd3d8cfb 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/searchactions/EditSearchActionSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/searchactions/EditSearchActionSheet.kt @@ -109,80 +109,96 @@ fun EditSearchActionSheet( onDismissRequest = { viewModel.onDismiss() onDismiss() - }, - footerItems = when (page) { - EditSearchActionPage.CustomizeAppSearch, - EditSearchActionPage.CustomizeWebSearch, - EditSearchActionPage.CustomizeCustomIntent -> { - { - Button(onClick = { - if (viewModel.validate()) { - viewModel.onSave() - searchAction?.let { onSave(it) } - } - }, enabled = !searchAction?.label.isNullOrBlank()) { - Text(stringResource(R.string.save)) - } - } + } + ) { + Column( + modifier = when (page) { + EditSearchActionPage.InitAppSearch, EditSearchActionPage.PickIcon -> Modifier + else -> Modifier.verticalScroll(rememberScrollState()).padding(it) + } + ) { + when (page) { + EditSearchActionPage.SelectType -> SelectTypePage(viewModel) + EditSearchActionPage.InitWebSearch -> InitWebSearchPage(viewModel) + EditSearchActionPage.InitAppSearch -> InitAppSearchPage(viewModel, it) + EditSearchActionPage.CustomizeWebSearch -> CustomizeWebSearch(viewModel) + EditSearchActionPage.CustomizeCustomIntent -> CustomizeCustomIntent(viewModel) + EditSearchActionPage.CustomizeAppSearch -> CustomizeAppSearch(viewModel) + EditSearchActionPage.PickIcon -> PickIcon(viewModel, it) } - EditSearchActionPage.InitWebSearch -> { - { - val density = LocalDensity.current - Button( - onClick = { - if (viewModel.skipWebsearchImport.value) { - viewModel.skipWebsearchImport() - } else { - viewModel.importWebsearch(density) + val button: (@Composable () -> Unit)? = when (page) { + EditSearchActionPage.CustomizeAppSearch, + EditSearchActionPage.CustomizeWebSearch, + EditSearchActionPage.CustomizeCustomIntent -> { + { + Button(onClick = { + if (viewModel.validate()) { + viewModel.onSave() + searchAction?.let { onSave(it) } } - }, - enabled = !viewModel.loadingWebsearch.value - ) { - Text( - stringResource( + }, enabled = !searchAction?.label.isNullOrBlank()) { + Text(stringResource(R.string.save)) + } + } + } + + EditSearchActionPage.InitWebSearch -> { + { + val density = LocalDensity.current + Button( + onClick = { if (viewModel.skipWebsearchImport.value) { - R.string.skip + viewModel.skipWebsearchImport() } else { - R.string.action_next + viewModel.importWebsearch(density) } + }, + enabled = !viewModel.loadingWebsearch.value + ) { + Text( + stringResource( + if (viewModel.skipWebsearchImport.value) { + R.string.skip + } else { + R.string.action_next + } + ) ) - ) + } } } - } - EditSearchActionPage.PickIcon -> { - { - OutlinedButton(onClick = { - viewModel.applyIcon() - }) { - Text(stringResource(R.string.ok)) + EditSearchActionPage.PickIcon -> { + { + OutlinedButton(onClick = { + viewModel.applyIcon() + }) { + Text(stringResource(R.string.ok)) + } } } + + else -> null } - else -> null - }) { - when (page) { - EditSearchActionPage.SelectType -> SelectTypePage(viewModel, it) - EditSearchActionPage.InitWebSearch -> InitWebSearchPage(viewModel, it) - EditSearchActionPage.InitAppSearch -> InitAppSearchPage(viewModel, it) - EditSearchActionPage.CustomizeWebSearch -> CustomizeWebSearch(viewModel, it) - EditSearchActionPage.CustomizeCustomIntent -> CustomizeCustomIntent(viewModel, it) - EditSearchActionPage.CustomizeAppSearch -> CustomizeAppSearch(viewModel, it) - EditSearchActionPage.PickIcon -> PickIcon(viewModel, it) + if (button != null) { + Row( + modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp), + horizontalArrangement = Arrangement.End, + ) { + button() + } + } } } } @Composable -private fun SelectTypePage(viewModel: EditSearchActionSheetVM, paddingValues: PaddingValues) { +private fun SelectTypePage(viewModel: EditSearchActionSheetVM) { Column( modifier = Modifier .fillMaxWidth() - .verticalScroll(rememberScrollState()) - .padding(paddingValues) ) { Text( text = stringResource(R.string.create_search_action_type), @@ -293,7 +309,7 @@ private fun InitAppSearchPage(viewModel: EditSearchActionSheetVM, paddingValues: SearchActionIcon( size = 24.dp, componentName = it.componentName, - icon = de.mm20.launcher2.searchactions.actions.SearchActionIcon.Custom, + icon = SearchActionIcon.Custom, color = 1, ) Text( @@ -309,15 +325,13 @@ private fun InitAppSearchPage(viewModel: EditSearchActionSheetVM, paddingValues: } @Composable -private fun InitWebSearchPage(viewModel: EditSearchActionSheetVM, paddingValues: PaddingValues) { +private fun InitWebSearchPage(viewModel: EditSearchActionSheetVM) { var url by viewModel.initWebsearchUrl val importError by viewModel.websearchImportError val loading by viewModel.loadingWebsearch Column( modifier = Modifier .fillMaxWidth() - .verticalScroll(rememberScrollState()) - .padding(paddingValues) ) { Text( text = stringResource(R.string.create_search_action_website_url), @@ -359,14 +373,12 @@ private fun InitWebSearchPage(viewModel: EditSearchActionSheetVM, paddingValues: } @Composable -fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM, paddingValues: PaddingValues) { +fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM) { val searchAction by viewModel.searchAction Column( modifier = Modifier - .verticalScroll(rememberScrollState()) .fillMaxWidth() - .padding(paddingValues) ) { if (searchAction != null && searchAction is CustomWebsearchActionBuilder) { @@ -486,7 +498,7 @@ fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM, paddingValues: Paddin } @Composable -fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM, paddingValues: PaddingValues) { +fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM) { val searchAction by viewModel.searchAction val context = LocalContext.current @@ -503,9 +515,7 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM, paddingValues: Paddin Column( modifier = Modifier - .verticalScroll(rememberScrollState()) .fillMaxWidth() - .padding(paddingValues) ) { if (searchAction != null) { @@ -606,7 +616,7 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM, paddingValues: Paddin } @Composable -fun CustomizeCustomIntent(viewModel: EditSearchActionSheetVM, paddingValues: PaddingValues) { +fun CustomizeCustomIntent(viewModel: EditSearchActionSheetVM) { val searchAction by viewModel.searchAction val action = searchAction @@ -614,9 +624,7 @@ fun CustomizeCustomIntent(viewModel: EditSearchActionSheetVM, paddingValues: Pad if (action is CustomIntentActionBuilder) { Column( modifier = Modifier - .verticalScroll(rememberScrollState()) .fillMaxWidth() - .padding(paddingValues) ) { Row( verticalAlignment = Alignment.Bottom @@ -1099,6 +1107,7 @@ private fun IntentExtrasEditor(viewModel: EditSearchActionSheetVM) { label = { Text("Key") }, value = newKey, onValueChange = { newKey = it }, + singleLine = true, ) FilledIconButton( modifier = Modifier.padding(start = 8.dp),