diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheet.kt index e9e9c9970..6ee3e9cea 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/component/BottomSheet.kt @@ -59,7 +59,7 @@ fun BottomSheet( fun BottomSheet( state: T, expanded: (T) -> Boolean, - onDismissRequest: () -> Unit, + onDismissRequest: () -> Unit = {}, content: @Composable (state: T) -> Unit, ) { val expandedState = remember { MutableTransitionState(state) } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/component/DismissableBottomSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/component/DismissableBottomSheet.kt index 67053c2ab..072c28303 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/component/DismissableBottomSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/component/DismissableBottomSheet.kt @@ -65,16 +65,16 @@ import kotlinx.coroutines.CancellationException @Composable fun DismissableBottomSheet( - expanded: Boolean = true, + expanded: Boolean, onDismissRequest: () -> Unit, - content: @Composable (contentPadding: PaddingValues) -> Unit, + content: @Composable () -> Unit, ) { DismissableBottomSheet( state = expanded, expanded = { it }, onDismissRequest = onDismissRequest, ) { - content(PaddingValues()) + content() } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/filters/SearchFilters.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/filters/SearchFilters.kt index 8ae782e91..5a8bbed38 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/filters/SearchFilters.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/filters/SearchFilters.kt @@ -29,7 +29,6 @@ fun SearchFilters( val allCategoriesEnabled = filters.allCategoriesEnabled Column( modifier = modifier - .verticalScroll(rememberScrollState()) .padding(horizontal = 4.dp), ) { FilterChip( diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/ConfigureWidgetSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/ConfigureWidgetSheet.kt index c7df8bb94..44b62f6dc 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/ConfigureWidgetSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/ConfigureWidgetSheet.kt @@ -29,7 +29,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding @@ -451,18 +450,17 @@ fun ColumnScope.ConfigureFavoritesWidget( } - if (createTag) { - EditTagSheet( - tag = null, - onTagSaved = { tag -> - val newTag = Tag(tag) - tagList = (tagList + newTag.tag).toImmutableList() - }, - onDismiss = { - createTag = false - } - ) - } + EditTagSheet( + expanded = createTag, + tag = null, + onTagSaved = { tag -> + val newTag = Tag(tag) + tagList = (tagList + newTag.tag).toImmutableList() + }, + onDismiss = { + createTag = false + } + ) OutlinedCard( modifier = Modifier.padding(top = 16.dp) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt index 348eed0b0..10875b446 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt @@ -4,7 +4,11 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -282,7 +286,12 @@ fun CustomizeSearchableSheet( viewModel.pickIcon(it) viewModel.closeIconPicker() }, - contentPadding = it, + contentPadding = PaddingValues( + start = 16.dp, + end = 16.dp, + top = 16.dp, + bottom = 16.dp + WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + ), ) } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt index 164722594..9b75af8a3 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt @@ -59,7 +59,6 @@ import androidx.compose.ui.graphics.drawOutline import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.painterResource @@ -87,7 +86,6 @@ import de.mm20.launcher2.ui.component.dragndrop.LazyDragAndDropRow import de.mm20.launcher2.ui.component.dragndrop.LazyVerticalDragAndDropGrid import de.mm20.launcher2.ui.component.dragndrop.rememberLazyDragAndDropGridState import de.mm20.launcher2.ui.component.dragndrop.rememberLazyDragAndDropListState -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.locals.LocalGridSettings import kotlin.math.roundToInt @@ -113,7 +111,7 @@ fun EditFavoritesSheet( modifier = Modifier .fillMaxWidth() .aspectRatio(1f) - .padding(it) + .padding(16.dp) ) { CircularProgressIndicator( modifier = Modifier @@ -122,18 +120,20 @@ fun EditFavoritesSheet( ) } } else { - ReorderFavoritesGrid( - viewModel, + val paddingValues = PaddingValues( start = 16.dp, end = 16.dp, bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() ) + ReorderFavoritesGrid( + viewModel, + paddingValues ) DismissableBottomSheet( expanded = createShortcutTarget != null, onDismissRequest = { viewModel.cancelPickShortcut() }) { - ShortcutPicker(viewModel, it) + ShortcutPicker(viewModel, paddingValues) } } } @@ -598,17 +598,16 @@ fun ReorderFavoritesGrid(viewModel: EditFavoritesSheetVM, paddingValues: Padding } } } - if (createTag) { - EditTagSheet( - tag = null, - onTagSaved = { tag -> - viewModel.pinTag(Tag(tag)) - }, - onDismiss = { - createTag = false - } - ) - } + EditTagSheet( + expanded = createTag, + tag = null, + onTagSaved = { tag -> + viewModel.pinTag(Tag(tag)) + }, + onDismiss = { + createTag = false + } + ) } @Composable diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheet.kt index c5a99234d..213e54e33 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheet.kt @@ -1,5 +1,6 @@ package de.mm20.launcher2.ui.launcher.sheets +import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background @@ -10,8 +11,11 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -24,13 +28,16 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonGroupDefaults -import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.FilledTonalIconButton +import androidx.compose.material3.FlexibleBottomAppBar import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -41,12 +48,13 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathEffect import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.platform.LocalDensity @@ -61,7 +69,7 @@ import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.search.Tag import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.common.IconPicker -import de.mm20.launcher2.ui.component.DismissableBottomSheet +import de.mm20.launcher2.ui.component.BottomSheet import de.mm20.launcher2.ui.component.ShapedLauncherIcon import de.mm20.launcher2.ui.component.SmallMessage import de.mm20.launcher2.ui.component.emojipicker.EmojiPicker @@ -70,44 +78,176 @@ import de.mm20.launcher2.ui.locals.LocalGridSettings @Composable fun EditTagSheet( + expanded: Boolean, tag: String?, onDismiss: () -> Unit, onTagSaved: (String) -> Unit = {}, ) { - val viewModel: EditTagSheetVM = viewModel() - val density = LocalDensity.current + BottomSheet( + state = tag to expanded, + expanded = { it.second }, + ) { (tag, _) -> + var confirmDismiss by remember { mutableStateOf(false) } + val viewModel: EditTagSheetVM = viewModel() + val isCreatingNewTag = tag == null - LaunchedEffect(tag) { - viewModel.init(tag, with(density) { 56.dp.toPx().toInt() }) - } + val density = LocalDensity.current + LaunchedEffect(tag) { + viewModel.init(tag, with(density) { 56.dp.toPx().toInt() }) + } + if (viewModel.loading) return@BottomSheet - if (viewModel.loading) return + if (confirmDismiss) { + AlertDialog( + onDismissRequest = { confirmDismiss = false }, + dismissButton = { + OutlinedButton(onClick = { + confirmDismiss = false + }) { + Text(stringResource(android.R.string.cancel)) + } + }, + confirmButton = { + Button(onClick = { + confirmDismiss = false + onDismiss() + }) { + Text(stringResource(R.string.action_quit)) + } + }, + text = { + Text(stringResource(R.string.dialog_discard_unsaved)) + } + ) + } - DismissableBottomSheet( - onDismissRequest = { - if (viewModel.page == EditTagSheetPage.CustomizeTag) { - viewModel.save() - onTagSaved(viewModel.tagName) + Column { + CenterAlignedTopAppBar( + title = { + when (viewModel.page) { + EditTagSheetPage.CreateTag, + EditTagSheetPage.CustomizeTag -> { + Text(stringResource(if (isCreatingNewTag) R.string.create_tag_title else R.string.edit_tag_title)) + } + + EditTagSheetPage.PickItems -> { + Text(stringResource(R.string.tag_select_items)) + } + + else -> {} + } + }, + navigationIcon = { + if (viewModel.page == EditTagSheetPage.PickIcon) { + FilledTonalIconButton(onClick = { + viewModel.closeItemPicker() + }) { + Icon( + painterResource(R.drawable.arrow_back_24px), + stringResource(R.string.menu_back) + ) + } + } + if (viewModel.page == EditTagSheetPage.PickItems && viewModel.wasOnLastPage) { + FilledTonalIconButton(onClick = { + viewModel.closeItemPicker() + }) { + Icon( + painterResource(R.drawable.arrow_back_24px), + stringResource(R.string.menu_back) + ) + } + } + }, + actions = { + if (viewModel.page != EditTagSheetPage.PickIcon && viewModel.page != EditTagSheetPage.PickItems || !viewModel.wasOnLastPage) { + FilledTonalIconButton( + onClick = { + if (viewModel.page == EditTagSheetPage.PickItems || viewModel.page == EditTagSheetPage.CustomizeTag) { + confirmDismiss = true + } else { + onDismiss() + } + }, + ) { + Icon( + painterResource(R.drawable.close_24px), + stringResource(R.string.close) + ) + } + } + }, + ) + + AnimatedContent( + viewModel.page, + modifier = Modifier.weight(1f, false) + ) { page -> + when (page) { + EditTagSheetPage.CreateTag -> CreateNewTagPage(viewModel) + EditTagSheetPage.PickItems -> PickItems(viewModel) + EditTagSheetPage.CustomizeTag -> CustomizeTag(viewModel) + EditTagSheetPage.PickIcon -> PickIcon(viewModel) + } + } + AnimatedVisibility( + viewModel.page == EditTagSheetPage.CustomizeTag || + viewModel.page == EditTagSheetPage.CreateTag || + (viewModel.page == EditTagSheetPage.PickItems) + ) { + FlexibleBottomAppBar( + horizontalArrangement = Arrangement.End, + ) { + when (viewModel.page) { + EditTagSheetPage.CreateTag -> { + Button( + modifier = Modifier.navigationBarsPadding(), + enabled = (viewModel.tagName.isNotBlank() && viewModel.page == EditTagSheetPage.CreateTag && !viewModel.tagNameExists), + onClick = { viewModel.onClickContinue() }) { + Text(stringResource(R.string.action_next)) + } + } + + EditTagSheetPage.PickItems -> { + Button( + modifier = Modifier.navigationBarsPadding(), + enabled = viewModel.taggedItems.isNotEmpty() || viewModel.wasOnLastPage, + onClick = { viewModel.onClickContinue() }) { + Text(stringResource(if (viewModel.wasOnLastPage) R.string.action_done else R.string.action_next)) + } + } + + EditTagSheetPage.CustomizeTag -> { + Button( + modifier = Modifier.navigationBarsPadding(), + enabled = (viewModel.tagName.isNotBlank()), + onClick = { + viewModel.save() + onTagSaved(viewModel.tagName) + onDismiss() + }) { + Text( + stringResource(if(viewModel.taggedItems.isEmpty()) R.string.menu_delete else R.string.save) + ) + } + } + + else -> {} + } + + } } - onDismiss() - }, - ) { - when (viewModel.page) { - EditTagSheetPage.CreateTag -> CreateNewTagPage(viewModel, it) - EditTagSheetPage.PickItems -> PickItems(viewModel, it) - EditTagSheetPage.CustomizeTag -> CustomizeTag(viewModel, it) - EditTagSheetPage.PickIcon -> PickIcon(viewModel, it) } } } @Composable -fun CreateNewTagPage(viewModel: EditTagSheetVM, paddingValues: PaddingValues) { +fun CreateNewTagPage(viewModel: EditTagSheetVM) { Column( modifier = Modifier .verticalScroll(rememberScrollState()) - .padding(paddingValues) + .padding(16.dp) ) { OutlinedTextField( modifier = Modifier.fillMaxWidth(), @@ -123,55 +263,47 @@ fun CreateNewTagPage(viewModel: EditTagSheetVM, paddingValues: PaddingValues) { value = viewModel.tagName, onValueChange = { viewModel.tagName = it } ) - - Button( - modifier = Modifier.align(Alignment.End), - enabled = (viewModel.tagName.isNotBlank() && viewModel.page == EditTagSheetPage.CreateTag && !viewModel.tagNameExists) - || (viewModel.page == EditTagSheetPage.PickItems && viewModel.taggedItems.isNotEmpty()), - onClick = { viewModel.onClickContinue() }) { - Text(stringResource(R.string.action_next)) - } } } @Composable -fun PickItems(viewModel: EditTagSheetVM, paddingValues: PaddingValues) { +fun PickItems(viewModel: EditTagSheetVM) { val columns = LocalGridSettings.current.columnCount - 1 - Scaffold( - contentWindowInsets = WindowInsets(0.dp), - containerColor = Color.Transparent, - bottomBar = { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 8.dp), - contentAlignment = Alignment.CenterEnd - ) { - - ExtendedFloatingActionButton( - modifier = Modifier.padding(paddingValues), - onClick = { viewModel.closeItemPicker() } - ) { - Text(stringResource(R.string.action_next)) - } - } + if (viewModel.wasOnLastPage) { + BackHandler { + viewModel.closeIconPicker() } + } + + LazyVerticalGrid( + modifier = Modifier.fillMaxWidth(), + columns = GridCells.Fixed(columns), + contentPadding = PaddingValues(16.dp) ) { - LazyVerticalGrid( - modifier = Modifier.fillMaxWidth(), - columns = GridCells.Fixed(columns), - contentPadding = it - ) { + items(viewModel.taggableApps) { + val iconSize = 32.dp.toPixels() + val icon by remember(it.item.key) { + viewModel.getIcon(it.item, iconSize.toInt()) + }.collectAsState(null) + ListItem(item = it, icon = icon, onTagChanged = { tagged -> + if (tagged) viewModel.tagItem(it.item) + else viewModel.untagItem(it.item) + }) + } + + if (viewModel.taggableOther.isNotEmpty()) { item(span = { GridItemSpan(columns) }) { - Text( - stringResource(id = R.string.tag_select_items), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.secondary, - modifier = Modifier.padding(bottom = 8.dp) + Box( + modifier = Modifier + .padding(vertical = 8.dp) + .background(MaterialTheme.colorScheme.outlineVariant) + .fillMaxWidth() + .height(1.dp) ) } - items(viewModel.taggableApps) { + + items(viewModel.taggableOther) { val iconSize = 32.dp.toPixels() val icon by remember(it.item.key) { viewModel.getIcon(it.item, iconSize.toInt()) @@ -181,29 +313,6 @@ fun PickItems(viewModel: EditTagSheetVM, paddingValues: PaddingValues) { else viewModel.untagItem(it.item) }) } - - if (viewModel.taggableOther.isNotEmpty()) { - item(span = { GridItemSpan(columns) }) { - Box( - modifier = Modifier - .padding(vertical = 8.dp) - .background(MaterialTheme.colorScheme.outlineVariant) - .fillMaxWidth() - .height(1.dp) - ) - } - - items(viewModel.taggableOther) { - val iconSize = 32.dp.toPixels() - val icon by remember(it.item.key) { - viewModel.getIcon(it.item, iconSize.toInt()) - }.collectAsState(null) - ListItem(item = it, icon = icon, onTagChanged = { tagged -> - if (tagged) viewModel.tagItem(it.item) - else viewModel.untagItem(it.item) - }) - } - } } } } @@ -261,14 +370,14 @@ fun ListItem( @Composable -fun CustomizeTag(viewModel: EditTagSheetVM, paddingValues: PaddingValues) { +fun CustomizeTag(viewModel: EditTagSheetVM) { val iconSize = 32.dp.toPixels() val tagIcon by remember(viewModel.tagCustomIcon) { viewModel.tagCustomIcon }.collectAsState() Column( modifier = Modifier .verticalScroll(rememberScrollState()) .fillMaxWidth() - .padding(paddingValues) + .padding(16.dp) ) { Row( @@ -329,6 +438,16 @@ fun CustomizeTag(viewModel: EditTagSheetVM, paddingValues: PaddingValues) { label = { Text(stringResource(R.string.tag_name)) }, value = viewModel.tagName, onValueChange = { viewModel.tagName = it }, + isError = viewModel.tagName.isBlank(), + supportingText = if (viewModel.tagName.isBlank() || viewModel.tagNameExists) { + { + Text( + stringResource( + if (viewModel.tagNameExists) R.string.tag_exists_message + else R.string.tag_name_empty_error) + ) + } + } else null ) } @@ -390,28 +509,19 @@ fun CustomizeTag(viewModel: EditTagSheetVM, paddingValues: PaddingValues) { } } } - AnimatedVisibility(viewModel.tagNameExists || viewModel.taggedItems.isEmpty() || viewModel.tagName.isEmpty()) { - SmallMessage( - modifier = Modifier.fillMaxWidth(), - icon = R.drawable.warning_24px, - text = stringResource( - if (viewModel.taggedItems.isEmpty()) R.string.tag_no_items_message - else if (viewModel.tagNameExists) R.string.tag_exists_message - else R.string.tag_empty_name - ) - ) - } } } @Composable fun PickIcon( viewModel: EditTagSheetVM, - paddingValues: PaddingValues ) { + BackHandler { + viewModel.closeIconPicker() + } val icon by remember(viewModel.tagCustomIcon) { viewModel.tagCustomIcon }.collectAsState() val tag = Tag(viewModel.tagName) - var selectedTabIndex = remember { + val selectedTabIndex = remember { mutableIntStateOf( when (icon) { is CustomTextIcon -> 1 @@ -420,7 +530,10 @@ fun PickIcon( ) } Column( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp) + .padding(horizontal = 16.dp) ) { Row( modifier = Modifier.fillMaxWidth(), @@ -437,8 +550,11 @@ fun PickIcon( if (selectedTabIndex.intValue == 0) R.drawable.check_20px else R.drawable.apps_20px ), null, - modifier = Modifier.padding(end = ToggleButtonDefaults.IconSpacing).size( - ToggleButtonDefaults.IconSize) + modifier = Modifier + .padding(end = ToggleButtonDefaults.IconSpacing) + .size( + ToggleButtonDefaults.IconSize + ) ) Text(stringResource(R.string.tag_icon_customicon)) } @@ -469,7 +585,10 @@ fun PickIcon( IconPicker( searchable = tag, onSelect = { viewModel.selectIcon(it) }, - contentPadding = paddingValues + contentPadding = PaddingValues( + bottom = 16.dp + WindowInsets.navigationBars.asPaddingValues() + .calculateBottomPadding() + ) ) } @@ -481,7 +600,10 @@ fun PickIcon( onEmojiSelected = { viewModel.selectIcon(CustomTextIcon(text = it)) }, - contentPadding = paddingValues + contentPadding = PaddingValues( + bottom = 16.dp + WindowInsets.navigationBars.asPaddingValues() + .calculateBottomPadding() + ) ) } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheetVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheetVM.kt index 962e6bbc8..7103a952b 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheetVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditTagSheetVM.kt @@ -41,6 +41,7 @@ class EditTagSheetVM : ViewModel(), KoinComponent { var loading by mutableStateOf(true) var page by mutableStateOf(EditTagSheetPage.CreateTag) + var wasOnLastPage by mutableStateOf(false) var taggedItems by mutableStateOf(emptyList()) var taggableApps by mutableStateOf(emptyList()) @@ -56,6 +57,7 @@ class EditTagSheetVM : ViewModel(), KoinComponent { this.oldTagName = tag this.tagName = tag ?: "" this.page = if (tag == null) EditTagSheetPage.CreateTag else EditTagSheetPage.CustomizeTag + this.wasOnLastPage = this.page == EditTagSheetPage.CustomizeTag this.taggedItems = emptyList() viewModelScope.launch(Dispatchers.Default) { allTags = tagService.getAllTags().first().toSet() @@ -80,7 +82,7 @@ class EditTagSheetVM : ViewModel(), KoinComponent { fun save() { val oldName = oldTagName val newName = tagName - val tagIcon = tagCustomIcon + val tagIcon = tagCustomIcon.value if ((taggedItems.isEmpty() || tagName.isEmpty()) && oldName != null) tagService.deleteTag(oldName) else if (oldName != null) tagService.updateTag(oldName, newName = newName, items = taggedItems) else tagService.createTag(tagName, taggedItems) @@ -89,16 +91,18 @@ class EditTagSheetVM : ViewModel(), KoinComponent { iconService.setCustomIcon(Tag(oldName), null) } if (tagIcon != null) { - iconService.setCustomIcon(Tag(newName), tagCustomIcon.value) + iconService.setCustomIcon(Tag(newName), tagIcon) } else { iconService.setCustomIcon(Tag(newName), null) } - loading = true } fun onClickContinue() { if (page == EditTagSheetPage.CreateTag && tagNameExists) return page = if (page == EditTagSheetPage.CreateTag) EditTagSheetPage.PickItems else EditTagSheetPage.CustomizeTag + if (page == EditTagSheetPage.CustomizeTag) { + wasOnLastPage = true + } oldTagName = tagName } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/LauncherBottomSheets.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/LauncherBottomSheets.kt index 0c581db52..b4ce537a3 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/LauncherBottomSheets.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/LauncherBottomSheets.kt @@ -11,9 +11,11 @@ fun LauncherBottomSheets() { EditFavoritesSheet( expanded = bottomSheetManager.editFavoritesSheetShown.value, onDismiss = { bottomSheetManager.dismissEditFavoritesSheet() }) - bottomSheetManager.editTagSheetShown.value?.let { - EditTagSheet(tag = it, onDismiss = { bottomSheetManager.dismissEditTagSheet() }) - } + EditTagSheet( + expanded = bottomSheetManager.editTagSheetShown.value != null, + tag = bottomSheetManager.editTagSheetShown.value, + onDismiss = { bottomSheetManager.dismissEditTagSheet() } + ) FailedGestureSheet( bottomSheetManager.failedGestureSheetShown.value, onDismiss = { bottomSheetManager.dismissFailedGestureSheet() } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt index a3bf86f1d..3b25b0fc8 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt @@ -5,6 +5,8 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -404,6 +406,7 @@ fun SearchSettingsScreen() { val filters by viewModel.searchFilters.collectAsStateWithLifecycle() Column( modifier = Modifier + .verticalScroll(rememberScrollState()) .padding(16.dp) .navigationBarsPadding() ) { diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/shapes/ShapeSchemeSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/shapes/ShapeSchemeSettingsScreen.kt index d9af08a19..a1279c3f4 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/shapes/ShapeSchemeSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/shapes/ShapeSchemeSettingsScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -505,8 +506,8 @@ fun ShapePreference( Column( modifier = Modifier .verticalScroll(rememberScrollState()) - .padding(it) - .padding(bottom = 8.dp), + .padding(16.dp) + .navigationBarsPadding(), verticalArrangement = Arrangement.spacedBy(16.dp) ) { val previewShape = if ((currentCornerStyle ?: baseShape.corners diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/tags/TagsSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/tags/TagsSettingsScreen.kt index 2c6707454..f2dba2b0a 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/tags/TagsSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/tags/TagsSettingsScreen.kt @@ -111,21 +111,20 @@ fun TagsSettingsScreen() { } } } - if (viewModel.editTag.value != null) { - EditTagSheet( - tag = viewModel.editTag.value, - onDismiss = { - viewModel.editTag.value = null - viewModel.createTag.value = false - } - ) - } else if (viewModel.createTag.value) { - EditTagSheet( - tag = null, - onDismiss = { - viewModel.createTag.value = false - viewModel.editTag.value = null - } - ) - } + EditTagSheet( + expanded = viewModel.editTag.value != null, + tag = viewModel.editTag.value, + onDismiss = { + viewModel.editTag.value = null + viewModel.createTag.value = false + } + ) + EditTagSheet( + expanded = viewModel.createTag.value, + tag = null, + onDismiss = { + viewModel.createTag.value = false + viewModel.editTag.value = null + } + ) } \ No newline at end of file diff --git a/core/i18n/src/main/res/values/strings.xml b/core/i18n/src/main/res/values/strings.xml index 4eb1e009b..b1dfc3ae4 100644 --- a/core/i18n/src/main/res/values/strings.xml +++ b/core/i18n/src/main/res/values/strings.xml @@ -768,10 +768,10 @@ More information Experimental A tag with this name already exists + Tag name cannot be empty A tag with this name already exists. If you continue, the two tags will be merged No items are assigned to this tag. If you continue, the tag will be deleted - A tag cannot exist without a name. If you continue, the tag will be deleted - Select items: + Select items Tag name Icon Emoji @@ -1088,5 +1088,7 @@ Automatic Disabled Select tag + New tag + Edit tag Quit without saving?