Updated on 2026-08-14
This commit is contained in:
commit
edec3fcdff
391 changed files with 10988 additions and 3221 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.core.analytics.utils
|
||||
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -9,9 +10,15 @@ interface AnalyticsContextProxy {
|
|||
|
||||
fun setContext(scanResponse: ScanResponse)
|
||||
|
||||
fun addContext(userWallet: UserWallet)
|
||||
|
||||
fun setHotWalletContext()
|
||||
|
||||
fun eraseContext()
|
||||
|
||||
fun addContext(scanResponse: ScanResponse)
|
||||
|
||||
fun addHotWalletContext()
|
||||
|
||||
fun removeContext()
|
||||
}
|
||||
|
|
@ -30,9 +30,5 @@
|
|||
{
|
||||
"name": "zklink",
|
||||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
"name": "scroll",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package com.tangem.datasource.api.express.models
|
||||
|
||||
object TangemExpressValues {
|
||||
const val EMPTY_CONTRACT_ADDRESS_VALUE = "0"
|
||||
}
|
||||
|
|
@ -20,4 +20,18 @@ data class GetWalletAccountsResponse(
|
|||
@Json(name = "sort") val sort: SortType,
|
||||
@Json(name = "totalAccounts") val totalAccounts: Int,
|
||||
)
|
||||
}
|
||||
|
||||
/** Flattens the tokens from all wallet accounts into a single list */
|
||||
fun GetWalletAccountsResponse.flattenTokens(): List<UserTokensResponse.Token> {
|
||||
return accounts.flatMap { it.tokens.orEmpty() }
|
||||
}
|
||||
|
||||
/** Converts the [GetWalletAccountsResponse] into a [UserTokensResponse] */
|
||||
fun GetWalletAccountsResponse.toUserTokensResponse(): UserTokensResponse {
|
||||
return UserTokensResponse(
|
||||
group = wallet.group,
|
||||
sort = wallet.sort,
|
||||
tokens = flattenTokens(),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.tangem.datasource.di.exchangeservice
|
||||
|
||||
import com.tangem.datasource.exchangeservice.swap.DefaultExpressServiceLoader
|
||||
import com.tangem.datasource.exchangeservice.swap.ExpressServiceLoader
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface ExchangeServiceLoaderModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindExpressServiceLoader(defaultExpressServiceLoader: DefaultExpressServiceLoader): ExpressServiceLoader
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
package com.tangem.datasource.exchangeservice.swap
|
||||
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.express.models.request.AssetsRequestBody
|
||||
import com.tangem.datasource.api.express.models.request.LeastTokenInfo
|
||||
import com.tangem.datasource.api.express.models.response.Asset
|
||||
import com.tangem.datasource.exchangeservice.swap.ExpressUtils.getRefCode
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.token.ExpressAssetsStore
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.utils.lceContent
|
||||
import com.tangem.domain.core.utils.lceError
|
||||
import com.tangem.domain.core.utils.lceLoading
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
typealias InitializationStatusFlow = MutableStateFlow<Lce<Throwable, List<Asset>>>
|
||||
|
||||
/**
|
||||
* Default implementation of [ExpressServiceLoader]
|
||||
*
|
||||
* @property tangemExpressApi express api
|
||||
* @property expressAssetsStore local storage
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultExpressServiceLoader @Inject constructor(
|
||||
private val tangemExpressApi: TangemExpressApi,
|
||||
private val expressAssetsStore: ExpressAssetsStore,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : ExpressServiceLoader {
|
||||
|
||||
private val initializationStatuses =
|
||||
MutableStateFlow<Map<UserWalletId, InitializationStatusFlow>>(value = emptyMap())
|
||||
|
||||
override suspend fun update(userWallet: UserWallet, userTokens: List<LeastTokenInfo>) {
|
||||
withContext(dispatchers.io) {
|
||||
val initializationStatus = getInitializationStatusInternal(userWallet.walletId)
|
||||
|
||||
try {
|
||||
if (userTokens.isNotEmpty()) {
|
||||
val response = tangemExpressApi.getAssets(
|
||||
userWalletId = userWallet.walletId.stringValue,
|
||||
refCode = getRefCode(userWallet, appPreferencesStore),
|
||||
body = AssetsRequestBody(tokensList = userTokens),
|
||||
).getOrThrow()
|
||||
|
||||
expressAssetsStore.store(userWallet.walletId, response)
|
||||
|
||||
initializationStatus.update { response.lceContent() }
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (expressAssetsStore.getSyncOrNull(userWallet.walletId) == null) {
|
||||
initializationStatus.update { e.lceError() }
|
||||
}
|
||||
Timber.e(e, "Unable to fetch assets for: ${userWallet.walletId.stringValue}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInitializationStatus(userWalletId: UserWalletId): Flow<Lce<Throwable, List<Asset>>> {
|
||||
return flow { getInitializationStatusInternal(userWalletId).collect { emit(it) } }
|
||||
}
|
||||
|
||||
@Suppress("SuspendFunWithFlowReturnType")
|
||||
private suspend fun getInitializationStatusInternal(userWalletId: UserWalletId): InitializationStatusFlow {
|
||||
val initializationStatus = initializationStatuses.value[userWalletId]
|
||||
if (initializationStatus != null) return initializationStatus
|
||||
|
||||
val cached = expressAssetsStore.getSyncOrNull(userWalletId)
|
||||
val default: InitializationStatusFlow = MutableStateFlow(value = cached?.lceContent() ?: lceLoading())
|
||||
|
||||
initializationStatuses.update { statuses ->
|
||||
statuses.toMutableMap().apply {
|
||||
put(key = userWalletId, value = default)
|
||||
}
|
||||
}
|
||||
|
||||
return default
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package com.tangem.datasource.exchangeservice.swap
|
||||
|
||||
import com.tangem.datasource.api.express.models.request.LeastTokenInfo
|
||||
import com.tangem.datasource.api.express.models.response.Asset
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Express service loader
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface ExpressServiceLoader {
|
||||
|
||||
/** Update service using [userWallet] and [userTokens] */
|
||||
suspend fun update(userWallet: UserWallet, userTokens: List<LeastTokenInfo>)
|
||||
|
||||
/** Get initialization status by [userWalletId] */
|
||||
fun getInitializationStatus(userWalletId: UserWalletId): Flow<Lce<Throwable, List<Asset>>>
|
||||
}
|
||||
|
|
@ -6,18 +6,21 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.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.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.conditional
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -34,6 +37,7 @@ data class SmallButtonConfig(
|
|||
val onClick: () -> Unit,
|
||||
val icon: TangemButtonIconPosition = TangemButtonIconPosition.None,
|
||||
val isEnabled: Boolean = true,
|
||||
val isLoading: Boolean = false,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -68,7 +72,7 @@ private fun SmallButton(config: SmallButtonConfig, isPrimary: Boolean, modifier:
|
|||
label = "Update background color",
|
||||
)
|
||||
|
||||
Row(
|
||||
Box(
|
||||
modifier = modifier
|
||||
.defaultMinSize(
|
||||
minWidth = TangemTheme.dimens.size46,
|
||||
|
|
@ -79,7 +83,7 @@ private fun SmallButton(config: SmallButtonConfig, isPrimary: Boolean, modifier:
|
|||
color = backgroundColor,
|
||||
shape = shape,
|
||||
)
|
||||
.clickable(enabled = config.isEnabled, onClick = config.onClick)
|
||||
.clickable(enabled = !config.isLoading && config.isEnabled, onClick = config.onClick)
|
||||
.padding(
|
||||
paddingValues = when (config.icon) {
|
||||
is TangemButtonIconPosition.None -> PaddingValues(
|
||||
|
|
@ -95,42 +99,54 @@ private fun SmallButton(config: SmallButtonConfig, isPrimary: Boolean, modifier:
|
|||
)
|
||||
},
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
ContentContainer(
|
||||
iconPosition = config.icon,
|
||||
text = {
|
||||
val textColor by animateColorAsState(
|
||||
targetValue = when {
|
||||
!config.isEnabled -> TangemTheme.colors.text.disabled
|
||||
isPrimary -> TangemTheme.colors.text.primary2
|
||||
else -> TangemTheme.colors.text.primary1
|
||||
},
|
||||
label = "Update text color",
|
||||
)
|
||||
if (config.isLoading) {
|
||||
CircularProgressIndicator(
|
||||
strokeWidth = TangemTheme.dimens.size2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier.size(TangemTheme.dimens.size16),
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.conditional(config.isLoading) { alpha(0f) },
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
ContentContainer(
|
||||
iconPosition = config.icon,
|
||||
text = {
|
||||
val textColor by animateColorAsState(
|
||||
targetValue = when {
|
||||
!config.isEnabled -> TangemTheme.colors.text.disabled
|
||||
isPrimary -> TangemTheme.colors.text.primary2
|
||||
else -> TangemTheme.colors.text.primary1
|
||||
},
|
||||
label = "Update text color",
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing4),
|
||||
text = config.text.resolveReference(),
|
||||
color = textColor,
|
||||
maxLines = 1,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
},
|
||||
icon = { iconResId ->
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size16),
|
||||
painter = painterResource(id = iconResId),
|
||||
tint = if (config.isEnabled) {
|
||||
TangemTheme.colors.icon.secondary
|
||||
} else {
|
||||
TangemTheme.colors.icon.inactive
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing4),
|
||||
text = config.text.resolveReference(),
|
||||
color = textColor,
|
||||
maxLines = 1,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
},
|
||||
icon = { iconResId ->
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size16),
|
||||
painter = painterResource(id = iconResId),
|
||||
tint = if (config.isEnabled) {
|
||||
TangemTheme.colors.icon.secondary
|
||||
} else {
|
||||
TangemTheme.colors.icon.inactive
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +188,7 @@ private fun ButtonsSample() {
|
|||
)
|
||||
PrimarySmallButton(config = config)
|
||||
SecondarySmallButton(config = config.copy(text = TextReference.Str(value = "Add")))
|
||||
SecondarySmallButton(config = config.copy(text = TextReference.Str(value = "Add"), isLoading = true))
|
||||
SecondarySmallButton(
|
||||
config = config.copy(
|
||||
text = TextReference.Str(value = "Rating"),
|
||||
|
|
@ -191,5 +208,12 @@ private fun ButtonsSample() {
|
|||
isEnabled = false,
|
||||
),
|
||||
)
|
||||
SecondarySmallButton(
|
||||
config = config.copy(
|
||||
text = TextReference.Str(value = "Add token"),
|
||||
icon = TangemButtonIconPosition.Start(iconResId = R.drawable.ic_plus_24),
|
||||
isLoading = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package com.tangem.core.ui.components.feature
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
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.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
@Composable
|
||||
fun FeatureBlock(title: String, description: String, iconRes: Int, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 12.dp),
|
||||
painter = painterResource(iconRes),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = 4.dp),
|
||||
text = description,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewFeatureBlock() {
|
||||
TangemThemePreview {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.primary)
|
||||
.padding(16.dp),
|
||||
) {
|
||||
FeatureBlock(
|
||||
title = stringResourceSafe(R.string.backup_info_save_title),
|
||||
description = stringResourceSafe(R.string.backup_info_save_description, "12"),
|
||||
iconRes = R.drawable.ic_lock_24,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
FeatureBlock(
|
||||
title = stringResourceSafe(R.string.backup_info_keep_title),
|
||||
description = stringResourceSafe(R.string.backup_info_keep_description),
|
||||
iconRes = R.drawable.ic_settings_24,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import com.tangem.core.ui.utils.getGreyScaleColorFilter
|
|||
* @param onImageError composable to show if image loading failed
|
||||
*/
|
||||
@Composable
|
||||
internal fun InputRowAsyncImage(
|
||||
fun InputRowAsyncImage(
|
||||
imageUrl: String,
|
||||
modifier: Modifier = Modifier,
|
||||
isGrayscale: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ fun SelectorRowItem(
|
|||
val textStyle = if (isSelected && showSelectedAppearance) {
|
||||
TangemTheme.typography.subtitle2
|
||||
} else {
|
||||
TangemTheme.typography.body2
|
||||
TangemTheme.typography.body1
|
||||
}
|
||||
Box(
|
||||
modifier = modifier
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.tangem.core.ui.components.marketprice.PriceChangeType
|
|||
import com.tangem.core.ui.components.token.internal.*
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.Subtitle2State
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
|
|
@ -691,7 +692,10 @@ object AccountItemPreviewData {
|
|||
value = stringReference("24 tokens"),
|
||||
isAvailable = false,
|
||||
),
|
||||
subtitle2State = null,
|
||||
subtitle2State = Subtitle2State.PriceChangeContent(
|
||||
priceChangePercent = "0,43 %",
|
||||
type = PriceChangeType.UP,
|
||||
),
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import com.tangem.core.ui.R
|
|||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.audits.AuditLabel
|
||||
import com.tangem.core.ui.components.text.applyBladeBrush
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -31,7 +30,7 @@ internal fun TokenCryptoAmount(
|
|||
isFlickering = state.isFlickering,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Subtitle2State.LabelContent -> {
|
||||
is TokenCryptoAmountState.LabelContent -> {
|
||||
AuditLabel(state = state.auditLabelUM, modifier = modifier)
|
||||
}
|
||||
is TokenCryptoAmountState.Unreachable -> {
|
||||
|
|
@ -46,6 +45,15 @@ internal fun TokenCryptoAmount(
|
|||
is TokenCryptoAmountState.Locked -> {
|
||||
LockedRectangle(modifier = modifier.placeholderSize())
|
||||
}
|
||||
is TokenCryptoAmountState.PriceChangeContent -> {
|
||||
PriceBlock(
|
||||
modifier = modifier,
|
||||
price = null,
|
||||
type = state.type,
|
||||
priceChangePercent = state.priceChangePercent,
|
||||
isFlickering = state.isFlickering,
|
||||
)
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ internal fun TokenPrice(state: TokenPriceState?, modifier: Modifier = Modifier)
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun PriceBlock(
|
||||
price: String,
|
||||
internal fun PriceBlock(
|
||||
price: String?,
|
||||
isFlickering: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
type: PriceChangeType? = null,
|
||||
|
|
@ -75,13 +75,15 @@ private fun PriceBlock(
|
|||
modifier = modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
PriceText(
|
||||
modifier = Modifier.weight(weight = 1f, fill = false),
|
||||
text = price,
|
||||
isFlickering = isFlickering,
|
||||
)
|
||||
if (price != null) {
|
||||
PriceText(
|
||||
modifier = Modifier.weight(weight = 1f, fill = false),
|
||||
text = price,
|
||||
isFlickering = isFlickering,
|
||||
)
|
||||
|
||||
SpacerW6()
|
||||
SpacerW6()
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
PriceChangeIcon(
|
||||
|
|
|
|||
|
|
@ -230,6 +230,12 @@ sealed class TokenItemState {
|
|||
val isFlickering: Boolean = false,
|
||||
) : Subtitle2State()
|
||||
|
||||
data class PriceChangeContent(
|
||||
val priceChangePercent: String,
|
||||
val type: PriceChangeType,
|
||||
val isFlickering: Boolean = false,
|
||||
) : Subtitle2State()
|
||||
|
||||
data class LabelContent(val auditLabelUM: AuditLabelUM) : Subtitle2State()
|
||||
|
||||
data object Unreachable : Subtitle2State()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.core.ui.extensions
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
/**
|
||||
* Utility class for keeping themed color reference from app theme.
|
||||
*
|
||||
* It necessary to use [Immutable] annotation for runtime stability.
|
||||
*
|
||||
* @property value color provider from theme
|
||||
*/
|
||||
@Immutable
|
||||
data class ColorReference(val value: @Composable () -> Color)
|
||||
|
||||
/**
|
||||
* Creates a [ColorReference] using a themed color from the app theme with a lambda.
|
||||
*
|
||||
* @param value The color provider from theme.
|
||||
* @return A [ColorReference] representing the themed color.
|
||||
*/
|
||||
fun themedColor(value: @Composable () -> Color): ColorReference {
|
||||
return ColorReference(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves [ColorReference] to [Color]
|
||||
*/
|
||||
@Composable
|
||||
fun ColorReference.resolveReference(): Color {
|
||||
return value()
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ object TangemColorPalette {
|
|||
|
||||
// region Light
|
||||
val Light1 = Color(0xFFF5F5F5)
|
||||
val Light1V2 = Color(0xFFF4F4F4)
|
||||
val Light2 = Color(0xFFEBEBEB)
|
||||
val Light3 = Color(0xFFD3D3D3)
|
||||
val Light4 = Color(0xFFC9C9C9)
|
||||
|
|
@ -27,6 +28,7 @@ object TangemColorPalette {
|
|||
// endregion Light
|
||||
|
||||
// region Green
|
||||
val Green = Color(0xFF0C9F3D)
|
||||
val Meadow = Color(0xFF1ACE80)
|
||||
val MagicMint = Color(0xFFA3EBCC)
|
||||
val DarkGreen = Color(0xFF06311F)
|
||||
|
|
@ -45,4 +47,9 @@ object TangemColorPalette {
|
|||
val Tangerine = Color(0xFFFFB71B)
|
||||
val Mustard = Color(0xFFFDDE55)
|
||||
// endregion Yellow
|
||||
|
||||
// region Overlay
|
||||
val Overlay1 = Color(0x66000000)
|
||||
val Overlay2 = Color(0xB2000000)
|
||||
// endregion Overlay
|
||||
}
|
||||
536
core/ui/src/main/java/com/tangem/core/ui/res/TangemColors2.kt
Normal file
536
core/ui/src/main/java/com/tangem/core/ui/res/TangemColors2.kt
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
@file:Suppress("LongParameterList")
|
||||
package com.tangem.core.ui.res
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
@Stable
|
||||
class TangemColors2 internal constructor(
|
||||
val text: Text,
|
||||
val graphic: Graphic,
|
||||
val button: Button,
|
||||
val surface: Surface,
|
||||
val controls: Controls,
|
||||
val field: Field,
|
||||
val overlay: Overlay,
|
||||
val border: Border,
|
||||
val fill: Fill,
|
||||
val skeleton: Skeleton,
|
||||
val markers: Markers,
|
||||
) {
|
||||
|
||||
@Stable
|
||||
class Text internal constructor(
|
||||
val neutral: Neutral,
|
||||
val status: Status,
|
||||
) {
|
||||
@Stable
|
||||
class Neutral internal constructor(
|
||||
primary: Color,
|
||||
primaryInverted: Color,
|
||||
secondary: Color,
|
||||
tertiary: Color,
|
||||
primaryInvertedConstant: Color,
|
||||
) {
|
||||
var primary by mutableStateOf(primary)
|
||||
private set
|
||||
var primaryInverted by mutableStateOf(primaryInverted)
|
||||
private set
|
||||
var secondary by mutableStateOf(secondary)
|
||||
private set
|
||||
var tertiary by mutableStateOf(tertiary)
|
||||
private set
|
||||
var primaryInvertedConstant by mutableStateOf(primaryInvertedConstant)
|
||||
private set
|
||||
|
||||
fun update(other: Neutral) {
|
||||
primary = other.primary
|
||||
primaryInverted = other.primaryInverted
|
||||
secondary = other.secondary
|
||||
tertiary = other.tertiary
|
||||
primaryInvertedConstant = other.primaryInvertedConstant
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Status internal constructor(
|
||||
disabled: Color,
|
||||
accent: Color,
|
||||
warning: Color,
|
||||
attention: Color,
|
||||
positive: Color,
|
||||
) {
|
||||
var disabled by mutableStateOf(disabled)
|
||||
private set
|
||||
var accent by mutableStateOf(accent)
|
||||
private set
|
||||
var warning by mutableStateOf(warning)
|
||||
private set
|
||||
var attention by mutableStateOf(attention)
|
||||
private set
|
||||
var positive by mutableStateOf(positive)
|
||||
private set
|
||||
|
||||
fun update(other: Status) {
|
||||
disabled = other.disabled
|
||||
accent = other.accent
|
||||
warning = other.warning
|
||||
attention = other.attention
|
||||
positive = other.positive
|
||||
}
|
||||
}
|
||||
|
||||
fun update(other: Text) {
|
||||
neutral.update(other.neutral)
|
||||
status.update(other.status)
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Graphic internal constructor(
|
||||
val neutral: Neutral,
|
||||
val status: Status,
|
||||
) {
|
||||
@Stable
|
||||
class Neutral internal constructor(
|
||||
primary: Color,
|
||||
primaryInverted: Color,
|
||||
secondary: Color,
|
||||
tertiary: Color,
|
||||
quaternary: Color,
|
||||
primaryInvertedConstant: Color,
|
||||
tertiaryConstant: Color,
|
||||
) {
|
||||
var primary by mutableStateOf(primary)
|
||||
private set
|
||||
var primaryInverted by mutableStateOf(primaryInverted)
|
||||
private set
|
||||
var secondary by mutableStateOf(secondary)
|
||||
private set
|
||||
var tertiary by mutableStateOf(tertiary)
|
||||
private set
|
||||
var quaternary by mutableStateOf(quaternary)
|
||||
private set
|
||||
var primaryInvertedConstant by mutableStateOf(primaryInvertedConstant)
|
||||
private set
|
||||
var tertiaryConstant by mutableStateOf(tertiaryConstant)
|
||||
private set
|
||||
|
||||
fun update(other: Neutral) {
|
||||
primary = other.primary
|
||||
primaryInverted = other.primaryInverted
|
||||
secondary = other.secondary
|
||||
tertiary = other.tertiary
|
||||
quaternary = other.quaternary
|
||||
primaryInvertedConstant = other.primaryInvertedConstant
|
||||
tertiaryConstant = other.tertiaryConstant
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Status internal constructor(
|
||||
accent: Color,
|
||||
warning: Color,
|
||||
attention: Color,
|
||||
) {
|
||||
var accent by mutableStateOf(accent)
|
||||
private set
|
||||
var warning by mutableStateOf(warning)
|
||||
private set
|
||||
var attention by mutableStateOf(attention)
|
||||
private set
|
||||
|
||||
fun update(other: Status) {
|
||||
accent = other.accent
|
||||
warning = other.warning
|
||||
attention = other.attention
|
||||
}
|
||||
}
|
||||
|
||||
fun update(other: Graphic) {
|
||||
neutral.update(other.neutral)
|
||||
status.update(other.status)
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Button internal constructor(
|
||||
backgroundPrimary: Color,
|
||||
backgroundSecondary: Color,
|
||||
backgroundDisabled: Color,
|
||||
backgroundPositive: Color,
|
||||
textPrimary: Color,
|
||||
textSecondary: Color,
|
||||
textDisabled: Color,
|
||||
iconPrimary: Color,
|
||||
iconSecondary: Color,
|
||||
iconDisabled: Color,
|
||||
borderPrimary: Color,
|
||||
) {
|
||||
var backgroundPrimary by mutableStateOf(backgroundPrimary)
|
||||
private set
|
||||
var backgroundSecondary by mutableStateOf(backgroundSecondary)
|
||||
private set
|
||||
var backgroundDisabled by mutableStateOf(backgroundDisabled)
|
||||
private set
|
||||
var backgroundPositive by mutableStateOf(backgroundPositive)
|
||||
private set
|
||||
var textPrimary by mutableStateOf(textPrimary)
|
||||
private set
|
||||
var textSecondary by mutableStateOf(textSecondary)
|
||||
private set
|
||||
var textDisabled by mutableStateOf(textDisabled)
|
||||
private set
|
||||
var iconPrimary by mutableStateOf(iconPrimary)
|
||||
private set
|
||||
var iconSecondary by mutableStateOf(iconSecondary)
|
||||
private set
|
||||
var iconDisabled by mutableStateOf(iconDisabled)
|
||||
private set
|
||||
var borderPrimary by mutableStateOf(borderPrimary)
|
||||
private set
|
||||
|
||||
fun update(other: Button) {
|
||||
backgroundPrimary = other.backgroundPrimary
|
||||
backgroundSecondary = other.backgroundSecondary
|
||||
backgroundDisabled = other.backgroundDisabled
|
||||
backgroundPositive = other.backgroundPositive
|
||||
textPrimary = other.textPrimary
|
||||
textSecondary = other.textSecondary
|
||||
textDisabled = other.textDisabled
|
||||
iconPrimary = other.iconPrimary
|
||||
iconSecondary = other.iconSecondary
|
||||
iconDisabled = other.iconDisabled
|
||||
borderPrimary = other.borderPrimary
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Surface internal constructor(
|
||||
level1: Color,
|
||||
level2: Color,
|
||||
level3: Color,
|
||||
level4: Color,
|
||||
) {
|
||||
var level1 by mutableStateOf(level1)
|
||||
private set
|
||||
var level2 by mutableStateOf(level2)
|
||||
private set
|
||||
var level3 by mutableStateOf(level3)
|
||||
private set
|
||||
var level4 by mutableStateOf(level4)
|
||||
private set
|
||||
|
||||
fun update(other: Surface) {
|
||||
level1 = other.level1
|
||||
level2 = other.level2
|
||||
level3 = other.level3
|
||||
level4 = other.level4
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Controls internal constructor(
|
||||
backgroundDefault: Color,
|
||||
backgroundChecked: Color,
|
||||
iconDefault: Color,
|
||||
iconDisabled: Color,
|
||||
) {
|
||||
var backgroundDefault by mutableStateOf(backgroundDefault)
|
||||
private set
|
||||
var backgroundChecked by mutableStateOf(backgroundChecked)
|
||||
private set
|
||||
var iconDefault by mutableStateOf(iconDefault)
|
||||
private set
|
||||
var iconDisabled by mutableStateOf(iconDisabled)
|
||||
private set
|
||||
|
||||
fun update(other: Controls) {
|
||||
backgroundDefault = other.backgroundDefault
|
||||
backgroundChecked = other.backgroundChecked
|
||||
iconDefault = other.iconDefault
|
||||
iconDisabled = other.iconDisabled
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Field internal constructor(
|
||||
backgroundDefault: Color,
|
||||
backgroundFocused: Color,
|
||||
textPlaceholder: Color,
|
||||
textDefault: Color,
|
||||
textDisabled: Color,
|
||||
iconDefault: Color,
|
||||
iconDisabled: Color,
|
||||
textInvalid: Color,
|
||||
borderInvalid: Color,
|
||||
) {
|
||||
var backgroundDefault by mutableStateOf(backgroundDefault)
|
||||
private set
|
||||
var backgroundFocused by mutableStateOf(backgroundFocused)
|
||||
private set
|
||||
var textPlaceholder by mutableStateOf(textPlaceholder)
|
||||
private set
|
||||
var textDefault by mutableStateOf(textDefault)
|
||||
private set
|
||||
var textDisabled by mutableStateOf(textDisabled)
|
||||
private set
|
||||
var iconDefault by mutableStateOf(iconDefault)
|
||||
private set
|
||||
var iconDisabled by mutableStateOf(iconDisabled)
|
||||
private set
|
||||
var textInvalid by mutableStateOf(textInvalid)
|
||||
private set
|
||||
var borderInvalid by mutableStateOf(borderInvalid)
|
||||
private set
|
||||
|
||||
fun update(other: Field) {
|
||||
backgroundDefault = other.backgroundDefault
|
||||
backgroundFocused = other.backgroundFocused
|
||||
textPlaceholder = other.textPlaceholder
|
||||
textDefault = other.textDefault
|
||||
textDisabled = other.textDisabled
|
||||
iconDefault = other.iconDefault
|
||||
iconDisabled = other.iconDisabled
|
||||
textInvalid = other.textInvalid
|
||||
borderInvalid = other.borderInvalid
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Overlay internal constructor(
|
||||
overlayPrimary: Color,
|
||||
overlaySecondary: Color,
|
||||
) {
|
||||
var overlayPrimary by mutableStateOf(overlayPrimary)
|
||||
private set
|
||||
var overlaySecondary by mutableStateOf(overlaySecondary)
|
||||
private set
|
||||
|
||||
fun update(other: Overlay) {
|
||||
overlayPrimary = other.overlayPrimary
|
||||
overlaySecondary = other.overlaySecondary
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Border internal constructor(
|
||||
val neutral: Neutral,
|
||||
val status: Status,
|
||||
) {
|
||||
|
||||
@Stable
|
||||
class Neutral internal constructor(
|
||||
primary: Color,
|
||||
secondary: Color,
|
||||
) {
|
||||
var primary by mutableStateOf(primary)
|
||||
private set
|
||||
var secondary by mutableStateOf(secondary)
|
||||
private set
|
||||
|
||||
fun update(other: Neutral) {
|
||||
primary = other.primary
|
||||
secondary = other.secondary
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Status internal constructor(
|
||||
accent: Color,
|
||||
warning: Color,
|
||||
attention: Color,
|
||||
) {
|
||||
var accent by mutableStateOf(accent)
|
||||
private set
|
||||
var warning by mutableStateOf(warning)
|
||||
private set
|
||||
var attention by mutableStateOf(attention)
|
||||
private set
|
||||
|
||||
fun update(other: Status) {
|
||||
accent = other.accent
|
||||
warning = other.warning
|
||||
attention = other.attention
|
||||
}
|
||||
}
|
||||
|
||||
fun update(other: Border) {
|
||||
neutral.update(other.neutral)
|
||||
status.update(other.status)
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Fill internal constructor(
|
||||
val neutral: Neutral,
|
||||
val status: Status,
|
||||
) {
|
||||
|
||||
@Stable
|
||||
class Neutral internal constructor(
|
||||
primary: Color,
|
||||
primaryInverted: Color,
|
||||
primaryInvertedConstant: Color,
|
||||
secondary: Color,
|
||||
tertiaryConstant: Color,
|
||||
quaternary: Color,
|
||||
) {
|
||||
var primary by mutableStateOf(primary)
|
||||
private set
|
||||
var primaryInverted by mutableStateOf(primaryInverted)
|
||||
private set
|
||||
var primaryInvertedConstant by mutableStateOf(primaryInvertedConstant)
|
||||
private set
|
||||
var secondary by mutableStateOf(secondary)
|
||||
private set
|
||||
var tertiaryConstant by mutableStateOf(tertiaryConstant)
|
||||
private set
|
||||
var quaternary by mutableStateOf(quaternary)
|
||||
private set
|
||||
|
||||
fun update(other: Neutral) {
|
||||
primary = other.primary
|
||||
primaryInverted = other.primaryInverted
|
||||
primaryInvertedConstant = other.primaryInvertedConstant
|
||||
secondary = other.secondary
|
||||
tertiaryConstant = other.tertiaryConstant
|
||||
quaternary = other.quaternary
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Status internal constructor(
|
||||
accent: Color,
|
||||
warning: Color,
|
||||
attention: Color,
|
||||
) {
|
||||
var accent by mutableStateOf(accent)
|
||||
private set
|
||||
var warning by mutableStateOf(warning)
|
||||
private set
|
||||
var attention by mutableStateOf(attention)
|
||||
private set
|
||||
|
||||
fun update(other: Status) {
|
||||
accent = other.accent
|
||||
warning = other.warning
|
||||
attention = other.attention
|
||||
}
|
||||
}
|
||||
|
||||
fun update(other: Fill) {
|
||||
neutral.update(other.neutral)
|
||||
status.update(other.status)
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Skeleton internal constructor(
|
||||
backgroundPrimary: Color,
|
||||
) {
|
||||
var backgroundPrimary by mutableStateOf(backgroundPrimary)
|
||||
private set
|
||||
|
||||
fun update(other: Skeleton) {
|
||||
backgroundPrimary = other.backgroundPrimary
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
class Markers internal constructor(
|
||||
backgroundSolidGray: Color,
|
||||
backgroundDisabled: Color,
|
||||
backgroundSolidBlue: Color,
|
||||
textGray: Color,
|
||||
textDisabled: Color,
|
||||
iconGray: Color,
|
||||
iconDisabled: Color,
|
||||
borderGray: Color,
|
||||
backgroundTintedBlue: Color,
|
||||
textBlue: Color,
|
||||
backgroundSolidRed: Color,
|
||||
backgroundTintedRed: Color,
|
||||
iconBlue: Color,
|
||||
iconRed: Color,
|
||||
textRed: Color,
|
||||
backgroundTintedGray: Color,
|
||||
borderTintedBlue: Color,
|
||||
borderTintedRed: Color,
|
||||
) {
|
||||
var backgroundSolidGray by mutableStateOf(backgroundSolidGray)
|
||||
private set
|
||||
var backgroundDisabled by mutableStateOf(backgroundDisabled)
|
||||
private set
|
||||
var backgroundSolidBlue by mutableStateOf(backgroundSolidBlue)
|
||||
private set
|
||||
var textGray by mutableStateOf(textGray)
|
||||
private set
|
||||
var textDisabled by mutableStateOf(textDisabled)
|
||||
private set
|
||||
var iconGray by mutableStateOf(iconGray)
|
||||
private set
|
||||
var iconDisabled by mutableStateOf(iconDisabled)
|
||||
private set
|
||||
var borderGray by mutableStateOf(borderGray)
|
||||
private set
|
||||
var backgroundTintedBlue by mutableStateOf(backgroundTintedBlue)
|
||||
private set
|
||||
var textBlue by mutableStateOf(textBlue)
|
||||
private set
|
||||
var backgroundSolidRed by mutableStateOf(backgroundSolidRed)
|
||||
private set
|
||||
var backgroundTintedRed by mutableStateOf(backgroundTintedRed)
|
||||
private set
|
||||
var iconBlue by mutableStateOf(iconBlue)
|
||||
private set
|
||||
var iconRed by mutableStateOf(iconRed)
|
||||
private set
|
||||
var textRed by mutableStateOf(textRed)
|
||||
private set
|
||||
var backgroundTintedGray by mutableStateOf(backgroundTintedGray)
|
||||
private set
|
||||
var borderTintedBlue by mutableStateOf(borderTintedBlue)
|
||||
private set
|
||||
var borderTintedRed by mutableStateOf(borderTintedRed)
|
||||
private set
|
||||
|
||||
fun update(other: Markers) {
|
||||
backgroundSolidGray = other.backgroundSolidGray
|
||||
backgroundDisabled = other.backgroundDisabled
|
||||
backgroundSolidBlue = other.backgroundSolidBlue
|
||||
textGray = other.textGray
|
||||
textDisabled = other.textDisabled
|
||||
iconGray = other.iconGray
|
||||
iconDisabled = other.iconDisabled
|
||||
borderGray = other.borderGray
|
||||
backgroundTintedBlue = other.backgroundTintedBlue
|
||||
textBlue = other.textBlue
|
||||
backgroundSolidRed = other.backgroundSolidRed
|
||||
backgroundTintedRed = other.backgroundTintedRed
|
||||
iconBlue = other.iconBlue
|
||||
iconRed = other.iconRed
|
||||
textRed = other.textRed
|
||||
backgroundTintedGray = other.backgroundTintedGray
|
||||
borderTintedBlue = other.borderTintedBlue
|
||||
borderTintedRed = other.borderTintedRed
|
||||
}
|
||||
}
|
||||
|
||||
fun update(other: TangemColors2) {
|
||||
text.update(other.text)
|
||||
graphic.update(other.graphic)
|
||||
button.update(other.button)
|
||||
surface.update(other.surface)
|
||||
controls.update(other.controls)
|
||||
field.update(other.field)
|
||||
overlay.update(other.overlay)
|
||||
border.update(other.border)
|
||||
fill.update(other.fill)
|
||||
skeleton.update(other.skeleton)
|
||||
markers.update(other.markers)
|
||||
}
|
||||
}
|
||||
|
|
@ -138,6 +138,11 @@ object TangemTheme {
|
|||
@ReadOnlyComposable
|
||||
get() = LocalTangemColors.current
|
||||
|
||||
val colors2: TangemColors2
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = LocalTangemColors2.current
|
||||
|
||||
val typography: TangemTypography
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
|
|
@ -156,7 +161,7 @@ object TangemTheme {
|
|||
|
||||
@Stable
|
||||
@Composable
|
||||
private fun tangemColorScheme(colors: TangemColors): ColorScheme {
|
||||
internal fun tangemColorScheme(colors: TangemColors): ColorScheme {
|
||||
return ColorScheme(
|
||||
primary = colors.background.primary,
|
||||
onPrimary = colors.text.primary1,
|
||||
|
|
@ -206,7 +211,7 @@ private fun tangemColorScheme(colors: TangemColors): ColorScheme {
|
|||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun lightThemeColors(): TangemColors {
|
||||
internal fun lightThemeColors(redesign: Boolean = false): TangemColors {
|
||||
return TangemColors(
|
||||
text = TangemColors.Text(
|
||||
primary1 = TangemColorPalette.Dark6,
|
||||
|
|
@ -233,8 +238,8 @@ private fun lightThemeColors(): TangemColors {
|
|||
),
|
||||
background = TangemColors.Background(
|
||||
primary = TangemColorPalette.White,
|
||||
secondary = TangemColorPalette.Light1,
|
||||
tertiary = TangemColorPalette.Light1,
|
||||
secondary = if (redesign) TangemColorPalette.Light1V2 else TangemColorPalette.Light1,
|
||||
tertiary = if (redesign) TangemColorPalette.Light1V2 else TangemColorPalette.Light1,
|
||||
action = TangemColorPalette.White,
|
||||
),
|
||||
control = TangemColors.Control(
|
||||
|
|
@ -248,7 +253,7 @@ private fun lightThemeColors(): TangemColors {
|
|||
transparency = TangemColorPalette.White,
|
||||
),
|
||||
field = TangemColors.Field(
|
||||
primary = TangemColorPalette.Light1,
|
||||
primary = if (redesign) TangemColorPalette.Light1V2 else TangemColorPalette.Light1,
|
||||
focused = TangemColorPalette.Light2,
|
||||
),
|
||||
overlay = TangemColors.Overlay(
|
||||
|
|
@ -260,7 +265,7 @@ private fun lightThemeColors(): TangemColors {
|
|||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun darkThemeColors(): TangemColors {
|
||||
internal fun darkThemeColors(): TangemColors {
|
||||
return TangemColors(
|
||||
text = TangemColors.Text(
|
||||
primary1 = TangemColorPalette.White,
|
||||
|
|
@ -320,12 +325,16 @@ private val TangemTextSelectionColors: TextSelectionColors
|
|||
backgroundColor = TangemTheme.colors.text.accent.copy(alpha = 0.3f),
|
||||
)
|
||||
|
||||
private val LocalTangemColors = staticCompositionLocalOf<TangemColors> {
|
||||
internal val LocalTangemColors = staticCompositionLocalOf<TangemColors> {
|
||||
error("No TangemColors provided")
|
||||
}
|
||||
|
||||
private val LocalTangemTypography = staticCompositionLocalOf {
|
||||
TangemTypography()
|
||||
internal val LocalTangemColors2 = staticCompositionLocalOf<TangemColors2> {
|
||||
error("No TangemColors2 provided")
|
||||
}
|
||||
|
||||
internal val LocalTangemTypography = staticCompositionLocalOf {
|
||||
TangemTypography(RobotoFamily)
|
||||
}
|
||||
|
||||
private val LocalTangemDimens = staticCompositionLocalOf {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,309 @@
|
|||
@file:Suppress("LongMethod")
|
||||
package com.tangem.core.ui.res
|
||||
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.*
|
||||
|
||||
/**
|
||||
* Provides additional theming for redesigned components.
|
||||
* Used together with [TangemTheme].
|
||||
* @param content Composable content where the theme is applied.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemThemeRedesign(content: @Composable () -> Unit) {
|
||||
val themeColors = if (LocalIsInDarkTheme.current) darkThemeColors() else lightThemeColors(redesign = true)
|
||||
val rememberedColors = remember { themeColors }
|
||||
.also { it.update(themeColors) }
|
||||
val rootBackgroundColor = rememberedColors.background.secondary
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = tangemColorScheme(colors = themeColors),
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalTangemColors provides themeColors,
|
||||
LocalTangemColors2 provides if (LocalIsInDarkTheme.current) darkThemeColors2() else lightThemeColors2(),
|
||||
LocalTangemTypography provides TangemTypography(InterFamily),
|
||||
LocalRootBackgroundColor provides remember(rootBackgroundColor) { mutableStateOf(rootBackgroundColor) },
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun lightThemeColors2(): TangemColors2 {
|
||||
val text = TangemColors2.Text(
|
||||
neutral = TangemColors2.Text.Neutral(
|
||||
primary = TangemColorPalette.Dark6,
|
||||
primaryInverted = TangemColorPalette.White,
|
||||
secondary = TangemColorPalette.Dark2,
|
||||
tertiary = TangemColorPalette.Dark3,
|
||||
primaryInvertedConstant = TangemColorPalette.White,
|
||||
),
|
||||
status = TangemColors2.Text.Status(
|
||||
disabled = TangemColorPalette.Light4,
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Amaranth,
|
||||
attention = TangemColorPalette.Tangerine,
|
||||
positive = TangemColorPalette.Green,
|
||||
),
|
||||
)
|
||||
val graphic = TangemColors2.Graphic(
|
||||
neutral = TangemColors2.Graphic.Neutral(
|
||||
primary = TangemColorPalette.Dark6,
|
||||
primaryInverted = TangemColorPalette.White,
|
||||
secondary = TangemColorPalette.Dark2,
|
||||
tertiary = TangemColorPalette.Dark3,
|
||||
quaternary = TangemColorPalette.Light4,
|
||||
primaryInvertedConstant = TangemColorPalette.White,
|
||||
tertiaryConstant = TangemColorPalette.Dark3,
|
||||
),
|
||||
status = TangemColors2.Graphic.Status(
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Amaranth,
|
||||
attention = TangemColorPalette.Tangerine,
|
||||
),
|
||||
)
|
||||
val border = TangemColors2.Border(
|
||||
neutral = TangemColors2.Border.Neutral(
|
||||
primary = TangemColorPalette.Light3,
|
||||
secondary = TangemColorPalette.Light5,
|
||||
),
|
||||
status = TangemColors2.Border.Status(
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Amaranth,
|
||||
attention = TangemColorPalette.Tangerine,
|
||||
),
|
||||
)
|
||||
val overlay = TangemColors2.Overlay(
|
||||
overlayPrimary = TangemColorPalette.Overlay1,
|
||||
overlaySecondary = TangemColorPalette.Overlay2,
|
||||
)
|
||||
val fill = TangemColors2.Fill(
|
||||
neutral = TangemColors2.Fill.Neutral(
|
||||
primary = TangemColorPalette.Dark6,
|
||||
primaryInverted = TangemColorPalette.White,
|
||||
primaryInvertedConstant = TangemColorPalette.White,
|
||||
secondary = TangemColorPalette.Dark3,
|
||||
tertiaryConstant = TangemColorPalette.Dark3,
|
||||
quaternary = TangemColorPalette.Light4,
|
||||
),
|
||||
status = TangemColors2.Fill.Status(
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Amaranth,
|
||||
attention = TangemColorPalette.Tangerine,
|
||||
),
|
||||
)
|
||||
val button = TangemColors2.Button(
|
||||
backgroundPrimary = TangemColorPalette.Dark6,
|
||||
backgroundSecondary = TangemColorPalette.Dark6.copy(alpha = 0.1f),
|
||||
backgroundDisabled = TangemColorPalette.Light3,
|
||||
backgroundPositive = TangemColorPalette.Azure,
|
||||
textSecondary = TangemColorPalette.Dark6,
|
||||
textPrimary = TangemColorPalette.Light2,
|
||||
textDisabled = text.neutral.tertiary,
|
||||
iconPrimary = TangemColorPalette.Dark6,
|
||||
iconSecondary = TangemColorPalette.Light1V2,
|
||||
iconDisabled = TangemColorPalette.Light2,
|
||||
borderPrimary = TangemColorPalette.Dark6,
|
||||
)
|
||||
val surface = TangemColors2.Surface(
|
||||
level1 = TangemColorPalette.White,
|
||||
level2 = TangemColorPalette.Light1V2,
|
||||
level3 = TangemColorPalette.Light1V2,
|
||||
level4 = TangemColorPalette.White,
|
||||
)
|
||||
val controls = TangemColors2.Controls(
|
||||
backgroundChecked = TangemColorPalette.Dark6,
|
||||
backgroundDefault = TangemColorPalette.Light2,
|
||||
iconDefault = TangemColorPalette.White,
|
||||
iconDisabled = TangemColorPalette.White,
|
||||
)
|
||||
val field = TangemColors2.Field(
|
||||
backgroundDefault = TangemColorPalette.Light1V2,
|
||||
backgroundFocused = TangemColorPalette.Light3,
|
||||
textPlaceholder = text.neutral.secondary,
|
||||
textDefault = text.neutral.primary,
|
||||
textDisabled = text.neutral.tertiary,
|
||||
iconDefault = graphic.neutral.tertiary,
|
||||
iconDisabled = graphic.neutral.quaternary,
|
||||
textInvalid = text.status.warning,
|
||||
borderInvalid = border.status.warning,
|
||||
)
|
||||
val skeleton = TangemColors2.Skeleton(
|
||||
backgroundPrimary = TangemColorPalette.Light1V2,
|
||||
)
|
||||
val markers = TangemColors2.Markers(
|
||||
backgroundSolidGray = TangemColorPalette.Light3,
|
||||
backgroundDisabled = TangemColorPalette.Light3,
|
||||
backgroundSolidBlue = TangemColorPalette.Azure,
|
||||
textGray = TangemColorPalette.Dark2,
|
||||
textDisabled = text.neutral.tertiary,
|
||||
iconGray = TangemColorPalette.Dark1,
|
||||
iconDisabled = TangemColorPalette.Light2,
|
||||
borderGray = TangemColorPalette.Light3,
|
||||
backgroundTintedBlue = TangemColorPalette.Azure.copy(alpha = 0.1f),
|
||||
textBlue = text.status.accent,
|
||||
backgroundSolidRed = TangemColorPalette.Amaranth,
|
||||
backgroundTintedRed = TangemColorPalette.Amaranth.copy(alpha = 0.1f),
|
||||
iconBlue = TangemColorPalette.Azure,
|
||||
iconRed = TangemColorPalette.Amaranth,
|
||||
textRed = TangemColorPalette.Amaranth,
|
||||
backgroundTintedGray = TangemColorPalette.Dark6.copy(alpha = 0.1f),
|
||||
borderTintedBlue = TangemColorPalette.Azure.copy(alpha = 0.1f),
|
||||
borderTintedRed = TangemColorPalette.Amaranth.copy(alpha = 0.1f),
|
||||
)
|
||||
return TangemColors2(
|
||||
text = text,
|
||||
graphic = graphic,
|
||||
border = border,
|
||||
overlay = overlay,
|
||||
fill = fill,
|
||||
button = button,
|
||||
surface = surface,
|
||||
controls = controls,
|
||||
field = field,
|
||||
skeleton = skeleton,
|
||||
markers = markers,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun darkThemeColors2(): TangemColors2 {
|
||||
val text = TangemColors2.Text(
|
||||
neutral = TangemColors2.Text.Neutral(
|
||||
primary = TangemColorPalette.White,
|
||||
primaryInverted = TangemColorPalette.Dark6,
|
||||
secondary = TangemColorPalette.Light5,
|
||||
tertiary = TangemColorPalette.Dark1,
|
||||
primaryInvertedConstant = TangemColorPalette.White,
|
||||
),
|
||||
status = TangemColors2.Text.Status(
|
||||
disabled = TangemColorPalette.Dark3,
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Flamingo,
|
||||
attention = TangemColorPalette.Mustard,
|
||||
positive = TangemColorPalette.Green,
|
||||
),
|
||||
)
|
||||
val graphic = TangemColors2.Graphic(
|
||||
neutral = TangemColors2.Graphic.Neutral(
|
||||
primary = TangemColorPalette.White,
|
||||
primaryInverted = TangemColorPalette.Dark6,
|
||||
secondary = TangemColorPalette.Light5,
|
||||
tertiary = TangemColorPalette.Dark3,
|
||||
quaternary = TangemColorPalette.Dark3,
|
||||
tertiaryConstant = TangemColorPalette.Dark3,
|
||||
primaryInvertedConstant = TangemColorPalette.White,
|
||||
),
|
||||
status = TangemColors2.Graphic.Status(
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Flamingo,
|
||||
attention = TangemColorPalette.Mustard,
|
||||
),
|
||||
)
|
||||
val border = TangemColors2.Border(
|
||||
neutral = TangemColors2.Border.Neutral(
|
||||
primary = TangemColorPalette.Dark4,
|
||||
secondary = TangemColorPalette.Dark4,
|
||||
),
|
||||
status = TangemColors2.Border.Status(
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Flamingo,
|
||||
attention = TangemColorPalette.Mustard,
|
||||
),
|
||||
)
|
||||
val overlay = TangemColors2.Overlay(
|
||||
overlayPrimary = TangemColorPalette.Overlay1,
|
||||
overlaySecondary = TangemColorPalette.Overlay2,
|
||||
)
|
||||
val fill = TangemColors2.Fill(
|
||||
neutral = TangemColors2.Fill.Neutral(
|
||||
primary = TangemColorPalette.White,
|
||||
primaryInverted = TangemColorPalette.Dark6,
|
||||
primaryInvertedConstant = TangemColorPalette.White,
|
||||
secondary = TangemColorPalette.Light5,
|
||||
tertiaryConstant = TangemColorPalette.Dark1,
|
||||
quaternary = TangemColorPalette.Dark3,
|
||||
),
|
||||
status = TangemColors2.Fill.Status(
|
||||
accent = TangemColorPalette.Azure,
|
||||
warning = TangemColorPalette.Flamingo,
|
||||
attention = TangemColorPalette.Mustard,
|
||||
),
|
||||
)
|
||||
val button = TangemColors2.Button(
|
||||
backgroundPrimary = TangemColorPalette.Light1V2,
|
||||
backgroundSecondary = TangemColorPalette.White.copy(alpha = 0.1f),
|
||||
backgroundDisabled = TangemColorPalette.Dark5,
|
||||
backgroundPositive = TangemColorPalette.Azure,
|
||||
textSecondary = TangemColorPalette.Light4,
|
||||
textPrimary = TangemColorPalette.Dark4,
|
||||
textDisabled = text.neutral.secondary,
|
||||
iconPrimary = TangemColorPalette.Light4,
|
||||
iconSecondary = TangemColorPalette.Dark4,
|
||||
iconDisabled = TangemColorPalette.Dark5,
|
||||
borderPrimary = TangemColorPalette.Light4,
|
||||
)
|
||||
val surface = TangemColors2.Surface(
|
||||
level1 = TangemColorPalette.Dark6,
|
||||
level2 = TangemColorPalette.Black,
|
||||
level3 = TangemColorPalette.Dark6,
|
||||
level4 = TangemColorPalette.Dark5,
|
||||
)
|
||||
val controls = TangemColors2.Controls(
|
||||
backgroundChecked = TangemColorPalette.Azure,
|
||||
backgroundDefault = TangemColorPalette.Dark4,
|
||||
iconDefault = TangemColorPalette.White,
|
||||
iconDisabled = TangemColorPalette.White,
|
||||
)
|
||||
val field = TangemColors2.Field(
|
||||
backgroundDefault = TangemColorPalette.Dark6,
|
||||
backgroundFocused = TangemColorPalette.Dark4,
|
||||
textPlaceholder = text.neutral.secondary,
|
||||
textDefault = text.neutral.primary,
|
||||
textDisabled = text.neutral.tertiary,
|
||||
iconDefault = graphic.neutral.tertiary,
|
||||
iconDisabled = graphic.neutral.quaternary,
|
||||
textInvalid = text.status.warning,
|
||||
borderInvalid = border.status.warning,
|
||||
)
|
||||
val skeleton = TangemColors2.Skeleton(
|
||||
backgroundPrimary = TangemColorPalette.Dark5,
|
||||
)
|
||||
val markers = TangemColors2.Markers(
|
||||
backgroundSolidGray = TangemColorPalette.Dark5,
|
||||
backgroundDisabled = TangemColorPalette.Dark5,
|
||||
backgroundSolidBlue = TangemColorPalette.Azure,
|
||||
textGray = TangemColorPalette.Light4,
|
||||
textDisabled = text.neutral.secondary,
|
||||
iconGray = TangemColorPalette.Dark2,
|
||||
iconDisabled = TangemColorPalette.Dark5,
|
||||
borderGray = TangemColorPalette.White.copy(alpha = 0.2f),
|
||||
backgroundTintedBlue = TangemColorPalette.Azure.copy(alpha = 0.1f),
|
||||
textBlue = text.status.accent,
|
||||
backgroundSolidRed = TangemColorPalette.Amaranth,
|
||||
backgroundTintedRed = TangemColorPalette.Amaranth.copy(alpha = 0.1f),
|
||||
iconBlue = TangemColorPalette.Azure,
|
||||
iconRed = TangemColorPalette.Flamingo,
|
||||
textRed = TangemColorPalette.Flamingo,
|
||||
backgroundTintedGray = TangemColorPalette.White.copy(alpha = 0.1f),
|
||||
borderTintedBlue = TangemColorPalette.Azure.copy(alpha = 0.1f),
|
||||
borderTintedRed = TangemColorPalette.Amaranth.copy(alpha = 0.1f),
|
||||
)
|
||||
return TangemColors2(
|
||||
text = text,
|
||||
graphic = graphic,
|
||||
border = border,
|
||||
overlay = overlay,
|
||||
fill = fill,
|
||||
button = button,
|
||||
surface = surface,
|
||||
controls = controls,
|
||||
field = field,
|
||||
skeleton = skeleton,
|
||||
markers = markers,
|
||||
)
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
|
|||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.LineHeightStyle
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
|
|
@ -11,15 +12,22 @@ import androidx.compose.ui.unit.TextUnitType
|
|||
import androidx.compose.ui.unit.sp
|
||||
import com.tangem.core.ui.R
|
||||
|
||||
private val RobotoFamily = FontFamily(
|
||||
internal val RobotoFamily = FontFamily(
|
||||
Font(R.font.roboto_regular, FontWeight.Normal),
|
||||
Font(R.font.roboto_medium, FontWeight.Medium),
|
||||
)
|
||||
|
||||
internal val InterFamily = FontFamily(
|
||||
Font(R.font.inter_regular),
|
||||
Font(R.font.inter_italic, style = FontStyle.Italic),
|
||||
)
|
||||
|
||||
@Immutable
|
||||
data class TangemTypography internal constructor(
|
||||
class TangemTypography internal constructor(
|
||||
fontFamily: FontFamily,
|
||||
) {
|
||||
val head: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 34.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
letterSpacing = TextUnit(value = 0f, type = TextUnitType.Sp),
|
||||
|
|
@ -28,9 +36,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val h1: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 34.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
letterSpacing = TextUnit(value = 0f, type = TextUnitType.Sp),
|
||||
|
|
@ -39,9 +47,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val h2: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 24.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
letterSpacing = TextUnit(value = 0.18f, type = TextUnitType.Sp),
|
||||
|
|
@ -50,9 +58,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val h3: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
letterSpacing = TextUnit(value = 0.15f, type = TextUnitType.Sp),
|
||||
|
|
@ -61,9 +69,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val subtitle1: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
letterSpacing = TextUnit(value = 0.15f, type = TextUnitType.Sp),
|
||||
|
|
@ -72,9 +80,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val subtitle2: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
letterSpacing = TextUnit(value = 0.1f, type = TextUnitType.Sp),
|
||||
|
|
@ -83,9 +91,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val body1: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
letterSpacing = TextUnit(value = 0.5f, type = TextUnitType.Sp),
|
||||
|
|
@ -94,9 +102,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val body2: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
letterSpacing = TextUnit(value = 0.25f, type = TextUnitType.Sp),
|
||||
|
|
@ -105,9 +113,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val button: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
letterSpacing = TextUnit(value = 0.1f, type = TextUnitType.Sp),
|
||||
|
|
@ -116,9 +124,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val caption1: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
letterSpacing = TextUnit(value = 0.4f, type = TextUnitType.Sp),
|
||||
|
|
@ -127,9 +135,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val caption2: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
letterSpacing = TextUnit(value = 0.4f, type = TextUnitType.Sp),
|
||||
|
|
@ -138,9 +146,9 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
val overline: TextStyle = TextStyle(
|
||||
fontFamily = RobotoFamily,
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 10.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
letterSpacing = TextUnit(value = 1.5f, type = TextUnitType.Sp),
|
||||
|
|
@ -149,5 +157,5 @@ data class TangemTypography internal constructor(
|
|||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.core.ui.test
|
||||
|
||||
object BaseAmountBlockTestTags {
|
||||
const val PRIMARY_AMOUNT = "STAKING_SEND_DETAILS_SCREEN_PRIMARY_AMOUNT"
|
||||
const val SECONDARY_AMOUNT = "TAKING_SEND_DETAILS_SCREEN_SECONDARY_AMOUNT"
|
||||
const val PRIMARY_AMOUNT = "SEND_DETAILS_SCREEN_PRIMARY_AMOUNT"
|
||||
const val SECONDARY_AMOUNT = "SEND_DETAILS_SCREEN_SECONDARY_AMOUNT"
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
15
core/ui/src/main/res/drawable/ic_attention_72.xml
Normal file
15
core/ui/src/main/res/drawable/ic_attention_72.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="72dp"
|
||||
android:height="72dp"
|
||||
android:viewportWidth="72"
|
||||
android:viewportHeight="72">
|
||||
<path
|
||||
android:pathData="M69.781,45.692L69.79,45.709C71.126,48.06 72,50.879 72,53.877C72,57.927 70.612,62.075 67.529,65.265C64.394,68.508 60.145,70.096 55.73,70.096H16.27C11.855,70.096 7.606,68.508 4.471,65.265C1.388,62.075 0,57.927 0,53.877C0,51.094 0.713,48.238 2.266,45.611L21.966,11.287C25.02,5.881 30.514,3.086 36,3.086C41.553,3.086 46.97,5.934 50.018,11.26C50.02,11.263 50.022,11.266 50.023,11.269L69.781,45.692ZM41.932,15.893L61.688,50.313C62.324,51.433 62.68,52.681 62.68,53.877C62.68,57.772 60.058,60.777 55.73,60.777H16.27C11.942,60.777 9.32,57.772 9.32,53.877C9.32,52.681 9.625,51.459 10.312,50.313L30.068,15.893C31.367,13.577 33.658,12.406 36,12.406C38.342,12.406 40.608,13.577 41.932,15.893Z"
|
||||
android:strokeAlpha="0.12"
|
||||
android:fillColor="#FF3333"
|
||||
android:fillType="evenOdd"
|
||||
android:fillAlpha="0.12"/>
|
||||
<path
|
||||
android:pathData="M36,9.771C39.182,9.771 42.273,11.382 44.047,14.484L44.049,14.486L63.49,48.36C64.308,49.799 64.8,51.456 64.8,53.126C64.8,55.617 63.955,57.976 62.262,59.728C60.554,61.494 58.159,62.462 55.414,62.462H16.586C13.842,62.462 11.446,61.494 9.738,59.728C8.045,57.976 7.2,55.617 7.2,53.126C7.2,51.514 7.613,49.864 8.526,48.331L27.948,14.493C29.705,11.368 32.836,9.771 36,9.771ZM36,12.318C33.695,12.318 31.441,13.471 30.163,15.751L10.725,49.618C10.048,50.745 9.747,51.949 9.747,53.126C9.747,56.958 12.328,59.914 16.586,59.914H55.414C59.673,59.914 62.253,56.958 62.253,53.126C62.253,51.949 61.902,50.72 61.275,49.618L41.837,15.751C40.534,13.471 38.305,12.318 36,12.318ZM34.984,45.657C35.942,45.657 36.718,46.433 36.718,47.391C36.718,48.348 35.942,49.124 34.984,49.124C34.027,49.124 33.251,48.348 33.251,47.391C33.251,46.433 34.027,45.657 34.984,45.657ZM34.984,25.845C35.805,25.845 36.471,26.51 36.471,27.331V42.189C36.471,43.01 35.805,43.676 34.984,43.676C34.164,43.676 33.499,43.01 33.499,42.189V27.331C33.499,26.511 34.164,25.845 34.984,25.845Z"
|
||||
android:fillColor="#FF3333"/>
|
||||
</vector>
|
||||
BIN
core/ui/src/main/res/font/inter_italic.ttf
Normal file
BIN
core/ui/src/main/res/font/inter_italic.ttf
Normal file
Binary file not shown.
BIN
core/ui/src/main/res/font/inter_regular.ttf
Normal file
BIN
core/ui/src/main/res/font/inter_regular.ttf
Normal file
Binary file not shown.
|
|
@ -28,5 +28,4 @@ class TestingCoroutineDispatcherProvider(
|
|||
override val io: CoroutineDispatcher = Dispatchers.Unconfined,
|
||||
override val default: CoroutineDispatcher = Dispatchers.Unconfined,
|
||||
override val single: CoroutineDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher(),
|
||||
) : CoroutineDispatcherProvider
|
||||
|
||||
) : CoroutineDispatcherProvider
|
||||
Loading…
Add table
Add a link
Reference in a new issue