Updated on 2026-08-14

This commit is contained in:
Tangem 2025-03-12 11:33:24 +03:00
commit 8148f32272
642 changed files with 10717 additions and 5789 deletions

View file

@ -113,6 +113,7 @@ sealed class AnalyticsParam {
const val SEED_PHRASE_LENGTH = "Seed Phrase Length"
const val DAPP_NAME = "DApp Name"
const val DAPP_URL = "DApp Url"
const val NETWORKS = "Networks"
const val METHOD_NAME = "Method Name"
const val VALIDATION = "Validation"
const val BLOCKCHAIN_EXCEPTION_HOST = "exception_host"

View file

@ -1,6 +1,7 @@
package com.tangem.tap.common.analytics.events
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction.OpenSession.SourceType
/**
[REDACTED_AUTHOR]
@ -12,8 +13,41 @@ internal sealed class WalletConnect(
) : AnalyticsEvent("Wallet Connect", event, params, error) {
class ScreenOpened : WalletConnect(event = "WC Screen Opened")
class NewSessionEstablished(dAppName: String, dAppUrl: String, blockchainNames: List<String>) : WalletConnect(
event = "New Session Established",
class NewSessionInitiated(source: SourceType) : WalletConnect(
event = "Session Initiated",
params = mapOf(
AnalyticsParam.SOURCE to when (source) {
SourceType.QR -> "QR"
SourceType.DEEPLINK -> "DeepLink"
SourceType.ETC -> "etc"
},
),
)
data object SessionFailed : WalletConnect(
event = "Session Failed",
)
class DAppConnectionRequested(
blockchainNames: List<String>,
) : WalletConnect(
event = "dApp Connection Requested",
params = mapOf(
AnalyticsParam.NETWORKS to blockchainNames.joinToString(","),
),
)
class DAppConnected(dAppName: String, dAppUrl: String, blockchainNames: List<String>) : WalletConnect(
event = "dApp Connected",
params = mapOf(
AnalyticsParam.DAPP_NAME to dAppName,
AnalyticsParam.DAPP_URL to dAppUrl,
AnalyticsParam.BLOCKCHAIN to blockchainNames.joinToString(","),
),
)
class DAppConnectionFailed(dAppName: String, dAppUrl: String, blockchainNames: List<String>) : WalletConnect(
event = "dApp Connection Failed",
params = mapOf(
AnalyticsParam.DAPP_NAME to dAppName,
AnalyticsParam.DAPP_URL to dAppUrl,
@ -22,17 +56,31 @@ internal sealed class WalletConnect(
)
class SessionDisconnected(dAppName: String, dAppUrl: String) : WalletConnect(
event = "Session Disconnected",
event = "dApp Disconnected",
params = mapOf(
AnalyticsParam.DAPP_NAME to dAppName,
AnalyticsParam.DAPP_URL to dAppUrl,
),
)
class RequestHandled(
class SignatureRequestHandled(
params: RequestHandledParams,
) : WalletConnect(
event = "Request Handled",
event = "Signature Request Handled",
params = params.toParamsMap(),
)
class SignatureRequestReceived(
params: RequestHandledParams,
) : WalletConnect(
event = "Signature Request Received",
params = params.toParamsMap(),
)
class SignatureRequestFailed(
params: RequestHandledParams,
) : WalletConnect(
event = "Signature Request Failed",
params = params.toParamsMap(),
)

View file

@ -1,152 +0,0 @@
package com.tangem.tap.common.compose
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.material.TextFieldColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.graphics.Color
import com.tangem.core.ui.res.TangemTheme
// Copy from com.tangem.core.ui.components
// TODO: Delete this after fields has been moved to core-ui module
internal object TangemTextFieldsDefault {
val defaultTextFieldColors: TangemTextFieldColors
@Composable @Stable get() = TangemTextFieldColors(
textColor = TangemTheme.colors.text.primary1,
disabledTextColor = TangemTheme.colors.text.disabled,
backgroundColor = Color.Transparent,
cursorColor = TangemTheme.colors.icon.primary1,
errorCursorColor = TangemTheme.colors.icon.warning,
focusedIndicatorColor = TangemTheme.colors.icon.primary1,
unfocusedIndicatorColor = TangemTheme.colors.stroke.primary,
disabledIndicatorColor = TangemTheme.colors.stroke.primary,
errorIndicatorColor = TangemTheme.colors.icon.warning,
leadingIconColor = TangemTheme.colors.icon.informative,
disabledLeadingIconColor = Color.Transparent,
errorLeadingIconColor = TangemTheme.colors.icon.warning,
trailingIconColor = TangemTheme.colors.icon.informative,
disabledTrailingIconColor = Color.Transparent,
errorTrailingIconColor = TangemTheme.colors.icon.warning,
focusedLabelColor = TangemTheme.colors.text.primary1,
unfocusedLabelColor = TangemTheme.colors.text.secondary,
disabledLabelColor = TangemTheme.colors.text.disabled,
errorLabelColor = TangemTheme.colors.icon.warning,
placeholderColor = TangemTheme.colors.text.secondary,
disabledPlaceholderColor = TangemTheme.colors.text.disabled,
captionColor = TangemTheme.colors.text.tertiary,
disabledCaptionColor = TangemTheme.colors.text.disabled,
errorCaptionColor = TangemTheme.colors.icon.warning,
)
}
@Immutable
internal data class TangemTextFieldColors(
private val textColor: Color,
private val disabledTextColor: Color,
private val cursorColor: Color,
private val errorCursorColor: Color,
private val focusedIndicatorColor: Color,
private val unfocusedIndicatorColor: Color,
private val errorIndicatorColor: Color,
private val disabledIndicatorColor: Color,
private val leadingIconColor: Color,
private val disabledLeadingIconColor: Color,
private val errorLeadingIconColor: Color,
private val trailingIconColor: Color,
private val disabledTrailingIconColor: Color,
private val errorTrailingIconColor: Color,
private val backgroundColor: Color,
private val focusedLabelColor: Color,
private val unfocusedLabelColor: Color,
private val disabledLabelColor: Color,
private val errorLabelColor: Color,
private val placeholderColor: Color,
private val disabledPlaceholderColor: Color,
private val captionColor: Color,
private val disabledCaptionColor: Color,
private val errorCaptionColor: Color,
) : TextFieldColors {
@Composable
override fun leadingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledLeadingIconColor
isError -> errorLeadingIconColor
else -> leadingIconColor
},
)
}
@Composable
override fun trailingIconColor(enabled: Boolean, isError: Boolean): State<Color> {
return rememberUpdatedState(
when {
!enabled -> disabledTrailingIconColor
isError -> errorTrailingIconColor
else -> trailingIconColor
},
)
}
@Composable
override fun indicatorColor(
enabled: Boolean,
isError: Boolean,
interactionSource: InteractionSource,
): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
!enabled -> disabledIndicatorColor
isError -> errorIndicatorColor
focused -> focusedIndicatorColor
else -> unfocusedIndicatorColor
}
return if (enabled) {
animateColorAsState(targetValue, tween(durationMillis = 120))
} else {
rememberUpdatedState(targetValue)
}
}
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(backgroundColor)
}
@Composable
override fun placeholderColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) placeholderColor else disabledPlaceholderColor)
}
@Composable
override fun labelColor(enabled: Boolean, error: Boolean, interactionSource: InteractionSource): State<Color> {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
!enabled -> disabledLabelColor
error -> errorLabelColor
focused -> focusedLabelColor
else -> unfocusedLabelColor
}
return rememberUpdatedState(targetValue)
}
@Composable
override fun textColor(enabled: Boolean): State<Color> {
return rememberUpdatedState(if (enabled) textColor else disabledTextColor)
}
@Composable
override fun cursorColor(isError: Boolean): State<Color> {
return rememberUpdatedState(if (isError) errorCursorColor else cursorColor)
}
}

View file

@ -1,58 +0,0 @@
package com.tangem.tap.common.extensions
import android.view.View
import android.widget.EditText
import android.widget.TextSwitcher
import android.widget.TextView
import com.google.android.material.textfield.TextInputLayout
/**
[REDACTED_AUTHOR]
*/
fun TextView.update(text: String?) {
if (this.text?.toString() != text) this.text = text
}
fun EditText.update(text: String?) {
if (this.text?.toString() == text) return
val textLength = text?.length ?: 0
// prevent cursor jumping while editing a text
val cursorPosition = if (selectionEnd > textLength) textLength else selectionEnd
this.setText(text)
if (!isFocused || textLength == 0) return
if (cursorPosition == 0) setSelection(textLength) else setSelection(cursorPosition)
}
fun EditText.setOnImeActionListener(action: Int, handler: (EditText) -> Unit) {
this.setOnEditorActionListener { view, actionId, event ->
if (actionId == action) {
handler.invoke(this)
return@setOnEditorActionListener true
}
return@setOnEditorActionListener false
}
}
fun TextSwitcher.update(text: CharSequence?) {
val textView = this.currentView as? TextView ?: return
if (textView.text?.toString() != text?.toString()) this.setText(text)
}
// By default the TextInputLayout didn't activates the error state if the message is empty or null
fun TextInputLayout.enableError(enable: Boolean, errorMessage: String? = null) {
if (enable) {
if (errorMessage == null || errorMessage.isEmpty()) {
error = "Any message"
if (childCount == 2) getChildAt(1).visibility = View.GONE
} else {
error = errorMessage
}
} else {
error = null
isErrorEnabled = false
}
}