Updated on 2026-08-14

This commit is contained in:
Tangem 2023-08-25 15:07:47 +03:00
parent c353710ba2
commit f6a0cb6428
22 changed files with 403 additions and 224 deletions

View file

@ -2,13 +2,13 @@
package com.tangem.tap.features.home.compose
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -18,24 +18,22 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.learn2earn.presentation.ui.Learn2earnStoriesScreen
import com.tangem.tap.features.home.compose.content.*
import com.tangem.tap.features.home.compose.views.HomeButtons
import com.tangem.tap.features.home.compose.views.SearchCurrenciesButton
import com.tangem.tap.features.home.compose.views.StoriesProgressBar
import com.tangem.tap.features.home.redux.HomeState
import com.tangem.tap.features.home.redux.Stories
import com.tangem.wallet.R
import kotlin.math.max
@Suppress("LongMethod", "ComplexMethod")
@Composable
fun StoriesScreen(
homeState: MutableState<HomeState>,
@ -48,24 +46,21 @@ fun StoriesScreen(
val state = homeState.value
var currentStory by remember { mutableStateOf(state.firstStory) }
val currentStep = { state.stepOf(currentStory) }
val currentStoryIndex by rememberUpdatedState(newValue = state.stepOf(currentStory))
val goToPreviousScreen = {
currentStory = state.stories[max(0, currentStep() - 1)]
val goToPreviousStory = remember(currentStory, currentStoryIndex) {
{ currentStory = state.stories[max(0, currentStoryIndex - 1)] }
}
val goToNextScreen = {
currentStory = if (currentStep() < state.stories.lastIndex) {
state.stories[currentStep() + 1]
} else {
state.firstStory
val goToNextStory = remember(currentStory, currentStoryIndex) {
{
currentStory = if (currentStoryIndex < state.stories.lastIndex) {
state.stories[currentStoryIndex + 1]
} else {
state.firstStory
}
}
}
val isPressed = remember { mutableStateOf(false) }
val isPaused = isPressed.value || homeState.value.scanInProgress
val hideContent = remember { mutableStateOf(true) }
LaunchedEffect(key1 = currentStory.isDarkBackground) {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
@ -73,10 +68,34 @@ fun StoriesScreen(
)
}
StoriesScreenContent(
modifier = Modifier.fillMaxSize(),
config = StoriesScreenContentConfig(
storiesSize = state.stories.lastIndex,
currentStoryIndex = currentStoryIndex,
currentStory = currentStory,
isScanInProgress = homeState.value.scanInProgress,
onGoToPreviousStory = goToPreviousStory,
onGoToNextStory = goToNextStory,
onLearn2earnClick = onLearn2earnClick,
onSearchTokensClick = onSearchTokensClick,
onScanButtonClick = onScanButtonClick,
onShopButtonClick = onShopButtonClick,
),
)
}
@Suppress("LongMethod")
@Composable
private fun StoriesScreenContent(config: StoriesScreenContentConfig, modifier: Modifier = Modifier) {
var isPressed by remember { mutableStateOf(value = false) }
var hideContent by remember { mutableStateOf(value = true) }
val isPaused = isPressed || config.isScanInProgress
val currentStoryDuration = config.currentStory.duration
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF090E13)),
modifier = modifier.background(Color(0xFF090E13)),
) {
Row(
modifier = Modifier.fillMaxSize(),
@ -85,16 +104,16 @@ fun StoriesScreen(
Modifier
.weight(1f)
.fillMaxHeight()
.pointerInput(isPressed) {
.pointerInput(Unit) {
detectTapGestures(
onPress = {
val pressStartTime = System.currentTimeMillis()
isPressed.value = true
isPressed = true
this.tryAwaitRelease()
val pressEndTime = System.currentTimeMillis()
val totalPressTime = pressEndTime - pressStartTime
if (totalPressTime < 200) goToPreviousScreen()
isPressed.value = false
if (totalPressTime < 200) config.onGoToPreviousStory()
isPressed = false
},
)
},
@ -103,22 +122,22 @@ fun StoriesScreen(
Modifier
.weight(1f)
.fillMaxHeight()
.pointerInput(isPressed) {
.pointerInput(Unit) {
detectTapGestures(
onPress = {
val pressStartTime = System.currentTimeMillis()
isPressed.value = true
isPressed = true
this.tryAwaitRelease()
val pressEndTime = System.currentTimeMillis()
val totalPressTime = pressEndTime - pressStartTime
if (totalPressTime < 200) goToNextScreen()
isPressed.value = false
if (totalPressTime < 200) config.onGoToNextStory()
isPressed = false
},
)
},
)
}
if (!currentStory.isDarkBackground) {
if (!config.currentStory.isDarkBackground) {
Image(
modifier = Modifier.fillMaxSize(),
painter = painterResource(id = R.drawable.ic_overlay),
@ -127,22 +146,19 @@ fun StoriesScreen(
)
}
val statusBarInsets = WindowInsets.statusBars
.union(WindowInsets(top = 32.dp))
Column(
modifier = Modifier
.windowInsetsPadding(statusBarInsets)
.statusBarsPadding()
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
StoriesProgressBar(
steps = state.stories.lastIndex,
currentStep = currentStep(),
stepDuration = currentStory.duration,
steps = config.storiesSize,
currentStep = config.currentStoryIndex,
stepDuration = currentStoryDuration,
paused = isPaused,
onStepFinish = goToNextScreen,
onStepFinish = config.onGoToNextStory,
)
Image(
painter = painterResource(id = R.drawable.ic_tangem_logo),
@ -151,78 +167,127 @@ fun StoriesScreen(
modifier = Modifier
.padding(start = 16.dp, top = 10.dp)
.height(17.dp)
.alpha(if (hideContent.value) 0f else 1f)
.alpha(if (hideContent) 0f else 1f)
.align(Alignment.Start),
colorFilter = if (currentStory.isDarkBackground) null else ColorFilter.tint(Color.Black),
colorFilter = if (config.currentStory.isDarkBackground) null else ColorFilter.tint(Color.Black),
)
when (currentStory) {
Stories.OneInchPromo -> Learn2earnStoriesScreen(onLearn2earnClick)
Stories.TangemIntro -> FirstStoriesContent(isPaused, currentStory.duration) { hideContent.value = it }
Stories.RevolutionaryWallet -> StoriesRevolutionaryWallet(currentStory.duration)
Stories.UltraSecureBackup -> StoriesUltraSecureBackup(isPaused, currentStory.duration)
Stories.Currencies -> StoriesCurrencies(isPaused, currentStory.duration)
Stories.Web3 -> StoriesWeb3(isPaused, currentStory.duration)
Stories.WalletForEveryone -> StoriesWalletForEveryone(currentStory.duration)
when (config.currentStory) {
Stories.OneInchPromo -> Learn2earnStoriesScreen(config.onLearn2earnClick)
Stories.TangemIntro -> FirstStoriesContent(isPaused, currentStoryDuration) {
hideContent = it
}
Stories.RevolutionaryWallet -> StoriesRevolutionaryWallet(currentStoryDuration)
Stories.UltraSecureBackup -> StoriesUltraSecureBackup(isPaused, currentStoryDuration)
Stories.Currencies -> StoriesCurrencies(isPaused, currentStoryDuration)
Stories.Web3 -> StoriesWeb3(isPaused, currentStoryDuration)
Stories.WalletForEveryone -> StoriesWalletForEveryone(currentStoryDuration)
}
}
Column(
modifier = Modifier
.navigationBarsPadding()
.padding(bottom = TangemTheme.dimens.spacing16)
.padding(horizontal = TangemTheme.dimens.spacing16)
.align(Alignment.BottomCenter)
.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
) {
if (currentStory == Stories.Currencies) {
Button(
onClick = onSearchTokensClick,
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
.heightIn(48.dp),
colors = ButtonDefaults.textButtonColors(
backgroundColor = Color.White,
contentColor = Color(0xFF080C10),
),
) {
Image(
painter = painterResource(id = R.drawable.ic_search),
contentDescription = null,
)
Text(
text = stringResource(id = R.string.common_search_tokens),
fontWeight = FontWeight.Medium,
fontSize = 16.sp,
textAlign = TextAlign.Center,
)
}
AnimatedVisibility(
visible = config.currentStory == Stories.Currencies,
enter = fadeIn(),
exit = fadeOut(),
) {
SearchCurrenciesButton(
modifier = Modifier.fillMaxWidth(),
onClick = config.onSearchTokensClick,
)
}
if (currentStory != Stories.OneInchPromo) {
AnimatedVisibility(
visible = config.currentStory != Stories.OneInchPromo,
enter = fadeIn(),
exit = fadeOut(),
) {
HomeButtons(
modifier = Modifier
.padding(
start = TangemTheme.dimens.size16,
end = TangemTheme.dimens.size16,
bottom = TangemTheme.dimens.size36,
)
.fillMaxWidth(),
isDarkBackground = currentStory.isDarkBackground,
btnScanStateInProgress = homeState.value.btnScanStateInProgress,
onScanButtonClick = onScanButtonClick,
onShopButtonClick = onShopButtonClick,
modifier = Modifier.fillMaxWidth(),
isDarkBackground = config.currentStory.isDarkBackground,
btnScanStateInProgress = config.isScanInProgress,
onScanButtonClick = config.onScanButtonClick,
onShopButtonClick = config.onShopButtonClick,
)
}
}
}
}
@Preview
private data class StoriesScreenContentConfig(
val storiesSize: Int,
val currentStoryIndex: Int,
val currentStory: Stories,
val isScanInProgress: Boolean,
val onGoToPreviousStory: () -> Unit = {},
val onGoToNextStory: () -> Unit = {},
val onLearn2earnClick: () -> Unit = {},
val onSearchTokensClick: () -> Unit = {},
val onScanButtonClick: () -> Unit = {},
val onShopButtonClick: () -> Unit = {},
)
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun StoriesScreenPreview() {
StoriesScreen(
onLearn2earnClick = {},
onScanButtonClick = {},
onShopButtonClick = {},
onSearchTokensClick = {},
homeState = remember { mutableStateOf(HomeState()) },
)
}
private fun StoriesScreenContentPreview(
@PreviewParameter(StoriesScreenContentConfigProvider::class) config: StoriesScreenContentConfig,
) {
TangemTheme {
StoriesScreenContent(config = config)
}
}
private class StoriesScreenContentConfigProvider : CollectionPreviewParameterProvider<StoriesScreenContentConfig>(
collection = listOf(
StoriesScreenContentConfig(
storiesSize = 6,
currentStoryIndex = 0,
currentStory = Stories.TangemIntro,
isScanInProgress = true,
),
StoriesScreenContentConfig(
storiesSize = 6,
currentStoryIndex = 1,
currentStory = Stories.RevolutionaryWallet,
isScanInProgress = false,
),
StoriesScreenContentConfig(
storiesSize = 6,
currentStoryIndex = 2,
currentStory = Stories.UltraSecureBackup,
isScanInProgress = false,
),
StoriesScreenContentConfig(
storiesSize = 6,
currentStoryIndex = 3,
currentStory = Stories.Currencies,
isScanInProgress = false,
),
StoriesScreenContentConfig(
storiesSize = 6,
currentStoryIndex = 4,
currentStory = Stories.Web3,
isScanInProgress = false,
),
StoriesScreenContentConfig(
storiesSize = 6,
currentStoryIndex = 5,
currentStory = Stories.WalletForEveryone,
isScanInProgress = false,
),
StoriesScreenContentConfig(
storiesSize = 6,
currentStoryIndex = 6,
currentStory = Stories.OneInchPromo,
isScanInProgress = false,
),
),
)
// endregion Preview

View file

@ -1,22 +1,22 @@
package com.tangem.tap.features.home.compose.content
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.common.compose.extensions.dpSize
import com.tangem.tap.common.compose.extensions.halfHeight
import com.tangem.tap.common.compose.extensions.toPx
@ -112,27 +112,30 @@ fun StoriesWeb3Content(paused: Boolean, duration: Int) {
@Composable
private fun LightenBox(content: @Composable () -> Unit) {
Box {
val bottomInsetsPx = WindowInsets.navigationBars.getBottom(LocalDensity.current)
Box(modifier = Modifier.fillMaxSize()) {
content()
Box(
modifier = Modifier
.fillMaxSize()
.padding(top = 250.dp)
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.White.copy(alpha = 0f),
Color.White.copy(alpha = 0.75f),
Color.White.copy(alpha = 0.95f),
Color.White,
),
),
),
) {}
.align(Alignment.BottomCenter)
.fillMaxWidth()
.height(TangemTheme.dimens.size164 + bottomInsetsPx.dp)
.background(BottomGradient),
)
}
}
private fun scaleToDesignSize(itemSize: DpSize, designItemHeight: Dp): DpSize {
val scaleRate = itemSize.height / designItemHeight
return itemSize / scaleRate
}
}
private val BottomGradient: Brush = Brush.verticalGradient(
colors = listOf(
TangemColorPalette.White.copy(alpha = 0f),
TangemColorPalette.White.copy(alpha = 0.75f),
TangemColorPalette.White.copy(alpha = 0.95f),
TangemColorPalette.White,
),
)

View file

@ -5,21 +5,15 @@ import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
@ -28,6 +22,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.common.compose.FontSizeRange
import com.tangem.tap.common.compose.TextAutoSize
import com.tangem.tap.features.home.compose.StoriesBottomImageAnimation
@ -37,6 +33,8 @@ import com.tangem.wallet.R
@Suppress("LongMethod", "ComplexMethod", "MagicNumber")
@Composable
fun FirstStoriesContent(isPaused: Boolean, duration: Int, onHideContent: (Boolean) -> Unit) {
val bottomInsetsPx = WindowInsets.navigationBars.getBottom(LocalDensity.current)
val screenState = remember { mutableStateOf(StartingScreenState.INIT) }
val progress = remember { Animatable(0f) }
@ -123,16 +121,33 @@ fun FirstStoriesContent(isPaused: Boolean, duration: Int, onHideContent: (Boolea
) { modifier ->
Image(
modifier = modifier.fillMaxWidth(),
painter = painterResource(id = R.drawable.meet_tangem),
painter = painterResource(id = R.drawable.img_meet_tangem),
contentDescription = "Tangem Wallet card",
)
}
}
}
}
Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.height(TangemTheme.dimens.size72 + bottomInsetsPx.dp)
.background(BottomGradient),
)
}
}
private val BottomGradient: Brush = Brush.verticalGradient(
colors = listOf(
TangemColorPalette.Black.copy(alpha = 0f),
TangemColorPalette.Black.copy(alpha = 0.75f),
TangemColorPalette.Black.copy(alpha = 0.95f),
TangemColorPalette.Black,
),
)
private enum class StartingScreenState {
INIT, BUY, STORE, SEND, PAY, EXCHANGE, BORROW, LEND, SHOW_CARD, MEET_TANGEM
}

View file

@ -1,11 +1,17 @@
package com.tangem.tap.features.home.compose.content
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.tap.common.compose.extensions.AnimatedValue
import com.tangem.tap.common.compose.extensions.asImageBitmap
import com.tangem.tap.common.compose.extensions.toAnimatable
@ -16,13 +22,15 @@ import com.tangem.wallet.R
*/
@Composable
fun FloatingCardsContent(isPaused: Boolean, stepDuration: Int) {
val imageBitmap = asImageBitmap(R.drawable.card_placeholder_wallet)
val bottomInsetsPx = WindowInsets.navigationBars.getBottom(LocalDensity.current)
val imageBitmap = asImageBitmap(R.drawable.img_card_placeholder_wallet_2)
val cards = listOf(
FloatingCard.first(),
FloatingCard.second(),
FloatingCard.third(),
)
Box {
Box(modifier = Modifier.fillMaxSize()) {
cards.forEach { floatingCard ->
FloatingCard.Item(
isPaused = isPaused,
@ -31,6 +39,14 @@ fun FloatingCardsContent(isPaused: Boolean, stepDuration: Int) {
stepDuration = stepDuration,
)
}
Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.height(bottomInsetsPx.dp)
.background(BottomGradient),
)
}
}
@ -93,4 +109,12 @@ private object FloatingCard {
rotationZ = -45f to -30f,
scale = 0.6f to 0.75f,
)
}
}
private val BottomGradient: Brush = Brush.verticalGradient(
colors = listOf(
TangemColorPalette.White.copy(alpha = 0f),
TangemColorPalette.White.copy(alpha = 0.75f),
TangemColorPalette.White.copy(alpha = 0.95f),
),
)

View file

@ -1,107 +1,155 @@
package com.tangem.tap.features.home.compose.views
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material.ButtonColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.tangem.core.ui.components.SpacerS8
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.SpacerW8
import com.tangem.core.ui.components.buttons.common.TangemButton
import com.tangem.core.ui.components.buttons.common.TangemButtonColors
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.wallet.R
@Suppress("MagicNumber")
@Composable
fun HomeButtons(
internal fun HomeButtons(
isDarkBackground: Boolean,
btnScanStateInProgress: Boolean,
onScanButtonClick: () -> Unit,
onShopButtonClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val darkColorBackground = Color(0xFF26292E)
val darkColorButton = Color(0xFF080C10)
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = modifier,
) {
ProgressButton(
inProgress = btnScanStateInProgress,
backgroundColor = if (isDarkBackground) darkColorBackground else Color.White,
contentColor = if (isDarkBackground) Color.White else darkColorButton,
ScanCardButton(
modifier = Modifier.weight(weight = 1f),
isDarkBackground = isDarkBackground,
showProgress = btnScanStateInProgress,
onClick = onScanButtonClick,
progressContent = {
CircularProgressIndicator(
modifier = Modifier.size(30.dp),
color = if (isDarkBackground) Color.White else darkColorBackground,
strokeWidth = 3.dp,
)
},
content = {
Text(
text = stringResource(id = R.string.home_button_scan),
fontWeight = FontWeight.Medium,
fontSize = 16.sp,
textAlign = TextAlign.Center,
maxLines = 1,
)
},
)
SpacerS8()
Button(
modifier = Modifier
.weight(1f)
.heightIn(48.dp),
SpacerW8()
OrderCardButton(
modifier = Modifier.weight(weight = 1f),
isDarkBackground = isDarkBackground,
onClick = onShopButtonClick,
enabled = !btnScanStateInProgress,
colors = ButtonDefaults.textButtonColors(
backgroundColor = if (isDarkBackground) Color.White else darkColorBackground,
contentColor = if (isDarkBackground) darkColorButton else Color.White,
),
)
}
}
@Composable
private fun ScanCardButton(
isDarkBackground: Boolean,
showProgress: Boolean,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
TangemButton(
modifier = modifier,
text = stringResource(id = R.string.home_button_scan),
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_tangem_24),
colors = if (isDarkBackground) DarkBgScanCardButtonColors else LightBgScanCardButtonColors,
showProgress = showProgress,
enabled = true,
onClick = onClick,
)
}
@Composable
private fun OrderCardButton(isDarkBackground: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) {
TangemButton(
modifier = modifier,
text = stringResource(id = R.string.home_button_order),
icon = TangemButtonIconPosition.None,
colors = if (isDarkBackground) DarkBgOrderCardButtonColors else LightBgOrderCardButtonColors,
showProgress = false,
enabled = true,
onClick = onClick,
)
}
private val LightBgScanCardButtonColors: ButtonColors = TangemButtonColors(
backgroundColor = TangemColorPalette.Light2,
contentColor = TangemColorPalette.Dark6,
disabledBackgroundColor = TangemColorPalette.Light2,
disabledContentColor = TangemColorPalette.Dark6,
)
private val DarkBgScanCardButtonColors: ButtonColors = TangemButtonColors(
backgroundColor = TangemColorPalette.Dark5,
contentColor = TangemColorPalette.White,
disabledBackgroundColor = TangemColorPalette.Dark5,
disabledContentColor = TangemColorPalette.White,
)
private val LightBgOrderCardButtonColors: ButtonColors = TangemButtonColors(
backgroundColor = TangemColorPalette.Dark6,
contentColor = TangemColorPalette.White,
disabledBackgroundColor = TangemColorPalette.Dark6,
disabledContentColor = TangemColorPalette.White,
)
private val DarkBgOrderCardButtonColors: ButtonColors = TangemButtonColors(
backgroundColor = TangemColorPalette.Light1,
contentColor = TangemColorPalette.Dark6,
disabledBackgroundColor = TangemColorPalette.Light1,
disabledContentColor = TangemColorPalette.Dark6,
)
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun HomeButtonsPreview(@PreviewParameter(HomeButtonsParameterProvider::class) state: HomeButtonsState) {
TangemTheme {
Box(
modifier = Modifier.background(if (state.isDarkBackground) Color.Black else Color.White),
) {
Text(
text = stringResource(id = R.string.home_button_order),
fontWeight = FontWeight.Medium,
fontSize = 16.sp,
textAlign = TextAlign.Center,
maxLines = 1,
HomeButtons(
modifier = Modifier.padding(all = TangemTheme.dimens.spacing16),
isDarkBackground = state.isDarkBackground,
btnScanStateInProgress = state.btnScanStateInProgress,
onScanButtonClick = {},
onShopButtonClick = {},
)
}
}
}
@Suppress("LongParameterList")
@Composable
fun RowScope.ProgressButton(
backgroundColor: Color,
contentColor: Color,
onClick: () -> Unit,
inProgress: Boolean,
progressContent: @Composable (() -> Unit)? = null,
content: @Composable () -> Unit,
) {
Button(
modifier = Modifier
.weight(1f)
.height(48.dp),
onClick = onClick,
enabled = !inProgress,
colors = ButtonDefaults.textButtonColors(
backgroundColor = backgroundColor,
contentColor = contentColor,
private class HomeButtonsParameterProvider : CollectionPreviewParameterProvider<HomeButtonsState>(
collection = listOf(
HomeButtonsState(
isDarkBackground = false,
btnScanStateInProgress = false,
),
) {
if (progressContent != null && inProgress) {
progressContent()
} else {
content()
}
}
}
HomeButtonsState(
isDarkBackground = true,
btnScanStateInProgress = false,
),
HomeButtonsState(
isDarkBackground = false,
btnScanStateInProgress = true,
),
HomeButtonsState(
isDarkBackground = true,
btnScanStateInProgress = true,
),
),
)
private data class HomeButtonsState(
val isDarkBackground: Boolean,
val btnScanStateInProgress: Boolean,
)
// endregion Preview

View file

@ -0,0 +1,31 @@
package com.tangem.tap.features.home.compose.views
import androidx.compose.material.ButtonColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.tangem.core.ui.components.buttons.common.TangemButton
import com.tangem.core.ui.components.buttons.common.TangemButtonColors
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.wallet.R
@Composable
internal fun SearchCurrenciesButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
TangemButton(
modifier = modifier,
text = stringResource(id = R.string.common_search_tokens),
icon = TangemButtonIconPosition.Start(R.drawable.ic_search_24),
onClick = onClick,
colors = SearchCurrenciesButtonColors,
showProgress = false,
enabled = true,
)
}
private val SearchCurrenciesButtonColors: ButtonColors = TangemButtonColors(
backgroundColor = TangemColorPalette.Light2,
contentColor = TangemColorPalette.Dark6,
disabledBackgroundColor = TangemColorPalette.Light2,
disabledContentColor = TangemColorPalette.Dark6,
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View file

@ -11,7 +11,7 @@ import com.tangem.core.ui.res.TangemTheme
@Suppress("LongParameterList")
@Composable
internal fun TangemButton(
fun TangemButton(
text: String,
icon: TangemButtonIconPosition,
onClick: () -> Unit,

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.graphics.Color
internal class TangemButtonColors(
class TangemButtonColors(
private val backgroundColor: Color,
private val contentColor: Color,
private val disabledBackgroundColor: Color,

View file

@ -1,8 +1,10 @@
package com.tangem.core.ui.components.buttons.common
import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
internal sealed interface TangemButtonIconPosition {
@Immutable
sealed interface TangemButtonIconPosition {
val iconResId: Int?
data class Start(@DrawableRes override val iconResId: Int) : TangemButtonIconPosition

View file

@ -8,7 +8,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.res.TangemTheme
internal enum class TangemButtonSize {
enum class TangemButtonSize {
Default,
Text,
Selector,

View file

@ -11,7 +11,8 @@ import com.tangem.core.ui.res.TangemTheme
internal object TangemButtonsDefaults {
val elevation: ButtonElevation
@Composable get() = ButtonDefaults.elevation(
@Composable
get() = ButtonDefaults.elevation(
defaultElevation = TangemTheme.dimens.elevation0,
pressedElevation = TangemTheme.dimens.elevation0,
)
@ -65,14 +66,4 @@ internal object TangemButtonsDefaults {
disabledBackgroundColor = Color.Transparent,
disabledContentColor = TangemTheme.colors.text.disabled,
)
val backgroundButtonColors: ButtonColors
@Composable
@ReadOnlyComposable
get() = TangemButtonColors(
backgroundColor = TangemTheme.colors.background.primary,
contentColor = TangemTheme.colors.text.primary1,
disabledBackgroundColor = TangemTheme.colors.button.disabled,
disabledContentColor = TangemTheme.colors.text.disabled,
)
}