Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-14 16:01:54 +05:00
parent 3ed3dc91b1
commit 7c0cc2d75a
6 changed files with 0 additions and 367 deletions

View file

@ -1,51 +0,0 @@
package com.tangem.core.ui.components
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
/**
* Currency placeholder icon
*
* @param id currency id
* @param modifier modifier
*/
@Composable
fun CurrencyPlaceholderIcon(id: String, modifier: Modifier = Modifier) {
Box(
contentAlignment = Alignment.Center,
modifier = modifier.background(color = TangemTheme.colors.icon.secondary, shape = CircleShape),
) {
Text(
text = id.firstOrNull()?.titlecase().orEmpty(),
modifier = Modifier.padding(TangemTheme.dimens.spacing4),
color = TangemTheme.colors.text.primary2,
textAlign = TextAlign.Center,
// FIXME("Incorrect typography. Replace with typography from design system")
style = TangemTheme.typography.h3.copy(fontWeight = FontWeight.Bold),
)
}
}
// region preview
@Preview(showBackground = true, heightDp = 40, widthDp = 40)
@Preview(showBackground = true, heightDp = 40, widthDp = 40, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_CurrencyPlaceholderIcon() {
TangemThemePreview {
CurrencyPlaceholderIcon(id = "DAI")
}
}
// endregion preview

View file

@ -70,17 +70,6 @@ fun BasicDialog(
)
}
@Composable
fun SimpleOkDialog(message: String, onDismissDialog: () -> Unit) {
TangemDialog(
type = DialogType.Message(message),
confirmButton = DialogButtonUM(onClick = onDismissDialog),
onDismissDialog = onDismissDialog,
title = null,
dismissButton = null,
)
}
/**
* Dialog with text field
*
@ -124,34 +113,6 @@ fun TextInputDialog(
)
}
@Composable
fun TextInputDialog(
fieldValue: String,
confirmButton: DialogButtonUM,
onDismissDialog: () -> Unit,
onValueChange: (String) -> Unit,
textFieldParams: AdditionalTextInputDialogUM = remember { AdditionalTextInputDialogUM() },
title: String? = null,
dismissButton: DialogButtonUM? = null,
isDismissable: Boolean = true,
) {
TangemDialog(
type = DialogType.SimpleTextInput(
value = fieldValue,
onValueChange = onValueChange,
params = textFieldParams,
),
confirmButton = confirmButton,
onDismissDialog = onDismissDialog,
title = title,
dismissButton = dismissButton,
properties = DialogProperties(
dismissOnBackPress = isDismissable,
dismissOnClickOutside = isDismissable,
),
)
}
@Composable
fun SelectorDialog(
selectedItemIndex: Int,
@ -441,14 +402,6 @@ private sealed class DialogType {
// endregion Defaults
// region Preview
@Composable
private fun SimpleOkDialogPreview() {
SimpleOkDialog(
message = "All protected passwords will be deleted from the " +
"secure storage, you must enter the wallet password to work with the app.",
) {}
}
@Composable
private fun BasicDialogPreview() {
BasicDialog(
@ -461,15 +414,6 @@ private fun BasicDialogPreview() {
)
}
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_SimpleOkDialog() {
TangemThemePreview {
SimpleOkDialogPreview()
}
}
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable

View file

@ -1,142 +0,0 @@
package com.tangem.core.ui.components
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
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.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.TextUnit
import com.tangem.core.ui.components.atoms.text.BoundCounter
/**
* https://stackoverflow.com/questions/69083061/how-to-make-middle-ellipsis-in-text-with-jetpack-compose
*/
@Deprecated("Use EllipsisText with TextEllipsis.Middle ellipsis instead")
@Suppress("LongMethod")
@Composable
fun MiddleEllipsisText(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
fontFamily: FontFamily? = null,
letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null,
lineHeight: TextUnit = TextUnit.Unspecified,
softWrap: Boolean = true,
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current,
) {
// some letters, like "r", will have less width when placed right before "."
// adding a space to prevent such case
val layoutText = remember(text) { "$text $ellipsisText" }
val textLayoutResultState = remember(layoutText) {
mutableStateOf<TextLayoutResult?>(null)
}
SubcomposeLayout(modifier) { constraints ->
// result is ignored - we only need to fill our textLayoutResult
subcompose("measure") {
Text(
text = layoutText,
color = color,
fontSize = fontSize,
fontStyle = fontStyle,
fontWeight = fontWeight,
fontFamily = fontFamily,
letterSpacing = letterSpacing,
textDecoration = textDecoration,
textAlign = textAlign,
lineHeight = lineHeight,
softWrap = softWrap,
maxLines = 1,
onTextLayout = { textLayoutResultState.value = it },
style = style,
)
}.first().measure(Constraints())
// to allow smart cast
val textLayoutResult = textLayoutResultState.value
?: // shouldn't happen - onTextLayout is called before subcompose finishes
return@SubcomposeLayout layout(0, 0) {}
val placeable = subcompose("visible") {
val finalText = remember(text, textLayoutResult, constraints.maxWidth) {
if (
text.isEmpty() ||
textLayoutResult.getBoundingBox(text.indices.last).right <= constraints.maxWidth
) {
// text not including ellipsis fits on the first line.
return@remember text
}
val ellipsisWidth = layoutText.indices.toList()
.takeLast(ELLIPSIS_CHARACTERS_COUNT)
.let widthLet@{ indices ->
// fix this bug: https://issuetracker.google.com/issues/197146630
// in this case width is invalid
for (i in indices) {
val width = textLayoutResult.getBoundingBox(i).width
if (width > 0) {
return@widthLet width * ELLIPSIS_CHARACTERS_COUNT
}
}
// this should not happen, because
// this error occurs only for the last character in the string
error("all ellipsis chars have invalid width")
}
val availableWidth = constraints.maxWidth - ellipsisWidth
val startCounter = BoundCounter(text, textLayoutResult) { it }
val endCounter = BoundCounter(text, textLayoutResult) { text.indices.last - it }
while (availableWidth - startCounter.width - endCounter.width > 0) {
val possibleEndWidth = endCounter.widthWithNextChar()
if (
startCounter.width >= possibleEndWidth &&
availableWidth - startCounter.width - possibleEndWidth >= 0
) {
endCounter.addNextChar()
} else if (availableWidth - startCounter.widthWithNextChar() - endCounter.width >= 0) {
startCounter.addNextChar()
} else {
break
}
}
startCounter.string.trimEnd() + ellipsisText + endCounter.string.reversed().trimStart()
}
Text(
text = finalText,
color = color,
fontSize = fontSize,
fontStyle = fontStyle,
fontWeight = fontWeight,
fontFamily = fontFamily,
letterSpacing = letterSpacing,
textDecoration = textDecoration,
textAlign = textAlign,
lineHeight = lineHeight,
softWrap = softWrap,
onTextLayout = onTextLayout,
style = style,
)
}[0].measure(constraints)
layout(placeable.width, placeable.height) {
placeable.place(0, 0)
}
}
}
private const val ELLIPSIS_CHARACTERS_COUNT = 3
private const val ELLIPSIS_CHARACTER = '.'
private val ellipsisText = List(ELLIPSIS_CHARACTERS_COUNT) { ELLIPSIS_CHARACTER }.joinToString(separator = "")

