Updated on 2026-08-14

This commit is contained in:
Tangem 2025-07-27 22:16:37 +05:00
parent 9ab23a953d
commit c89a95265d
23 changed files with 126 additions and 90 deletions

View file

@ -43,9 +43,9 @@ fun GiveTxPermissionBottomSheet(config: TangemBottomSheetConfig) {
config = config,
containerColor = TangemTheme.colors.background.secondary,
titleText = resourceReference(R.string.give_permission_title),
titleAction = TopAppBarButtonUM(
titleAction = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_information_24,
onIconClicked = { isPermissionAlertShow = true },
onClicked = { isPermissionAlertShow = true },
),
content = { content: GiveTxPermissionBottomSheetConfig ->
GiveTxPermissionBottomSheetContent(content = content)

View file

@ -32,9 +32,9 @@ fun AppBarWithBackButton(
TangemTopAppBar(
modifier = modifier,
title = text,
startButton = TopAppBarButtonUM(
startButton = TopAppBarButtonUM.Icon(
iconRes = iconRes ?: R.drawable.ic_back_24,
onIconClicked = onBackClick,
onClicked = onBackClick,
),
containerColor = containerColor,
)

View file

@ -27,14 +27,14 @@ fun AppBarWithBackButtonAndIcon(
title = text,
subtitle = subtitle,
containerColor = backgroundColor,
startButton = TopAppBarButtonUM(
startButton = TopAppBarButtonUM.Icon(
iconRes = backIconRes ?: R.drawable.ic_back_24,
onIconClicked = onBackClick,
onClicked = onBackClick,
),
endButton = if (iconRes != null && onIconClick != null) {
TopAppBarButtonUM(
TopAppBarButtonUM.Icon(
iconRes = iconRes,
onIconClicked = onIconClick,
onClicked = onIconClick,
)
} else {
null

View file

@ -301,25 +301,25 @@ private class BasicTopAppBarPMPreviewProvider : PreviewParameterProvider<BasicTo
height = TangemTopAppBarHeight.BOTTOM_SHEET,
),
BasicTopAppBarPM(
startButton = TopAppBarButtonUM(
startButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
onClicked = {},
),
endButton = TopAppBarButtonUM(
endButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
onClicked = {},
),
),
BasicTopAppBarPM(
startButton = TopAppBarButtonUM(
startButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
onClicked = {},
),
),
BasicTopAppBarPM(
endButton = TopAppBarButtonUM(
endButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
onClicked = {},
),
height = TangemTopAppBarHeight.BOTTOM_SHEET,
),
@ -327,13 +327,13 @@ private class BasicTopAppBarPMPreviewProvider : PreviewParameterProvider<BasicTo
title = "1234567891011121314151617181920",
subtitle = "12345678910111213141516171819202122232425",
titleAlignment = Alignment.Start,
startButton = TopAppBarButtonUM(
startButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_scan_24,
onIconClicked = {},
onClicked = {},
),
endButton = TopAppBarButtonUM(
endButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = {},
onClicked = {},
),
),
)

View file

@ -1,27 +1,49 @@
package com.tangem.core.ui.components.appbar
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.extensions.conditional
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
@Composable
fun TopAppBarButton(button: TopAppBarButtonUM, tint: Color, modifier: Modifier = Modifier) {
IconButton(
enabled = button.enabled,
modifier = modifier.size(TangemTheme.dimens.size32),
onClick = button.onIconClicked,
) {
Icon(
modifier = Modifier.size(TangemTheme.dimens.size24),
painter = painterResource(id = button.iconRes),
tint = tint,
contentDescription = null,
)
when (button) {
is TopAppBarButtonUM.Icon -> {
IconButton(
enabled = button.enabled,
modifier = modifier.size(TangemTheme.dimens.size32),
onClick = button.onClicked,
) {
Icon(
modifier = Modifier.size(TangemTheme.dimens.size24),
painter = painterResource(id = button.iconRes),
tint = tint,
contentDescription = null,
)
}
}
is TopAppBarButtonUM.Text -> {
Text(
modifier = modifier
.conditional(button.enabled) {
clickable { button.onClicked() }
}
.padding(4.dp),
text = button.text.resolveReference(),
color = tint,
style = TangemTheme.typography.body1,
)
}
}
}

View file

@ -2,21 +2,39 @@ package com.tangem.core.ui.components.appbar.models
import androidx.annotation.DrawableRes
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.TextReference
data class TopAppBarButtonUM(
@DrawableRes val iconRes: Int,
val onIconClicked: () -> Unit,
val enabled: Boolean = true,
sealed class TopAppBarButtonUM(
open val onClicked: () -> Unit,
open val enabled: Boolean = true,
) {
data class Icon(
@DrawableRes val iconRes: Int,
override val onClicked: () -> Unit,
override val enabled: Boolean = true,
) : TopAppBarButtonUM(onClicked, enabled)
data class Text(
val text: TextReference,
override val onClicked: () -> Unit,
override val enabled: Boolean = true,
) : TopAppBarButtonUM(onClicked, enabled)
@Suppress("FunctionName")
companion object {
fun Back(onBackClicked: () -> Unit) = Back(true, onBackClicked)
fun Back(enabled: Boolean = true, onBackClicked: () -> Unit) = TopAppBarButtonUM(
fun Back(enabled: Boolean = true, onBackClicked: () -> Unit) = Icon(
iconRes = R.drawable.ic_back_24,
onIconClicked = onBackClicked,
onClicked = onBackClicked,
enabled = enabled,
)
fun Text(text: TextReference, onTextClicked: () -> Unit, enabled: Boolean = true) = Text(
text = text,
onClicked = onTextClicked,
enabled = enabled,
)
}

View file

@ -57,9 +57,9 @@ private fun Preview_TangemBottomSheetTitle() {
TangemThemePreview {
TangemBottomSheetTitle(
title = "Title",
endButton = TopAppBarButtonUM(
endButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_information_24,
onIconClicked = {},
onClicked = {},
),
containerColor = TangemTheme.colors.background.secondary,
)

View file

@ -66,9 +66,8 @@ internal fun DisclaimerScreen(state: DisclaimerUM) {
) {
TangemTopAppBar(
title = resourceReference(R.string.disclaimer_title),
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = state.popBack,
startButton = TopAppBarButtonUM.Back(
onBackClicked = state.popBack,
).takeIf { state.isTosAccepted },
titleAlignment = Alignment.CenterHorizontally,
textColor = textColor,

View file

@ -42,9 +42,9 @@ internal class PreviewManageTokensComponent(
ManageTokensTopBarUM.ManageContent(
title = resourceReference(id = R.string.main_manage_tokens),
onBackButtonClick = {},
endButton = TopAppBarButtonUM(
endButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_plus_24,
onIconClicked = {},
onClicked = {},
),
)
} else {

View file

@ -129,9 +129,9 @@ internal class ManageTokensModel @Inject constructor(
topBar = ManageTokensTopBarUM.ManageContent(
title = resourceReference(id = R.string.main_manage_tokens),
onBackButtonClick = router::pop,
endButton = TopAppBarButtonUM(
endButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_plus_24,
onIconClicked = ::navigateToAddCustomToken,
onClicked = ::navigateToAddCustomToken,
),
),
search = SearchBarUM(

View file

@ -28,9 +28,8 @@ internal fun NFTDetails(state: NFTDetailsUM, modifier: Modifier = Modifier) {
) {
TangemTopAppBar(
modifier = Modifier,
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = state.onBackClick,
startButton = TopAppBarButtonUM.Back(
onBackClicked = state.onBackClick,
),
title = state.nftAsset.name,
)

View file

@ -28,9 +28,8 @@ internal fun NFTReceive(state: NFTReceiveUM, modifier: Modifier = Modifier) {
) {
TangemTopAppBar(
modifier = Modifier,
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_close_24,
onIconClicked = state.onBackClick,
startButton = TopAppBarButtonUM.Back(
onBackClicked = state.onBackClick,
),
title = stringResourceSafe(id = R.string.nft_receive_title),
subtitle = state.appBarSubtitle.resolveReference(),

View file

@ -22,9 +22,8 @@ internal fun NFTAssetTraits(state: NFTAssetTraitsUM, modifier: Modifier = Modifi
) {
TangemTopAppBar(
modifier = Modifier,
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = state.onBackClick,
startButton = TopAppBarButtonUM.Back(
onBackClicked = state.onBackClick,
),
title = stringResourceSafe(R.string.nft_traits_title),
)

View file

@ -49,7 +49,7 @@ internal fun OnboardingStepper(
) {
TangemTopAppBar(
startButton = TopAppBarButtonUM.Back(onBackClick),
endButton = TopAppBarButtonUM(iconRes = R.drawable.ic_chat_24, onIconClicked = onSupportButtonClick)
endButton = TopAppBarButtonUM.Icon(iconRes = R.drawable.ic_chat_24, onClicked = onSupportButtonClick)
.takeIf { state.steps != state.currentStep },
title = if (state.steps == state.currentStep) {
resourceReference(R.string.common_done)

View file

@ -24,14 +24,13 @@ internal sealed interface OnrampMainComponentUM {
) : OnrampMainComponentUM {
override val topBarConfig: OnrampMainTopBarUM = OnrampMainTopBarUM(
title = combinedReference(resourceReference(R.string.common_buy), stringReference(" $currency")),
startButtonUM = TopAppBarButtonUM(
iconRes = R.drawable.ic_close_24,
onIconClicked = onClose,
startButtonUM = TopAppBarButtonUM.Back(
onBackClicked = onClose,
enabled = true,
),
endButtonUM = TopAppBarButtonUM(
endButtonUM = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_more_vertical_24,
onIconClicked = openSettings,
onClicked = openSettings,
enabled = false,
),
)

View file

@ -6,6 +6,7 @@ import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import com.tangem.common.ui.amountScreen.models.AmountFieldModel
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.currency.CryptoCurrency
@ -37,7 +38,10 @@ internal class OnrampStateFactory(
fun getReadyState(currency: OnrampCurrency): OnrampMainComponentUM.Content {
val state = currentStateProvider()
val endButton = state.topBarConfig.endButtonUM.copy(enabled = true)
val endButton = when (val button = state.topBarConfig.endButtonUM) {
is TopAppBarButtonUM.Icon -> button.copy(enabled = true)
is TopAppBarButtonUM.Text -> button.copy(enabled = true)
}
return OnrampMainComponentUM.Content(
topBarConfig = state.topBarConfig.copy(endButtonUM = endButton),
buyButtonConfig = state.buyButtonConfig,
@ -80,7 +84,10 @@ internal class OnrampStateFactory(
fun getErrorState(errorCode: String? = null, onRefresh: () -> Unit): OnrampMainComponentUM {
val state = currentStateProvider()
val endButton = state.topBarConfig.endButtonUM.copy(enabled = true)
val endButton = when (val button = state.topBarConfig.endButtonUM) {
is TopAppBarButtonUM.Icon -> button.copy(enabled = true)
is TopAppBarButtonUM.Text -> button.copy(enabled = true)
}
return when (state) {
is OnrampMainComponentUM.Content -> state.copy(

View file

@ -54,9 +54,8 @@ internal class OnrampRedirectModel @Inject constructor(
resourceReference(R.string.common_buy),
stringReference(" ${params.cryptoCurrency.name}"),
),
startButtonUM = TopAppBarButtonUM(
iconRes = R.drawable.ic_close_24,
onIconClicked = appRouter::pop,
startButtonUM = TopAppBarButtonUM.Back(
onBackClicked = appRouter::pop,
enabled = true,
),
),

View file

@ -61,9 +61,8 @@ private fun Content(state: OnrampSuccessComponentUM.Content, onBackClick: () ->
.systemBarsPadding(),
topBar = {
TangemTopAppBar(
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_close_24,
onIconClicked = onBackClick,
startButton = TopAppBarButtonUM.Back(
onBackClicked = onBackClick,
),
)
},

View file

@ -66,9 +66,9 @@ internal fun QrScanningContent(
TangemTopAppBar(
modifier = Modifier.statusBarsPadding(),
title = uiState.topBarConfig.title?.resolveReference(),
startButton = TopAppBarButtonUM(
startButton = TopAppBarButtonUM.Icon(
iconRes = uiState.topBarConfig.startIcon,
onIconClicked = uiState.onBackClick,
onClicked = uiState.onBackClick,
),
textColor = TangemTheme.colors.text.constantWhite,
iconTint = TangemColorPalette.White,
@ -80,9 +80,9 @@ internal fun QrScanningContent(
label = "Flash Change",
) {
TopAppBarButton(
button = TopAppBarButtonUM(
button = TopAppBarButtonUM.Icon(
iconRes = if (it) R.drawable.ic_flash_on_24 else R.drawable.ic_flash_off_24,
onIconClicked = {
onClicked = {
isFlash = !isFlash
},
),
@ -91,9 +91,9 @@ internal fun QrScanningContent(
}
TopAppBarButton(
button = TopAppBarButtonUM(
button = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_gallery_24,
onIconClicked = uiState.onGalleryClick,
onClicked = uiState.onGalleryClick,
),
tint = TangemColorPalette.White,
)

View file

@ -46,9 +46,9 @@ internal fun ExcludedBlockchainsScreen(state: ExcludedBlockchainsScreenUM, modif
TangemTopAppBar(
title = resourceReference(R.string.excluded_blockchains),
startButton = TopAppBarButtonUM.Back(onBackClicked = state.popBack),
endButton = TopAppBarButtonUM(
endButton = TopAppBarButtonUM.Icon(
iconRes = R.drawable.ic_refresh_24,
onIconClicked = state.onRecoverClick,
onClicked = state.onRecoverClick,
),
)
},

View file

@ -134,9 +134,8 @@ internal class WcConnectionsModel @Inject constructor(
private fun getInitialState(): WcConnectionsState {
return WcConnectionsState(
topAppBarConfig = WcConnectionsTopAppBarConfig(
startButtonUM = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = router::pop,
startButtonUM = TopAppBarButtonUM.Back(
onBackClicked = router::pop,
enabled = true,
),
disconnectAllItem = TangemDropdownMenuItem(

View file

@ -28,6 +28,7 @@ import androidx.compose.ui.util.fastForEach
import coil.compose.AsyncImage
import com.tangem.core.ui.components.BottomFade
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.appbar.TopAppBarButton
import com.tangem.core.ui.components.dropdownmenu.TangemDropdownItem
import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenu
import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
@ -251,13 +252,10 @@ private fun ConnectionsTopBar(
actionIconContentColor = TangemTheme.colors.icon.primary1,
),
navigationIcon = {
IconButton(onClick = config.startButtonUM.onIconClicked) {
Icon(
painter = painterResource(id = config.startButtonUM.iconRes),
tint = TangemTheme.colors.icon.primary1,
contentDescription = "Back",
)
}
TopAppBarButton(
button = config.startButtonUM,
tint = TangemTheme.colors.icon.primary1,
)
},
title = {
Text(

View file

@ -118,9 +118,8 @@ internal object WcConnectionsPreviewData {
)
val stateWithEmptyConnections = WcConnectionsState(
topAppBarConfig = WcConnectionsTopAppBarConfig(
startButtonUM = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = {},
startButtonUM = TopAppBarButtonUM.Back(
onBackClicked = {},
enabled = true,
),
disconnectAllItem = TangemDropdownMenuItem(