From 71d4ecf4bc3dc77ff03067407cd65ed0a7c6197e Mon Sep 17 00:00:00 2001 From: Alexandre G Pereira Date: Fri, 16 Aug 2024 12:59:14 -0300 Subject: [PATCH] Improve button and remove focus when scrolling (#319) * Improve button and remove focus when scrolling * Scroll to start of folder preview when monster size changes --- .../hunter/app/ui/AppBottomNavigation.kt | 1 + .../hunter/folder/list/ui/ItemSelection.kt | 4 +- .../folder/preview/FolderPreviewFeature.kt | 2 + .../hunter/folder/preview/ui/FolderPreview.kt | 4 ++ .../folder/preview/ui/FolderPreviewScreen.kt | 19 +++++++ .../folder/preview/FolderPreviewAction.kt | 5 ++ .../preview/FolderPreviewStateHolder.kt | 10 +++- .../monster/content/ui/MonsterContentCard.kt | 8 +-- .../hunter/detail/ui/IconInfo.kt | 10 ++-- .../hunter/detail/ui/MonsterDetailScreen.kt | 4 +- .../ui/MonsterRegistrationScreen.kt | 3 ++ .../hunter/search/ui/SearchScreen.kt | 3 ++ .../hunter/ui/compendium/Compendium.kt | 4 +- .../hunter/ui/compose/AppButton.kt | 34 ++++++++----- .../hunter/ui/compose/AppTextField.kt | 10 ++++ .../hunter/ui/compose/Card.kt | 51 +++++++++++++++++++ .../hunter/ui/compose/Common.kt | 19 +++---- .../hunter/ui/compose/IconInfo.kt | 5 +- .../hunter/ui/compose/MonsterCard.kt | 3 +- .../compose/tablecontent/TableContentPopup.kt | 4 +- .../hunter/ui/theme/Theme.kt | 4 +- 21 files changed, 157 insertions(+), 50 deletions(-) create mode 100644 feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewAction.kt create mode 100644 ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Card.kt diff --git a/app/src/commonMain/kotlin/br/alexandregpereira/hunter/app/ui/AppBottomNavigation.kt b/app/src/commonMain/kotlin/br/alexandregpereira/hunter/app/ui/AppBottomNavigation.kt index 2118b7346..269d54e15 100644 --- a/app/src/commonMain/kotlin/br/alexandregpereira/hunter/app/ui/AppBottomNavigation.kt +++ b/app/src/commonMain/kotlin/br/alexandregpereira/hunter/app/ui/AppBottomNavigation.kt @@ -82,6 +82,7 @@ internal fun AppBottomNavigation( val paddingBottom = contentPadding.calculateBottomPadding() BottomNavigation( backgroundColor = MaterialTheme.colors.surface, + contentColor = MaterialTheme.colors.onSurface, elevation = 0.dp, modifier = Modifier.height(BottomNavigationHeight + paddingBottom) .padding(bottom = paddingBottom) diff --git a/feature/folder-list/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/list/ui/ItemSelection.kt b/feature/folder-list/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/list/ui/ItemSelection.kt index b9b2af15f..ccad5a84a 100644 --- a/feature/folder-list/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/list/ui/ItemSelection.kt +++ b/feature/folder-list/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/list/ui/ItemSelection.kt @@ -24,12 +24,12 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import br.alexandregpereira.hunter.ui.compose.AppButton +import br.alexandregpereira.hunter.ui.compose.AppCard import br.alexandregpereira.hunter.ui.compose.BottomSheet import br.alexandregpereira.hunter.ui.compose.ScreenHeader import br.alexandregpereira.hunter.ui.theme.HunterTheme @@ -50,7 +50,7 @@ internal fun ItemSelection( closeClickingOutside = false, onClose = onClose, ) { - Card( + AppCard( shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), modifier = modifier .fillMaxWidth() diff --git a/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewFeature.kt b/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewFeature.kt index b5f32675f..74e7a757d 100644 --- a/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewFeature.kt +++ b/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewFeature.kt @@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import br.alexandregpereira.hunter.folder.preview.ui.FolderPreviewScreen import org.koin.compose.koinInject @@ -34,6 +35,7 @@ fun FolderPreviewFeature( FolderPreviewScreen( state = state, + actionHandler = remember(stateHolder) { stateHolder }, contentPadding = contentPadding, onClick = stateHolder::onItemClick, onLongClick = stateHolder::onItemLongClick, diff --git a/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreview.kt b/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreview.kt index 8e588c5f0..8490c3320 100644 --- a/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreview.kt +++ b/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreview.kt @@ -26,8 +26,10 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -43,6 +45,7 @@ fun FolderPreview( monsters: List, saveButtonText: String, modifier: Modifier = Modifier, + lazyListState: LazyListState = rememberLazyListState(), contentPadding: PaddingValues = PaddingValues(), onClick: (index: String) -> Unit = {}, onLongClick: (index: String) -> Unit = {}, @@ -53,6 +56,7 @@ fun FolderPreview( Row { LazyRow( modifier = Modifier.fillMaxWidth(0.7f), + state = lazyListState, horizontalArrangement = Arrangement.spacedBy(16.dp), contentPadding = PaddingValues(horizontal = 16.dp) ) { diff --git a/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreviewScreen.kt b/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreviewScreen.kt index a05744a84..855b27f19 100644 --- a/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreviewScreen.kt +++ b/feature/folder-preview/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/ui/FolderPreviewScreen.kt @@ -24,13 +24,19 @@ import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier +import br.alexandregpereira.hunter.folder.preview.FolderPreviewAction import br.alexandregpereira.hunter.folder.preview.FolderPreviewState +import br.alexandregpereira.hunter.state.ActionHandler +import kotlinx.coroutines.flow.collectLatest @Composable internal fun FolderPreviewScreen( state: FolderPreviewState, + actionHandler: ActionHandler, contentPadding: PaddingValues = PaddingValues(), modifier: Modifier = Modifier, onClick: (index: String) -> Unit = {}, @@ -43,8 +49,21 @@ internal fun FolderPreviewScreen( exit = fadeOut(animationSpec = spring()), modifier = modifier ) { + val lazyListState = rememberLazyListState() + + LaunchedEffect(lazyListState, actionHandler) { + actionHandler.action.collectLatest { event -> + when (event) { + is FolderPreviewAction.ScrollToStart -> { + lazyListState.animateScrollToItem(0) + } + } + } + } + FolderPreview( monsters = state.monsters, + lazyListState = lazyListState, saveButtonText = state.strings.save, contentPadding = contentPadding, onClick = onClick, diff --git a/feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewAction.kt b/feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewAction.kt new file mode 100644 index 000000000..13f79fe66 --- /dev/null +++ b/feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewAction.kt @@ -0,0 +1,5 @@ +package br.alexandregpereira.hunter.folder.preview + +sealed class FolderPreviewAction { + data object ScrollToStart : FolderPreviewAction() +} diff --git a/feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewStateHolder.kt b/feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewStateHolder.kt index 1abef20b4..cc5b65776 100644 --- a/feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewStateHolder.kt +++ b/feature/folder-preview/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/folder/preview/FolderPreviewStateHolder.kt @@ -29,8 +29,10 @@ import br.alexandregpereira.hunter.localization.AppLocalization import br.alexandregpereira.hunter.monster.event.MonsterEvent.OnVisibilityChanges.Show import br.alexandregpereira.hunter.monster.event.MonsterEventDispatcher import br.alexandregpereira.hunter.monster.event.collectOnMonsterCompendiumChanges +import br.alexandregpereira.hunter.state.MutableActionHandler import br.alexandregpereira.hunter.state.UiModel import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn @@ -49,7 +51,8 @@ class FolderPreviewStateHolder internal constructor( private val dispatcher: CoroutineDispatcher, private val analytics: FolderPreviewAnalytics, private val appLocalization: AppLocalization, -) : UiModel(FolderPreviewState()) { +) : UiModel(FolderPreviewState()), + MutableActionHandler by MutableActionHandler() { init { observeEvents() @@ -113,7 +116,12 @@ class FolderPreviewStateHolder internal constructor( addMonsterToFolderPreview(index) .flowOn(dispatcher) .onEach { monsters -> + val previousMonsterListSize = state.value.monsters.size setState { changeMonsters(monsters) } + if (monsters.size > previousMonsterListSize) { + delay(300) + sendAction(FolderPreviewAction.ScrollToStart) + } } .launchIn(scope) } diff --git a/feature/monster-content-manager/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/content/ui/MonsterContentCard.kt b/feature/monster-content-manager/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/content/ui/MonsterContentCard.kt index ac35d91bf..11606be67 100644 --- a/feature/monster-content-manager/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/content/ui/MonsterContentCard.kt +++ b/feature/monster-content-manager/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/content/ui/MonsterContentCard.kt @@ -8,9 +8,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.material.Card import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -24,6 +22,8 @@ import br.alexandregpereira.hunter.monster.content.MonsterContentManagerEmptyStr import br.alexandregpereira.hunter.monster.content.MonsterContentManagerStrings import br.alexandregpereira.hunter.ui.compose.AppButton import br.alexandregpereira.hunter.ui.compose.AppButtonSize +import br.alexandregpereira.hunter.ui.compose.AppCard +import br.alexandregpereira.hunter.ui.compose.AppSurface import br.alexandregpereira.hunter.ui.compose.CoilImage import br.alexandregpereira.hunter.ui.compose.SectionTitle import br.alexandregpereira.hunter.ui.compose.cardShape @@ -44,7 +44,7 @@ internal fun MonsterContentCard( onAddClick: () -> Unit = {}, onRemoveClick: () -> Unit = {}, onPreviewClick: () -> Unit = {}, -) = Card(modifier = modifier, shape = cardShape) { +) = AppCard(modifier = modifier, shape = cardShape) { Column(Modifier.padding(16.dp)) { Title( name = name, @@ -189,7 +189,7 @@ private fun Buttons( @Preview @Composable private fun MonsterContentCardPreview() = HunterTheme { - Surface { + AppSurface { MonsterContentCard( name = "Name", originalName = "Other name", diff --git a/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/IconInfo.kt b/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/IconInfo.kt index de6556fd6..db18c75c6 100644 --- a/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/IconInfo.kt +++ b/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/IconInfo.kt @@ -19,7 +19,6 @@ package br.alexandregpereira.hunter.detail.ui import androidx.compose.foundation.layout.PaddingValues import androidx.compose.material.LocalContentAlpha import androidx.compose.material.LocalContentColor -import androidx.compose.material.Surface import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite import androidx.compose.runtime.Composable @@ -27,13 +26,14 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.rememberVectorPainter -import org.jetbrains.compose.resources.painterResource -import org.jetbrains.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import br.alexandregpereira.hunter.detail.ui.resources.Res import br.alexandregpereira.hunter.detail.ui.resources.ic_shield +import br.alexandregpereira.hunter.ui.compose.AppSurface import br.alexandregpereira.hunter.ui.theme.HunterTheme +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview import br.alexandregpereira.hunter.ui.compose.IconInfo as IconInfoUi @Composable @@ -61,7 +61,7 @@ internal fun IconInfo( @Composable private fun IconInfoArmorClassPreview() { HunterTheme { - Surface { + AppSurface { IconInfo( title = "Armor Class", painter = painterResource(Res.drawable.ic_shield), @@ -77,7 +77,7 @@ private fun IconInfoArmorClassPreview() { @Composable private fun IconInfoHitPointPreview() { HunterTheme { - Surface { + AppSurface { IconInfo( title = "28d20 + 252", painter = rememberVectorPainter(image = Icons.Filled.Favorite), diff --git a/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/MonsterDetailScreen.kt b/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/MonsterDetailScreen.kt index e4da3c13b..1bf0be6b6 100644 --- a/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/MonsterDetailScreen.kt +++ b/feature/monster-detail/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/detail/ui/MonsterDetailScreen.kt @@ -41,7 +41,6 @@ import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.runtime.Composable @@ -70,6 +69,7 @@ import br.alexandregpereira.hunter.monster.detail.MonsterState import br.alexandregpereira.hunter.monster.detail.SpeedState import br.alexandregpereira.hunter.monster.detail.StatsState import br.alexandregpereira.hunter.ui.compose.AppBarIcon +import br.alexandregpereira.hunter.ui.compose.AppSurface import br.alexandregpereira.hunter.ui.compose.BoxCloseButton import br.alexandregpereira.hunter.ui.compose.ChallengeRatingCircle import br.alexandregpereira.hunter.ui.compose.LocalScreenSize @@ -99,7 +99,7 @@ internal fun MonsterDetailScreen( onSpellClicked: (String) -> Unit = {}, onLoreClicked: (String) -> Unit = {}, onClose: () -> Unit = {}, -) = Surface(color = Color.Transparent) { +) = AppSurface(color = Color.Transparent) { HorizontalPagerTransitionController(pagerState) MonsterImageCompose( diff --git a/feature/monster-registration/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/registration/ui/MonsterRegistrationScreen.kt b/feature/monster-registration/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/registration/ui/MonsterRegistrationScreen.kt index b54c5042f..0985ae35f 100644 --- a/feature/monster-registration/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/registration/ui/MonsterRegistrationScreen.kt +++ b/feature/monster-registration/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/monster/registration/ui/MonsterRegistrationScreen.kt @@ -18,6 +18,7 @@ import br.alexandregpereira.hunter.monster.registration.MonsterRegistrationInten import br.alexandregpereira.hunter.monster.registration.MonsterRegistrationState import br.alexandregpereira.hunter.state.ActionHandler import br.alexandregpereira.hunter.ui.compose.AppScreen +import br.alexandregpereira.hunter.ui.compose.ClearFocusWhenScrolling import br.alexandregpereira.hunter.ui.compose.LocalScreenSize import br.alexandregpereira.hunter.ui.compose.isLandscape import br.alexandregpereira.hunter.ui.compose.maxBottomSheetWidth @@ -53,6 +54,8 @@ internal fun MonsterRegistrationScreen( } } + ClearFocusWhenScrolling(lazyListState) + MonsterRegistrationForm( monster = state.monster, lazyListState = lazyListState, diff --git a/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/ui/SearchScreen.kt b/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/ui/SearchScreen.kt index 3290633bd..a191a2143 100644 --- a/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/ui/SearchScreen.kt +++ b/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/ui/SearchScreen.kt @@ -37,6 +37,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import br.alexandregpereira.hunter.ui.compose.ClearFocusWhenScrolling import kotlin.math.absoluteValue @Composable @@ -52,6 +53,8 @@ internal fun SearchScreen( val listState = rememberLazyGridState() val focusManager = LocalFocusManager.current + ClearFocusWhenScrolling(listState) + SearchGrid( monsterRows = state.monsterRows, totalResults = state.searchResults, diff --git a/ui/compendium/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compendium/Compendium.kt b/ui/compendium/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compendium/Compendium.kt index 401e15d54..f8152550a 100644 --- a/ui/compendium/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compendium/Compendium.kt +++ b/ui/compendium/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compendium/Compendium.kt @@ -27,7 +27,6 @@ import androidx.compose.foundation.lazy.grid.LazyGridItemScope import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.material.Card import androidx.compose.material.MaterialTheme.colors import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -36,6 +35,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import br.alexandregpereira.hunter.ui.compose.AppCard import br.alexandregpereira.hunter.ui.compose.SectionTitle import br.alexandregpereira.hunter.ui.compose.imageCardElevation import br.alexandregpereira.hunter.ui.compose.imageCardShape @@ -95,7 +95,7 @@ fun Compendium( } val titleModifier = Modifier.monsterAspectRatio().takeIf { isTileCard } ?: Modifier - Card( + AppCard( shape = imageCardShape, elevation = imageCardElevation.takeIf { isTileCard } ?: 0.dp, backgroundColor = colors.surface.takeIf { isTileCard } diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppButton.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppButton.kt index 8f9eb1a85..93697f5df 100644 --- a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppButton.kt +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppButton.kt @@ -16,17 +16,21 @@ package br.alexandregpereira.hunter.ui.compose +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Button -import androidx.compose.material.ButtonDefaults import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -40,21 +44,21 @@ fun AppButton( enabled: Boolean = true, onClick: () -> Unit = {} ) { - Button( - enabled = enabled, - shape = RoundedCornerShape(24.dp), - colors = ButtonDefaults.buttonColors( - backgroundColor = MaterialTheme.colors.surface, - ), - elevation = ButtonDefaults.elevation( - defaultElevation = 8.dp, - pressedElevation = 2.dp, - ), + val backgroundColorAlpha by animateFloatAsState( + targetValue = if (enabled) 1f else 0.5f + ) + + Box( modifier = modifier .height(size.height.dp) .fillMaxWidth() - .animatePressed(), - onClick = onClick + .animatePressed( + enabled = enabled, + onClick = onClick + ) + .clip(RoundedCornerShape(24.dp)) + .background(color = MaterialTheme.colors.primary.copy(alpha = backgroundColorAlpha)), + contentAlignment = Alignment.Center ) { val fontSizes = when (size) { AppButtonSize.VERY_SMALL -> 12.sp @@ -64,7 +68,9 @@ fun AppButton( Text( text = text, fontWeight = FontWeight.Normal, + color = MaterialTheme.colors.onPrimary.copy(alpha = backgroundColorAlpha), fontSize = fontSizes, + modifier = Modifier.padding(horizontal = 16.dp) ) } } diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppTextField.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppTextField.kt index cc8eb4915..d476a934c 100644 --- a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppTextField.kt +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/AppTextField.kt @@ -19,6 +19,7 @@ package br.alexandregpereira.hunter.ui.compose import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.foundation.gestures.ScrollableState import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardActions @@ -32,6 +33,7 @@ import androidx.compose.material.TextFieldDefaults import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Clear import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.input.KeyboardCapitalization @@ -182,3 +184,11 @@ enum class AppKeyboardType { TEXT, NUMBER } + +@Composable +fun ClearFocusWhenScrolling(scrollableState: ScrollableState) { + val focusManager = LocalFocusManager.current + LaunchedEffect(scrollableState.isScrollInProgress) { + if (scrollableState.isScrollInProgress) focusManager.clearFocus() + } +} diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Card.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Card.kt new file mode 100644 index 000000000..645e8f9c1 --- /dev/null +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Card.kt @@ -0,0 +1,51 @@ +package br.alexandregpereira.hunter.ui.compose + +import androidx.compose.foundation.BorderStroke +import androidx.compose.material.Card +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +@Composable +fun AppSurface( + modifier: Modifier = Modifier, + shape: Shape = RectangleShape, + color: Color = MaterialTheme.colors.surface, + contentColor: Color = MaterialTheme.colors.onSurface, + border: BorderStroke? = null, + elevation: Dp = 0.dp, + content: @Composable () -> Unit +) = Surface( + modifier = modifier, + shape = shape, + color = color, + contentColor = contentColor, + border = border, + elevation = elevation, + content = content +) + +@Composable +fun AppCard( + modifier: Modifier = Modifier, + shape: Shape = MaterialTheme.shapes.medium, + backgroundColor: Color = MaterialTheme.colors.surface, + contentColor: Color = MaterialTheme.colors.onSurface, + border: BorderStroke? = null, + elevation: Dp = 1.dp, + content: @Composable () -> Unit +) = Card( + modifier = modifier, + shape = shape, + backgroundColor = backgroundColor, + contentColor = contentColor, + border = border, + elevation = elevation, + content = content +) diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Common.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Common.kt index c486d3051..f2fd11a13 100644 --- a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Common.kt +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/Common.kt @@ -28,7 +28,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -59,16 +58,14 @@ fun Window( backgroundColor: Color = MaterialTheme.colors.surface, level: Int = 1, content: @Composable () -> Unit -) { - Surface( - color = backgroundColor, - content = content, - elevation = elevation, - modifier = modifier - .padding((level * 4).dp) - .clip(shape = cardShape), - ) -} +) = AppSurface( + color = backgroundColor, + content = content, + elevation = elevation, + modifier = modifier + .padding((level * 4).dp) + .clip(shape = cardShape), +) @Composable fun PreviewWindow( diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/IconInfo.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/IconInfo.kt index f1cf694a2..731edcbb8 100644 --- a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/IconInfo.kt +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/IconInfo.kt @@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.material.Icon import androidx.compose.material.LocalContentAlpha import androidx.compose.material.LocalContentColor -import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite @@ -99,7 +98,7 @@ fun IconInfo( @Composable fun IconInfoArmorClassPreview() { HunterTheme { - Surface { + AppSurface { IconInfo( painter = painterResource(resource = Res.drawable.ic_school_conjuration), iconColor = Color.Blue, @@ -114,7 +113,7 @@ fun IconInfoArmorClassPreview() { @Composable fun IconInfoHitPointPreview() { HunterTheme { - Surface { + AppSurface { IconInfo( title = "28d20 + 252", painter = rememberVectorPainter(image = Icons.Filled.Favorite), diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/MonsterCard.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/MonsterCard.kt index 0f0f81eda..0a5be94d1 100644 --- a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/MonsterCard.kt +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/MonsterCard.kt @@ -21,7 +21,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.Card import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -79,7 +78,7 @@ fun ImageCard( val shape = imageCardShape val alpha = 0.7f val borderColor = MaterialTheme.colors.surface - Card( + AppCard( backgroundColor = Color.Transparent, contentColor = MaterialTheme.colors.onSurface, elevation = imageCardElevation, diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/tablecontent/TableContentPopup.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/tablecontent/TableContentPopup.kt index efd9d5db2..1b3fb5853 100644 --- a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/tablecontent/TableContentPopup.kt +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/compose/tablecontent/TableContentPopup.kt @@ -39,7 +39,6 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close @@ -57,6 +56,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import br.alexandregpereira.hunter.ui.compose.AppSurface import br.alexandregpereira.hunter.ui.compose.BackHandler import br.alexandregpereira.hunter.ui.compose.noIndicationClick import kotlin.math.ln @@ -208,7 +208,7 @@ private fun CircleLetter( private fun Circle( onClick: () -> Unit, content: @Composable BoxScope.() -> Unit -) = Surface( +) = AppSurface( elevation = elevation.dp, shape = CircleShape, modifier = Modifier.padding( diff --git a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/theme/Theme.kt b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/theme/Theme.kt index 12cb41f3d..89d553cef 100644 --- a/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/theme/Theme.kt +++ b/ui/core/src/commonMain/kotlin/br/alexandregpereira/hunter/ui/theme/Theme.kt @@ -31,7 +31,7 @@ private val DarkColorPalette = darkColors( background = Color.Black, surface = Color(0xFF121212), error = Color(0xFFCF6679), - onPrimary = Color.White, + onPrimary = Color.Black, onSecondary = Color.White, onBackground = Color.White, onSurface = Color.White, @@ -46,7 +46,7 @@ private val LightColorPalette = lightColors( background = GrayScale100, surface = Color.White, error = Color(0xFFB00020), - onPrimary = Color.Black, + onPrimary = Color.White, onSecondary = Color.Black, onBackground = Color.Black, onSurface = Color.Black,