Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-02 10:43:16 +03:00
commit 4daf088b89
648 changed files with 20086 additions and 2462 deletions

View file

@ -14,6 +14,11 @@ fun SpacerH(height: Dp, modifier: Modifier = Modifier) {
Spacer(modifier = modifier.height(height))
}
@Composable
fun SpacerH2(modifier: Modifier = Modifier) {
SpacerH(2.dp, modifier)
}
@Composable
fun SpacerH4(modifier: Modifier = Modifier) {
SpacerH(4.dp, modifier)

View file

@ -0,0 +1,47 @@
package com.tangem.core.ui.components
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.buttons.SecondarySmallButton
import com.tangem.core.ui.components.buttons.SmallButtonConfig
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@Composable
fun UnableToLoadData(onRetryClick: () -> Unit, modifier: Modifier = Modifier) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = stringResourceSafe(R.string.markets_loading_error_title),
style = TangemTheme.typography.caption1,
color = TangemTheme.colors.text.tertiary,
)
SecondarySmallButton(
config = SmallButtonConfig(
text = resourceReference(R.string.try_to_load_data_again_button_title),
onClick = onRetryClick,
),
)
}
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview() {
TangemThemePreview {
UnableToLoadData(onRetryClick = {})
}
}

View file

@ -109,7 +109,7 @@ private fun BoxScope.ContentIconContainer(
)
if (icon.topBadgeIconResId != null && shouldShowTopBadge) {
TopBadge(
CurrencyIconTopBadge(
modifier = Modifier
.offset(x = networkBadgeOffset, y = -networkBadgeOffset)
.align(Alignment.TopEnd),
@ -120,7 +120,7 @@ private fun BoxScope.ContentIconContainer(
}
if (icon.showCustomBadge) {
BottomBadge(
CurrencyIconBottomBadge(
modifier = Modifier.align(Alignment.BottomEnd),
)
}

View file

@ -0,0 +1,32 @@
package com.tangem.core.ui.components.currency.icon
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.ui.res.TangemTheme
@Composable
internal fun CurrencyIconBottomBadge(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.size(TangemTheme.dimens.size12)
.background(
color = TangemTheme.colors.background.primary,
shape = CircleShape,
),
) {
Box(
modifier = Modifier
.padding(all = TangemTheme.dimens.spacing2)
.matchParentSize()
.background(
color = TangemTheme.colors.icon.informative,
shape = CircleShape,
),
)
}
}

View file

@ -14,7 +14,7 @@ import androidx.compose.ui.res.painterResource
import com.tangem.core.ui.res.TangemTheme
@Composable
internal fun TopBadge(
fun CurrencyIconTopBadge(
@DrawableRes iconResId: Int,
alpha: Float,
colorFilter: ColorFilter?,
@ -38,26 +38,4 @@ internal fun TopBadge(
contentDescription = null,
)
}
}
@Composable
internal fun BottomBadge(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.size(TangemTheme.dimens.size12)
.background(
color = TangemTheme.colors.background.primary,
shape = CircleShape,
),
) {
Box(
modifier = Modifier
.padding(all = TangemTheme.dimens.spacing2)
.matchParentSize()
.background(
color = TangemTheme.colors.icon.informative,
shape = CircleShape,
),
)
}
}

View file

@ -0,0 +1,47 @@
package com.tangem.core.ui.components.dropdownmenu
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@Suppress("ComposableEventParameterNaming")
@Composable
fun TangemDropdownItem(item: TangemDropdownMenuItem, dismissParent: () -> Unit, modifier: Modifier = Modifier) {
Text(
modifier = modifier
.clickable {
dismissParent()
item.onClick()
}
.padding(vertical = TangemTheme.dimens.spacing8, horizontal = TangemTheme.dimens.spacing16),
text = item.title.resolveReference(),
style = TangemTheme.typography.button.copy(color = item.textColorProvider()),
)
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_TokenDetailsAppBarDropdownItem() {
TangemThemePreview {
TangemDropdownItem(
modifier = Modifier.background(TangemTheme.colors.background.primary),
dismissParent = {},
item = TangemDropdownMenuItem(
title = TextReference.Res(id = R.string.token_details_hide_token),
textColorProvider = { TangemTheme.colors.text.warning },
onClick = { },
),
)
}
}

View file

@ -0,0 +1,232 @@
@file:Suppress("TopLevelPropertyNaming")
package com.tangem.core.ui.components.dropdownmenu
import androidx.compose.animation.core.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DropdownMenu
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.*
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupPositionProvider
import androidx.compose.ui.window.PopupProperties
import com.tangem.core.ui.res.TangemTheme
import kotlin.math.max
import kotlin.math.min
/**
* Just copy paste [DropdownMenu] from material3 with deleting vertical paddings.
*/
@Composable
fun TangemDropdownMenu(
expanded: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
offset: DpOffset = DpOffset(x = TangemTheme.dimens.spacing20, y = TangemTheme.dimens.spacing10.times(-1)),
properties: PopupProperties = PopupProperties(focusable = true),
content: @Composable ColumnScope.() -> Unit,
) {
val expandedStates = remember { MutableTransitionState(false) }
expandedStates.targetState = expanded
if (expandedStates.currentState || expandedStates.targetState) {
val transformOriginState = remember { mutableStateOf(TransformOrigin.Center) }
val density = LocalDensity.current
val popupPositionProvider = DropdownMenuPositionProvider(
offset,
density,
) { parentBounds, menuBounds ->
transformOriginState.value = calculateTransformOrigin(parentBounds, menuBounds)
}
Popup(
onDismissRequest = onDismissRequest,
popupPositionProvider = popupPositionProvider,
properties = properties,
) {
DropdownMenuContent(
expandedStates = expandedStates,
transformOriginState = transformOriginState,
modifier = modifier,
content = content,
)
}
}
}
private const val InTransitionDuration = 120
private const val OutTransitionDuration = 75
@Suppress("ReusedModifierInstance", "MagicNumber")
@Composable
private fun DropdownMenuContent(
expandedStates: MutableTransitionState<Boolean>,
transformOriginState: MutableState<TransformOrigin>,
modifier: Modifier = Modifier,
content: @Composable ColumnScope.() -> Unit,
) {
// Menu open/close animation.
val transition = updateTransition(expandedStates, "DropDownMenu")
val scale by transition.animateFloat(
transitionSpec = {
if (false isTransitioningTo true) {
// Dismissed to expanded
tween(
durationMillis = InTransitionDuration,
easing = LinearOutSlowInEasing,
)
} else {
// Expanded to dismissed.
tween(
durationMillis = 1,
delayMillis = OutTransitionDuration - 1,
)
}
},
label = "",
) {
if (it) {
// Menu is expanded.
1f
} else {
// Menu is dismissed.
0.8f
}
}
val alpha by transition.animateFloat(
transitionSpec = {
if (false isTransitioningTo true) {
// Dismissed to expanded
tween(durationMillis = 30)
} else {
// Expanded to dismissed.
tween(durationMillis = OutTransitionDuration)
}
},
label = "",
) {
if (it) {
// Menu is expanded.
1f
} else {
// Menu is dismissed.
0f
}
}
Card(
modifier = Modifier.graphicsLayer {
scaleX = scale
scaleY = scale
this.alpha = alpha
transformOrigin = transformOriginState.value
},
elevation = CardDefaults.cardElevation(),
) {
Column(
modifier = modifier
.width(IntrinsicSize.Max)
.verticalScroll(rememberScrollState()),
content = content,
)
}
}
private fun calculateTransformOrigin(parentBounds: IntRect, menuBounds: IntRect): TransformOrigin {
val pivotX = when {
menuBounds.left >= parentBounds.right -> 0f
menuBounds.right <= parentBounds.left -> 1f
menuBounds.width == 0 -> 0f
else -> {
val intersectionCenter =
(max(parentBounds.left, menuBounds.left) + min(parentBounds.right, menuBounds.right)) / 2
(intersectionCenter - menuBounds.left).toFloat() / menuBounds.width
}
}
val pivotY = when {
menuBounds.top >= parentBounds.bottom -> 0f
menuBounds.bottom <= parentBounds.top -> 1f
menuBounds.height == 0 -> 0f
else -> {
val intersectionCenter =
(max(parentBounds.top, menuBounds.top) + min(parentBounds.bottom, menuBounds.bottom)) / 2
(intersectionCenter - menuBounds.top).toFloat() / menuBounds.height
}
}
return TransformOrigin(pivotX, pivotY)
}
private val MenuVerticalMargin = 48.dp
@Immutable
internal data class DropdownMenuPositionProvider(
val contentOffset: DpOffset,
val density: Density,
val onPositionCalculated: (IntRect, IntRect) -> Unit = { _, _ -> },
) : PopupPositionProvider {
override fun calculatePosition(
anchorBounds: IntRect,
windowSize: IntSize,
layoutDirection: LayoutDirection,
popupContentSize: IntSize,
): IntOffset {
// The min margin above and below the menu, relative to the screen.
val verticalMargin = with(density) { MenuVerticalMargin.roundToPx() }
// The content offset specified using the dropdown offset parameter.
val contentOffsetX = with(density) { contentOffset.x.roundToPx() }
val contentOffsetY = with(density) { contentOffset.y.roundToPx() }
// Compute horizontal position.
val toRight = anchorBounds.left + contentOffsetX
val toLeft = anchorBounds.right - contentOffsetX - popupContentSize.width
val toDisplayRight = windowSize.width - popupContentSize.width
val toDisplayLeft = 0
val x = if (layoutDirection == LayoutDirection.Ltr) {
sequenceOf(
toRight,
toLeft,
// If the anchor gets outside of the window on the left, we want to position
// toDisplayLeft for proximity to the anchor. Otherwise, toDisplayRight.
if (anchorBounds.left >= 0) toDisplayRight else toDisplayLeft,
)
} else {
sequenceOf(
toLeft,
toRight,
// If the anchor gets outside of the window on the right, we want to position
// toDisplayRight for proximity to the anchor. Otherwise, toDisplayLeft.
if (anchorBounds.right <= windowSize.width) toDisplayLeft else toDisplayRight,
)
}.firstOrNull {
it >= 0 && it + popupContentSize.width <= windowSize.width
} ?: toLeft
// Compute vertical position.
val toBottom = maxOf(anchorBounds.bottom + contentOffsetY, verticalMargin)
val toTop = anchorBounds.top - contentOffsetY - popupContentSize.height
val toCenter = anchorBounds.top - popupContentSize.height / 2
val toDisplayBottom = windowSize.height - popupContentSize.height - verticalMargin
val y = sequenceOf(toBottom, toTop, toCenter, toDisplayBottom).firstOrNull {
it >= verticalMargin &&
it + popupContentSize.height <= windowSize.height - verticalMargin
} ?: toTop
onPositionCalculated(
anchorBounds,
IntRect(x, y, x + popupContentSize.width, y + popupContentSize.height),
)
return IntOffset(x, y)
}
}

View file

@ -0,0 +1,11 @@
package com.tangem.core.ui.components.dropdownmenu
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import com.tangem.core.ui.extensions.TextReference
data class TangemDropdownMenuItem(
val title: TextReference,
val textColorProvider: @Composable () -> Color,
val onClick: () -> Unit,
)

View file

@ -0,0 +1,34 @@
package com.tangem.core.ui.components.fields
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.withDebounce
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject
/**
* Search tokens manager
*
[REDACTED_AUTHOR]
*/
class InputManager @Inject constructor() {
val query: Flow<String>
get() = _query
private val _query = MutableStateFlow(value = "")
private val jobHolder = JobHolder()
suspend fun update(value: String) {
coroutineScope {
if (value.isEmpty()) {
jobHolder.cancel()
_query.value = value
} else {
withDebounce(jobHolder) { _query.value = value }
}
}
}
}

View file

@ -11,6 +11,7 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusManager
@ -36,7 +37,11 @@ import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@Composable
fun SearchBar(state: SearchBarUM, modifier: Modifier = Modifier, colors: TextFieldColors = TangemSearchBarColors) {
fun SearchBar(
state: SearchBarUM,
modifier: Modifier = Modifier,
colors: TextFieldColors = TangemSearchBarDefaults.defaultTextFieldColors,
) {
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
val interactionSource = remember { MutableInteractionSource() }
@ -161,18 +166,30 @@ private fun ClearButton(
}
}
private val TangemSearchBarColors: TextFieldColors
@Composable
get() = TextFieldDefaults.colors().copy(
focusedContainerColor = TangemTheme.colors.field.primary,
unfocusedContainerColor = TangemTheme.colors.field.primary,
focusedTextColor = TangemTheme.colors.text.primary1,
unfocusedTextColor = TangemTheme.colors.text.primary1,
cursorColor = TangemTheme.colors.icon.primary1,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
)
object TangemSearchBarDefaults {
val defaultTextFieldColors: TextFieldColors
@Composable @Stable get() = TextFieldDefaults.colors().copy(
focusedContainerColor = TangemTheme.colors.field.primary,
unfocusedContainerColor = TangemTheme.colors.field.primary,
focusedTextColor = TangemTheme.colors.text.primary1,
unfocusedTextColor = TangemTheme.colors.text.primary1,
cursorColor = TangemTheme.colors.icon.primary1,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
)
val secondaryTextFieldColors: TextFieldColors
@Composable @Stable get() = TextFieldDefaults.colors().copy(
focusedContainerColor = TangemTheme.colors.field.focused,
unfocusedContainerColor = TangemTheme.colors.field.focused,
focusedTextColor = TangemTheme.colors.text.primary1,
unfocusedTextColor = TangemTheme.colors.text.primary1,
cursorColor = TangemTheme.colors.icon.primary1,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
)
}
// region Previews
@Preview(widthDp = 328)

View file

@ -32,7 +32,7 @@ fun Modifier.roundedShapeItemDecoration(
val applyShape: Modifier.(shape: RoundedCornerShape?) -> Modifier = { shape ->
if (backgroundColor != null) {
if (shape != null) {
background(color = backgroundColor, shape = shape)
clip(shape).background(color = backgroundColor, shape = shape)
} else {
background(color = backgroundColor)
}

View file

@ -1,8 +1,10 @@
package com.tangem.core.ui.message.dialog
import com.tangem.core.error.UniversalError
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.EventMessageAction
@ -36,4 +38,17 @@ object Dialogs {
secondActionBuilder = { cancelAction(onClick = onCancelClick) },
)
}
/**
* Universal error dialog
*/
fun universalErrorDialog(universalError: UniversalError, onOkClick: () -> Unit): DialogMessage {
return DialogMessage(
message = resourceReference(R.string.universal_error, wrappedList(universalError.errorCode)),
firstAction = EventMessageAction(
title = resourceReference(R.string.common_ok),
onClick = onOkClick,
),
)
}
}

View file

@ -22,9 +22,9 @@ object TangemAnimations {
forwardWhen: (initial: S, target: S) -> Boolean,
): AnimatedContentTransitionScope<S>.() -> ContentTransform = {
val direction = if (forwardWhen(initialState, targetState)) {
AnimatedContentTransitionScope.SlideDirection.End
} else {
AnimatedContentTransitionScope.SlideDirection.Start
} else {
AnimatedContentTransitionScope.SlideDirection.End
}
slideIntoContainer(towards = direction, animationSpec = tween())

View file

@ -312,6 +312,11 @@ val LocalBladeAnimation = staticCompositionLocalOf<BladeAnimation> {
error("No MainBottomSheetColor provided")
}
// TODO remove this after migration to new navigation
val LocalIsNavigationRefactoringEnabled = staticCompositionLocalOf<Boolean> {
false
}
/**
* Determines whether the dark theme should be used based on the given [AppThemeMode].
*

View file

@ -0,0 +1,9 @@
package com.tangem.core.ui.utils
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.error.UniversalError
import com.tangem.core.ui.message.dialog.Dialogs
fun UiMessageSender.showErrorDialog(universalError: UniversalError) {
send(Dialogs.universalErrorDialog(universalError) {})
}

View file

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="20dp"
android:viewportHeight="20" android:viewportWidth="20"
android:width="20dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#1ACE80" android:fillType="evenOdd" android:pathData="M10,0C4.48,0 0,4.48 0,10C0,15.52 4.48,20 10,20C15.52,20 20,15.52 20,10C20,4.48 15.52,0 10,0ZM8,15L3,10L4.41,8.59L8,12.17L15.59,4.58L17,6L8,15Z"/>
</vector>

View file

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="76dp"
android:height="76dp"
android:viewportWidth="76"
android:viewportHeight="76">
<path
android:pathData="M26.284,20.9C23.136,20.9 20.584,23.451 20.584,26.6C20.584,29.748 23.136,32.3 26.284,32.3C29.432,32.3 31.984,29.748 31.984,26.6C31.984,23.451 29.432,20.9 26.284,20.9Z"
android:fillColor="#C9C9C9"/>
<path
android:pathData="M9.118,18.911L33.829,4.644C34.961,3.99 36.411,4.418 37.007,5.581C37.564,6.666 37.172,7.996 36.116,8.606L11.602,22.758V47.139L20.57,40.834C21.884,39.911 23.61,39.822 25.012,40.604L35.544,46.484L50.911,35.182C52.29,34.169 54.147,34.097 55.599,35.003L64.399,40.49V25.046C64.399,23.782 65.423,22.758 66.686,22.758C67.949,22.758 68.973,23.782 68.973,25.046V53.468C68.973,54.961 68.176,56.341 66.883,57.088L40.09,72.557C38.797,73.303 37.204,73.303 35.911,72.557L9.118,57.088C7.825,56.341 7.028,54.961 7.028,53.468V22.531C7.028,21.038 7.825,19.658 9.118,18.911ZM53.406,39.026L64.399,45.881V53.24L38,68.481L11.602,53.24V52.731L22.999,44.719L33.535,50.602C34.965,51.4 36.73,51.29 38.049,50.319L53.406,39.026Z"
android:fillColor="#C9C9C9"
android:fillType="evenOdd"/>
<path
android:pathData="M56.891,1.843C55.743,1.843 54.813,2.774 54.813,3.921V9.265H48.875C47.727,9.265 46.797,10.196 46.797,11.343C46.797,12.491 47.727,13.421 48.875,13.421H54.813V18.765C54.813,19.913 55.743,20.843 56.891,20.843C58.038,20.843 58.969,19.913 58.969,18.765V13.421H64.906C66.054,13.421 66.984,12.491 66.984,11.343C66.984,10.196 66.054,9.265 64.906,9.265H58.969V3.921C58.969,2.774 58.038,1.843 56.891,1.843Z"
android:fillColor="#C9C9C9"/>
</vector>

View file

@ -0,0 +1,8 @@
<vector android:autoMirrored="true" android:height="20dp"
android:viewportHeight="20" android:viewportWidth="20"
android:width="20dp" xmlns:android="http://schemas.android.com/apk/res/android">
<group>
<clip-path android:fillType="evenOdd" android:pathData="M0,10C0,4.48 4.48,0 10,0C15.52,0 20,4.48 20,10C20,15.52 15.52,20 10,20C4.48,20 0,15.52 0,10ZM2,10C2,14.42 5.58,18 10,18C14.42,18 18,14.42 18,10C18,5.58 14.42,2 10,2C5.58,2 2,5.58 2,10Z"/>
<path android:fillColor="#656565" android:pathData="M-2,-2h24v24h-24z"/>
</group>
</vector>

View file

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="76dp"
android:height="76dp"
android:viewportWidth="76"
android:viewportHeight="76">
<path
android:fillColor="#3B99FC"
android:pathData="M16,0L60,0A16,16 0,0 1,76 16L76,60A16,16 0,0 1,60 76L16,76A16,16 0,0 1,0 60L0,16A16,16 0,0 1,16 0z" />
<group>
<clip-path android:pathData="M11.084,22.167h53.833v31.667h-53.833z" />
<path
android:fillColor="#ffffff"
android:pathData="M22.112,28.351C30.889,20.101 45.126,20.101 53.903,28.351L54.959,29.337C55.403,29.751 55.403,30.417 54.959,30.83L51.348,34.229C51.126,34.429 50.778,34.429 50.556,34.229L49.098,32.856C42.973,27.098 33.042,27.098 26.917,32.856L25.362,34.322C25.139,34.522 24.792,34.522 24.57,34.322L20.945,30.937C20.501,30.524 20.501,29.857 20.945,29.444L22.112,28.351ZM61.376,35.375L64.598,38.4C65.042,38.813 65.042,39.48 64.598,39.893L50.084,53.527C49.639,53.94 48.931,53.94 48.501,53.527L38.209,43.851C38.098,43.745 37.917,43.745 37.806,43.851L27.514,53.527C27.07,53.94 26.362,53.94 25.931,53.527L11.417,39.893C10.973,39.48 10.973,38.813 11.417,38.4L14.639,35.375C15.084,34.962 15.792,34.962 16.223,35.375L26.514,45.051C26.626,45.158 26.806,45.158 26.917,45.051L37.209,35.375C37.653,34.962 38.362,34.962 38.792,35.375L49.084,45.051C49.195,45.158 49.376,45.158 49.487,45.051L59.778,35.375C60.223,34.962 60.931,34.962 61.376,35.375Z" />
</group>
</vector>