View file

@ -1,86 +0,0 @@
package com.tangem.core.ui.components.rows
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.SpacerH28
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
/**
* Simple clickable action row, without input and icon
*
* https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-807&mode=design&t=Ygv5sohTTHYAQcBS-4
*/
@Composable
fun SimpleActionRow(title: String, description: String, modifier: Modifier = Modifier, isClickable: Boolean = true) {
Box(
modifier = modifier
.background(color = TangemTheme.colors.background.action)
.height(TangemTheme.dimens.size44)
.fillMaxWidth(),
) {
Column(
modifier = Modifier
.padding(end = TangemTheme.dimens.spacing48)
.align(Alignment.CenterStart),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
AnimatedContent(targetState = title, label = "") { title ->
Text(
text = title,
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.secondary,
)
}
AnimatedContent(targetState = description, label = "") { description ->
Text(
text = description,
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.primary1,
)
}
}
if (isClickable) {
Icon(
painter = painterResource(id = R.drawable.ic_chevron_right_24),
contentDescription = null,
modifier = Modifier
.align(alignment = Alignment.CenterEnd)
.padding(end = TangemTheme.dimens.spacing12),
tint = TangemTheme.colors.icon.informative,
)
}
}
}
@Preview
@Composable
private fun SimpleActionRowPreview() {
Column {
TangemThemePreview(isDark = false) {
SimpleActionRow(
title = "Title",
description = "Description",
)
}
SpacerH28()
TangemThemePreview(isDark = false) {
SimpleActionRow(
title = "Title",
description = "Description",
)
}
}
}

View file

@ -1,17 +0,0 @@
package com.tangem.core.ui.components.states
import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList
data class SelectableItemsState<T>(
val selectedItem: Item<T>,
val items: ImmutableList<Item<T>>,
)
data class Item<T>(
val id: Int,
val startText: TextReference,
val endText: TextReference,
val isSelected: Boolean,
val data: T,
)

View file

@ -1,15 +0,0 @@
package com.tangem.core.ui.utils
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
fun Modifier.disableNestedScroll(): Modifier = nestedScroll(DisableParentConnection)
private object DisableParentConnection : NestedScrollConnection {
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
return available.copy(x = 0f)
}
}