Updated on 2026-08-14
This commit is contained in:
parent
7141c0e6ee
commit
91ec85c3eb
12 changed files with 269 additions and 93 deletions
|
|
@ -95,7 +95,6 @@ dependencies {
|
|||
implementation(deps.lifecycle.common.java8)
|
||||
implementation(deps.lifecycle.viewModel.ktx)
|
||||
implementation(deps.lifecycle.compose)
|
||||
implementation(deps.androidx.palette)
|
||||
|
||||
/** Compose libraries */
|
||||
implementation(deps.compose.constraintLayout)
|
||||
|
|
|
|||
|
|
@ -3,19 +3,20 @@ package com.tangem.tap.features.tokens.impl.presentation.ui
|
|||
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.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.features.tokens.impl.presentation.states.NetworkItemState
|
||||
|
|
@ -69,11 +70,21 @@ internal fun BriefNetworksList(
|
|||
*/
|
||||
@Composable
|
||||
internal fun BriefNetworkItem(model: NetworkItemState, modifier: Modifier = Modifier) {
|
||||
val isAdded = model is NetworkItemState.ManageContent && model.isAdded.value
|
||||
Box(modifier = modifier.size(size = TangemTheme.dimens.size20)) {
|
||||
Image(
|
||||
if (!isAdded) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size20)
|
||||
.clip(CircleShape)
|
||||
.background(TangemTheme.colors.control.unchecked),
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
painter = painterResource(id = model.iconResId.value),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(size = TangemTheme.dimens.size20),
|
||||
tint = if (isAdded) Color.Unspecified else TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
|
||||
if (model.isMainNetwork) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.features.tokens.impl.presentation.ui
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
|
|
@ -20,16 +19,15 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.palette.graphics.Palette
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.components.CurrencyPlaceholderIcon
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.ImageBackgroundContrastChecker
|
||||
import com.tangem.tap.common.compose.extensions.toPx
|
||||
import com.tangem.tap.features.tokens.impl.presentation.states.TokenItemState
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -130,6 +128,7 @@ private fun Icon(name: String, iconUrl: String, onContrastCalculate: (Color) ->
|
|||
val iconModifier = modifier.size(size = TangemTheme.dimens.size46)
|
||||
val screenBackgroundColor = TangemTheme.colors.background.primary.toArgb()
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
SubcomposeAsyncImage(
|
||||
modifier = iconModifier,
|
||||
|
|
@ -141,11 +140,13 @@ private fun Icon(name: String, iconUrl: String, onContrastCalculate: (Color) ->
|
|||
.listener(
|
||||
onSuccess = { _, result ->
|
||||
if (isDarkTheme) {
|
||||
setContrastBackgroundIfNeeded(
|
||||
drawable = result.drawable,
|
||||
screenBackgroundColor = screenBackgroundColor,
|
||||
onContrastCalculate = onContrastCalculate,
|
||||
)
|
||||
coroutineScope.launch {
|
||||
val color = ImageBackgroundContrastChecker(
|
||||
drawable = result.drawable,
|
||||
backgroundColor = screenBackgroundColor,
|
||||
).getContrastColorIfNeeded(isDarkTheme)
|
||||
onContrastCalculate(color)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -156,26 +157,6 @@ private fun Icon(name: String, iconUrl: String, onContrastCalculate: (Color) ->
|
|||
)
|
||||
}
|
||||
|
||||
private fun setContrastBackgroundIfNeeded(
|
||||
drawable: Drawable,
|
||||
screenBackgroundColor: Int,
|
||||
onContrastCalculate: (Color) -> Unit,
|
||||
) {
|
||||
Palette.Builder(drawable.toBitmap()).generate { palette ->
|
||||
val color = palette?.getDominantColor(screenBackgroundColor) ?: screenBackgroundColor
|
||||
val contrast = ColorUtils.calculateContrast(color, screenBackgroundColor)
|
||||
val colorToSet = if (contrast > LOW_CONTRAST_RATIO) {
|
||||
Color.Transparent
|
||||
} else {
|
||||
Color.White
|
||||
}
|
||||
onContrastCalculate(colorToSet)
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
|
||||
private const val LOW_CONTRAST_RATIO = 1.5f
|
||||
|
||||
@Composable
|
||||
private fun Title(title: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:startColor="#FFFFFF"
|
||||
android:centerColor="#F0FFFFFF"
|
||||
android:endColor="#19FFFFFF"
|
||||
android:centerColor="@color/gradient_center_color"
|
||||
android:endColor="@color/gradient_end_color"
|
||||
android:startColor="@color/gradient_start_color"
|
||||
android:type="linear" />
|
||||
</shape>
|
||||
|
|
@ -51,4 +51,8 @@
|
|||
<!--<color name="text_warning">#DE1010</color>-->
|
||||
|
||||
<color name="card_background">#333333</color>
|
||||
|
||||
<color name="gradient_start_color">#000000</color>
|
||||
<color name="gradient_center_color">#0F0000</color>
|
||||
<color name="gradient_end_color">#19000000</color>
|
||||
</resources>
|
||||
|
|
@ -80,6 +80,10 @@
|
|||
|
||||
<color name="background_splash">#000000</color>
|
||||
<color name="transparent">#00000000</color>
|
||||
|
||||
d
|
||||
<color name="card_background">#1B1D1C</color>
|
||||
|
||||
<color name="gradient_start_color">#FFFFFF</color>
|
||||
<color name="gradient_center_color">#F0FFFF</color>
|
||||
<color name="gradient_end_color">#19FFFFFF</color>
|
||||
</resources>
|
||||
|
|
@ -18,6 +18,7 @@ dependencies {
|
|||
/** AndroidX libraries */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
implementation(deps.androidx.paging.runtime)
|
||||
implementation(deps.androidx.palette)
|
||||
|
||||
/** Compose */
|
||||
implementation(deps.compose.constraintLayout)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package com.tangem.core.ui.utils
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.palette.graphics.Palette
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ImageBackgroundContrastChecker(
|
||||
private val image: Bitmap,
|
||||
private val backgroundColor: Int,
|
||||
) {
|
||||
constructor(drawable: Drawable, backgroundColor: Int) : this(
|
||||
image = drawable.toBitmap(),
|
||||
backgroundColor = backgroundColor,
|
||||
)
|
||||
|
||||
suspend fun getContrastColorIfNeeded(isDarkTheme: Boolean): Color {
|
||||
return if (isLowContrast()) {
|
||||
if (isDarkTheme) Color.White else Color.Black
|
||||
} else {
|
||||
Color.Transparent
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun isLowContrast(): Boolean {
|
||||
val palette = generatePaletteAsync(bitmap = image)
|
||||
val color = palette.getDominantColor(backgroundColor)
|
||||
val contrast = ColorUtils.calculateContrast(color, backgroundColor)
|
||||
return contrast <= LOW_CONTRAST_RATIO
|
||||
}
|
||||
|
||||
private suspend fun generatePaletteAsync(bitmap: Bitmap): Palette = withContext(Dispatchers.Default) {
|
||||
return@withContext Palette.Builder(bitmap).generate()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
|
||||
private const val LOW_CONTRAST_RATIO = 1.5f
|
||||
}
|
||||
}
|
||||
|
|
@ -5,17 +5,20 @@ import androidx.annotation.StringRes
|
|||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -29,11 +32,13 @@ import com.tangem.core.ui.components.SpacerW2
|
|||
import com.tangem.core.ui.components.appbar.ExpandableSearchView
|
||||
import com.tangem.core.ui.extensions.getActiveIconRes
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.ImageBackgroundContrastChecker
|
||||
import com.tangem.feature.swap.models.Network
|
||||
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
|
||||
import com.tangem.feature.swap.models.TokenBalanceData
|
||||
import com.tangem.feature.swap.models.TokenToSelect
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun SwapSelectTokenScreen(
|
||||
|
|
@ -66,9 +71,10 @@ fun SwapSelectTokenScreen(
|
|||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier = Modifier) {
|
||||
val screenBackgroundColor = TangemTheme.colors.background.secondary
|
||||
LazyColumn(
|
||||
modifier = modifier
|
||||
.background(color = TangemTheme.colors.background.secondary)
|
||||
.background(color = screenBackgroundColor)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
|
|
@ -77,7 +83,15 @@ private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier =
|
|||
}
|
||||
|
||||
itemsIndexed(items = state.addedTokens) { index, item ->
|
||||
TokenItem(token = item, network = state.network, onTokenClick = { state.onTokenSelected(item.id) })
|
||||
TokenItem(
|
||||
token = item,
|
||||
network = state.network,
|
||||
screenBackgroundColor = screenBackgroundColor,
|
||||
onTokenClick = {
|
||||
state
|
||||
.onTokenSelected(item.id)
|
||||
},
|
||||
)
|
||||
|
||||
if (index != state.addedTokens.lastIndex) {
|
||||
Divider(
|
||||
|
|
@ -92,7 +106,12 @@ private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier =
|
|||
}
|
||||
|
||||
itemsIndexed(items = state.otherTokens) { index, item ->
|
||||
TokenItem(token = item, network = state.network, onTokenClick = { state.onTokenSelected(item.id) })
|
||||
TokenItem(
|
||||
token = item,
|
||||
network = state.network,
|
||||
screenBackgroundColor = screenBackgroundColor,
|
||||
onTokenClick = { state.onTokenSelected(item.id) },
|
||||
)
|
||||
if (index != state.otherTokens.lastIndex) {
|
||||
Divider(
|
||||
color = TangemTheme.colors.stroke.primary,
|
||||
|
|
@ -121,7 +140,7 @@ private fun Header(@StringRes title: Int) {
|
|||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun TokenItem(token: TokenToSelect, network: Network, onTokenClick: () -> Unit) {
|
||||
private fun TokenItem(token: TokenToSelect, network: Network, screenBackgroundColor: Color, onTokenClick: () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -134,6 +153,7 @@ private fun TokenItem(token: TokenToSelect, network: Network, onTokenClick: () -
|
|||
) {
|
||||
TokenIcon(
|
||||
token = token,
|
||||
screenBackgroundColor = screenBackgroundColor,
|
||||
iconPlaceholder = if (token.isNative) getActiveIconRes(network.blockchainId) else null,
|
||||
)
|
||||
|
||||
|
|
@ -187,13 +207,21 @@ private fun TokenItem(token: TokenToSelect, network: Network, onTokenClick: () -
|
|||
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
private fun TokenIcon(token: TokenToSelect, @DrawableRes iconPlaceholder: Int?) {
|
||||
private fun TokenIcon(token: TokenToSelect, screenBackgroundColor: Color, @DrawableRes iconPlaceholder: Int?) {
|
||||
var iconBackgroundColor by remember { mutableStateOf(Color.Transparent) }
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val data = token.iconUrl.ifEmpty {
|
||||
iconPlaceholder
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(end = TangemTheme.dimens.spacing12),
|
||||
.padding(end = TangemTheme.dimens.spacing12)
|
||||
.background(
|
||||
color = iconBackgroundColor,
|
||||
shape = TangemTheme.shapes.roundedCorners8,
|
||||
),
|
||||
) {
|
||||
val iconModifier = Modifier
|
||||
.size(TangemTheme.dimens.size40)
|
||||
|
|
@ -208,7 +236,20 @@ private fun TokenIcon(token: TokenToSelect, @DrawableRes iconPlaceholder: Int?)
|
|||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.data(data)
|
||||
.crossfade(true)
|
||||
.build(),
|
||||
.allowHardware(false)
|
||||
.listener(
|
||||
onSuccess = { _, result ->
|
||||
if (isDarkTheme) {
|
||||
coroutineScope.launch {
|
||||
val color = ImageBackgroundContrastChecker(
|
||||
drawable = result.drawable,
|
||||
backgroundColor = screenBackgroundColor.toArgb(),
|
||||
).getContrastColorIfNeeded(isDarkTheme)
|
||||
iconBackgroundColor = color
|
||||
}
|
||||
}
|
||||
},
|
||||
).build(),
|
||||
contentDescription = token.id,
|
||||
loading = { CircleShimmer(modifier = iconModifier) },
|
||||
error = { CurrencyPlaceholderIcon(modifier = iconModifier, id = token.id) },
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.foundation.Image
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
|
@ -13,11 +14,11 @@ import androidx.compose.material.Icon
|
|||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -27,15 +28,16 @@ import androidx.compose.ui.text.buildAnnotatedString
|
|||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
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 coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.ImageBackgroundContrastChecker
|
||||
import com.tangem.feature.swap.models.SwapWarning
|
||||
import com.tangem.feature.swap.models.TransactionCardType
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
|
|
@ -265,47 +267,13 @@ fun Token(
|
|||
verticalArrangement = Arrangement.Bottom,
|
||||
horizontalAlignment = Alignment.End,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(end = TangemTheme.dimens.spacing16)
|
||||
.size(TangemTheme.dimens.size42),
|
||||
) {
|
||||
val tokenImageModifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.size(TangemTheme.dimens.size36)
|
||||
|
||||
val data = tokenIconUrl.ifEmpty {
|
||||
iconPlaceholder
|
||||
}
|
||||
SubcomposeAsyncImage(
|
||||
modifier = tokenImageModifier,
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.data(data)
|
||||
.crossfade(true)
|
||||
.build(),
|
||||
loading = { CircleShimmer(modifier = tokenImageModifier) },
|
||||
contentDescription = tokenCurrency,
|
||||
)
|
||||
|
||||
if (networkIconRes != null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.size(TangemTheme.dimens.size18)
|
||||
.background(color = Color.White, shape = CircleShape),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.padding(all = 0.5.dp),
|
||||
painter = painterResource(id = networkIconRes),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TokenIcon(
|
||||
tokenIconUrl = tokenIconUrl,
|
||||
tokenCurrency = tokenCurrency,
|
||||
iconPlaceholder = iconPlaceholder,
|
||||
networkIconRes = networkIconRes,
|
||||
)
|
||||
SpacerH4()
|
||||
|
||||
Text(
|
||||
text = tokenCurrency,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
|
|
@ -317,6 +285,75 @@ fun Token(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenIcon(
|
||||
tokenIconUrl: String,
|
||||
tokenCurrency: String,
|
||||
@DrawableRes iconPlaceholder: Int? = null,
|
||||
@DrawableRes networkIconRes: Int? = null,
|
||||
) {
|
||||
val itemBackgroundColor = TangemTheme.colors.background.primary.toArgb()
|
||||
var iconBackgroundColor by remember { mutableStateOf(Color.Transparent) }
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(end = TangemTheme.dimens.spacing16)
|
||||
.size(TangemTheme.dimens.size42),
|
||||
) {
|
||||
val tokenImageModifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.size(TangemTheme.dimens.size36)
|
||||
.background(
|
||||
color = iconBackgroundColor,
|
||||
shape = TangemTheme.shapes.roundedCorners8,
|
||||
)
|
||||
|
||||
val data = tokenIconUrl.ifEmpty {
|
||||
iconPlaceholder
|
||||
}
|
||||
SubcomposeAsyncImage(
|
||||
modifier = tokenImageModifier,
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.data(data)
|
||||
.crossfade(true)
|
||||
.allowHardware(false)
|
||||
.listener(
|
||||
onSuccess = { _, result ->
|
||||
if (isDarkTheme) {
|
||||
coroutineScope.launch {
|
||||
val color = ImageBackgroundContrastChecker(
|
||||
drawable = result.drawable,
|
||||
backgroundColor = itemBackgroundColor,
|
||||
).getContrastColorIfNeeded(isDarkTheme)
|
||||
iconBackgroundColor = color
|
||||
}
|
||||
}
|
||||
},
|
||||
).build(),
|
||||
loading = { CircleShimmer(modifier = tokenImageModifier) },
|
||||
contentDescription = tokenCurrency,
|
||||
)
|
||||
|
||||
if (networkIconRes != null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.size(TangemTheme.dimens.size18)
|
||||
.background(color = TangemTheme.colors.background.primary, shape = CircleShape),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.padding(all = TangemTheme.dimens.spacing0_5),
|
||||
painter = painterResource(id = networkIconRes),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChangeTokenSelector() {
|
||||
Box(
|
||||
|
|
|
|||
|
|
@ -3,21 +3,26 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.ImageBackgroundContrastChecker
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenInfoBlockState
|
||||
import com.tangem.features.tokendetails.impl.R
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
internal fun CurrencyIcon(
|
||||
|
|
@ -131,12 +136,34 @@ private inline fun DefaultCurrencyIcon(
|
|||
crossinline errorIcon: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val itemBackgroundColor = TangemTheme.colors.background.primary.toArgb()
|
||||
var iconBackgroundColor by remember { mutableStateOf(Color.Transparent) }
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
SubcomposeAsyncImage(
|
||||
modifier = modifier,
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = iconBackgroundColor,
|
||||
shape = TangemTheme.shapes.roundedCorners8,
|
||||
),
|
||||
model = ImageRequest.Builder(context = LocalContext.current)
|
||||
.data(iconData)
|
||||
.crossfade(enable = true)
|
||||
.build(),
|
||||
.allowHardware(false)
|
||||
.listener(
|
||||
onSuccess = { _, result ->
|
||||
if (isDarkTheme) {
|
||||
coroutineScope.launch {
|
||||
val color = ImageBackgroundContrastChecker(
|
||||
drawable = result.drawable,
|
||||
backgroundColor = itemBackgroundColor,
|
||||
).getContrastColorIfNeeded(isDarkTheme)
|
||||
iconBackgroundColor = color
|
||||
}
|
||||
}
|
||||
},
|
||||
).build(),
|
||||
loading = { CircleShimmer() },
|
||||
error = { errorIcon() },
|
||||
alpha = alpha,
|
||||
|
|
|
|||
|
|
@ -3,20 +3,25 @@ package com.tangem.feature.wallet.presentation.common.component.token.icon
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.ImageBackgroundContrastChecker
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
internal fun ContentIcon(
|
||||
|
|
@ -133,12 +138,34 @@ private inline fun DefaultCurrencyIcon(
|
|||
crossinline errorIcon: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var iconBackgroundColor by remember { mutableStateOf(Color.Transparent) }
|
||||
val itemBackgroundColor = TangemTheme.colors.background.primary.toArgb()
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
SubcomposeAsyncImage(
|
||||
modifier = modifier,
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = iconBackgroundColor,
|
||||
shape = TangemTheme.shapes.roundedCorners8,
|
||||
),
|
||||
model = ImageRequest.Builder(context = LocalContext.current)
|
||||
.data(iconData)
|
||||
.crossfade(enable = true)
|
||||
.build(),
|
||||
.allowHardware(false)
|
||||
.listener(
|
||||
onSuccess = { _, result ->
|
||||
if (isDarkTheme) {
|
||||
coroutineScope.launch {
|
||||
val color = ImageBackgroundContrastChecker(
|
||||
drawable = result.drawable,
|
||||
backgroundColor = itemBackgroundColor,
|
||||
).getContrastColorIfNeeded(isDarkTheme)
|
||||
iconBackgroundColor = color
|
||||
}
|
||||
}
|
||||
},
|
||||
).build(),
|
||||
loading = { LoadingIcon() },
|
||||
error = { errorIcon() },
|
||||
alpha = alpha,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue