Updated on 2026-08-14
This commit is contained in:
parent
e6fcb9e2fe
commit
40c37826bf
198 changed files with 791 additions and 704 deletions
|
|
@ -1,5 +1,4 @@
|
|||
[*.{kt,kts}]
|
||||
ktlint_ignore_back_ticked_identifier = true
|
||||
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
|
|
|
|||
|
|
@ -162,7 +162,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
if (snackbar != null) return
|
||||
|
||||
snackbar = Snackbar.make(
|
||||
binding.fragmentContainer, getString(text), Snackbar.LENGTH_INDEFINITE,
|
||||
binding.fragmentContainer,
|
||||
getString(text),
|
||||
Snackbar.LENGTH_INDEFINITE,
|
||||
)
|
||||
if (buttonTitle != null && action != null) {
|
||||
snackbar?.setAction(getString(buttonTitle), action)
|
||||
|
|
|
|||
|
|
@ -36,4 +36,4 @@ class NavBarInsetsFragmentLifecycleCallback : FragmentLifecycleCallbacks() {
|
|||
windowInsets
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,8 +9,8 @@ import java.math.RoundingMode
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class CurrencyConverter(
|
||||
private val rateValue: BigDecimal,
|
||||
private val decimals: Int
|
||||
private val rateValue: BigDecimal,
|
||||
private val decimals: Int
|
||||
) {
|
||||
private val roundingMode = RoundingMode.HALF_UP
|
||||
|
||||
|
|
|
|||
|
|
@ -140,7 +140,9 @@ class DialogManager : StoreSubscriber<GlobalState> {
|
|||
is WalletDialog.TokensAreLinkedDialog -> SimpleAlertDialog.create(
|
||||
title = context.getString(state.dialog.titleRes, state.dialog.currencySymbol),
|
||||
message = context.getString(
|
||||
state.dialog.messageRes, state.dialog.currencySymbol, state.dialog.currencyTitle,
|
||||
state.dialog.messageRes,
|
||||
state.dialog.currencySymbol,
|
||||
state.dialog.currencyTitle,
|
||||
),
|
||||
context = context,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import timber.log.Timber
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class GlobalLayoutStateHandler<T: View>(
|
||||
private val view: T,
|
||||
attachImmediately: Boolean = true
|
||||
class GlobalLayoutStateHandler<T : View>(
|
||||
private val view: T,
|
||||
attachImmediately: Boolean = true
|
||||
) : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
|
||||
var onStateChanged: ((T) -> Unit)? = null
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ class IntentHandler {
|
|||
|
||||
fun handleBackgroundScan(intent: Intent?) {
|
||||
if (intent != null && (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action ||
|
||||
NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action
|
||||
)
|
||||
NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action
|
||||
)
|
||||
) {
|
||||
val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
|
||||
if (tag != null) {
|
||||
|
|
|
|||
|
|
@ -14,12 +14,15 @@ object TangemSdkErrorMapper {
|
|||
is TangemSdkError.SerializeCommandError -> TangemSdkError.SerializeCommandError()
|
||||
is TangemSdkError.DeserializeApduFailed -> TangemSdkError.DeserializeApduFailed()
|
||||
is TangemSdkError.EncodingFailedTypeMismatch -> TangemSdkError.EncodingFailedTypeMismatch(
|
||||
error.customMessage)
|
||||
error.customMessage
|
||||
)
|
||||
is TangemSdkError.EncodingFailed -> TangemSdkError.EncodingFailed(error.customMessage)
|
||||
is TangemSdkError.DecodingFailedMissingTag -> TangemSdkError.DecodingFailedMissingTag(
|
||||
error.customMessage)
|
||||
error.customMessage
|
||||
)
|
||||
is TangemSdkError.DecodingFailedTypeMismatch -> TangemSdkError.DecodingFailedTypeMismatch(
|
||||
error.customMessage)
|
||||
error.customMessage
|
||||
)
|
||||
is TangemSdkError.DecodingFailed -> TangemSdkError.DecodingFailed(error.customMessage)
|
||||
is TangemSdkError.InvalidResponse -> TangemSdkError.InvalidResponse()
|
||||
is TangemSdkError.UnknownStatus -> TangemSdkError.UnknownStatus(error.statusWord)
|
||||
|
|
@ -113,5 +116,4 @@ object TangemSdkErrorMapper {
|
|||
is TangemSdkError.BiometricsAuthenticationFailed -> error
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -33,4 +33,4 @@ sealed class Basic(
|
|||
event = "Scan",
|
||||
error = error,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ private fun OutlinedProgressTextField(
|
|||
)
|
||||
|
||||
logger.log("RECOMPOSE ---------------------------------------------------------------START [${logger.count}]")
|
||||
logger.log("RECOMPOSE --data: fieldData.value: [${fieldData}]")
|
||||
logger.log("RECOMPOSE --data: fieldData.value: [$fieldData]")
|
||||
logger.log("RECOMPOSE --data: textValueState.value: [${textValueState.value}]")
|
||||
logger.log("RECOMPOSE --data: textDebouncer.emittedValue = [${textDebouncer.emittedValue}]")
|
||||
logger.log("RECOMPOSE --data: textDebouncer.debounced = [${textDebouncer.debounced}]")
|
||||
|
|
@ -131,17 +131,28 @@ private fun OutlinedProgressTextField(
|
|||
logger.log("$isNotUserInput: пользователь ВВОДИТ данные -> внешние данные игнорируем, ждем RECOMPOSE")
|
||||
} else {
|
||||
logger.log("$isNotUserInput: пользователь НЕ вводит данные -> пытаемся обработать внешние данные")
|
||||
if (textValueState.value != textDebouncer.emittedValue || textValueState.value != textDebouncer.debounced) {
|
||||
if (textValueState.value != textDebouncer.emittedValue ||
|
||||
textValueState.value != textDebouncer.debounced
|
||||
) {
|
||||
logger.log("$isNotUserInput: даннные в поле не соответствуют данным из textDebouncer")
|
||||
if (textDebouncer.emittedValue.isEmpty() && textDebouncer.debounced.isEmpty()) {
|
||||
logger.log("$isNotUserInput: даннные в textDebouncer ПУСТЫ -> start RECOMPOSE новые данные для textValueState.value = [${fieldData.value}]")
|
||||
logger.log(
|
||||
"$isNotUserInput: даннные в textDebouncer ПУСТЫ -> start RECOMPOSE новые данные для " +
|
||||
"textValueState.value = [${fieldData.value}]",
|
||||
)
|
||||
textValueState.value = fieldData.value
|
||||
} else {
|
||||
logger.log("$isNotUserInput: даннные в textDebouncer НЕ ПУСТЫ -> start RECOMPOSE новые данные для textValueState.value = [${fieldData.value}]")
|
||||
logger.log(
|
||||
"$isNotUserInput: даннные в textDebouncer НЕ ПУСТЫ -> start RECOMPOSE новые данные для " +
|
||||
"textValueState.value = [${fieldData.value}]",
|
||||
)
|
||||
textValueState.value = fieldData.value
|
||||
}
|
||||
} else {
|
||||
logger.log("$isNotUserInput: в пустое поле вставляются данные -> start RECOMPOSE новые данные для textValueState.value = [${fieldData.value}]")
|
||||
logger.log(
|
||||
"$isNotUserInput: в пустое поле вставляются данные -> start RECOMPOSE новые данные для " +
|
||||
"textValueState.value = [${fieldData.value}]",
|
||||
)
|
||||
textValueState.value = fieldData.value
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ fun TitleSubtitle(
|
|||
title: String,
|
||||
subtitle: String
|
||||
) {
|
||||
Column() {
|
||||
Column {
|
||||
Text(text = title)
|
||||
Text(
|
||||
text = subtitle,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,5 @@ fun AddCustomTokenWarning(
|
|||
lineHeight = 18.sp
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import com.tangem.tap.features.wallet.redux.ProgressState
|
|||
open class Button(val enabled: Boolean)
|
||||
|
||||
open class IndeterminateProgressButton(
|
||||
val state: ButtonState
|
||||
val state: ButtonState
|
||||
) : Button(state != ButtonState.DISABLED) {
|
||||
|
||||
val progressState: ProgressState
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ fun Activity.sendEmail(
|
|||
) {
|
||||
fun createEmailShareIntent(recipient: String, subject: String, text: String, file: File? = null): Intent {
|
||||
val builder = ShareCompat.IntentBuilder.from(this)
|
||||
.setType("message/rfc822")
|
||||
.setEmailTo(arrayOf(recipient))
|
||||
.setSubject(subject)
|
||||
.setText(text)
|
||||
file?.let { builder.setStream(FileProvider.getUriForFile(this, "${packageName}.provider", it)) }
|
||||
.setType("message/rfc822")
|
||||
.setEmailTo(arrayOf(recipient))
|
||||
.setSubject(subject)
|
||||
.setText(text)
|
||||
file?.let { builder.setStream(FileProvider.getUriForFile(this, "$packageName.provider", it)) }
|
||||
return builder.intent
|
||||
}
|
||||
|
||||
|
|
@ -41,17 +41,17 @@ fun Activity.sendEmail(
|
|||
val emailFilterIntentResults = packageManager.queryIntentActivities(emailFilterIntent, 0)
|
||||
|
||||
val targetedIntents = originalIntentResults
|
||||
.filter { originalResult ->
|
||||
emailFilterIntentResults.any {
|
||||
originalResult.activityInfo.packageName == it.activityInfo.packageName
|
||||
}
|
||||
.filter { originalResult ->
|
||||
emailFilterIntentResults.any {
|
||||
originalResult.activityInfo.packageName == it.activityInfo.packageName
|
||||
}
|
||||
.map {
|
||||
createEmailShareIntent(email, subject, message, file).apply {
|
||||
setPackage(it.activityInfo.packageName)
|
||||
}
|
||||
}
|
||||
.map {
|
||||
createEmailShareIntent(email, subject, message, file).apply {
|
||||
setPackage(it.activityInfo.packageName)
|
||||
}
|
||||
.toMutableList()
|
||||
}
|
||||
.toMutableList()
|
||||
try {
|
||||
val chooserIntent = Intent.createChooser(targetedIntents.removeAt(0), "Send mail...")
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toTypedArray())
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@ package com.tangem.tap.common.extensions
|
|||
import android.content.res.AssetManager
|
||||
|
||||
fun AssetManager.readJsonFileToString(fileName: String): String =
|
||||
this.open("$fileName.json").bufferedReader().readText()
|
||||
this.open("$fileName.json").bufferedReader().readText()
|
||||
|
|
@ -35,8 +35,8 @@ fun Context.isPermissionGranted(permission: String): Boolean {
|
|||
fun Context.resourceUri(@AnyRes resId: Int): Uri {
|
||||
return Uri.parse(
|
||||
ContentResolver.SCHEME_ANDROID_RESOURCE +
|
||||
"://" + resources.getResourcePackageName(resId)
|
||||
+ '/' + resources.getResourceTypeName(resId)
|
||||
+ '/' + resources.getResourceEntryName(resId),
|
||||
"://" + resources.getResourcePackageName(resId) +
|
||||
'/' + resources.getResourceTypeName(resId) +
|
||||
'/' + resources.getResourceEntryName(resId),
|
||||
)
|
||||
}
|
||||
|
|
@ -11,9 +11,11 @@ import java.text.DecimalFormat
|
|||
import java.text.DecimalFormatSymbols
|
||||
import java.util.*
|
||||
|
||||
//todo move extensions to utils
|
||||
// todo move extensions to utils
|
||||
fun BigDecimal.toFormattedString(
|
||||
decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN, locale: Locale = Locale.US,
|
||||
decimals: Int,
|
||||
roundingMode: RoundingMode = RoundingMode.DOWN,
|
||||
locale: Locale = Locale.US,
|
||||
): String {
|
||||
val symbols = DecimalFormatSymbols(locale)
|
||||
val df = DecimalFormat()
|
||||
|
|
@ -27,7 +29,9 @@ fun BigDecimal.toFormattedString(
|
|||
|
||||
@Suppress("MagicNumber")
|
||||
fun BigDecimal.toFormattedCurrencyString(
|
||||
decimals: Int, currency: String, roundingMode: RoundingMode = RoundingMode.DOWN,
|
||||
decimals: Int,
|
||||
currency: String,
|
||||
roundingMode: RoundingMode = RoundingMode.DOWN,
|
||||
limitNumberOfDecimals: Boolean = true,
|
||||
): String {
|
||||
val decimalsForRounding = if (limitNumberOfDecimals) {
|
||||
|
|
@ -36,7 +40,8 @@ fun BigDecimal.toFormattedCurrencyString(
|
|||
decimals
|
||||
}
|
||||
val formattedAmount = this.toFormattedString(
|
||||
decimals = decimalsForRounding, roundingMode = roundingMode,
|
||||
decimals = decimalsForRounding,
|
||||
roundingMode = roundingMode,
|
||||
)
|
||||
return "$formattedAmount $currency"
|
||||
}
|
||||
|
|
@ -70,7 +75,7 @@ fun BigDecimal.toFormattedFiatValue(
|
|||
): String {
|
||||
val fiatValue = this.setScale(2, RoundingMode.HALF_UP)
|
||||
.let { if (formatWithSpaces) it.formatWithSpaces() else it }
|
||||
return " ${fiatValue} $fiatCurrencyName"
|
||||
return " $fiatValue $fiatCurrencyName"
|
||||
}
|
||||
|
||||
fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ fun EditText.update(text: String?) {
|
|||
|
||||
val textLength = text?.length ?: 0
|
||||
|
||||
//prevent cursor jumping while editing a text
|
||||
// prevent cursor jumping while editing a text
|
||||
val cursorPosition = if (selectionEnd > textLength) textLength else selectionEnd
|
||||
this.setText(text)
|
||||
if (!isFocused || textLength == 0) return
|
||||
|
|
|
|||
|
|
@ -86,7 +86,9 @@ fun View.invisible(invisible: Boolean = true, invokeBeforeStateChanged: (() -> U
|
|||
|
||||
fun Context.dpToPixels(dp: Int): Int =
|
||||
TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), this.resources.displayMetrics,
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
dp.toFloat(),
|
||||
this.resources.displayMetrics,
|
||||
).toInt()
|
||||
|
||||
fun Context.pixelsToDp(pixels: Int): Int {
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ package com.tangem.tap.common.feature
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface Feature {
|
||||
fun featureIsSwitchedOn():Boolean
|
||||
fun featureIsSwitchedOn(): Boolean
|
||||
}
|
||||
|
|
@ -30,13 +30,11 @@ fun createCoilImageLoader(
|
|||
}
|
||||
)
|
||||
.build()
|
||||
|
||||
}
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
private class CoilTimberLogger : Logger {
|
||||
|
||||
override var level: Int = Log.DEBUG
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
|
|||
store.state.globalState.warningManager?.let {
|
||||
if (it.hideWarning(action.warning)) {
|
||||
if (WarningMessagesManager.isAlreadySignedHashesWarning(action.warning)) {
|
||||
//TODO: No appropriate warningMessage identification. Make it better later
|
||||
// TODO: No appropriate warningMessage identification. Make it better later
|
||||
store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import org.rekotlin.Action
|
|||
|
||||
@Suppress("LongMethod", "ComplexMethod")
|
||||
fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolder): GlobalState {
|
||||
|
||||
if (action !is GlobalAction) return state.globalState
|
||||
|
||||
val globalState = state.globalState
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ object NavigationReducer {
|
|||
}
|
||||
|
||||
private fun internalReduce(action: Action, state: AppState): NavigationState {
|
||||
|
||||
val navigationAction = action as? NavigationAction ?: return state.navigationState
|
||||
val navState = state.navigationState
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,8 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) {
|
|||
fun buyWithGooglePay(productType: ProductType) {
|
||||
val totalPrice = checkouts[productType]!!.totalPriceV2.amount
|
||||
googlePayService.payWithGooglePay(
|
||||
totalPriceCents = totalPrice, currencyCode = checkouts[productType]!!.currencyCode.name,
|
||||
totalPriceCents = totalPrice,
|
||||
currencyCode = checkouts[productType]!!.currencyCode.name,
|
||||
merchantID = shopifyService.shop.merchantID,
|
||||
)
|
||||
}
|
||||
|
|
@ -189,7 +190,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) {
|
|||
appliedDiscount = it.getAppliedDiscount(),
|
||||
),
|
||||
|
||||
)
|
||||
)
|
||||
}
|
||||
return Result.failure(result.exceptionOrNull()!!)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ class GooglePayService(private val paymentsClient: PaymentsClient, private val a
|
|||
// var responseCallback: ((Result<PaymentData>) -> Unit)? = null
|
||||
|
||||
suspend fun checkIfGooglePayAvailable(): Result<Boolean> {
|
||||
|
||||
val isReadyToPayJson = GooglePayUtil.isReadyToPayRequest() ?: return Result.success(false)
|
||||
val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString())
|
||||
|
||||
|
|
@ -60,7 +59,9 @@ class GooglePayService(private val paymentsClient: PaymentsClient, private val a
|
|||
val request = PaymentDataRequest.fromJson(paymentDataRequestJson.toString())
|
||||
|
||||
AutoResolveHelper.resolveTask(
|
||||
paymentsClient.loadPaymentData(request), activity, LOAD_PAYMENT_DATA_REQUEST_CODE,
|
||||
paymentsClient.loadPaymentData(request),
|
||||
activity,
|
||||
LOAD_PAYMENT_DATA_REQUEST_CODE,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ object GooglePayUtil {
|
|||
|
||||
private fun baseCardPaymentMethod(): JSONObject {
|
||||
return JSONObject().apply {
|
||||
|
||||
val parameters = JSONObject().apply {
|
||||
put("allowedAuthMethods", allowedCardAuthMethods)
|
||||
put("allowedCardNetworks", allowedCardNetworks)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop
|
|||
}
|
||||
|
||||
suspend fun checkout(pollUntilOrder: Boolean, checkoutID: ID): Result<Checkout> {
|
||||
|
||||
val query = query { rootQuery: QueryRootQuery ->
|
||||
rootQuery
|
||||
.node(checkoutID) { query ->
|
||||
|
|
@ -76,7 +75,8 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop
|
|||
}
|
||||
}
|
||||
val retryHandler = RetryHandler.build<QueryRoot>(
|
||||
1, TimeUnit.SECONDS,
|
||||
delay = 1,
|
||||
timeUnit = TimeUnit.SECONDS,
|
||||
) {
|
||||
this.retryWhen { result ->
|
||||
when (result) {
|
||||
|
|
@ -109,7 +109,6 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop
|
|||
checkoutItems: List<CheckoutItem>,
|
||||
checkoutID: ID? = null,
|
||||
): Result<Checkout> {
|
||||
|
||||
val storefrontLineItems: MutableList<CheckoutLineItemInput> = checkoutItems
|
||||
.map { CheckoutLineItemInput(it.quantity, it.id) }.toMutableList()
|
||||
|
||||
|
|
@ -117,7 +116,8 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop
|
|||
mutation { mutationQuery: MutationQuery ->
|
||||
mutationQuery
|
||||
.checkoutLineItemsReplace(
|
||||
storefrontLineItems, checkoutID,
|
||||
storefrontLineItems,
|
||||
checkoutID,
|
||||
) { payloadQuery: CheckoutLineItemsReplacePayloadQuery ->
|
||||
payloadQuery
|
||||
.checkout { checkoutQuery: CheckoutQuery ->
|
||||
|
|
@ -159,7 +159,8 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop
|
|||
val query = mutation { mutationQuery: MutationQuery ->
|
||||
mutationQuery
|
||||
.checkoutDiscountCodeApplyV2(
|
||||
discountCode, checkoutID,
|
||||
discountCode,
|
||||
checkoutID,
|
||||
) { payloadQuery: CheckoutDiscountCodeApplyV2PayloadQuery ->
|
||||
payloadQuery
|
||||
.checkout { checkoutQuery: CheckoutQuery ->
|
||||
|
|
@ -199,11 +200,11 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop
|
|||
payment: TokenizedPaymentInputV3,
|
||||
checkoutID: ID,
|
||||
): Result<Checkout> {
|
||||
|
||||
val query = mutation { mutationQuery: MutationQuery ->
|
||||
mutationQuery
|
||||
.checkoutCompleteWithTokenizedPaymentV3(
|
||||
checkoutID, payment,
|
||||
checkoutID,
|
||||
payment,
|
||||
) { payloadQuery: CheckoutCompleteWithTokenizedPaymentV3PayloadQuery ->
|
||||
payloadQuery
|
||||
.payment { paymentQuery: PaymentQuery ->
|
||||
|
|
|
|||
|
|
@ -17,15 +17,15 @@ import com.tangem.wallet.R
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class MaxAmountSnackbar(
|
||||
parent: ViewGroup,
|
||||
content: MaxAmountSnackbarView
|
||||
parent: ViewGroup,
|
||||
content: MaxAmountSnackbarView
|
||||
) : BaseTransientBottomBar<MaxAmountSnackbar>(parent, content, content) {
|
||||
|
||||
companion object {
|
||||
|
||||
fun make(view: View, onClick: () -> Unit): MaxAmountSnackbar {
|
||||
val parent = view.findSuitableParent() ?: throw IllegalArgumentException(
|
||||
"No suitable parent found from the given view. Please provide a valid view."
|
||||
"No suitable parent found from the given view. Please provide a valid view."
|
||||
)
|
||||
val inflater = LayoutInflater.from(view.context)
|
||||
val customView = inflater.inflate(R.layout.view_snackbar_max_amount, parent, false) as MaxAmountSnackbarView
|
||||
|
|
@ -57,14 +57,13 @@ class MaxAmountSnackbar(
|
|||
} while (view != null)
|
||||
return fallback
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class MaxAmountSnackbarView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), ContentViewCallback {
|
||||
|
||||
init {
|
||||
|
|
@ -72,10 +71,9 @@ class MaxAmountSnackbarView @JvmOverloads constructor(
|
|||
clipToPadding = false
|
||||
}
|
||||
|
||||
|
||||
override fun animateContentIn(delay: Int, duration: Int) {
|
||||
}
|
||||
|
||||
override fun animateContentOut(delay: Int, duration: Int) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,9 +12,10 @@ class DecimalDigitsInputFilter(
|
|||
digitsAfterDecimal: Int,
|
||||
private val decimalSeparator: String,
|
||||
) : InputFilter {
|
||||
@Suppress("MaxLineLength")
|
||||
private val pattern: Pattern =
|
||||
Pattern.compile("(([1-9]{1}[0-9]{0,${digitsBeforeDecimal - 1}})?||[0]{1})((\\$decimalSeparator[0-9]{0,$digitsAfterDecimal})?)||(\\$decimalSeparator)?")
|
||||
private val pattern: Pattern = Pattern.compile(
|
||||
"(([1-9]{1}[0-9]{0,${digitsBeforeDecimal - 1}})?||[0]{1})" +
|
||||
"((\\$decimalSeparator[0-9]{0,$digitsAfterDecimal})?)||(\\$decimalSeparator)?",
|
||||
)
|
||||
|
||||
override fun filter(
|
||||
source: CharSequence,
|
||||
|
|
@ -56,4 +57,4 @@ class DecimalDigitsInputFilter(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,9 +16,9 @@ interface Truncate {
|
|||
companion object {
|
||||
fun create(type: TruncateType): Truncate {
|
||||
return when (type) {
|
||||
TruncateType.START -> TruncateStart()
|
||||
TruncateType.MIDDLE -> TruncateMiddle()
|
||||
TruncateType.END -> TruncateEnd()
|
||||
TruncateType.START -> TruncateStart()
|
||||
TruncateType.MIDDLE -> TruncateMiddle()
|
||||
TruncateType.END -> TruncateEnd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,10 +127,10 @@ fun TextView.truncateWith(text: String, type: TruncateType, with: String = "..."
|
|||
}
|
||||
|
||||
fun TextView.truncateStartWith(text: String, with: String = "..."): String =
|
||||
this.truncateWith(text, TruncateType.START, with)
|
||||
this.truncateWith(text, TruncateType.START, with)
|
||||
|
||||
fun TextView.truncateMiddleWith(text: String, with: String = "..."): String =
|
||||
this.truncateWith(text, TruncateType.MIDDLE, with)
|
||||
this.truncateWith(text, TruncateType.MIDDLE, with)
|
||||
|
||||
fun TextView.truncateEndWith(text: String, with: String = "..."): String =
|
||||
this.truncateWith(text, TruncateType.END, with)
|
||||
this.truncateWith(text, TruncateType.END, with)
|
||||
|
|
@ -67,9 +67,18 @@ class RefreshBalanceWidget(
|
|||
}
|
||||
ProgressState.Loading -> {
|
||||
progressViewAnimation = RotateAnimation(
|
||||
0f, 360f,
|
||||
Animation.RELATIVE_TO_SELF, 0.5f,
|
||||
Animation.RELATIVE_TO_SELF, 0.5f,
|
||||
/* fromDegrees = */
|
||||
0f,
|
||||
/* toDegrees = */
|
||||
360f,
|
||||
/* pivotXType = */
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
/* pivotXValue = */
|
||||
0.5f,
|
||||
/* pivotYType = */
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
/* pivotYValue = */
|
||||
0.5f,
|
||||
)
|
||||
progressViewAnimation?.duration = 700
|
||||
progressViewAnimation?.interpolator = AccelerateInterpolator()
|
||||
|
|
@ -101,10 +110,14 @@ class ShowAnimation : AnimationSet(true) {
|
|||
init {
|
||||
addAnimation(
|
||||
ScaleAnimation(
|
||||
0f, 1f,
|
||||
0f, 1f,
|
||||
Animation.RELATIVE_TO_SELF, 0.5f,
|
||||
Animation.RELATIVE_TO_SELF, 0.5f,
|
||||
0f,
|
||||
1f,
|
||||
0f,
|
||||
1f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
),
|
||||
)
|
||||
addAnimation(AlphaAnimation(0f, 1f))
|
||||
|
|
|
|||
|
|
@ -1,33 +1,13 @@
|
|||
package com.tangem.tap.common.transitions
|
||||
|
||||
import androidx.transition.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class FrontCardEnterTransition : TransitionSet() {
|
||||
init {
|
||||
ordering = ORDERING_TOGETHER;
|
||||
addTransition(Fade())
|
||||
addTransition(ChangeImageTransform()) // изменения внутри ImageView
|
||||
addTransition(ChangeTransform()) // изменение размеров, углов накона
|
||||
addTransition(ChangeBounds()) // изменение положения
|
||||
}
|
||||
}
|
||||
|
||||
class FrontCardExitTransition : TransitionSet() {
|
||||
init {
|
||||
ordering = ORDERING_TOGETHER;
|
||||
addTransition(Fade())
|
||||
addTransition(ChangeImageTransform())
|
||||
addTransition(ChangeTransform())
|
||||
addTransition(ChangeBounds())
|
||||
}
|
||||
}
|
||||
import androidx.transition.ChangeBounds
|
||||
import androidx.transition.ChangeTransform
|
||||
import androidx.transition.Fade
|
||||
import androidx.transition.TransitionSet
|
||||
|
||||
class HomeToOnboardingTransition : TransitionSet() {
|
||||
init {
|
||||
ordering = ORDERING_TOGETHER;
|
||||
ordering = ORDERING_TOGETHER
|
||||
addTransition(Fade())
|
||||
addTransition(ChangeTransform())
|
||||
addTransition(ChangeBounds())
|
||||
|
|
@ -36,7 +16,7 @@ class HomeToOnboardingTransition : TransitionSet() {
|
|||
|
||||
class InternalNoteLayoutTransition : TransitionSet() {
|
||||
init {
|
||||
ordering = ORDERING_TOGETHER;
|
||||
ordering = ORDERING_TOGETHER
|
||||
addTransition(ChangeTransform())
|
||||
addTransition(ChangeBounds())
|
||||
addTransition(Fade())
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ object SimpleCancelableAlertDialog {
|
|||
secondaryButtonAction: () -> Unit = {},
|
||||
context: Context,
|
||||
): AlertDialog {
|
||||
|
||||
return AlertDialog.Builder(context).apply {
|
||||
setTitle(titleRes?.let { context.getString(it) } ?: title)
|
||||
setMessage(messageRes?.let { context.getString(it) } ?: message)
|
||||
|
|
|
|||
|
|
@ -23,16 +23,15 @@ class PayIdManager {
|
|||
|
||||
private fun Blockchain.getPayIdNetwork(): String {
|
||||
return when (this) {
|
||||
Blockchain.XRP -> "XRPL"
|
||||
Blockchain.RSK -> "RSK"
|
||||
else -> this.currency
|
||||
}.lowercase(Locale.getDefault())
|
||||
Blockchain.XRP -> "XRPL"
|
||||
Blockchain.RSK -> "RSK"
|
||||
else -> this.currency
|
||||
}.lowercase(Locale.getDefault())
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Suppress("MaxLineLength")
|
||||
val payIdRegExp =
|
||||
"^[a-z0-9!#@%&*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#@%&*+/=?^_`{|}~-]+)*\\\$(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z-]*[a-z0-9])?|(?:[0-9]{1,3}\\.){3}[0-9]{1,3})\$".toRegex()
|
||||
private val payIdRegExp = ("^[a-z0-9!#@%&*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#@%&*+/=?^_`{|}~-]+)*\\\$(?:(?:[a-z0-9]" +
|
||||
"(?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z-]*[a-z0-9])?|(?:[0-9]{1,3}\\.){3}[0-9]{1,3})\$").toRegex()
|
||||
|
||||
val payIdSupported: EnumSet<Blockchain> = EnumSet.of(
|
||||
Blockchain.XRP,
|
||||
|
|
|
|||
|
|
@ -167,8 +167,8 @@ class TapWalletManager {
|
|||
store.dispatch(WalletConnectAction.RestoreSessions(data))
|
||||
store.dispatch(
|
||||
WalletAction.MultiWallet.ShowWalletBackupWarning(
|
||||
show = data.card.settings.isBackupAllowed
|
||||
&& data.card.backupStatus == CardDTO.BackupStatus.NoBackup,
|
||||
show = data.card.settings.isBackupAllowed &&
|
||||
data.card.backupStatus == CardDTO.BackupStatus.NoBackup,
|
||||
),
|
||||
)
|
||||
loadData(data)
|
||||
|
|
@ -181,8 +181,8 @@ class TapWalletManager {
|
|||
if (data.cardTypesResolver.isStart2Coin()) {
|
||||
configManager?.turnOff(ConfigManager.isSendingToPayIdEnabled)
|
||||
configManager?.turnOff(ConfigManager.isTopUpEnabled)
|
||||
} else if (blockchain == Blockchain.Bitcoin
|
||||
|| data.walletData?.blockchain == Blockchain.Bitcoin.id
|
||||
} else if (blockchain == Blockchain.Bitcoin ||
|
||||
data.walletData?.blockchain == Blockchain.Bitcoin.id
|
||||
) {
|
||||
configManager?.resetToDefault(ConfigManager.isSendingToPayIdEnabled)
|
||||
configManager?.resetToDefault(ConfigManager.isTopUpEnabled)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ data class WarningMessage(
|
|||
blockchains?.map { Blockchain.fromId(it.uppercase()) }
|
||||
}
|
||||
|
||||
|
||||
var isHidden = false
|
||||
|
||||
enum class Priority {
|
||||
|
|
@ -40,15 +39,14 @@ data class WarningMessage(
|
|||
|
||||
enum class Type {
|
||||
@Json(name = "permanent")
|
||||
Permanent, // нельзя скрыть
|
||||
Permanent, // нельзя скрыть
|
||||
|
||||
@Json(name = "temporary")
|
||||
Temporary, // можно скрыть (кнопка ОК)
|
||||
Temporary, // можно скрыть (кнопка ОК)
|
||||
|
||||
AppRating,
|
||||
|
||||
TestCard
|
||||
|
||||
}
|
||||
|
||||
enum class Location {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ class WarningMessagesManager {
|
|||
val foundWarning = findWarning(warning)
|
||||
return when {
|
||||
foundWarning == null -> false
|
||||
foundWarning.type == WarningMessage.Type.Temporary
|
||||
|| foundWarning.type == WarningMessage.Type.AppRating -> {
|
||||
foundWarning.type == WarningMessage.Type.Temporary ||
|
||||
foundWarning.type == WarningMessage.Type.AppRating -> {
|
||||
if (foundWarning.isHidden) {
|
||||
false
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ fun WalletManagerFactory.makeWalletManagerForApp(
|
|||
}
|
||||
|
||||
fun WalletManagerFactory.makeWalletManagerForApp(
|
||||
scanResponse: ScanResponse, blockchainNetwork: BlockchainNetwork,
|
||||
scanResponse: ScanResponse,
|
||||
blockchainNetwork: BlockchainNetwork,
|
||||
): WalletManager? {
|
||||
return makeWalletManagerForApp(
|
||||
scanResponse,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,6 @@ class UserWalletBuilder(
|
|||
|
||||
private fun getUrlForArtwork(cardId: String, cardPublicKeyHex: String, artworkId: String): String {
|
||||
return TangemApi.Companion.BaseUrl.VERIFY.url + TangemApi.ARTWORK +
|
||||
"?artworkId=${artworkId}&CID=${cardId}&publicKey=$cardPublicKeyHex"
|
||||
"?artworkId=$artworkId&CID=$cardId&publicKey=$cardPublicKeyHex"
|
||||
}
|
||||
}
|
||||
|
|
@ -31,4 +31,4 @@ class SaltPayErrorConverter(
|
|||
is SaltPayActivationError -> SaltPayActivationErrorConverter(context).convert(message)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ class OnboardingWalletStateConverter : StringStateConverter<AppState> {
|
|||
BackupStepAdapter(),
|
||||
BigIntegerAdapter(),
|
||||
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun convert(stateHolder: AppState): String {
|
||||
|
|
|
|||
|
|
@ -29,14 +29,12 @@ class ScanResponseConverter : StringStateConverter<AppState> {
|
|||
)
|
||||
}
|
||||
derivedKeysMap[keyWalletPubKey.bytes.toHexString()] = exPubKeysMap
|
||||
|
||||
}
|
||||
scanResponseMap["derivedKeys"] = derivedKeysMap
|
||||
|
||||
val json = converter.prettyPrint(scanResponseMap)
|
||||
|
||||
return json
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import com.tangem.operations.wallet.CreateWalletTask
|
|||
class CreateWalletsTask(curves: List<EllipticCurve>? = null) : CardSessionRunnable<Card> {
|
||||
|
||||
private val curves = curves ?: listOf(
|
||||
EllipticCurve.Secp256k1,
|
||||
EllipticCurve.Ed25519,
|
||||
EllipticCurve.Secp256r1,
|
||||
EllipticCurve.Secp256k1,
|
||||
EllipticCurve.Ed25519,
|
||||
EllipticCurve.Secp256r1,
|
||||
)
|
||||
|
||||
private var index = 0
|
||||
|
|
@ -26,10 +26,10 @@ class CreateWalletsTask(curves: List<EllipticCurve>? = null) : CardSessionRunnab
|
|||
}
|
||||
|
||||
private fun createWallet(
|
||||
curve: EllipticCurve, session: CardSession,
|
||||
curve: EllipticCurve,
|
||||
session: CardSession,
|
||||
callback: (result: CompletionResult<Card>) -> Unit
|
||||
) {
|
||||
|
||||
CreateWalletTask(curve).run(session) { result ->
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
|
|
|
|||
|
|
@ -34,4 +34,4 @@ class SignHashTask(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -210,7 +210,8 @@ private class CreateWalletTangemWallet : ProductCommandProcessor<CreateProductWa
|
|||
callback(
|
||||
CompletionResult.Success(
|
||||
CreateProductWalletTaskResponse(
|
||||
card = session.environment.card!!, primaryCard = primaryCard,
|
||||
card = session.environment.card!!,
|
||||
primaryCard = primaryCard,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class CreateWalletsTask(
|
|||
private val createdWalletsResponses = mutableListOf<CreateWalletResponse>()
|
||||
|
||||
override fun run(session: CardSession, callback: (result: CompletionResult<CreateWalletsResponse>) -> Unit) {
|
||||
if (curves.isEmpty()){
|
||||
if (curves.isEmpty()) {
|
||||
callback(CompletionResult.Failure(TangemSdkError.WalletIsNotCreated()))
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ class ResetToFactorySettingsTask : CardSessionRunnable<Card> {
|
|||
session: CardSession,
|
||||
callback: (result: CompletionResult<Card>) -> Unit,
|
||||
) {
|
||||
|
||||
val wallet = session.environment.card?.wallets?.lastOrNull().guard {
|
||||
resetBackup(session, callback)
|
||||
return
|
||||
|
|
@ -38,7 +37,6 @@ class ResetToFactorySettingsTask : CardSessionRunnable<Card> {
|
|||
session: CardSession,
|
||||
callback: (result: CompletionResult<Card>) -> Unit,
|
||||
) {
|
||||
|
||||
val backupStatus = session.environment.card?.backupStatus
|
||||
if (backupStatus == null || backupStatus == Card.BackupStatus.NoBackup) {
|
||||
callback(CompletionResult.Success(session.environment.card!!))
|
||||
|
|
|
|||
|
|
@ -101,24 +101,6 @@ class ScanProductTask(
|
|||
}
|
||||
}
|
||||
|
||||
private class ScanNoteProcessor : ProductCommandProcessor<ScanResponse> {
|
||||
override fun proceed(
|
||||
card: CardDTO,
|
||||
session: CardSession,
|
||||
callback: (result: CompletionResult<ScanResponse>) -> Unit,
|
||||
) {
|
||||
callback(
|
||||
CompletionResult.Success(
|
||||
ScanResponse(
|
||||
card = card,
|
||||
productType = ProductType.Note,
|
||||
walletData = session.environment.walletData,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class ScanWalletProcessor(
|
||||
private val userTokensRepository: UserTokensRepository?,
|
||||
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null,
|
||||
|
|
@ -130,12 +112,10 @@ private class ScanWalletProcessor(
|
|||
session: CardSession,
|
||||
callback: (result: CompletionResult<ScanResponse>) -> Unit,
|
||||
) {
|
||||
|
||||
if (card.firmwareVersion.doubleValue >= 4.39) {
|
||||
if (card.settings.maxWalletsCount == 1) {
|
||||
readFile(card, session, callback)
|
||||
return
|
||||
}
|
||||
@Suppress("MagicNumber")
|
||||
if (card.firmwareVersion.doubleValue >= 4.39 && card.settings.maxWalletsCount == 1) {
|
||||
readFile(card, session, callback)
|
||||
return
|
||||
}
|
||||
|
||||
createMissingWalletsIfNeeded(card, session, callback)
|
||||
|
|
@ -198,7 +178,6 @@ private class ScanWalletProcessor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,8 +223,8 @@ private class ScanWalletProcessor(
|
|||
val activationInProgress = preferencesStorage.usedCardsPrefStorage.isActivationInProgress(card.cardId)
|
||||
|
||||
@Suppress("ComplexCondition")
|
||||
if (card.backupStatus == CardDTO.BackupStatus.NoBackup && card.wallets.isNotEmpty()
|
||||
&& (activationInProgress || card.isSaltPay)
|
||||
if (card.backupStatus == CardDTO.BackupStatus.NoBackup && card.wallets.isNotEmpty() &&
|
||||
(activationInProgress || card.isSaltPay)
|
||||
) {
|
||||
StartPrimaryCardLinkingTask().run(session) { linkingResult ->
|
||||
when (linkingResult) {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ class OldUserTokensRepository(
|
|||
}
|
||||
|
||||
private suspend fun loadSavedCurrenciesOldWay(
|
||||
cardId: String, isHdWalletSupported: Boolean = false,
|
||||
cardId: String,
|
||||
isHdWalletSupported: Boolean = false,
|
||||
): List<BlockchainNetwork> {
|
||||
val blockchains = loadSavedBlockchains(cardId)
|
||||
val tokens = loadSavedTokens(cardId)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ data class BlockchainNetwork(
|
|||
}
|
||||
|
||||
override fun hashCode(): Int = calculateHashCode(
|
||||
blockchain.hashCode(), derivationPath?.hashCode() ?: 0,
|
||||
blockchain.hashCode(),
|
||||
derivationPath?.hashCode() ?: 0,
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -26,5 +26,4 @@ data class TokenDao(
|
|||
customIconUrl?.let { this.setCustomIconUrl(it) }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -10,7 +10,8 @@ import com.tangem.operations.PreflightReadTask
|
|||
import com.tangem.tap.domain.tasks.product.ScanProductTask
|
||||
|
||||
class FinalizeTwinTask(
|
||||
private val twinPublicKey: ByteArray, private val issuerKeys: KeyPair,
|
||||
private val twinPublicKey: ByteArray,
|
||||
private val issuerKeys: KeyPair,
|
||||
) : CardSessionRunnable<ScanResponse> {
|
||||
|
||||
override val allowsRequestAccessCodeFromRepository: Boolean = false
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ import com.tangem.operations.issuerAndUserData.WriteIssuerDataCommand
|
|||
import com.tangem.operations.sign.SignHashCommand
|
||||
|
||||
class WriteProtectedIssuerDataTask(
|
||||
private val twinPublicKey: ByteArray, private val issuerKeys: KeyPair,
|
||||
private val twinPublicKey: ByteArray,
|
||||
private val issuerKeys: KeyPair,
|
||||
) : CardSessionRunnable<SuccessResponse> {
|
||||
|
||||
override fun run(
|
||||
|
|
@ -33,8 +34,12 @@ class WriteProtectedIssuerDataTask(
|
|||
when (readResult) {
|
||||
is CompletionResult.Success -> {
|
||||
writeIssuerData(
|
||||
twinPublicKey, issuerKeys, signResult.data.signature,
|
||||
readResult.data, session, callback,
|
||||
twinPublicKey,
|
||||
issuerKeys,
|
||||
signResult.data.signature,
|
||||
readResult.data,
|
||||
session,
|
||||
callback,
|
||||
)
|
||||
}
|
||||
is CompletionResult.Failure -> callback(
|
||||
|
|
@ -52,7 +57,9 @@ class WriteProtectedIssuerDataTask(
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
private fun writeIssuerData(
|
||||
twinPublicKey: ByteArray, issuerKeys: KeyPair, cardSignature: ByteArray,
|
||||
twinPublicKey: ByteArray,
|
||||
issuerKeys: KeyPair,
|
||||
cardSignature: ByteArray,
|
||||
readResponse: ReadIssuerDataResponse,
|
||||
session: CardSession,
|
||||
callback: (
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import com.tangem.tap.domain.userWalletList.UserWalletListError
|
|||
import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey
|
||||
import com.tangem.tap.domain.userWalletList.model.UserWalletSensitiveInformation
|
||||
import com.tangem.tap.domain.userWalletList.repository.UserWalletsSensitiveInformationRepository
|
||||
import com.tangem.tap.domain.userWalletList.utils.encryptionKey
|
||||
import com.tangem.tap.domain.userWalletList.utils.sensitiveInformation
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -180,7 +179,7 @@ internal class DefaultUserWalletsSensitiveInformationRepository(
|
|||
}
|
||||
|
||||
class SensitiveInformationIv(userWalletId: String) : StorageKey {
|
||||
override val name: String = "user_wallet_sensitive_information_iv_${userWalletId}"
|
||||
override val name: String = "user_wallet_sensitive_information_iv_$userWalletId"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ internal class DefaultWalletCurrenciesManager(
|
|||
): CompletionResult<Unit> = withContext(Dispatchers.Default) {
|
||||
val walletStore = walletStoresRepository.getSync(userWallet.walletId)
|
||||
.find {
|
||||
it.blockchain == currency.blockchain
|
||||
&& it.derivationPath?.rawPath == currency.derivationPath
|
||||
it.blockchain == currency.blockchain &&
|
||||
it.derivationPath?.rawPath == currency.derivationPath
|
||||
}
|
||||
|
||||
if (walletStore != null) {
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ internal class DefaultWalletAmountsRepository(
|
|||
"""
|
||||
Unable to fetch fiat rates
|
||||
|- Coins ids: $coinsIds
|
||||
""".trimIndent(),
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return@withContext CompletionResult.Failure(error)
|
||||
|
|
@ -175,7 +175,7 @@ internal class DefaultWalletAmountsRepository(
|
|||
): CompletionResult<Unit> = coroutineScope {
|
||||
walletStores.map { walletStore ->
|
||||
async {
|
||||
//TODO: Find wallet manager via [com.tangem.tap.domain.walletStores.repository.WalletManagersRepository]
|
||||
// TODO: Find wallet manager via [com.tangem.tap.domain.walletStores.repository.WalletManagersRepository]
|
||||
val walletManager = walletStore.walletManager
|
||||
fetchAmountsForWalletStore(userWalletId, scanResponse, walletStore, walletManager)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,9 +195,9 @@ class WalletConnectManager {
|
|||
|
||||
fun removeSimilarSessions(activeData: WalletConnectActiveData) {
|
||||
val sessionsToRemove = sessions.filter {
|
||||
it.value.wallet.walletPublicKey?.equals(activeData.wallet.walletPublicKey) == true
|
||||
&& it.value.peerMeta?.url == activeData.peerMeta?.url
|
||||
&& it.value.session != activeData.session
|
||||
it.value.wallet.walletPublicKey?.equals(activeData.wallet.walletPublicKey) == true &&
|
||||
it.value.peerMeta?.url == activeData.peerMeta?.url &&
|
||||
it.value.session != activeData.session
|
||||
}
|
||||
Timber.d("RemoveSimilarSessions: ${sessionsToRemove.values.map { it.client.session }}")
|
||||
sessionsToRemove.forEach { disconnect(it.value.session) }
|
||||
|
|
@ -288,7 +288,9 @@ class WalletConnectManager {
|
|||
}
|
||||
|
||||
fun signBnb(
|
||||
id: Long, data: ByteArray, sessionData: WCSession,
|
||||
id: Long,
|
||||
data: ByteArray,
|
||||
sessionData: WCSession,
|
||||
) {
|
||||
val activeData = sessions[sessionData] ?: return
|
||||
scope.launch {
|
||||
|
|
@ -313,7 +315,9 @@ class WalletConnectManager {
|
|||
val activeData = sessions[session.session] ?: return
|
||||
scope.launch {
|
||||
val data = WalletConnectSdkHelper().prepareDataForPersonalSign(
|
||||
message = message, session = session, id = id,
|
||||
message = message,
|
||||
session = session,
|
||||
id = id,
|
||||
)
|
||||
sessions[session.session] = activeData.copy(personalSignData = data)
|
||||
store.dispatchOnMain(
|
||||
|
|
@ -435,15 +439,15 @@ class WalletConnectManager {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
client.onBnbCancel = { id: Long, order: WCBinanceCancelOrder ->
|
||||
|
||||
}
|
||||
client.onBnbTrade = { id: Long, order: WCBinanceTradeOrder ->
|
||||
sessions[client.session]?.toWalletConnectSession()?.let { sessionData ->
|
||||
store.dispatchOnMain(
|
||||
WalletConnectAction.BinanceTransaction.Trade(
|
||||
id = id, order = order, sessionData = sessionData,
|
||||
id = id,
|
||||
order = order,
|
||||
sessionData = sessionData,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -452,7 +456,9 @@ class WalletConnectManager {
|
|||
sessions[client.session]?.toWalletConnectSession()?.let { sessionData ->
|
||||
store.dispatchOnMain(
|
||||
WalletConnectAction.BinanceTransaction.Transfer(
|
||||
id = id, order = order, sessionData = sessionData,
|
||||
id = id,
|
||||
order = order,
|
||||
sessionData = sessionData,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class WalletConnectSdkHelper {
|
|||
|
||||
val gas = transaction.gas?.hexToBigDecimal()
|
||||
?: transaction.gasLimit?.hexToBigDecimal()
|
||||
?: BigDecimal(300000) //Set high gasLimit if not provided
|
||||
?: BigDecimal(300000) // Set high gasLimit if not provided
|
||||
|
||||
val decimals = wallet.blockchain.decimals()
|
||||
|
||||
|
|
@ -71,8 +71,7 @@ class WalletConnectSdkHelper {
|
|||
?.movePointLeft(decimals) ?: return null
|
||||
|
||||
val gasPrice = transaction.gasPrice?.hexToBigDecimal()
|
||||
?: when (val result =
|
||||
(walletManager as? EthereumGasLoader)?.getGasPrice()) {
|
||||
?: when (val result = (walletManager as? EthereumGasLoader)?.getGasPrice()) {
|
||||
is Result.Success -> result.data.toBigDecimal()
|
||||
is Result.Failure -> {
|
||||
(result.error as? Throwable)?.let { Timber.e(it) }
|
||||
|
|
@ -271,7 +270,9 @@ class WalletConnectSdkHelper {
|
|||
is CompletionResult.Success -> {
|
||||
val hash = result.data.signature
|
||||
return EthereumUtils.prepareSignedMessageData(
|
||||
hash, hashToSign, CryptoUtils.decompressPublicKey(key!!),
|
||||
signedHash = hash,
|
||||
hashToSign = hashToSign,
|
||||
publicKey = CryptoUtils.decompressPublicKey(key!!),
|
||||
)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ abstract class BaseFragment(layoutId: Int) : Fragment(layoutId), FragmentOnBackP
|
|||
}
|
||||
}
|
||||
|
||||
protected open fun loadToolbarMenu():MenuProvider? = null
|
||||
protected open fun loadToolbarMenu(): MenuProvider? = null
|
||||
|
||||
fun showRetrySnackbar(message: String, action: VoidCallback) {
|
||||
val snackbar = Snackbar.make(mainView, message, Snackbar.LENGTH_INDEFINITE)
|
||||
|
|
|
|||
|
|
@ -486,8 +486,7 @@ class DemoConfig {
|
|||
)
|
||||
|
||||
@Suppress("ClassOrdering")
|
||||
private val debugTestDemoCardIds = listOf<String>(
|
||||
)
|
||||
private val debugTestDemoCardIds = listOf<String>()
|
||||
}
|
||||
|
||||
class DemoTransactionSender(private val walletManager: WalletManager) : TransactionSender {
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ private fun handleSecurityAction(
|
|||
currentOption = state.cardSettingsState.manageSecurityState.selectedOption,
|
||||
allowedOptions = state.scanResponse?.cardTypesResolver?.let {
|
||||
prepareAllowedSecurityOptions(
|
||||
it, state.cardSettingsState.manageSecurityState.selectedOption,
|
||||
cardTypesResolver = it,
|
||||
currentSecurityOption = state.cardSettingsState.manageSecurityState.selectedOption,
|
||||
)
|
||||
} ?: EnumSet.of(SecurityOption.LongTap),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ sealed class WalletConnectAction : Action {
|
|||
object RefuseOpeningSession : WalletConnectAction()
|
||||
data class OpeningSessionTimeout(val session: WCSession) : WalletConnectAction()
|
||||
data class ScanCard(
|
||||
val session: WalletConnectSession, val chainId: Int?,
|
||||
val session: WalletConnectSession,
|
||||
val chainId: Int?,
|
||||
) : WalletConnectAction()
|
||||
|
||||
data class ApproveSession(
|
||||
|
|
@ -93,17 +94,21 @@ sealed class WalletConnectAction : Action {
|
|||
|
||||
object BinanceTransaction : WalletConnectAction() {
|
||||
data class Trade(
|
||||
val id: Long, val order: WCBinanceTradeOrder,
|
||||
val id: Long,
|
||||
val order: WCBinanceTradeOrder,
|
||||
val sessionData: WalletConnectSession,
|
||||
) : WalletConnectAction()
|
||||
|
||||
data class Transfer(
|
||||
val id: Long, val order: WCBinanceTransferOrder,
|
||||
val id: Long,
|
||||
val order: WCBinanceTransferOrder,
|
||||
val sessionData: WalletConnectSession,
|
||||
) : WalletConnectAction()
|
||||
|
||||
data class Sign(
|
||||
val id: Long, val data: ByteArray, val sessionData: WCSession,
|
||||
val id: Long,
|
||||
val data: ByteArray,
|
||||
val sessionData: WCSession,
|
||||
) : WalletConnectAction()
|
||||
}
|
||||
}
|
||||
|
|
@ -187,7 +187,9 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
is WalletConnectAction.BinanceTransaction.Sign -> {
|
||||
walletConnectManager.signBnb(
|
||||
action.id, action.data, action.sessionData,
|
||||
id = action.id,
|
||||
data = action.data,
|
||||
sessionData = action.sessionData,
|
||||
)
|
||||
}
|
||||
is WalletConnectAction.SwitchBlockchain -> {
|
||||
|
|
@ -309,7 +311,9 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
|
||||
private fun getWalletManager(
|
||||
wallet: WalletForSession, blockchain: Blockchain, walletState: WalletState,
|
||||
wallet: WalletForSession,
|
||||
blockchain: Blockchain,
|
||||
walletState: WalletState,
|
||||
): WalletManager? {
|
||||
val blockchainToMake = if (blockchain == Blockchain.Ethereum && wallet.isTestNet) {
|
||||
Blockchain.EthereumTestnet
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import org.rekotlin.Action
|
|||
|
||||
object WalletConnectReducer {
|
||||
fun reduce(
|
||||
action: Action, state: WalletConnectState,
|
||||
action: Action,
|
||||
state: WalletConnectState,
|
||||
): WalletConnectState {
|
||||
if (action !is WalletConnectAction) return state
|
||||
|
||||
|
|
@ -35,8 +36,7 @@ object WalletConnectReducer {
|
|||
is WalletConnectAction.FailureEstablishingSession -> state.copy(loading = false)
|
||||
is WalletConnectAction.UpdateBlockchain -> state.copy(
|
||||
sessions = state.sessions
|
||||
.filterNot { it.peerId == action.updatedSession.peerId }
|
||||
+ action.updatedSession,
|
||||
.filterNot { it.peerId == action.updatedSession.peerId } + action.updatedSession,
|
||||
)
|
||||
|
||||
else -> state
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ data class WalletForSession(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
sealed class WalletConnectDialog : StateDialog {
|
||||
data class ClipboardOrScanQr(val clipboardUri: String) : WalletConnectDialog()
|
||||
object UnsupportedCard : WalletConnectDialog()
|
||||
|
|
@ -133,7 +132,7 @@ data class WcPersonalSignData(
|
|||
val id: Long,
|
||||
val dialogData: PersonalSignDialogData,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
sealed class BinanceMessageData(
|
||||
val address: String,
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ private fun onCheckedChange(
|
|||
onSettingToggled: (PrivacySetting, Boolean) -> Unit,
|
||||
onDialogStateChange: (PrivacySetting?) -> Unit,
|
||||
) {
|
||||
//Show warning if user wants to disable the switch
|
||||
// Show warning if user wants to disable the switch
|
||||
if (!enabled) {
|
||||
onDialogStateChange(element)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import org.rekotlin.Store
|
|||
class CardSettingsViewModel(private val store: Store<AppState>) {
|
||||
|
||||
fun updateState(state: CardSettingsState?): CardSettingsScreenState {
|
||||
|
||||
return if (state?.manageSecurityState == null) {
|
||||
CardSettingsScreenState(
|
||||
cardDetails = null,
|
||||
|
|
|
|||
|
|
@ -132,9 +132,11 @@ fun DetailsMainButton(
|
|||
),
|
||||
) {
|
||||
Text(text = title)
|
||||
Spacer(modifier = Modifier
|
||||
.padding(start = 20.dp, end = 20.dp)
|
||||
.size(8.dp))
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.padding(start = 20.dp, end = 20.dp)
|
||||
.size(8.dp),
|
||||
)
|
||||
Icon(painter = painterResource(id = R.drawable.ic_tangem_24), contentDescription = "")
|
||||
}
|
||||
}
|
||||
|
|
@ -174,7 +174,8 @@ private fun Preview() {
|
|||
tangemLinks = TangemSocialAccounts.accountsEn,
|
||||
tangemVersion = "Tangem 2.14.12 (343)",
|
||||
appCurrency = "Dollar",
|
||||
onItemsClick = {}, onSocialNetworkClick = {},
|
||||
onItemsClick = {},
|
||||
onSocialNetworkClick = {},
|
||||
),
|
||||
onBackClick = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ fun SecurityModeOptions(state: SecurityModeScreenState) {
|
|||
) {
|
||||
ScreenTitle(titleRes = R.string.card_settings_security_mode, Modifier.padding(bottom = 36.dp))
|
||||
|
||||
|
||||
state.availableOptions.map {
|
||||
SecurityOption(option = it, state = state)
|
||||
}
|
||||
|
|
@ -79,13 +78,14 @@ fun SecurityOption(option: SecurityOption, state: SecurityModeScreenState) {
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = selected, onClick = { state.onNewModeSelected(option) },
|
||||
selected = selected,
|
||||
onClick = { state.onNewModeSelected(option) },
|
||||
)
|
||||
.padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 16.dp),
|
||||
) {
|
||||
|
||||
RadioButton(
|
||||
selected = selected, onClick = null,
|
||||
selected = selected,
|
||||
onClick = null,
|
||||
modifier = Modifier.padding(end = 20.dp),
|
||||
colors = RadioButtonDefaults.colors(
|
||||
unselectedColor = colorResource(id = R.color.icon_secondary),
|
||||
|
|
|
|||
|
|
@ -88,5 +88,4 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
|
|||
private fun requestPermission() {
|
||||
requestPermissions(arrayOf(Manifest.permission.CAMERA), CameraView.PERMISSION_REQUEST_CODE)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -177,4 +177,4 @@ private fun WalletConnectScreenPreview() {
|
|||
),
|
||||
{},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -21,5 +21,4 @@ data class WcSessionForScreen(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -17,7 +17,6 @@ object BnbTransactionDialog {
|
|||
dAppName: String,
|
||||
context: Context,
|
||||
): AlertDialog {
|
||||
|
||||
val message = when (data) {
|
||||
is BinanceMessageData.Trade -> data.tradeData.map {
|
||||
context.getString(
|
||||
|
|
@ -38,7 +37,8 @@ object BnbTransactionDialog {
|
|||
|
||||
val fullMessage = context.getString(
|
||||
R.string.wallet_connect_bnb_sign_message,
|
||||
dAppName, message,
|
||||
dAppName,
|
||||
message,
|
||||
)
|
||||
val positiveButtonTitle = context.getText(R.string.common_sign)
|
||||
|
||||
|
|
|
|||
|
|
@ -99,9 +99,9 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
|
|||
}
|
||||
|
||||
/*
|
||||
* !!! Workaround !!!
|
||||
* Used to roll back the color of icons in the system bars after the stories screen
|
||||
* */
|
||||
* !!! Workaround !!!
|
||||
* Used to roll back the color of icons in the system bars after the stories screen
|
||||
*/
|
||||
private fun rollbackStatusBarIconsColor() {
|
||||
val windowInsetsController = WindowInsetsControllerCompat(
|
||||
activity?.window ?: return,
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@ fun StoriesWeb3Content(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ fun FirstStoriesContent(
|
|||
val textId = screenState.textId()
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
|
||||
if (screenState.isSplashingTextDisplaying()) {
|
||||
TextAutoSize(
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ fun FloatingCardsContent(
|
|||
isPaused: Boolean,
|
||||
stepDuration: Int,
|
||||
) {
|
||||
|
||||
val imageBitmap = asImageBitmap(R.drawable.card_placeholder_wallet)
|
||||
val cards = listOf(
|
||||
FloatingCard.first(),
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ fun StoriesProgressBar(
|
|||
progress.snapTo(0f)
|
||||
onStepFinish()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ object HomeReducer {
|
|||
}
|
||||
|
||||
private fun internalReduce(action: Action, state: AppState): HomeState {
|
||||
|
||||
if (action !is HomeAction) return state.homeState
|
||||
|
||||
var state = state.homeState
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ class OnboardingManager(
|
|||
|
||||
return balance.copy(
|
||||
currency = Currency.Blockchain(
|
||||
walletManager.wallet.blockchain, walletManager.wallet.publicKey.derivationPath?.rawPath,
|
||||
blockchain = walletManager.wallet.blockchain,
|
||||
derivationPath = walletManager.wallet.publicKey.derivationPath?.rawPath,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
state.walletBalance.amountToCreateAccount?.let { amount ->
|
||||
val tvBodyMessage = getString(
|
||||
R.string.onboarding_top_up_body_no_account_error,
|
||||
amount, state.walletBalance.currency.currencySymbol,
|
||||
amount,
|
||||
state.walletBalance.currency.currencySymbol,
|
||||
)
|
||||
tvBody.text = tvBodyMessage
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,6 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
|
|||
requireContext().getDrawableCompat(R.drawable.shape_circle),
|
||||
)
|
||||
updateConstraints(R.layout.lp_onboarding_create_wallet)
|
||||
|
||||
}
|
||||
|
||||
private fun setupDoneState() = with(mainBinding.onboardingActionContainer) {
|
||||
|
|
|
|||
|
|
@ -121,9 +121,9 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
}
|
||||
}
|
||||
is TwinCardsAction.Wallet.HandleOnBackPressed -> {
|
||||
val shouldReturnCardBack = twinCardsState.mode == CreateTwinWalletMode.CreateWallet
|
||||
&& twinCardsState.currentStep != TwinCardsStep.TopUpWallet
|
||||
&& twinCardsState.currentStep != TwinCardsStep.Done
|
||||
val shouldReturnCardBack = twinCardsState.mode == CreateTwinWalletMode.CreateWallet &&
|
||||
twinCardsState.currentStep != TwinCardsStep.TopUpWallet &&
|
||||
twinCardsState.currentStep != TwinCardsStep.Done
|
||||
|
||||
if (twinCardsState.showAlert) {
|
||||
val onInterruptPrompt = {
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
//here we must use updated scanResponse after createWallet & derivation
|
||||
// here we must use updated scanResponse after createWallet & derivation
|
||||
val updatedResponse = globalState.onboardingState.onboardingManager.scanResponse.copy(
|
||||
card = result.data.card,
|
||||
derivedKeys = result.data.derivedKeys,
|
||||
|
|
@ -192,7 +192,8 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
}
|
||||
|
||||
private fun updateScanResponseAfterBackup(
|
||||
scanResponse: ScanResponse, backupState: BackupState,
|
||||
scanResponse: ScanResponse,
|
||||
backupState: BackupState,
|
||||
): ScanResponse {
|
||||
val card = if (backupState.backupCardsNumber > 0) {
|
||||
val cardsCount = backupState.backupCardsNumber
|
||||
|
|
|
|||
|
|
@ -35,31 +35,31 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingWallet
|
|||
}
|
||||
|
||||
private object ReducerForGlobalAction {
|
||||
fun reduce(action: GlobalAction.Onboarding, state: OnboardingWalletState): OnboardingWalletState {
|
||||
return when (action) {
|
||||
is GlobalAction.Onboarding.Start -> {
|
||||
OnboardingWalletState(
|
||||
backupState = state.backupState.copy(
|
||||
maxBackupCards = if (action.scanResponse.cardTypesResolver.isSaltPay()) 1 else 2,
|
||||
canSkipBackup =
|
||||
if (action.scanResponse.cardTypesResolver.isSaltPay()) false else action.canSkipBackup,
|
||||
),
|
||||
isSaltPay = action.scanResponse.cardTypesResolver.isSaltPay(),
|
||||
)
|
||||
}
|
||||
is GlobalAction.Onboarding.StartForUnfinishedBackup -> {
|
||||
OnboardingWalletState(
|
||||
backupState = state.backupState.copy(
|
||||
maxBackupCards = action.addedBackupCardsCount,
|
||||
canSkipBackup = false,
|
||||
),
|
||||
isSaltPay = false,
|
||||
)
|
||||
}
|
||||
else -> state
|
||||
fun reduce(action: GlobalAction.Onboarding, state: OnboardingWalletState): OnboardingWalletState {
|
||||
return when (action) {
|
||||
is GlobalAction.Onboarding.Start -> {
|
||||
OnboardingWalletState(
|
||||
backupState = state.backupState.copy(
|
||||
maxBackupCards = if (action.scanResponse.cardTypesResolver.isSaltPay()) 1 else 2,
|
||||
canSkipBackup =
|
||||
if (action.scanResponse.cardTypesResolver.isSaltPay()) false else action.canSkipBackup,
|
||||
),
|
||||
isSaltPay = action.scanResponse.cardTypesResolver.isSaltPay(),
|
||||
)
|
||||
}
|
||||
is GlobalAction.Onboarding.StartForUnfinishedBackup -> {
|
||||
OnboardingWalletState(
|
||||
backupState = state.backupState.copy(
|
||||
maxBackupCards = action.addedBackupCardsCount,
|
||||
canSkipBackup = false,
|
||||
),
|
||||
isSaltPay = false,
|
||||
)
|
||||
}
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object BackupReducer {
|
||||
@Suppress("ComplexMethod")
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ class UtorgWebChromeClient(
|
|||
if (!readyToShowFileChooser()) return false
|
||||
|
||||
val type: String
|
||||
if (fileChooserParams != null && fileChooserParams.acceptTypes != null
|
||||
&& fileChooserParams.acceptTypes.isNotEmpty()
|
||||
if (fileChooserParams != null && fileChooserParams.acceptTypes != null &&
|
||||
fileChooserParams.acceptTypes.isNotEmpty()
|
||||
) {
|
||||
type = if (!TextUtils.isEmpty(fileChooserParams.acceptTypes[0])) fileChooserParams.acceptTypes[0] else "*/*"
|
||||
this.filePathCallback = filePathCallback
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ object NoFundsForActivationDialog {
|
|||
return AlertDialog.Builder(context).apply {
|
||||
setTitle(R.string.saltpay_error_no_gas_title)
|
||||
setMessage(R.string.saltpay_error_no_gas_message)
|
||||
//TODO: SaltPay: change onboarding_supplement_button_kyc_waiting -> to appropriate string
|
||||
// TODO: SaltPay: change onboarding_supplement_button_kyc_waiting -> to appropriate string
|
||||
setPositiveButton(R.string.onboarding_supplement_button_kyc_waiting) { _, _ ->
|
||||
val config = store.state.globalState.configManager?.config?.saltPayConfig?.zendesk.guard {
|
||||
store.dispatchDebugErrorNotification("SaltPayConfig not initialized")
|
||||
|
|
|
|||
|
|
@ -36,4 +36,4 @@ sealed class OnboardingSaltPayAction : Action {
|
|||
data class SetStep(val newStep: SaltPayActivationStep) : OnboardingSaltPayAction()
|
||||
data class SetAmountToClaim(val amount: Amount?) : OnboardingSaltPayAction()
|
||||
data class SetTokenBalance(val balanceValue: BigDecimal) : OnboardingSaltPayAction()
|
||||
}
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ internal class OnboardingSaltPayView(
|
|||
}
|
||||
|
||||
private fun handleCardArtworks(state: OnboardingWalletState) = with(walletFragment.binding) {
|
||||
//TODO: SaltPay: remove hardCode
|
||||
// TODO: SaltPay: remove hardCode
|
||||
if (state.onboardingSaltPayState?.saltPayCardArtworkUrl == null) {
|
||||
imvFrontCard.load(R.drawable.img_salt_pay_visa) {
|
||||
scale(Scale.FILL)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ class BackupInfoAdapter : RecyclerView.Adapter<BackupInfoViewHolder>() {
|
|||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BackupInfoViewHolder =
|
||||
BackupInfoViewHolder(
|
||||
ItemBackupInfoAdapterBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -51,7 +53,7 @@ private val backupInfoSnippets = listOf(
|
|||
R.string.onboarding_wallet_info_subtitle_fourth
|
||||
),
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
class BackupInfoViewHolder(val binding: ItemBackupInfoAdapterBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
|
@ -78,7 +78,7 @@ class OnboardingWalletFragment : BaseFragment(R.layout.fragment_onboarding_walle
|
|||
binding.tabLayoutBackupInfo,
|
||||
binding.viewPagerBackupInfo,
|
||||
) { tab, position ->
|
||||
//Some implementation
|
||||
// Some implementation
|
||||
}.attach()
|
||||
|
||||
(activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar)
|
||||
|
|
@ -436,4 +436,4 @@ class OnboardingWalletFragment : BaseFragment(R.layout.fragment_onboarding_walle
|
|||
resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true)
|
||||
return typedValue.float
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +65,6 @@ class AccessCodeDialog(context: Context) : BottomSheetDialog(context) {
|
|||
store.dispatch(BackupAction.SaveAccessCodeConfirmation(etAccessCode.text.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun showError(error: AccessCodeError?) = with(binding!!.layoutBackupAccessCodeSubmit) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ object AddMoreBackupCardsDialog {
|
|||
store.dispatch(BackupAction.ShowAccessCodeInfoScreen)
|
||||
}
|
||||
setNegativeButton(R.string.common_cancel) { _, _ ->
|
||||
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ internal fun SaveWalletScreenContent(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun Header(onCloseClick: () -> Unit, ) {
|
||||
private fun Header(onCloseClick: () -> Unit) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
|
|
|
|||
|
|
@ -6,12 +6,17 @@ import com.tangem.common.services.Result
|
|||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.PayIdManager
|
||||
import com.tangem.tap.domain.isPayIdSupported
|
||||
import com.tangem.tap.features.send.redux.*
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerification.SetAddressError
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerification.SetWalletAddress
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification.SetPayIdError
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification.SetPayIdWalletAddress
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi
|
||||
import com.tangem.tap.features.send.redux.FeeAction
|
||||
import com.tangem.tap.features.send.redux.TransactionExtrasAction
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -129,7 +134,7 @@ internal class AddressPayIdMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
val supposedAddress = noSchemeAddress.removeShareUriQuery() //TODO: parse query?
|
||||
val supposedAddress = noSchemeAddress.removeShareUriQuery() // TODO: parse query?
|
||||
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, supposedAddress)
|
||||
if (failReason == null) {
|
||||
|
|
@ -167,7 +172,6 @@ internal class AddressPayIdMiddleware {
|
|||
val addressPayId = input ?: return
|
||||
val wallet = appState?.sendState?.walletManager?.wallet ?: return
|
||||
|
||||
|
||||
val internalDispatcher: (Action) -> Unit = {
|
||||
when (it) {
|
||||
is SetWalletAddress, is SetPayIdWalletAddress -> {
|
||||
|
|
@ -193,7 +197,7 @@ internal class AddressPayIdMiddleware {
|
|||
|
||||
fun String.splitToMap(firstDelimiter: String, secondDelimiter: String): Map<String, String> {
|
||||
return this.split(firstDelimiter)
|
||||
.map { it.split(secondDelimiter) }
|
||||
.map { it.first() to it.last().toString() }
|
||||
.toMap()
|
||||
.map { it.split(secondDelimiter) }
|
||||
.map { it.first() to it.last().toString() }
|
||||
.toMap()
|
||||
}
|
||||
|
|
@ -83,7 +83,8 @@ class SendMiddleware {
|
|||
if (transactionData != null) {
|
||||
store.dispatchOnMain(
|
||||
AddressPayIdVerifyAction.AddressVerification.SetWalletAddress(
|
||||
transactionData.destinationAddress, false,
|
||||
address = transactionData.destinationAddress,
|
||||
isUserInput = false,
|
||||
),
|
||||
)
|
||||
store.dispatchOnMain(AmountActionUi.SetMainCurrency(MainCurrencyType.CRYPTO))
|
||||
|
|
@ -104,7 +105,9 @@ class SendMiddleware {
|
|||
}
|
||||
|
||||
private fun verifyAndSendTransaction(
|
||||
action: SendActionUi.SendAmountToRecipient, appState: AppState?, dispatch: (Action) -> Unit,
|
||||
action: SendActionUi.SendAmountToRecipient,
|
||||
appState: AppState?,
|
||||
dispatch: (Action) -> Unit,
|
||||
) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
val walletManager = sendState.walletManager ?: return
|
||||
|
|
|
|||
|
|
@ -37,21 +37,21 @@ class AmountReducer : SendInternalReducer {
|
|||
val rescaledBalance = sendState.convertExtractCryptoToFiat(state.balanceCrypto, true)
|
||||
val viewValue = state.restoreDecimalSeparator(fiatToSend.stripZeroPlainString())
|
||||
state.copy(
|
||||
viewAmountValue = InputViewValue(viewValue),
|
||||
viewBalanceValue = rescaledBalance.stripZeroPlainString(),
|
||||
mainCurrency = state.createMainCurrency(currency, currencyCanBeSwitched),
|
||||
maxLengthOfAmount = sendState.getDecimals(currency),
|
||||
cursorAtTheSamePosition = false
|
||||
viewAmountValue = InputViewValue(viewValue),
|
||||
viewBalanceValue = rescaledBalance.stripZeroPlainString(),
|
||||
mainCurrency = state.createMainCurrency(currency, currencyCanBeSwitched),
|
||||
maxLengthOfAmount = sendState.getDecimals(currency),
|
||||
cursorAtTheSamePosition = false
|
||||
)
|
||||
}
|
||||
MainCurrencyType.CRYPTO -> {
|
||||
val viewValue = state.restoreDecimalSeparator(state.amountToSendCrypto.stripZeroPlainString())
|
||||
state.copy(
|
||||
viewAmountValue = InputViewValue(viewValue),
|
||||
viewBalanceValue = state.balanceCrypto.stripZeroPlainString(),
|
||||
mainCurrency = state.createMainCurrency(currency, currencyCanBeSwitched),
|
||||
maxLengthOfAmount = sendState.getDecimals(currency),
|
||||
cursorAtTheSamePosition = false
|
||||
viewAmountValue = InputViewValue(viewValue),
|
||||
viewBalanceValue = state.balanceCrypto.stripZeroPlainString(),
|
||||
mainCurrency = state.createMainCurrency(currency, currencyCanBeSwitched),
|
||||
maxLengthOfAmount = sendState.getDecimals(currency),
|
||||
cursorAtTheSamePosition = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -72,10 +72,10 @@ class AmountReducer : SendInternalReducer {
|
|||
}
|
||||
val viewValue = state.restoreDecimalSeparator(amount.stripZeroPlainString())
|
||||
state.copy(
|
||||
viewAmountValue = InputViewValue(viewValue, action.isUserInput),
|
||||
amountToSendCrypto = action.amountCrypto,
|
||||
cursorAtTheSamePosition = true,
|
||||
error = null
|
||||
viewAmountValue = InputViewValue(viewValue, action.isUserInput),
|
||||
amountToSendCrypto = action.amountCrypto,
|
||||
cursorAtTheSamePosition = true,
|
||||
error = null
|
||||
)
|
||||
}
|
||||
is AmountAction.SetAmountError -> state.copy(error = action.error)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue