diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3e26bcc1f8..f3691ec571 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -40,18 +40,24 @@ dependencies { implementation(deps.androidx.constraintLayout) implementation(deps.androidx.activity.compose) implementation(deps.androidx.browser) + implementation(deps.androidx.paging.runtime) implementation(deps.lifecycle.runtime.ktx) implementation(deps.lifecycle.common.java8) implementation(deps.lifecycle.viewModel.ktx) /** Compose libraries */ + implementation(deps.compose.constraintLayout) implementation(deps.compose.material) implementation(deps.compose.animation) + implementation(deps.compose.coil) + implementation(deps.compose.constraintLayout) implementation(deps.compose.foundation) + implementation(deps.compose.material) + implementation(deps.compose.navigation.hilt) + implementation(deps.compose.shimmer) implementation(deps.compose.ui) implementation(deps.compose.ui.tooling) - implementation(deps.compose.coil) - implementation(deps.compose.shimmer) + implementation(deps.compose.paging) /** Firebase libraries */ implementation(platform(deps.firebase.bom)) @@ -72,6 +78,7 @@ dependencies { kapt(deps.hilt.kapt) /** Other libraries */ + implementation(deps.kotlin.immutable.collections) implementation(deps.material) implementation(deps.googlePlay.core) implementation(deps.googlePlay.core.ktx) diff --git a/app/src/main/assets/testnet_tokens.json b/app/src/main/assets/testnet_tokens.json index f1f1b8ce59..8b227fde97 100644 --- a/app/src/main/assets/testnet_tokens.json +++ b/app/src/main/assets/testnet_tokens.json @@ -463,8 +463,5 @@ } ] } - ], - - "total" : 0, - "imageHost" : "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/" + ] } diff --git a/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt b/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt index 9664f38966..ecfb707001 100644 --- a/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt +++ b/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt @@ -59,8 +59,6 @@ class ForegroundActivityObserver : ActivityResultCaller { } } -fun ForegroundActivityObserver.withForegroundActivity( - block: (Activity) -> Unit -) { +fun ForegroundActivityObserver.withForegroundActivity(block: (Activity) -> Unit) { foregroundActivity?.let { block(it) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt index 6e620bd0bc..cef921c1d6 100644 --- a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt +++ b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt @@ -11,12 +11,7 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks class NavBarInsetsFragmentLifecycleCallback : FragmentLifecycleCallbacks() { - override fun onFragmentViewCreated( - fm: FragmentManager, - f: Fragment, - v: View, - savedInstanceState: Bundle?, - ) { + override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?) { if (v is ComposeView) return ViewCompat.setOnApplyWindowInsetsListener(v) { view, windowInsets -> diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index de10af7d92..87f540fc6b 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -49,6 +49,7 @@ import com.tangem.tap.domain.walletStores.repository.WalletManagersRepository import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository import com.tangem.tap.domain.walletStores.repository.di.provideDefaultImplementation import com.tangem.tap.domain.walletconnect.WalletConnectRepository +import com.tangem.tap.features.tokens.api.featuretoggles.TokensListFeatureToggles import com.tangem.tap.persistence.PreferencesStorage import com.tangem.tap.proxy.AppStateHolder import com.tangem.tap.proxy.redux.DaggerGraphAction @@ -126,6 +127,9 @@ class TapApplication : Application(), ImageLoaderFactory { @Inject lateinit var networkConnectionManager: NetworkConnectionManager + @Inject + lateinit var tokensListFeatureToggles: TokensListFeatureToggles + override fun onCreate() { super.onCreate() @@ -174,6 +178,7 @@ class TapApplication : Application(), ImageLoaderFactory { action = DaggerGraphAction.SetApplicationDependencies( assetReader = assetReader, networkConnectionManager = networkConnectionManager, + tokensListFeatureToggles = tokensListFeatureToggles, ), ) diff --git a/app/src/main/java/com/tangem/tap/common/CompositionCounter.kt b/app/src/main/java/com/tangem/tap/common/CompositionCounter.kt index 4e80061209..b09112d39f 100644 --- a/app/src/main/java/com/tangem/tap/common/CompositionCounter.kt +++ b/app/src/main/java/com/tangem/tap/common/CompositionCounter.kt @@ -4,7 +4,7 @@ import timber.log.Timber class CompositionCounter( val id: String, - count: Int = 0 + count: Int = 0, ) { var count: Int = count private set @@ -20,7 +20,7 @@ class CompositionCounter( class CompositionLogger( private val recomposeViewId: String, private val tag: String = recomposeViewId, - private var turnOnForIds: List = listOf(recomposeViewId) + private var turnOnForIds: List = listOf(recomposeViewId), ) { val count: Int get() = compositionCounter.count diff --git a/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt b/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt index 2f3e688532..3f6b858b3b 100644 --- a/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt @@ -10,7 +10,7 @@ import java.math.RoundingMode */ class CurrencyConverter( private val rateValue: BigDecimal, - private val decimals: Int + private val decimals: Int, ) { private val roundingMode = RoundingMode.HALF_UP diff --git a/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt b/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt index a30af0f5d6..b66ed0a3ad 100644 --- a/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt +++ b/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt @@ -13,7 +13,7 @@ class CustomTabsManager { .setDefaultColorSchemeParams( CustomTabColorSchemeParams.Builder() .setNavigationBarColor(context.getColorCompat(R.color.toolbarColor)) - .build() + .build(), ) .build() customTabsIntent.launchUrl(context, Uri.parse(url)) diff --git a/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt b/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt index a716d772fe..298bc14995 100644 --- a/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt @@ -9,7 +9,7 @@ import timber.log.Timber */ class GlobalLayoutStateHandler( private val view: T, - attachImmediately: Boolean = true + attachImmediately: Boolean = true, ) : ViewTreeObserver.OnGlobalLayoutListener { var onStateChanged: ((T) -> Unit)? = null diff --git a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkErrorMapper.kt b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkErrorMapper.kt index 56262664e7..0cfa1388be 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkErrorMapper.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkErrorMapper.kt @@ -14,14 +14,14 @@ 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() diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt index 874338b33b..46e02683ae 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt @@ -54,7 +54,7 @@ sealed class Token( object ShowWalletAddress : Token( category = "Token", - event = "Button - Show the Wallet Address" + event = "Button - Show the Wallet Address", ) sealed class Receive( diff --git a/app/src/main/java/com/tangem/tap/common/analytics/topup/TopUpController.kt b/app/src/main/java/com/tangem/tap/common/analytics/topup/TopUpController.kt index e17985be26..42d9e80686 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/topup/TopUpController.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/topup/TopUpController.kt @@ -116,10 +116,7 @@ class TopUpController( } } - fun send( - scanResponse: ScanResponse, - cardBalanceState: AnalyticsParam.CardBalanceState, - ) { + fun send(scanResponse: ScanResponse, cardBalanceState: AnalyticsParam.CardBalanceState) { UserWalletIdBuilder.scanResponse(scanResponse).build()?.let { send(it, cardBalanceState, scanResponse.cardTypesResolver) } diff --git a/app/src/main/java/com/tangem/tap/common/compose/Button.kt b/app/src/main/java/com/tangem/tap/common/compose/Button.kt index c536af17bd..ee94c8b15b 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/Button.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/Button.kt @@ -8,10 +8,7 @@ import androidx.compose.runtime.CompositionLocalProvider * Used for disable ripple if button is enable = false */ @Composable -fun ToggledRippleTheme( - isEnabled: Boolean, - content: @Composable () -> Unit, -) { +fun ToggledRippleTheme(isEnabled: Boolean, content: @Composable () -> Unit) { val theme = LocalRippleTheme provides if (isEnabled) LocalRippleTheme.current else NoRippleTheme() CompositionLocalProvider(theme) { content() } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/compose/ComposeDialogManager.kt b/app/src/main/java/com/tangem/tap/common/compose/ComposeDialogManager.kt index 8d0de7df69..7afe67bf43 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/ComposeDialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/ComposeDialogManager.kt @@ -53,16 +53,22 @@ fun ComposeDialogManager() { ShowTheDialog(dialogSate) - LaunchedEffect(key1 = Unit, block = { - domainStore.subscribe(subscriber) { state -> - state.skipRepeats { oldState, newState -> - oldState.globalState == newState.globalState - }.select { it.globalState } - } - }) - DisposableEffect(key1 = Unit, effect = { - onDispose { domainStore.unsubscribe(subscriber) } - }) + LaunchedEffect( + key1 = Unit, + block = { + domainStore.subscribe(subscriber) { state -> + state.skipRepeats { oldState, newState -> + oldState.globalState == newState.globalState + }.select { it.globalState } + } + }, + ) + DisposableEffect( + key1 = Unit, + effect = { + onDispose { domainStore.unsubscribe(subscriber) } + }, + ) } @Composable @@ -77,7 +83,7 @@ private fun ShowTheDialog(dialogState: MutableState) { is DomainDialog.DialogError -> ErrorDialog( title = stringResource(id = R.string.common_error), body = errorConverter.convert(dialog.error).message, - onDismissRequest + onDismissRequest, ) is DomainDialog.SelectTokenDialog -> SelectTokenNetworkDialog(dialog, onDismissRequest) else -> {} @@ -97,14 +103,14 @@ fun SimpleDialog( ) { Dialog( properties = DialogProperties(false, false), - onDismissRequest = { } + onDismissRequest = { }, ) { Surface( modifier = Modifier.fillMaxWidth(), - shape = MaterialTheme.shapes.medium + shape = MaterialTheme.shapes.medium, ) { Column( - modifier = Modifier.padding(22.dp) + modifier = Modifier.padding(22.dp), ) { DialogTitle(title = title) LazyColumn { @@ -133,19 +139,15 @@ private fun DialogTitle(title: String) { style = LocalTextStyle.provides( TextStyle( fontWeight = FontWeight.Bold, - fontSize = 20.sp - ) - ).value + fontSize = 20.sp, + ), + ).value, ) SpacerH16() } @Composable -fun ErrorDialog( - title: String, - body: String, - onDismissRequest: () -> Unit, -) { +fun ErrorDialog(title: String, body: String, onDismissRequest: () -> Unit) { AlertDialog( title = { DialogTitle(title) }, text = { Text(body) }, @@ -154,6 +156,6 @@ fun ErrorDialog( Button(onClick = onDismissRequest) { Text(text = stringResource(id = R.string.common_ok)) } - } + }, ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt b/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt index c8d0701b2e..90928c9d15 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt @@ -15,11 +15,7 @@ import androidx.compose.ui.unit.dp [REDACTED_AUTHOR] */ @Composable -fun ErrorView( - text: String, - modifier: Modifier = Modifier, - style: TextStyle = LocalTextStyle.current, -) { +fun ErrorView(text: String, modifier: Modifier = Modifier, style: TextStyle = LocalTextStyle.current) { Text( text, color = MaterialTheme.colors.error, diff --git a/app/src/main/java/com/tangem/tap/common/compose/OutlinedTextFieldWidget.kt b/app/src/main/java/com/tangem/tap/common/compose/OutlinedTextFieldWidget.kt index 113dbfb809..59cf01d88c 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/OutlinedTextFieldWidget.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/OutlinedTextFieldWidget.kt @@ -213,10 +213,7 @@ private fun OutlinedProgressTextField( } @Composable -private fun AnimatedErrorView( - errorConverter: ModuleMessageConverter, - error: ModuleError? = null, -) { +private fun AnimatedErrorView(errorConverter: ModuleMessageConverter, error: ModuleError? = null) { AnimatedVisibility( visible = error != null, enter = fadeIn() + slideInVertically(), diff --git a/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt b/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt index f742bb5731..41e5637ba1 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt @@ -110,10 +110,7 @@ fun PinCodeWidget( } @Composable -private fun PinElement( - config: PinViewConfig, - pinSymbol: String, -) { +private fun PinElement(config: PinViewConfig, pinSymbol: String) { Box(Modifier.padding(config.pinBoxPadding)) { Box(config.pinBoxModifier) { Text( diff --git a/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt b/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt index 694fd8c376..945ffc182f 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt @@ -128,11 +128,7 @@ internal data class TangemTextFieldColors( } @Composable - override fun labelColor( - enabled: Boolean, - error: Boolean, - interactionSource: InteractionSource, - ): State { + override fun labelColor(enabled: Boolean, error: Boolean, interactionSource: InteractionSource): State { val focused by interactionSource.collectIsFocusedAsState() val targetValue = when { diff --git a/app/src/main/java/com/tangem/tap/common/compose/Undefined.kt b/app/src/main/java/com/tangem/tap/common/compose/Undefined.kt index 10e2ec9956..d5e5168be3 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/Undefined.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/Undefined.kt @@ -12,16 +12,13 @@ import androidx.compose.ui.unit.sp */ @Composable -fun TitleSubtitle( - title: String, - subtitle: String -) { +fun TitleSubtitle(title: String, subtitle: String) { Column { Text(text = title) Text( text = subtitle, fontSize = 12.sp, - color = Color.Gray + color = Color.Gray, ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/compose/Warning.kt b/app/src/main/java/com/tangem/tap/common/compose/Warning.kt index ea4d150e51..6d4a79d192 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/Warning.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/Warning.kt @@ -21,11 +21,7 @@ import com.tangem.wallet.R [REDACTED_AUTHOR] */ @Composable -fun AddCustomTokenWarning( - warning: ModuleMessage, - converter: ModuleMessageConverter, - modifier: Modifier = Modifier, -) { +fun AddCustomTokenWarning(warning: ModuleMessage, converter: ModuleMessageConverter, modifier: Modifier = Modifier) { Surface( modifier = modifier, shape = MaterialTheme.shapes.small, @@ -39,14 +35,14 @@ fun AddCustomTokenWarning( text = stringResource(id = R.string.common_warning), color = colorResource(id = R.color.white), fontSize = 14.sp, - fontWeight = FontWeight.Bold + fontWeight = FontWeight.Bold, ) SpacerH8() Text( text = converter.convert(warning).message, color = colorResource(id = R.color.white), fontSize = 13.sp, - lineHeight = 18.sp + lineHeight = 18.sp, ) } } diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt index 1952c6a058..b21726c8e7 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt @@ -1,6 +1,10 @@ package com.tangem.tap.common.compose.extensions -import androidx.compose.animation.core.* +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.AnimationVector1D +import androidx.compose.animation.core.Easing +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.tween import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember @@ -41,8 +45,8 @@ fun animatable( targetValue = values.second, animationSpec = tween( durationMillis = duration, - easing = easing - ) + easing = easing, + ), ) } } diff --git a/app/src/main/java/com/tangem/tap/common/entities/Button.kt b/app/src/main/java/com/tangem/tap/common/entities/Button.kt index d9ff2b27f8..b873b7ef3e 100644 --- a/app/src/main/java/com/tangem/tap/common/entities/Button.kt +++ b/app/src/main/java/com/tangem/tap/common/entities/Button.kt @@ -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 diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Activity.kt b/app/src/main/java/com/tangem/tap/common/extensions/Activity.kt index 5f531a9bc8..adf3e19fed 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Activity.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Activity.kt @@ -22,7 +22,7 @@ fun Activity.sendEmail( subject: String, message: String, file: File? = null, - onFail: ((Exception) -> Unit)? = null + onFail: ((Exception) -> Unit)? = null, ) { fun createEmailShareIntent(recipient: String, subject: String, text: String, file: File? = null): Intent { val builder = ShareCompat.IntentBuilder.from(this) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Context.kt b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt index 556f261f46..db544c0297 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Context.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt @@ -8,8 +8,7 @@ import android.net.Uri import androidx.annotation.AnyRes import androidx.core.content.ContextCompat -fun Context.readFile(fileName: String): String = - this.openFileInput(fileName).bufferedReader().readText() +fun Context.readFile(fileName: String): String = this.openFileInput(fileName).bufferedReader().readText() fun Context.rewriteFile(content: String, fileName: String) { this.openFileOutput(fileName, Context.MODE_PRIVATE).use { diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Map.kt b/app/src/main/java/com/tangem/tap/common/extensions/Map.kt index e970306219..313c83ff03 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Map.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Map.kt @@ -1,4 +1,3 @@ package com.tangem.tap.common.extensions -fun Map.filterNotNull(): Map = - filter { it.key != null && it.value != null } as Map \ No newline at end of file +fun Map.filterNotNull(): Map = filter { it.key != null && it.value != null } as Map \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt index 0755764b78..f6e77e9af9 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt @@ -27,10 +27,13 @@ import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.shop.ui.ShopFragment import com.tangem.tap.features.tokens.addCustomToken.AddCustomTokenFragment import com.tangem.tap.features.tokens.presentation.AddTokensFragment +import com.tangem.tap.features.tokens.presentation.TokensListFragment import com.tangem.tap.features.wallet.ui.WalletDetailsFragment import com.tangem.tap.features.wallet.ui.WalletFragment import com.tangem.tap.features.walletSelector.ui.WalletSelectorBottomSheetFragment import com.tangem.tap.features.welcome.ui.WelcomeFragment +import com.tangem.tap.proxy.redux.DaggerGraphState +import com.tangem.tap.store import com.tangem.wallet.R import timber.log.Timber @@ -107,7 +110,12 @@ private fun fragmentFactory(screen: AppScreen): Fragment { AppScreen.AppSettings -> AppSettingsFragment() AppScreen.ResetToFactory -> ResetCardFragment() AppScreen.Disclaimer -> DisclaimerFragment() - AppScreen.AddTokens -> AddTokensFragment() + AppScreen.AddTokens -> { + val featureToggles = store.state.daggerGraphState.get( + getDependency = DaggerGraphState::tokensListFeatureToggles, + ) + if (featureToggles.isRedesignedScreenEnabled) TokensListFragment() else AddTokensFragment() + } AppScreen.AddCustomToken -> AddCustomTokenFragment() AppScreen.WalletDetails -> WalletDetailsFragment() AppScreen.WalletConnectSessions -> WalletConnectFragment() diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt index ff4f898d8d..632a28fe81 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt @@ -46,9 +46,7 @@ fun BigDecimal.toFormattedCurrencyString( return "$formattedAmount $currency" } -fun BigDecimal.toFiatRateString( - fiatCurrencyName: String, -): String { +fun BigDecimal.toFiatRateString(fiatCurrencyName: String): String { val value = this .setScale(2, RoundingMode.HALF_UP) .formatWithSpaces() @@ -69,10 +67,7 @@ fun BigDecimal.toFiatValue(rateValue: BigDecimal): BigDecimal { return fiatValue.setScale(2, RoundingMode.HALF_UP) } -fun BigDecimal.toFormattedFiatValue( - fiatCurrencyName: String, - formatWithSpaces: Boolean = false, -): String { +fun BigDecimal.toFormattedFiatValue(fiatCurrencyName: String, formatWithSpaces: Boolean = false): String { val fiatValue = this.setScale(2, RoundingMode.HALF_UP) .let { if (formatWithSpaces) it.formatWithSpaces() else it } return " $fiatValue $fiatCurrencyName" diff --git a/app/src/main/java/com/tangem/tap/common/extensions/String.kt b/app/src/main/java/com/tangem/tap/common/extensions/String.kt index 3c4125d422..911bd470a1 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/String.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/String.kt @@ -25,12 +25,7 @@ fun String?.ellipsizeBeforeSpace(allowedSize: Int): String { newString.substring(startIndex until newString.length) } -fun String.colorSegment( - context: Context, - color: Int, - startIndex: Int = 0, - endIndex: Int = this.length, -): Spannable { +fun String.colorSegment(context: Context, color: Int, startIndex: Int = 0, endIndex: Int = this.length): Spannable { return this.toSpannable() .also { spannable -> spannable.setSpan( diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt b/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt index 69fbba97b6..d1e6b742f5 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt @@ -10,7 +10,7 @@ inline fun Transition.addListener( crossinline onEnd: (animator: Transition) -> Unit = {}, crossinline onCancel: (animator: Transition) -> Unit = {}, crossinline onPause: (animator: Transition) -> Unit = {}, - crossinline onRepeat: (animator: Transition) -> Unit = {} + crossinline onRepeat: (animator: Transition) -> Unit = {}, ): Transition.TransitionListener { val listener = object : Transition.TransitionListener { override fun onTransitionStart(transition: Transition) = onStart(transition) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt index 807d2baa56..980f206701 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt @@ -83,12 +83,11 @@ 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, - ).toInt() +fun Context.dpToPixels(dp: Int): Int = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp.toFloat(), + this.resources.displayMetrics, +).toInt() tailrec fun Context?.getActivity(): Activity? = this as? Activity ?: (this as? ContextWrapper)?.baseContext?.getActivity() diff --git a/app/src/main/java/com/tangem/tap/common/images/Coil.kt b/app/src/main/java/com/tangem/tap/common/images/Coil.kt index 4e5a88d6e0..b7305e86dc 100644 --- a/app/src/main/java/com/tangem/tap/common/images/Coil.kt +++ b/app/src/main/java/com/tangem/tap/common/images/Coil.kt @@ -10,10 +10,7 @@ import timber.log.Timber private const val COIL_LOG_TAG = "COIL" -fun createCoilImageLoader( - context: Context, - logEnabled: Boolean = false, -): ImageLoader { +fun createCoilImageLoader(context: Context, logEnabled: Boolean = false): ImageLoader { return ImageLoader.Builder(context) .apply { if (!logEnabled) return@apply @@ -27,7 +24,7 @@ fun createCoilImageLoader( } .apply { level = HttpLoggingInterceptor.Level.BODY - } + }, ) .build() } diff --git a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt b/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt index 4a86caa20d..f132cd319b 100644 --- a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt +++ b/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt @@ -54,7 +54,9 @@ class ScanQrCodeActivity : AppCompatActivity(), ZXingScannerView.ResultHandler { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { val cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) cameraPermission == PackageManager.PERMISSION_GRANTED - } else true + } else { + true + } } private fun requestPermission() { diff --git a/app/src/main/java/com/tangem/tap/common/recyclerView/SpaceItemDecoration.kt b/app/src/main/java/com/tangem/tap/common/recyclerView/SpaceItemDecoration.kt index cb8ea5186f..4ea08ea19e 100644 --- a/app/src/main/java/com/tangem/tap/common/recyclerView/SpaceItemDecoration.kt +++ b/app/src/main/java/com/tangem/tap/common/recyclerView/SpaceItemDecoration.kt @@ -12,17 +12,12 @@ class SpaceItemDecoration( private lateinit var space: Space - override fun getItemOffsets( - outRect: Rect, - view: View, - parent: RecyclerView, - state: RecyclerView.State - ) { + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { if (state.itemCount == 0) return if (!::space.isInitialized) { space = Space( view.dpToPx(horizontalSpaceDp).toInt(), - view.dpToPx(verticalSpaceDp).toInt() + view.dpToPx(verticalSpaceDp).toInt(), ) } diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt index 9685dd54b7..335228e10f 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt @@ -5,6 +5,7 @@ import android.content.Intent import com.google.android.gms.wallet.PaymentData import com.shopify.buy3.Storefront import com.tangem.core.analytics.Analytics +import com.tangem.datasource.config.models.ShopifyShop import com.tangem.tap.common.analytics.converters.ShopOrderToEventConverter import com.tangem.tap.common.extensions.filterNotNull import com.tangem.tap.common.shop.data.ProductType @@ -12,7 +13,6 @@ import com.tangem.tap.common.shop.data.TangemProduct import com.tangem.tap.common.shop.data.TotalSum import com.tangem.tap.common.shop.googlepay.GooglePayService import com.tangem.tap.common.shop.shopify.ShopifyService -import com.tangem.datasource.config.models.ShopifyShop import com.tangem.tap.common.shop.shopify.data.CheckoutItem import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -106,11 +106,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { // } // } - suspend fun handleGooglePayResult( - resultCode: Int, - data: Intent?, - productType: ProductType, - ): Result { + suspend fun handleGooglePayResult(resultCode: Int, data: Intent?, productType: ProductType): Result { val result = googlePayService.handleResponseFromGooglePay(resultCode, data) result.onSuccess { val finalizePaymentResult = completeTokenizedPayment(it, productType) diff --git a/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt b/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt index d8db451147..4238b4d883 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt @@ -4,7 +4,8 @@ import com.tangem.tap.common.shop.TangemShopService enum class ProductType(val sku: String) { WALLET_2_CARDS(TangemShopService.TANGEM_WALLET_2_CARDS_SKU), - WALLET_3_CARDS(TangemShopService.TANGEM_WALLET_3_CARDS_SKU); + WALLET_3_CARDS(TangemShopService.TANGEM_WALLET_3_CARDS_SKU), + ; companion object { fun fromSku(sku: String): ProductType? { diff --git a/app/src/main/java/com/tangem/tap/common/shop/data/TangemProduct.kt b/app/src/main/java/com/tangem/tap/common/shop/data/TangemProduct.kt index 022af2b4ea..79eb72e1f1 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/data/TangemProduct.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/data/TangemProduct.kt @@ -3,5 +3,5 @@ package com.tangem.tap.common.shop.data data class TangemProduct( val type: ProductType, val totalSum: TotalSum? = null, - val appliedDiscount: String? = null + val appliedDiscount: String? = null, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayUtil.kt b/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayUtil.kt index 82509e1180..1e5cfba714 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayUtil.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayUtil.kt @@ -94,11 +94,7 @@ object GooglePayUtil { } } - private fun getTransactionInfo( - price: String, - countryCode: String, - currencyCode: String, - ): JSONObject { + private fun getTransactionInfo(price: String, countryCode: String, currencyCode: String): JSONObject { return JSONObject().apply { put("totalPrice", price) put("totalPriceStatus", "FINAL") diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt index 71081fc7b1..0f7cfdf42b 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt @@ -106,10 +106,7 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop } } - suspend fun createCheckout( - checkoutItems: List, - checkoutID: ID? = null, - ): Result { + suspend fun createCheckout(checkoutItems: List, checkoutID: ID? = null): Result { val storefrontLineItems: MutableList = checkoutItems .map { CheckoutLineItemInput(it.quantity, it.id) }.toMutableList() @@ -197,10 +194,7 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop return runCheckoutMutation(query) } - suspend fun completeWithTokenizedPayment( - payment: TokenizedPaymentInputV3, - checkoutID: ID, - ): Result { + suspend fun completeWithTokenizedPayment(payment: TokenizedPaymentInputV3, checkoutID: ID): Result { val query = mutation { mutationQuery: MutationQuery -> mutationQuery .checkoutCompleteWithTokenizedPaymentV3( @@ -247,25 +241,21 @@ class ShopifyService(private val application: Application, val shop: ShopifyShop private suspend fun queryAsync( query: QueryRootQuery, retryHandler: RetryHandler, - ): GraphCallResult = - withContext(Dispatchers.IO) { - suspendCoroutine { continuation -> - client.queryGraph(query).enqueue(retryHandler = retryHandler) { result -> - continuation.resume(result) - } + ): GraphCallResult = withContext(Dispatchers.IO) { + suspendCoroutine { continuation -> + client.queryGraph(query).enqueue(retryHandler = retryHandler) { result -> + continuation.resume(result) } } + } - private suspend fun queryAsync( - query: QueryRootQuery, - ): GraphCallResult = - withContext(Dispatchers.IO) { - suspendCoroutine { continuation -> - client.queryGraph(query).enqueue { result -> - continuation.resume(result) - } + private suspend fun queryAsync(query: QueryRootQuery): GraphCallResult = withContext(Dispatchers.IO) { + suspendCoroutine { continuation -> + client.queryGraph(query).enqueue { result -> + continuation.resume(result) } } + } private suspend fun mutationQueryAsync(query: MutationQuery): GraphCallResult = withContext(Dispatchers.IO) { diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/CheckoutItem.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/data/CheckoutItem.kt index 5dc508df40..6d16e66908 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/CheckoutItem.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/shopify/data/CheckoutItem.kt @@ -4,5 +4,5 @@ import com.shopify.graphql.support.ID data class CheckoutItem( val id: ID, - val quantity: Int + val quantity: Int, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt b/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt index d224143c98..b540a9d7c2 100644 --- a/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt +++ b/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt @@ -18,14 +18,14 @@ import com.tangem.wallet.R */ class MaxAmountSnackbar( parent: ViewGroup, - content: MaxAmountSnackbarView + content: MaxAmountSnackbarView, ) : BaseTransientBottomBar(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 @@ -63,7 +63,7 @@ class MaxAmountSnackbar( class MaxAmountSnackbarView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, - defStyleAttr: Int = 0 + defStyleAttr: Int = 0, ) : ConstraintLayout(context, attrs, defStyleAttr), ContentViewCallback { init { diff --git a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt index d66ac2ed73..16565ff5a6 100644 --- a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt @@ -11,15 +11,13 @@ import java.util.* class PayIdManager { @Suppress("MagicNumber") - suspend fun verifyPayId( - payId: String, - blockchain: Blockchain, - ): Result = withContext(Dispatchers.IO) { - val splitPayId = payId.split("\$") - val user = splitPayId[0] - val baseUrl = "https://${splitPayId[1]}/" - return@withContext PayIdVerifyService(baseUrl).verifyAddress(user, blockchain.getPayIdNetwork()) - } + suspend fun verifyPayId(payId: String, blockchain: Blockchain): Result = + withContext(Dispatchers.IO) { + val splitPayId = payId.split("\$") + val user = splitPayId[0] + val baseUrl = "https://${splitPayId[1]}/" + return@withContext PayIdVerifyService(baseUrl).verifyAddress(user, blockchain.getPayIdNetwork()) + } private fun Blockchain.getPayIdNetwork(): String { return when (this) { @@ -30,8 +28,10 @@ class PayIdManager { } companion object { - 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() + 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 = EnumSet.of( Blockchain.XRP, diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index 3b13e7243e..36e5dcebdf 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -82,9 +82,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co ).also { sendScanResultsToAnalytics(it) } } - suspend fun createProductWallet( - scanResponse: ScanResponse, - ): CompletionResult { + suspend fun createProductWallet(scanResponse: ScanResponse): CompletionResult { return runTaskAsync( CreateProductWalletTask(scanResponse.cardTypesResolver), scanResponse.card.cardId, @@ -92,9 +90,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co ) } - private fun sendScanResultsToAnalytics( - result: CompletionResult, - ) { + private fun sendScanResultsToAnalytics(result: CompletionResult) { if (result is CompletionResult.Failure) { (result.error as? TangemSdkError)?.let { error -> Analytics.send(Basic.ScanError(error)) @@ -194,14 +190,13 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co cardId: String? = null, initialMessage: Message? = null, accessCode: String? = null, - ): CompletionResult = - withContext(Dispatchers.Main) { - suspendCancellableCoroutine { continuation -> - tangemSdk.startSessionWithRunnable(runnable, cardId, initialMessage, accessCode) { result -> - if (continuation.isActive) continuation.resume(result) - } + ): CompletionResult = withContext(Dispatchers.Main) { + suspendCancellableCoroutine { continuation -> + tangemSdk.startSessionWithRunnable(runnable, cardId, initialMessage, accessCode) { result -> + if (continuation.isActive) continuation.resume(result) } } + } private suspend fun runTaskAsyncReturnOnMain( runnable: CardSessionRunnable, @@ -226,9 +221,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co return context.getString(stringResId, *formatArgs) } - fun setAccessCodeRequestPolicy( - useBiometricsForAccessCode: Boolean, - ) { + fun setAccessCodeRequestPolicy(useBiometricsForAccessCode: Boolean) { tangemSdk.config.userCodeRequestPolicy = if (useBiometricsForAccessCode) { UserCodeRequestPolicy.AlwaysWithBiometrics(codeType = UserCodeType.AccessCode) } else { diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt index d9e3f1aa97..196ec2f0f4 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt @@ -53,10 +53,7 @@ class TangemSigner( } } - override suspend fun sign( - hash: ByteArray, - publicKey: Wallet.PublicKey, - ): CompletionResult { + override suspend fun sign(hash: ByteArray, publicKey: Wallet.PublicKey): CompletionResult { val result = sign( hashes = listOf(hash), publicKey = publicKey, diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt index 9800be1707..a36e254ee7 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt @@ -19,7 +19,7 @@ data class WarningMessage( val origin: Origin = Origin.Remote, @StringRes val buttonTextId: Int? = null, val titleFormatArg: String? = null, - val messageFormatArg: String? = null + val messageFormatArg: String? = null, ) { val blockchainList: List? by lazy { blockchains?.map { Blockchain.fromId(it.uppercase()) } @@ -35,7 +35,7 @@ data class WarningMessage( Warning, @Json(name = "info") - Info + Info, } enum class Type { @@ -47,7 +47,7 @@ data class WarningMessage( AppRating, - TestCard + TestCard, } enum class Location { @@ -55,7 +55,7 @@ data class WarningMessage( MainScreen, @Json(name = "send") - SendScreen + SendScreen, } enum class Origin { diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt index 996032f7d6..9d908f0724 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt @@ -107,7 +107,7 @@ class WarningMessagesManager { messageResId = R.string.warning_signed_tx_previously, origin = WarningMessage.Origin.Local, buttonTextId = R.string.warning_button_learn_more, - titleFormatArg = "\u26A0" + titleFormatArg = "\u26A0", ) fun appRatingWarning(): WarningMessage = WarningMessage( diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt b/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt index 59647cbde5..5298777226 100644 --- a/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt +++ b/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt @@ -92,10 +92,7 @@ private fun getDerivationParams(derivationPath: String?, card: CardDTO): Derivat } } -fun WalletManagerFactory.makeWalletManagerForApp( - scanResponse: ScanResponse, - currency: Currency, -): WalletManager? { +fun WalletManagerFactory.makeWalletManagerForApp(scanResponse: ScanResponse, currency: Currency): WalletManager? { return makeWalletManagerForApp( scanResponse, blockchain = currency.blockchain, @@ -112,9 +109,7 @@ fun WalletManagerFactory.makeWalletManagersForApp( .mapNotNull { this.makeWalletManagerForApp(scanResponse, it) } } -fun WalletManagerFactory.makePrimaryWalletManager( - scanResponse: ScanResponse, -): WalletManager? { +fun WalletManagerFactory.makePrimaryWalletManager(scanResponse: ScanResponse): WalletManager? { val blockchain = if (scanResponse.card.isTestCard) { scanResponse.cardTypesResolver.getBlockchain().getTestnetVersion() ?: return null } else { diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt index 6a3b71d604..70b7f005b5 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt @@ -21,7 +21,9 @@ class UserWalletIdBuilder private constructor( } else { publicKey } - } else null + } else { + null + } return seed?.let { UserWalletId(value = calculateUserWalletId(it)) @@ -34,7 +36,9 @@ class UserWalletIdBuilder private constructor( return if (keyHash != null) { message.calculateHmacSha256(keyHash) - } else null + } else { + null + } } companion object { diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt index 565f8fb826..921e8ccc3e 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt @@ -34,10 +34,7 @@ interface WalletStoreBuilder { return BlockchainNetworkWalletStoreBuilderImpl(userWallet, blockchainNetwork) } - operator fun invoke( - userWallet: UserWallet, - walletManager: WalletManager, - ): WalletMangerWalletStoreBuilder { + operator fun invoke(userWallet: UserWallet, walletManager: WalletManager): WalletMangerWalletStoreBuilder { return WalletMangerWalletStoreBuilderImpl(userWallet, walletManager) } } @@ -161,10 +158,7 @@ private fun Blockchain.toBlockchainWalletData(walletManager: WalletManager): Wal ) } -private fun Token.toTokenWalletData( - walletManager: WalletManager, - primaryToken: Token?, -): WalletDataModel { +private fun Token.toTokenWalletData(walletManager: WalletManager, primaryToken: Token?): WalletDataModel { val wallet = walletManager.wallet return WalletDataModel( currency = Currency.Token( diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt index facfc3d62e..7e0f77f2d1 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt @@ -99,10 +99,7 @@ object ScanCardProcessor { } } - private fun sendAnalytics( - analyticsEvent: AnalyticsEvent?, - scanResponse: ScanResponse, - ) { + private fun sendAnalytics(analyticsEvent: AnalyticsEvent?, scanResponse: ScanResponse) { analyticsEvent?.let { // this workaround needed to send CardWasScannedEvent without adding a context val interceptor = CardContextInterceptor(scanResponse) @@ -257,10 +254,7 @@ object ScanCardProcessor { } } - private suspend inline fun navigateTo( - screen: AppScreen, - onProgressStateChange: (showProgress: Boolean) -> Unit, - ) { + private suspend inline fun navigateTo(screen: AppScreen, onProgressStateChange: (showProgress: Boolean) -> Unit) { delay(DELAY_SDK_DIALOG_CLOSE) store.dispatchOnMain(NavigationAction.NavigateTo(screen)) onProgressStateChange(false) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt index 5c39928f88..260736b303 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt @@ -28,7 +28,7 @@ class CreateWalletsTask(curves: List? = null) : CardSessionRunnab private fun createWallet( curve: EllipticCurve, session: CardSession, - callback: (result: CompletionResult) -> Unit + callback: (result: CompletionResult) -> Unit, ) { CreateWalletTask(curve).run(session) { result -> when (result) { diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt index 3e5d37ac4b..d3b749658c 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt @@ -23,11 +23,15 @@ class SignHashTask( when (response) { is CompletionResult.Success -> { - callback(CompletionResult.Success(TangemSignHashResponse( - response.data.signature, - response.data.totalSignedHashes, - session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures - ))) + callback( + CompletionResult.Success( + TangemSignHashResponse( + response.data.signature, + response.data.totalSignedHashes, + session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures, + ), + ), + ) } is CompletionResult.Failure -> callback(CompletionResult.Failure(response.error)) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt index 4d25a1de56..3a8a5bd48c 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt @@ -22,11 +22,15 @@ class SignHashesTask( SignHashesCommand(hashes.toTypedArray(), publicKey.seedKey, publicKey.derivationPath).run(session) { response -> when (response) { is CompletionResult.Success -> { - callback(CompletionResult.Success(TangemSignHashesResponse( - response.data.signatures, - response.data.totalSignedHashes, - session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures - ))) + callback( + CompletionResult.Success( + TangemSignHashesResponse( + response.data.signatures, + response.data.totalSignedHashes, + session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures, + ), + ), + ) } is CompletionResult.Failure -> callback(CompletionResult.Failure(response.error)) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt index 7bbd4d1811..eeed6d4ad6 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt @@ -267,10 +267,7 @@ private class CreateWalletTangemWallet : ProductCommandProcessor { + private fun getBlockchains(cardId: String, card: CardDTO): List { return when { DemoHelper.isDemoCardId(cardId) -> DemoHelper.config.demoBlockchains card.isTestCard -> listOf(Blockchain.BitcoinTestnet, Blockchain.EthereumTestnet) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateWalletsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateWalletsTask.kt index da0e18e914..6c41807de9 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateWalletsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateWalletsTask.kt @@ -13,7 +13,7 @@ import com.tangem.operations.wallet.CreateWalletTask [REDACTED_AUTHOR] */ class CreateWalletsResponse( - val createWalletResponses: List + val createWalletResponses: List, ) : CommandResponse class CreateWalletsTask( @@ -35,7 +35,7 @@ class CreateWalletsTask( private fun createWallet( curve: EllipticCurve, session: CardSession, - callback: (result: CompletionResult) -> Unit + callback: (result: CompletionResult) -> Unit, ) { CreateWalletTask(curve).run(session) { result -> when (result) { diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ProductCommandProcessor.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ProductCommandProcessor.kt index 8b9d8d9d2f..474bbd49dd 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ProductCommandProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ProductCommandProcessor.kt @@ -8,9 +8,5 @@ import com.tangem.domain.common.CardDTO [REDACTED_AUTHOR] */ interface ProductCommandProcessor { - fun proceed( - card: CardDTO, - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) + fun proceed(card: CardDTO, session: CardSession, callback: (result: CompletionResult) -> Unit) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt index 398f369a54..1ab2b50b69 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt @@ -14,10 +14,7 @@ class ResetToFactorySettingsTask : CardSessionRunnable { deleteWallets(session, callback) } - private fun deleteWallets( - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { + private fun deleteWallets(session: CardSession, callback: (result: CompletionResult) -> Unit) { val wallet = session.environment.card?.wallets?.lastOrNull().guard { resetBackup(session, callback) return @@ -33,10 +30,7 @@ class ResetToFactorySettingsTask : CardSessionRunnable { } } - private fun resetBackup( - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { + private fun resetBackup(session: CardSession, callback: (result: CompletionResult) -> Unit) { val backupStatus = session.environment.card?.backupStatus if (backupStatus == null || backupStatus == Card.BackupStatus.NoBackup) { callback(CompletionResult.Success(session.environment.card!!)) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 8dde976a16..00ca32c553 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -52,10 +52,7 @@ class ScanProductTask( override val allowsRequestAccessCodeFromRepository: Boolean = false, ) : CardSessionRunnable { - override fun run( - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { + override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val card = this.card ?: session.environment.card.guard { callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) return diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt index 28bcdc9c35..f4c06f518a 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt @@ -5,10 +5,7 @@ import com.tangem.common.card.FirmwareVersion import com.tangem.domain.common.CardDTO object CurrenciesRepository { - fun getBlockchains( - cardFirmware: CardDTO.FirmwareVersion, - isTestNet: Boolean = false, - ): List { + fun getBlockchains(cardFirmware: CardDTO.FirmwareVersion, isTestNet: Boolean = false): List { val blockchains = if (cardFirmware < FirmwareVersion.MultiWalletAvailable) { Blockchain.secp256k1Blockchains(isTestNet) } else { @@ -23,7 +20,7 @@ object CurrenciesRepository { removeAll( listOf( // Any blockchain - ) + ), ) } } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt b/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt index c70127f7e2..2cb1488c24 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt @@ -10,20 +10,20 @@ data class CurrencyFromJson( val id: String, val name: String, val symbol: String, - val networks: List? = null + val networks: List? = null, ) @JsonClass(generateAdapter = true) data class ContractFromJson( val networkId: String, val contractAddress: String?, - val decimalCount: Int? + val decimalCount: Int?, ) @JsonClass(generateAdapter = true) data class CurrenciesFromJson( val imageHost: String?, - val coins: List + val coins: List, ) fun List.toContracts(): List { @@ -35,7 +35,7 @@ data class Currency( val name: String, val symbol: String, val iconUrl: String, - val contracts: List + val contracts: List, ) { companion object { @@ -45,7 +45,7 @@ data class Currency( name = currency.name, symbol = currency.symbol, iconUrl = getIconUrl(currency.id, null), - contracts = currency.networks?.toContracts() ?: emptyList() + contracts = currency.networks?.toContracts() ?: emptyList(), ) } @@ -55,7 +55,7 @@ data class Currency( name = currency.name, symbol = currency.symbol, iconUrl = getIconUrl(currency.id, imageHost), - contracts = currency.networks.mapNotNull { Contract.fromNetwork(it, imageHost) } + contracts = currency.networks.mapNotNull { Contract.fromNetwork(it, imageHost) }, ) } } @@ -77,7 +77,7 @@ data class Contract( blockchain = blockchain, address = contract.contractAddress, decimalCount = contract.decimalCount, - iconUrl = getIconUrl(contract.networkId, null) + iconUrl = getIconUrl(contract.networkId, null), ) } @@ -88,7 +88,7 @@ data class Contract( blockchain = blockchain, address = contract.contractAddress, decimalCount = contract.decimalCount?.toInt(), - iconUrl = getIconUrl(contract.networkId, imageHost) + iconUrl = getIconUrl(contract.networkId, imageHost), ) } } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt b/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt index 51c4c304e2..39e845f7b2 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt @@ -20,10 +20,10 @@ class LoadAvailableCoinsService( MoshiConverter.networkMoshi.adapter(CurrenciesFromJson::class.java) suspend fun getSupportedTokens( - isTestNet: Boolean = false, + isTestNet: Boolean, supportedBlockchains: List, page: Int, - searchInput: String? = null, + searchInput: String?, ): Result { if (isTestNet) { return Result.Success( @@ -33,15 +33,17 @@ class LoadAvailableCoinsService( ), ) } - val offset = page * LOAD_PER_PAGE - val result = loadCoins(supportedBlockchains, offset, searchInput) - return when (result) { + val offset = page * LOAD_PER_PAGE + return when (val result = loadCoins(supportedBlockchains, offset, searchInput)) { is Result.Success -> { val data = result.data + Result.Success( LoadedCoins( - currencies = data.coins.map { Currency.fromCoinResponse(it, data.imageHost) }, + currencies = data.coins.map { + Currency.fromCoinResponse(currency = it, imageHost = data.imageHost) + }, moreAvailable = data.total > offset + LOAD_PER_PAGE, ), ) @@ -55,22 +57,24 @@ class LoadAvailableCoinsService( private suspend fun loadCoins( supportedBlockchains: List, offset: Int, - searchInput: String? = null, + searchInput: String?, ): Result { return withContext(dispatchers.io) { runCatching { tangemTechApi.getCoins( - networkIds = supportedBlockchains.toSet().joinToString(",", transform = Blockchain::toNetworkId), + networkIds = supportedBlockchains.joinToString( + separator = ",", + transform = Blockchain::toNetworkId, + ), active = true, searchText = searchInput, offset = offset, limit = LOAD_PER_PAGE, ) - } - .onSuccess { return@withContext Result.Success(it) } - .onFailure { return@withContext Result.Failure(it) } - - error("Unreachable code because runCatching must return result") + }.fold( + onSuccess = { Result.Success(it) }, + onFailure = { Result.Failure(it) }, + ) } } @@ -83,15 +87,15 @@ class LoadAvailableCoinsService( private fun List.filter(searchInput: String?): List { if (searchInput.isNullOrBlank()) return this - return filter { - it.symbol.contains(searchInput, ignoreCase = true) || - it.name.contains(searchInput, ignoreCase = true) + return filter { currency -> + currency.symbol.contains(searchInput, ignoreCase = true) || + currency.name.contains(searchInput, ignoreCase = true) } } - companion object { + private companion object { const val LOAD_PER_PAGE = 100 - private const val FILE_NAME_TESTNET_COINS = "testnet_tokens" + const val FILE_NAME_TESTNET_COINS = "testnet_tokens" } } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt b/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt index 3ac6babc72..6c60dfbc89 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/converters/CurrencyConverter.kt @@ -15,6 +15,6 @@ object CurrencyConverter : Converter { name = value.currencyName, symbol = value.currencySymbol, decimals = value.decimals, - contractAddress = if (value is Currency.Token) value.token.contractAddress else null + contractAddress = if (value is Currency.Token) value.token.contractAddress else null, ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/models/ObsoleteTokenDao.kt b/app/src/main/java/com/tangem/tap/domain/tokens/models/ObsoleteTokenDao.kt index 19d8bbf73d..5ff4d8c8ca 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/models/ObsoleteTokenDao.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/models/ObsoleteTokenDao.kt @@ -18,7 +18,7 @@ data class ObsoleteTokenDao( contractAddress = contractAddress, decimalCount = decimalCount, blockchainDao = BlockchainDao.fromBlockchain(blockchain), - customIconUrl = customIconUrl + customIconUrl = customIconUrl, ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/models/TokenDao.kt b/app/src/main/java/com/tangem/tap/domain/tokens/models/TokenDao.kt index ef6f541f6e..a70e0606b3 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/models/TokenDao.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/models/TokenDao.kt @@ -14,7 +14,7 @@ data class TokenDao( @Json(name = "blockchain") val blockchainDao: BlockchainDao, val customIconUrl: String? = null, - val type: String? = null + val type: String? = null, ) { fun toToken(): Token { return Token( diff --git a/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt index 28016d704f..35d535aa53 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt @@ -13,10 +13,7 @@ class CreateFirstTwinWalletTask(private val firstCardId: String) : CardSessionRu override val allowsRequestAccessCodeFromRepository: Boolean = false - override fun run( - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { + override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val card = session.environment.card val publicKey = card?.wallets?.firstOrNull()?.publicKey if (publicKey != null) { diff --git a/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt index b173602e3d..127c10ec33 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt @@ -16,10 +16,7 @@ class FinalizeTwinTask( override val allowsRequestAccessCodeFromRepository: Boolean = false - override fun run( - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { + override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { WriteProtectedIssuerDataTask(twinPublicKey, issuerKeys).run(session) { result -> when (result) { is CompletionResult.Success -> diff --git a/app/src/main/java/com/tangem/tap/domain/twins/WriteProtectedIssuerDataTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/WriteProtectedIssuerDataTask.kt index 2a415c6eda..7eae636918 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/WriteProtectedIssuerDataTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/WriteProtectedIssuerDataTask.kt @@ -19,10 +19,7 @@ class WriteProtectedIssuerDataTask( private val issuerKeys: KeyPair, ) : CardSessionRunnable { - override fun run( - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { + override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { SignHashCommand( twinPublicKey.calculateSha256(), session.environment.card!!.wallets.first().publicKey, diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultSelectedUserWalletRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultSelectedUserWalletRepository.kt index ec44dbd914..6efa84fc70 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultSelectedUserWalletRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultSelectedUserWalletRepository.kt @@ -25,6 +25,6 @@ internal class DefaultSelectedUserWalletRepository( } private enum class StorageKey { - SelectedWalletId + SelectedWalletId, } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt index 7d1bd9333b..ab64d4a5fb 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt @@ -73,9 +73,7 @@ internal class DefaultUserWalletsPublicInformationRepository( } @JvmName("saveWithPublicInformation") - private suspend fun save( - publicInformation: List, - ): CompletionResult = catching { + private suspend fun save(publicInformation: List): CompletionResult = catching { withContext(Dispatchers.IO) { publicInformation .let(publicInformationAdapter::toJson) @@ -85,6 +83,6 @@ internal class DefaultUserWalletsPublicInformationRepository( } private enum class StorageKey { - UserWalletPublicInformation + UserWalletPublicInformation, } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt index 3cbf04ac4e..631d8d13c6 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt @@ -148,10 +148,7 @@ internal class DefaultUserWalletsSensitiveInformationRepository( } } - private suspend fun ByteArray.getIvAndDecrypt( - userWalletId: String, - encryptionKey: ByteArray, - ): ByteArray? { + private suspend fun ByteArray.getIvAndDecrypt(userWalletId: String, encryptionKey: ByteArray): ByteArray? { return withContext(Dispatchers.Default) { val iv = secureStorage.get(StorageKey.SensitiveInformationIv(userWalletId).name) ?: error("IV not found") diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt index 7d8170895c..4c7784a50a 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt @@ -50,7 +50,9 @@ internal fun UserWallet.updateWith(sensitiveInformation: UserWalletSensitiveInfo internal fun List.updateWith( walletIdToSensitiveInformation: Map, ): List { - return if (walletIdToSensitiveInformation.isEmpty()) this else { + return if (walletIdToSensitiveInformation.isEmpty()) { + this + } else { this.map { wallet -> walletIdToSensitiveInformation[wallet.walletId] ?.let(wallet::updateWith) diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/ByteArrayKeyAdapter.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/ByteArrayKeyAdapter.kt index 889438c346..cae2c47666 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/ByteArrayKeyAdapter.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/ByteArrayKeyAdapter.kt @@ -9,19 +9,12 @@ import com.tangem.common.extensions.ByteArrayKey internal class ByteArrayKeyAdapter { @ToJson - fun toJson( - writer: JsonWriter, - src: ByteArrayKey, - byteArrayAdapter: JsonAdapter, - ) { + fun toJson(writer: JsonWriter, src: ByteArrayKey, byteArrayAdapter: JsonAdapter) { byteArrayAdapter.toJson(writer, src.bytes) } @FromJson - fun fromJson( - reader: JsonReader, - byteArrayAdapter: JsonAdapter, - ): ByteArrayKey? { + fun fromJson(reader: JsonReader, byteArrayAdapter: JsonAdapter): ByteArrayKey? { return byteArrayAdapter.fromJson(reader)?.let { ByteArrayKey(bytes = it) } diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/CardBackupStatusAdapter.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/CardBackupStatusAdapter.kt index 419fd22dbf..2f7e2544f5 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/CardBackupStatusAdapter.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/json/CardBackupStatusAdapter.kt @@ -9,11 +9,7 @@ import com.tangem.domain.common.CardDTO internal class CardBackupStatusAdapter { @ToJson - fun toJson( - writer: JsonWriter, - src: CardDTO.BackupStatus?, - mapAdapter: JsonAdapter>, - ) { + fun toJson(writer: JsonWriter, src: CardDTO.BackupStatus?, mapAdapter: JsonAdapter>) { val jsonMap = mutableMapOf() when (src) { @@ -37,10 +33,7 @@ internal class CardBackupStatusAdapter { } @FromJson - fun fromJson( - reader: JsonReader, - mapAdapter: JsonAdapter>, - ): CardDTO.BackupStatus? { + fun fromJson(reader: JsonReader, mapAdapter: JsonAdapter>): CardDTO.BackupStatus? { val map = mapAdapter.fromJson(reader) ?: return null return when (map["status"]) { diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt index fa2bbc0424..f56949a1be 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt @@ -16,10 +16,7 @@ interface WalletCurrenciesManager { * * @return [CompletionResult] of operation * */ - suspend fun update( - userWallet: UserWallet, - currency: Currency, - ): CompletionResult + suspend fun update(userWallet: UserWallet, currency: Currency): CompletionResult /** * Add list of [Currency] to [UserWallet]. @@ -32,10 +29,7 @@ interface WalletCurrenciesManager { * * @return [CompletionResult] of operation * */ - suspend fun addCurrencies( - userWallet: UserWallet, - currenciesToAdd: List, - ): CompletionResult + suspend fun addCurrencies(userWallet: UserWallet, currenciesToAdd: List): CompletionResult /** * Remove [Currency] from [UserWallet] @@ -48,10 +42,7 @@ interface WalletCurrenciesManager { * * @return [CompletionResult] of operation * */ - suspend fun removeCurrency( - userWallet: UserWallet, - currencyToRemove: Currency, - ): CompletionResult + suspend fun removeCurrency(userWallet: UserWallet, currencyToRemove: Currency): CompletionResult /** * Remove list of [Currency] from [UserWallet] @@ -64,10 +55,7 @@ interface WalletCurrenciesManager { * * @return [CompletionResult] of operation * */ - suspend fun removeCurrencies( - userWallet: UserWallet, - currenciesToRemove: List, - ): CompletionResult + suspend fun removeCurrencies(userWallet: UserWallet, currenciesToRemove: List): CompletionResult /** * Add a callback [Listener] diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt index d32bdd60ff..2281fbfe5f 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt @@ -33,29 +33,27 @@ internal class DefaultWalletCurrenciesManager( private val listeners = mutableListOf() - override suspend fun update( - userWallet: UserWallet, - currency: Currency, - ): CompletionResult = withContext(Dispatchers.Default) { - listeners.forEach { it.willUpdate(userWallet, currency) } - val walletStore = walletStoresRepository.getSync(userWallet.walletId) - .find { - it.blockchain == currency.blockchain && - it.derivationPath?.rawPath == currency.derivationPath - } + override suspend fun update(userWallet: UserWallet, currency: Currency): CompletionResult = + withContext(Dispatchers.Default) { + listeners.forEach { it.willUpdate(userWallet, currency) } + val walletStore = walletStoresRepository.getSync(userWallet.walletId) + .find { + it.blockchain == currency.blockchain && + it.derivationPath?.rawPath == currency.derivationPath + } - val updateResult = if (walletStore == null) { - CompletionResult.Success(Unit) - } else { - walletAmountsRepository.updateAmountsForWalletStore( - walletStore = walletStore, - userWallet = userWallet, - fiatCurrency = appCurrencyProvider(), - ) + val updateResult = if (walletStore == null) { + CompletionResult.Success(Unit) + } else { + walletAmountsRepository.updateAmountsForWalletStore( + walletStore = walletStore, + userWallet = userWallet, + fiatCurrency = appCurrencyProvider(), + ) + } + listeners.forEach { it.didUpdate(userWallet, currency) } + updateResult } - listeners.forEach { it.didUpdate(userWallet, currency) } - updateResult - } override suspend fun addCurrencies( userWallet: UserWallet, @@ -110,10 +108,7 @@ internal class DefaultWalletCurrenciesManager( } } - override suspend fun removeCurrency( - userWallet: UserWallet, - currencyToRemove: Currency, - ): CompletionResult { + override suspend fun removeCurrency(userWallet: UserWallet, currencyToRemove: Currency): CompletionResult { listeners.forEach { it.willCurrencyRemove(userWallet, currencyToRemove) } return removeCurrencies(userWallet, listOf(currencyToRemove)) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt index e4bebc2c07..503bfe5cc0 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt @@ -49,10 +49,7 @@ interface WalletStoresManager { * * @return [CompletionResult] of operation * */ - suspend fun fetch( - userWallet: UserWallet, - refresh: Boolean = false, - ): CompletionResult + suspend fun fetch(userWallet: UserWallet, refresh: Boolean = false): CompletionResult /** * Fetch wallet stores associated with provided [UserWallet]s. Fetched [WalletStoreModel]s updates can be observed @@ -63,10 +60,7 @@ interface WalletStoresManager { * * @return [CompletionResult] of operation * */ - suspend fun fetch( - userWallets: List, - refresh: Boolean = false, - ): CompletionResult + suspend fun fetch(userWallets: List, refresh: Boolean = false): CompletionResult /** * Update [WalletStoreModel]s amounts associated with provided [UserWallet]s @@ -75,9 +69,7 @@ interface WalletStoresManager { * * @return [CompletionResult] of operation * */ - suspend fun updateAmounts( - userWallets: List, - ): CompletionResult + suspend fun updateAmounts(userWallets: List): CompletionResult // For provider companion object diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt index 00f000f14d..e6abbc56c7 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt @@ -58,38 +58,35 @@ internal class DefaultWalletStoresManager( return walletStoresRepository.clear() } - override suspend fun fetch( - userWallets: List, - refresh: Boolean, - ): CompletionResult = withContext(Dispatchers.Default) { - val fiatCurrency = appCurrencyProvider.invoke() - val isFiatCurrencyChanged = state.value.fiatCurrency != fiatCurrency + override suspend fun fetch(userWallets: List, refresh: Boolean): CompletionResult = + withContext(Dispatchers.Default) { + val fiatCurrency = appCurrencyProvider.invoke() + val isFiatCurrencyChanged = state.value.fiatCurrency != fiatCurrency - state.update { prevState -> - prevState.copy( - fiatCurrency = fiatCurrency, - ) + state.update { prevState -> + prevState.copy( + fiatCurrency = fiatCurrency, + ) + } + + userWallets + .mapNotNull { userWallet -> + val hasNotWalletStoresForUserWallet = !walletStoresRepository.contains(userWallet.walletId) + if (refresh || hasNotWalletStoresForUserWallet || isFiatCurrencyChanged) { + fetchWalletsIfNeeded(userWallet) + } else { + null + } + } + .fold(arrayListOf()) { acc, data -> + acc.apply { add(data) } + } + .flatMap { + walletAmountsRepository.updateAmountsForUserWallets(it, fiatCurrency) + } } - userWallets - .mapNotNull { userWallet -> - val hasNotWalletStoresForUserWallet = !walletStoresRepository.contains(userWallet.walletId) - if (refresh || hasNotWalletStoresForUserWallet || isFiatCurrencyChanged) { - fetchWalletsIfNeeded(userWallet) - } else null - } - .fold(arrayListOf()) { acc, data -> - acc.apply { add(data) } - } - .flatMap { - walletAmountsRepository.updateAmountsForUserWallets(it, fiatCurrency) - } - } - - override suspend fun fetch( - userWallet: UserWallet, - refresh: Boolean, - ): CompletionResult { + override suspend fun fetch(userWallet: UserWallet, refresh: Boolean): CompletionResult { return fetch(listOf(userWallet), refresh) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt index a054ed0ff2..924bbb5191 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt @@ -24,10 +24,7 @@ interface WalletAmountsRepository { * @param userWallet [UserWallet] which will be used to get the list of associated [WalletStoreModel] * @param fiatCurrency current app [FiatCurrency] * */ - suspend fun updateAmountsForUserWallet( - userWallet: UserWallet, - fiatCurrency: FiatCurrency, - ): CompletionResult + suspend fun updateAmountsForUserWallet(userWallet: UserWallet, fiatCurrency: FiatCurrency): CompletionResult suspend fun updateAmountsForWalletStores( walletStores: List, diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletManagersRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletManagersRepository.kt index 0d8a2044be..c49f863277 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletManagersRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletManagersRepository.kt @@ -17,10 +17,7 @@ interface WalletManagersRepository { suspend fun delete(userWalletIds: List): CompletionResult - suspend fun delete( - userWalletId: UserWalletId, - blockchain: Blockchain, - ): CompletionResult + suspend fun delete(userWalletId: UserWalletId, blockchain: Blockchain): CompletionResult companion object } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletStoresRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletStoresRepository.kt index 9e8a8a9287..8359759a0a 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletStoresRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletStoresRepository.kt @@ -22,10 +22,7 @@ interface WalletStoresRepository { suspend fun clear(): CompletionResult - suspend fun storeOrUpdate( - userWalletId: UserWalletId, - walletStore: WalletStoreModel, - ): CompletionResult + suspend fun storeOrUpdate(userWalletId: UserWalletId, walletStore: WalletStoreModel): CompletionResult companion object } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt index d2936d9dcc..30de69eec5 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt @@ -160,21 +160,19 @@ internal class DefaultWalletAmountsRepository( } } - private suspend fun fetchAmountsForUserWallets( - userWallets: List, - ): CompletionResult = withContext(Dispatchers.Default) { - userWallets.map { async { fetchAmountsForUserWallet(it) } }.awaitAll().fold() - } + private suspend fun fetchAmountsForUserWallets(userWallets: List): CompletionResult = + withContext(Dispatchers.Default) { + userWallets.map { async { fetchAmountsForUserWallet(it) } }.awaitAll().fold() + } - private suspend fun fetchAmountsForUserWallet( - userWallet: UserWallet, - ): CompletionResult = withContext(Dispatchers.Default) { - val userWalletId = userWallet.walletId - val scanResponse = userWallet.scanResponse - val walletStores = getWalletStores(listOf(userWallet)) + private suspend fun fetchAmountsForUserWallet(userWallet: UserWallet): CompletionResult = + withContext(Dispatchers.Default) { + val userWalletId = userWallet.walletId + val scanResponse = userWallet.scanResponse + val walletStores = getWalletStores(listOf(userWallet)) - fetchAmountForWalletStores(userWalletId, scanResponse, walletStores) - } + fetchAmountForWalletStores(userWalletId, scanResponse, walletStores) + } private suspend fun fetchAmountForWalletStores( userWalletId: UserWalletId, @@ -286,7 +284,9 @@ internal class DefaultWalletAmountsRepository( rent = rentProvider.rentAmount(), exemptionAmount = rentExempt, ) - } else null, + } else { + null + }, ) } is Failure -> Unit @@ -295,39 +295,36 @@ internal class DefaultWalletAmountsRepository( return CompletionResult.Success(Unit) } - private suspend fun updateWalletStoreWithError( - walletStore: WalletStoreModel, - wallet: Wallet, - error: TangemError, - ) = withContext(Dispatchers.Default) { - Timber.e( - error, - """ + private suspend fun updateWalletStoreWithError(walletStore: WalletStoreModel, wallet: Wallet, error: TangemError) = + withContext(Dispatchers.Default) { + Timber.e( + error, + """ Unable to fetch amounts |- User wallet id: ${walletStore.userWalletId} |- Blockchain: ${walletStore.blockchain} |- Derivation path: ${walletStore.derivationPath?.rawPath} - """.trimIndent(), - ) + """.trimIndent(), + ) - if (error is BlockchainSdkError) { - WalletStoresStorage.update { prevState -> - prevState.replaceWalletStore( - walletStoreToUpdate = walletStore, - update = { - it.updateWithError( - wallet = wallet, - error = error, - ) - }, - ) + if (error is BlockchainSdkError) { + WalletStoresStorage.update { prevState -> + prevState.replaceWalletStore( + walletStoreToUpdate = walletStore, + update = { + it.updateWithError( + wallet = wallet, + error = error, + ) + }, + ) + } + + CompletionResult.Success(Unit) + } else { + CompletionResult.Failure(error) } - - CompletionResult.Success(Unit) - } else { - CompletionResult.Failure(error) } - } private suspend fun updateWalletStoreWithAmounts( walletStore: WalletStoreModel, @@ -359,53 +356,51 @@ internal class DefaultWalletAmountsRepository( CompletionResult.Success(Unit) } - private suspend fun updateWalletStoreWithMissedDerivation( - walletStore: WalletStoreModel, - ) = withContext(Dispatchers.Default) { - Timber.e( - """ + private suspend fun updateWalletStoreWithMissedDerivation(walletStore: WalletStoreModel) = + withContext(Dispatchers.Default) { + Timber.e( + """ Missed derivation |- User wallet id: ${walletStore.userWalletId} |- Blockchain: ${walletStore.blockchain} |- Derivation path: ${walletStore.derivationPath?.rawPath} - """.trimIndent(), - ) - - WalletStoresStorage.update { prevState -> - prevState.replaceWalletStore( - walletStoreToUpdate = walletStore, - update = { - it.updateWithMissedDerivation() - }, + """.trimIndent(), ) + + WalletStoresStorage.update { prevState -> + prevState.replaceWalletStore( + walletStoreToUpdate = walletStore, + update = { + it.updateWithMissedDerivation() + }, + ) + } + + CompletionResult.Success(Unit) } - CompletionResult.Success(Unit) - } - - private suspend fun updateWalletStoreWithUnreachable( - walletStore: WalletStoreModel, - ) = withContext(Dispatchers.Default) { - Timber.e( - """ + private suspend fun updateWalletStoreWithUnreachable(walletStore: WalletStoreModel) = + withContext(Dispatchers.Default) { + Timber.e( + """ Wallet manager is null |- User wallet id: ${walletStore.userWalletId} |- Blockchain: ${walletStore.blockchain} |- Derivation path: ${walletStore.derivationPath?.rawPath} - """.trimIndent(), - ) - - WalletStoresStorage.update { prevState -> - prevState.replaceWalletStore( - walletStoreToUpdate = walletStore, - update = { - it.updateWithUnreachable() - }, + """.trimIndent(), ) - } - CompletionResult.Success(Unit) - } + WalletStoresStorage.update { prevState -> + prevState.replaceWalletStore( + walletStoreToUpdate = walletStore, + update = { + it.updateWithUnreachable() + }, + ) + } + + CompletionResult.Success(Unit) + } private suspend fun updateWalletStoresWithFiatRates( walletStores: List, @@ -428,48 +423,44 @@ internal class DefaultWalletAmountsRepository( } } - private suspend fun updateWalletStoreWithRent( - walletStore: WalletStoreModel, - rent: WalletStoreModel.WalletRent?, - ) = withContext(Dispatchers.Default) { - Timber.d( - """ + private suspend fun updateWalletStoreWithRent(walletStore: WalletStoreModel, rent: WalletStoreModel.WalletRent?) = + withContext(Dispatchers.Default) { + Timber.d( + """ Fetched wallet rent |- User wallet id: ${walletStore.userWalletId} |- Blockchain: ${walletStore.blockchain} |- Derivation path: ${walletStore.derivationPath?.rawPath} |- Rent: $rent - """.trimIndent(), - ) + """.trimIndent(), + ) - if (rent != walletStore.walletRent) { - WalletStoresStorage.update { prevState -> - prevState.replaceWalletStore( - walletStoreToUpdate = walletStore, - update = { - it.updateWithRent(rent) - }, - ) - } - } - } - - private suspend fun updateWalletManagerInStorage( - userWalletId: UserWalletId, - walletManager: WalletManager, - ) = withContext(Dispatchers.Default) { - WalletManagerStorage.update { prevManagers -> - val newManagersForUserWallet = prevManagers[userWalletId].orEmpty().toMutableList().apply { - replaceByOrAdd(walletManager) { - it.wallet.blockchain == walletManager.wallet.blockchain + if (rent != walletStore.walletRent) { + WalletStoresStorage.update { prevState -> + prevState.replaceWalletStore( + walletStoreToUpdate = walletStore, + update = { + it.updateWithRent(rent) + }, + ) } } + } - prevManagers.apply { - set(userWalletId, newManagersForUserWallet) + private suspend fun updateWalletManagerInStorage(userWalletId: UserWalletId, walletManager: WalletManager) = + withContext(Dispatchers.Default) { + WalletManagerStorage.update { prevManagers -> + val newManagersForUserWallet = prevManagers[userWalletId].orEmpty().toMutableList().apply { + replaceByOrAdd(walletManager) { + it.wallet.blockchain == walletManager.wallet.blockchain + } + } + + prevManagers.apply { + set(userWalletId, newManagersForUserWallet) + } } } - } private suspend fun getWalletStores(userWallets: List): List { return userWallets.map { it.walletId }.flatMap { userWalletId -> diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt index c7848db278..a09ea7abd2 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt @@ -125,10 +125,7 @@ internal class DefaultWalletManagersRepository( } } - override suspend fun delete( - userWalletId: UserWalletId, - blockchain: Blockchain, - ): CompletionResult = catching { + override suspend fun delete(userWalletId: UserWalletId, blockchain: Blockchain): CompletionResult = catching { deleteInternal(userWalletId, blockchain) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt index 4346396f56..849aad6056 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt @@ -14,17 +14,13 @@ import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.getPendingTransactions import java.math.BigDecimal -internal fun WalletDataModel.updateWithFiatRate( - fiatRate: BigDecimal?, -): WalletDataModel { +internal fun WalletDataModel.updateWithFiatRate(fiatRate: BigDecimal?): WalletDataModel { return this.copy( fiatRate = fiatRate, ) } -internal fun List.updateWithFiatRates( - fiatRates: Map, -): List { +internal fun List.updateWithFiatRates(fiatRates: Map): List { return this.map { walletData -> val rate = fiatRates[walletData.currency.coinId]?.toBigDecimal() walletData.updateWithFiatRate(rate) @@ -40,9 +36,7 @@ internal fun WalletDataModel.updateWithTxHistory(wallet: Wallet): WalletDataMode ) } -internal fun List.updateWithTxHistories( - wallet: Wallet, -): List { +internal fun List.updateWithTxHistories(wallet: Wallet): List { return this.map { walletData -> walletData.updateWithTxHistory(wallet) } @@ -114,10 +108,7 @@ internal fun List.updateWithDemoAmounts(wallet: Wallet): List { @@ -141,18 +132,13 @@ internal fun WalletDataModel.updateWithError( ) } -internal fun List.updateWithError( - wallet: Wallet, - error: TangemError, -): List { +internal fun List.updateWithError(wallet: Wallet, error: TangemError): List { return this.map { walletData -> walletData.updateWithError(wallet, error) } } -internal fun WalletDataModel.updateWithSelf( - newWalletData: WalletDataModel, -): WalletDataModel { +internal fun WalletDataModel.updateWithSelf(newWalletData: WalletDataModel): WalletDataModel { val oldWalletData = this val oldStatus = oldWalletData.status return oldWalletData.copy( @@ -191,9 +177,7 @@ internal fun List.updateWithUnreachable(): List.updateWithSelf( - newWalletsData: List, -): List { +internal fun List.updateWithSelf(newWalletsData: List): List { val oldWalletsData = this val updatedWalletsData = arrayListOf() diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt index efcd36e402..f77470a6f0 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt @@ -29,10 +29,7 @@ internal inline fun HashMap>.replaceWalletS } } -internal fun WalletStoreModel.updateWithError( - wallet: Wallet, - error: TangemError, -): WalletStoreModel { +internal fun WalletStoreModel.updateWithError(wallet: Wallet, error: TangemError): WalletStoreModel { return this.copy( walletsData = walletsData.updateWithError( wallet = wallet, @@ -41,41 +38,31 @@ internal fun WalletStoreModel.updateWithError( ) } -internal fun WalletStoreModel.updateWithTxHistories( - wallet: Wallet, -): WalletStoreModel { +internal fun WalletStoreModel.updateWithTxHistories(wallet: Wallet): WalletStoreModel { return this.copy( walletsData = walletsData.updateWithTxHistories(wallet = wallet), ) } -internal fun WalletStoreModel.updateWithAmounts( - wallet: Wallet, -): WalletStoreModel { +internal fun WalletStoreModel.updateWithAmounts(wallet: Wallet): WalletStoreModel { return this.copy( walletsData = walletsData.updateWithAmounts(wallet = wallet), ) } -internal fun WalletStoreModel.updateWithDemoAmounts( - wallet: Wallet, -): WalletStoreModel { +internal fun WalletStoreModel.updateWithDemoAmounts(wallet: Wallet): WalletStoreModel { return this.copy( walletsData = walletsData.updateWithDemoAmounts(wallet = wallet), ) } -internal fun WalletStoreModel.updateWithFiatRates( - rates: Map, -): WalletStoreModel { +internal fun WalletStoreModel.updateWithFiatRates(rates: Map): WalletStoreModel { return this.copy( walletsData = walletsData.updateWithFiatRates(rates), ) } -internal fun WalletStoreModel.updateWithSelf( - newWalletStore: WalletStoreModel, -): WalletStoreModel { +internal fun WalletStoreModel.updateWithSelf(newWalletStore: WalletStoreModel): WalletStoreModel { val oldStore = this return oldStore.copy( derivationPath = newWalletStore.derivationPath, diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt index 8759dc91d4..1cae897360 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt @@ -287,11 +287,7 @@ class WalletConnectManager { } } - fun signBnb( - id: Long, - data: ByteArray, - sessionData: WCSession, - ) { + fun signBnb(id: Long, data: ByteArray, sessionData: WCSession) { val activeData = sessions[sessionData] ?: return scope.launch { val hash = WalletConnectSdkHelper().signBnbTransaction(data, activeData, cardId).guard { @@ -307,11 +303,7 @@ class WalletConnectManager { } } - fun handlePersonalSignRequest( - message: WCEthereumSignMessage, - session: WalletConnectSession, - id: Long, - ) { + fun handlePersonalSignRequest(message: WCEthereumSignMessage, session: WalletConnectSession, id: Long) { val activeData = sessions[session.session] ?: return scope.launch { val data = WalletConnectSdkHelper().prepareDataForPersonalSign( diff --git a/app/src/main/java/com/tangem/tap/features/BaseFragment.kt b/app/src/main/java/com/tangem/tap/features/BaseFragment.kt index fe5c9a3926..cf8be74484 100644 --- a/app/src/main/java/com/tangem/tap/features/BaseFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/BaseFragment.kt @@ -71,10 +71,13 @@ interface FragmentOnBackPressedHandler { @SuppressLint("FragmentBackPressedCallback") fun Fragment.addBackPressHandler(handler: FragmentOnBackPressedHandler) { - activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - handler.handleOnBackPressed() - } - }) + activity?.onBackPressedDispatcher?.addCallback( + this, + object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + handler.handleOnBackPressed() + } + }, + ) view?.findViewById(R.id.toolbar)?.setNavigationOnClickListener { activity?.onBackPressed() } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index ab69008a6b..e7eab8cc49 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -275,10 +275,7 @@ class DetailsMiddleware { } } - private suspend fun toggleSaveWallets( - scanResponse: ScanResponse?, - enable: Boolean, - ): CompletionResult { + private suspend fun toggleSaveWallets(scanResponse: ScanResponse?, enable: Boolean): CompletionResult { return if (enable) { saveCurrentWallet(scanResponse, enableAccessCodesSaving = false) } else { diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index 5adbc797e0..380d7be88b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -44,9 +44,7 @@ private fun internalReduce(action: Action, state: AppState): DetailsState { } } -private fun handlePrepareScreen( - action: DetailsAction.PrepareScreen, -): DetailsState { +private fun handlePrepareScreen(action: DetailsAction.PrepareScreen): DetailsState { return DetailsState( scanResponse = action.scanResponse, wallets = action.wallets, @@ -64,8 +62,7 @@ private fun handlePrepareCardSettingsScreen( card: CardDTO, cardTypesResolver: CardTypesResolver, state: DetailsState, -): - DetailsState { +): DetailsState { val cardSettingsState = CardSettingsState( cardInfo = card.toCardInfo(cardTypesResolver), manageSecurityState = prepareSecurityOptions(card, cardTypesResolver), @@ -112,10 +109,7 @@ private fun isResetToFactoryAllowedByCard(card: CardDTO, cardTypesResolver: Card return !isNotAllowed } -private fun handleEraseWallet( - action: DetailsAction.ResetToFactory, - state: DetailsState, -): DetailsState { +private fun handleEraseWallet(action: DetailsAction.ResetToFactory, state: DetailsState): DetailsState { return when (action) { is DetailsAction.ResetToFactory.Confirm -> state.copy(cardSettingsState = state.cardSettingsState?.copy(resetConfirmed = action.confirmed)) @@ -123,10 +117,7 @@ private fun handleEraseWallet( } } -private fun handleSecurityAction( - action: DetailsAction.ManageSecurity, - state: DetailsState, -): DetailsState { +private fun handleSecurityAction(action: DetailsAction.ManageSecurity, state: DetailsState): DetailsState { return when (action) { is DetailsAction.ManageSecurity.SelectOption -> { val manageSecurityState = state.cardSettingsState?.manageSecurityState?.copy( @@ -155,10 +146,7 @@ private fun handleSecurityAction( } } -private fun handlePrivacyAction( - action: DetailsAction.AppSettings, - state: DetailsState, -): DetailsState { +private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: DetailsState): DetailsState { return when (action) { is DetailsAction.AppSettings.SwitchPrivacySetting -> state.copy( appSettingsState = when (action.setting) { diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index 0957c8f2dc..014ca34512 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -285,11 +285,7 @@ class WalletConnectMiddleware { } } - private fun handleScanResponse( - scanResponse: ScanResponse, - session: WalletConnectSession, - blockchain: Blockchain, - ) { + private fun handleScanResponse(scanResponse: ScanResponse, session: WalletConnectSession, blockchain: Blockchain) { val card = scanResponse.card if (!scanResponse.cardTypesResolver.isMultiwalletAllowed()) { store.dispatchOnMain(WalletConnectAction.UnsupportedCard) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt index a4990f5d8b..ed1573f3bb 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt @@ -3,10 +3,7 @@ package com.tangem.tap.features.details.redux.walletconnect import org.rekotlin.Action object WalletConnectReducer { - fun reduce( - action: Action, - state: WalletConnectState, - ): WalletConnectState { + fun reduce(action: Action, state: WalletConnectState): WalletConnectState { if (action !is WalletConnectAction) return state return when (action) { diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt index 70e41f4f0c..5c32fdb2cd 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt @@ -123,7 +123,7 @@ data class WcTransactionData( enum class WcTransactionType { EthSignTransaction, - EthSendTransaction + EthSendTransaction, } data class WcPersonalSignData( @@ -156,5 +156,5 @@ data class TradeData( val price: String, val quantity: String, val amount: String, - val symbol: String + val symbol: String, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt index 3302facf0b..5ced6c832e 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt @@ -30,11 +30,7 @@ class AppSettingsFragment : Fragment(), StoreSubscriber { viewModel.checkBiometricsStatus() } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return ComposeView(requireContext()).apply { setContent { isTransitionGroup = true diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt index 84ff3c3dba..9255526f4a 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt @@ -159,9 +159,7 @@ private fun onCheckedChange( // region Preview @Composable -private fun AppSettingsScreenSample( - modifier: Modifier = Modifier, -) { +private fun AppSettingsScreenSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), @@ -199,9 +197,7 @@ private fun AppSettingsScreenPreview_Dark() { } @Composable -private fun AppSettingsScreen_EnrollBiometrics_Sample( - modifier: Modifier = Modifier, -) { +private fun AppSettingsScreen_EnrollBiometrics_Sample(modifier: Modifier = Modifier) { Column(modifier = modifier.background(TangemTheme.colors.background.primary)) { AppSettingsScreen( state = AppSettingsScreenState( diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt index b541b88894..1386a364d7 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt @@ -63,9 +63,7 @@ internal fun EnrollBiometricsCard(onClick: () -> Unit) { // region Preview @Composable -private fun EnrollBiometricsCardSample( - modifier: Modifier = Modifier, -) { +private fun EnrollBiometricsCardSample(modifier: Modifier = Modifier) { Column( modifier = modifier.background(TangemTheme.colors.background.secondary), ) { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt index 0ed7409abd..c82113133b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt @@ -66,9 +66,7 @@ internal fun SettingsAlertDialog( // region Preview @Composable -private fun SettingsAlertDialogSample( - modifier: Modifier = Modifier, -) { +private fun SettingsAlertDialogSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt index 15a943d590..e67d9b5adf 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt @@ -31,11 +31,7 @@ class CardSettingsFragment : Fragment(), StoreSubscriber { exitTransition = inflater.inflateTransition(android.R.transition.fade) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return ComposeView(requireContext()).apply { setContent { isTransitionGroup = true diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt b/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt index 34ed64cceb..616fbaafc9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt @@ -76,10 +76,7 @@ fun SettingsScreensScaffold( } @Composable -fun ScreenTitle( - titleRes: Int, - modifier: Modifier = Modifier, -) { +fun ScreenTitle(titleRes: Int, modifier: Modifier = Modifier) { Text( text = stringResource(id = titleRes), modifier = modifier.padding(start = 20.dp, end = 20.dp), @@ -111,12 +108,7 @@ fun EmptyTopBarWithNavigation( } @Composable -fun DetailsMainButton( - title: String, - onClick: () -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, -) { +fun DetailsMainButton(title: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) { Button( onClick = onClick, modifier = modifier diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsFragment.kt index 1580b87400..3c37bacd20 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsFragment.kt @@ -27,11 +27,7 @@ class DetailsFragment : Fragment(), StoreSubscriber { exitTransition = inflater.inflateTransition(android.R.transition.fade) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return ComposeView(requireContext()).apply { setContent { isTransitionGroup = true diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt index 631f292c66..d4526edf76 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt @@ -159,10 +159,7 @@ fun DetailsItem(item: SettingsElement, appCurrency: String, onItemsClick: () -> } @Composable -fun TangemSocialAccounts( - links: List, - onSocialNetworkClick: (SocialNetworkLink) -> Unit, -) { +fun TangemSocialAccounts(links: List, onSocialNetworkClick: (SocialNetworkLink) -> Unit) { LazyRow(modifier = Modifier.padding(start = 8.dp, end = 8.dp)) { items(links) { Icon( diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt index df8b8979be..ce8e1fd1ef 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt @@ -33,7 +33,7 @@ enum class SettingsElement( LinkMoreCards(R.drawable.ic_more_cards, R.string.details_row_title_create_backup), TermsOfService(R.drawable.ic_text, R.string.disclaimer_title), // General Terms of Service of the App PrivacyPolicy(R.drawable.ic_lock_24, R.string.details_row_privacy_policy), - TesterMenu(R.drawable.ic_alert_24, R.string.tester_menu) + TesterMenu(R.drawable.ic_alert_24, R.string.tester_menu), } @Immutable diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt index 8ea18c0604..df48063920 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt @@ -30,11 +30,7 @@ class ResetCardFragment : Fragment(), StoreSubscriber { exitTransition = inflater.inflateTransition(android.R.transition.fade) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return ComposeView(requireContext()).apply { setContent { isTransitionGroup = true diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt index c73f6bf836..d64bf444ca 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt @@ -134,9 +134,7 @@ fun ResetCardView(state: ResetCardScreenState) { // region Preview @Composable -private fun ResetCardScreenSample( - modifier: Modifier = Modifier, -) { +private fun ResetCardScreenSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.secondary), diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt index dcddb62a2f..77eb446ad1 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt @@ -30,11 +30,7 @@ class SecurityModeFragment : Fragment(), StoreSubscriber { exitTransition = inflater.inflateTransition(android.R.transition.fade) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return ComposeView(requireContext()).apply { setContent { isTransitionGroup = true diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt index 927adfe845..a08b9af8b2 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt @@ -25,18 +25,17 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) } - activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - store.dispatch(NavigationAction.PopBackTo()) - } - }) + activity?.onBackPressedDispatcher?.addCallback( + this, + object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + store.dispatch(NavigationAction.PopBackTo()) + } + }, + ) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View? { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { if (!permissionIsGranted()) requestPermission() scannerView = ZXingScannerView(activity) @@ -62,11 +61,7 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler { } } - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray, - ) { + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { if (requestCode != CameraView.PERMISSION_REQUEST_CODE) return if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt index 3ed76fdee2..4d5354e3f4 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt @@ -31,11 +31,7 @@ class WalletConnectFragment : Fragment(), StoreSubscriber { exitTransition = inflater.inflateTransition(android.R.transition.fade) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return ComposeView(requireContext()).apply { setContent { isTransitionGroup = true diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt index caefb4546a..7b14107334 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt @@ -65,10 +65,7 @@ fun WalletConnectScreen(state: WalletConnectScreenState, onBackClick: () -> Unit } @Composable -private fun AddSessionFab( - onAddSession: () -> Unit, - modifier: Modifier = Modifier, -) { +private fun AddSessionFab(onAddSession: () -> Unit, modifier: Modifier = Modifier) { FloatingActionButton( onClick = onAddSession, backgroundColor = colorResource(id = R.color.button_primary), diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt index 8e0ffe0f4a..ba70ae5a54 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt @@ -10,11 +10,7 @@ import com.tangem.tap.store import com.tangem.wallet.R object ChooseNetworkDialog { - fun create( - session: WalletConnectSession, - networks: List, - context: Context, - ): AlertDialog { + fun create(session: WalletConnectSession, networks: List, context: Context): AlertDialog { return AlertDialog.Builder(context) .setTitle(context.getString(R.string.wallet_connect_select_network)) .setNegativeButton(context.getString(R.string.common_cancel)) { _, _ -> diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt index b88b4488ab..fb06687b57 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/DisclaimerType.kt @@ -13,7 +13,8 @@ import java.util.* enum class DisclaimerType { Tangem, SaltPay, - Start2Coin; + Start2Coin, + ; companion object { fun get(cardDTO: CardDTO): DisclaimerType { diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt index 4e07832feb..abc9d83f27 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt @@ -42,11 +42,7 @@ class DisclaimerWebViewClient : WebViewClient() { loadedUrl = url } - override fun onReceivedError( - view: WebView?, - resourceRequest: WebResourceRequest?, - error: WebResourceError?, - ) { + override fun onReceivedError(view: WebView?, resourceRequest: WebResourceRequest?, error: WebResourceError?) { super.onReceivedError(view, resourceRequest, error) error?.let { progressState = ProgressState.Error } } diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt index b32b6a6ab2..372866fafc 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt @@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.platform.ComposeView +import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.fragment.app.Fragment import com.google.accompanist.appcompattheme.AppCompatTheme @@ -33,11 +34,7 @@ class HomeFragment : Fragment(), StoreSubscriber { store.dispatch(HomeAction.Init) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return ComposeView(inflater.context).apply { setContent { BackHandler { @@ -53,6 +50,8 @@ class HomeFragment : Fragment(), StoreSubscriber { override fun onStart() { super.onStart() + activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, false) } + store.subscribe(this) { state -> state.skipRepeats { oldState, newState -> oldState.homeState == newState.homeState diff --git a/app/src/main/java/com/tangem/tap/features/home/RegionProvider.kt b/app/src/main/java/com/tangem/tap/features/home/RegionProvider.kt index 5c8483c259..ef3ab25517 100644 --- a/app/src/main/java/com/tangem/tap/features/home/RegionProvider.kt +++ b/app/src/main/java/com/tangem/tap/features/home/RegionProvider.kt @@ -14,7 +14,7 @@ interface RegionProvider { } class RegionService( - private val providers: List + private val providers: List, ) : RegionProvider { override fun getRegion(): String? { for (provider in providers) { diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/content/Content.kt b/app/src/main/java/com/tangem/tap/features/home/compose/content/Content.kt index 2a545e623b..d119f5b863 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/content/Content.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/content/Content.kt @@ -138,10 +138,7 @@ fun StoriesWalletForEveryone(stepDuration: Int) { } @Composable -private fun SplitContent( - topContent: @Composable () -> Unit, - bottomContent: @Composable () -> Unit, -) { +private fun SplitContent(topContent: @Composable () -> Unit, bottomContent: @Composable () -> Unit) { Column( modifier = Modifier .fillMaxSize(), @@ -154,11 +151,7 @@ private fun SplitContent( } @Composable -private fun TopContent( - titleText: String, - subtitleText: AnnotatedString, - isDarkBackground: Boolean, -) { +private fun TopContent(titleText: String, subtitleText: AnnotatedString, isDarkBackground: Boolean) { SpacerH32() StoriesTitleText( text = titleText, @@ -173,10 +166,7 @@ private fun TopContent( @Suppress("MagicNumber") @Composable -private fun StoriesTitleText( - text: String, - isDarkBackground: Boolean, -) { +private fun StoriesTitleText(text: String, isDarkBackground: Boolean) { StoriesTextAnimation( slideInDuration = 500, slideInDelay = 150, @@ -215,11 +205,7 @@ private fun StoriesSubtitleText(subtitleText: AnnotatedString) { } @Composable -private fun StoriesImage( - @DrawableRes drawableResId: Int, - isDarkBackground: Boolean, - modifier: Modifier = Modifier, -) { +private fun StoriesImage(@DrawableRes drawableResId: Int, isDarkBackground: Boolean, modifier: Modifier = Modifier) { Image( painter = painterResource(id = drawableResId), contentDescription = null, diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/content/CurrenciesWeb3Content.kt b/app/src/main/java/com/tangem/tap/features/home/compose/content/CurrenciesWeb3Content.kt index 87cee39eb4..d84debb7c6 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/content/CurrenciesWeb3Content.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/content/CurrenciesWeb3Content.kt @@ -25,10 +25,7 @@ import com.tangem.tap.features.home.compose.HorizontalSlidingImage import com.tangem.wallet.R @Composable -fun StoriesCurrenciesContent( - paused: Boolean, - duration: Int, -) { +fun StoriesCurrenciesContent(paused: Boolean, duration: Int) { val currencyDrawableList = remember { listOf( R.drawable.currency0, @@ -72,10 +69,7 @@ fun StoriesCurrenciesContent( @Suppress("MagicNumber") @Composable -fun StoriesWeb3Content( - paused: Boolean, - duration: Int, -) { +fun StoriesWeb3Content(paused: Boolean, duration: Int) { val dappsItemList = remember { listOf( R.drawable.dapps0, diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/content/FirstStoriesContent.kt b/app/src/main/java/com/tangem/tap/features/home/compose/content/FirstStoriesContent.kt index 5dcfbb5f1f..6678901f43 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/content/FirstStoriesContent.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/content/FirstStoriesContent.kt @@ -36,11 +36,7 @@ import com.tangem.wallet.R @Suppress("LongMethod", "ComplexMethod", "MagicNumber") @Composable -fun FirstStoriesContent( - isPaused: Boolean, - duration: Int, - onHideContent: (Boolean) -> Unit, -) { +fun FirstStoriesContent(isPaused: Boolean, duration: Int, onHideContent: (Boolean) -> Unit) { val screenState = remember { mutableStateOf(StartingScreenState.INIT) } val progress = remember { Animatable(0f) } diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/content/FloatingCardsContent.kt b/app/src/main/java/com/tangem/tap/features/home/compose/content/FloatingCardsContent.kt index fcb0fce154..ef021f5dc6 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/content/FloatingCardsContent.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/content/FloatingCardsContent.kt @@ -15,10 +15,7 @@ import com.tangem.wallet.R [REDACTED_AUTHOR] */ @Composable -fun FloatingCardsContent( - isPaused: Boolean, - stepDuration: Int, -) { +fun FloatingCardsContent(isPaused: Boolean, stepDuration: Int) { val imageBitmap = asImageBitmap(R.drawable.card_placeholder_wallet) val cards = listOf( FloatingCard.first(), @@ -50,12 +47,7 @@ private object FloatingCard { @Suppress("TopLevelComposableFunctions") @Composable - fun Item( - isPaused: Boolean, - stepDuration: Int, - imageBitmap: ImageBitmap, - cardValues: CardValues, - ) { + fun Item(isPaused: Boolean, stepDuration: Int, imageBitmap: ImageBitmap, cardValues: CardValues) { Image( bitmap = imageBitmap, contentDescription = "Floating Tangem card", diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesProgressBar.kt b/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesProgressBar.kt index 4692fa91aa..f92adcf9d1 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesProgressBar.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesProgressBar.kt @@ -38,8 +38,8 @@ fun StoriesProgressBar( targetValue = 1f, animationSpec = tween( durationMillis = (stepDuration * (1f - progress.value)).toInt(), - easing = LinearEasing - ) + easing = LinearEasing, + ), ) progress.snapTo(0f) onStepFinish() @@ -57,7 +57,7 @@ fun StoriesProgressBar( modifier = Modifier .height(2.dp) .weight(1f) - .background(Color.White.copy(alpha = 0.4f)) + .background(Color.White.copy(alpha = 0.4f)), ) { Box( modifier = Modifier diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt index 5a6132c72a..53c844cd40 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt @@ -14,10 +14,7 @@ import com.tangem.tap.preferencesStorage */ object OnboardingSaltPayHelper { - suspend fun isOnboardingCase( - scanResponse: ScanResponse, - manager: SaltPayActivationManager, - ): Result { + suspend fun isOnboardingCase(scanResponse: ScanResponse, manager: SaltPayActivationManager): Result { return try { val updatedStep = manager.update(SaltPayActivationStep.None, null).successOr { return it } @@ -37,14 +34,10 @@ object OnboardingSaltPayHelper { } @Suppress("UnusedPrivateMember") - fun testProceedToOnboarding( - scanResponse: ScanResponse, - manager: SaltPayActivationManager, - ): Result = Result.Success(true) + fun testProceedToOnboarding(scanResponse: ScanResponse, manager: SaltPayActivationManager): Result = + Result.Success(true) @Suppress("UnusedPrivateMember") - fun testProceedToMainScreen( - scanResponse: ScanResponse, - manager: SaltPayActivationManager, - ): Result = Result.Success(false) + fun testProceedToMainScreen(scanResponse: ScanResponse, manager: SaltPayActivationManager): Result = + Result.Success(false) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt index 3549ea11ab..39fea7dbfd 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt @@ -108,28 +108,27 @@ class OnboardingNoteFragment : BaseOnboardingFragment() { tvBody.text = "" } - private fun setupCreateWalletState(state: OnboardingNoteState) = - with(mainBinding.onboardingActionContainer) { - btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet) - btnMainAction.setOnClickListener { - Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet()) - store.dispatch(OnboardingNoteAction.CreateWallet) - } - btnAlternativeAction.setText(R.string.onboarding_button_what_does_it_mean) - btnAlternativeAction.setOnClickListener { } - - btnRefreshBalanceWidget.mainView.setOnClickListener(null) - - tvHeader.setText(R.string.onboarding_create_wallet_header) - tvBody.setText(R.string.onboarding_create_wallet_body) - - mainBinding.onboardingTopContainer.imvCardBackground.setBackgroundDrawable( - requireContext().getDrawableCompat(R.drawable.shape_circle), - ) - updateConstraints(state.currentStep, R.layout.lp_onboarding_create_wallet) - - btnAlternativeAction.isVisible = false // temporary + private fun setupCreateWalletState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) { + btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet) + btnMainAction.setOnClickListener { + Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet()) + store.dispatch(OnboardingNoteAction.CreateWallet) } + btnAlternativeAction.setText(R.string.onboarding_button_what_does_it_mean) + btnAlternativeAction.setOnClickListener { } + + btnRefreshBalanceWidget.mainView.setOnClickListener(null) + + tvHeader.setText(R.string.onboarding_create_wallet_header) + tvBody.setText(R.string.onboarding_create_wallet_body) + + mainBinding.onboardingTopContainer.imvCardBackground.setBackgroundDrawable( + requireContext().getDrawableCompat(R.drawable.shape_circle), + ) + updateConstraints(state.currentStep, R.layout.lp_onboarding_create_wallet) + + btnAlternativeAction.isVisible = false // temporary + } private fun setupTopUpWalletState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) { if (state.isBuyAllowed) { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 94fe803ccc..4dad678741 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -193,10 +193,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: } } -private fun updateScanResponseAfterBackup( - scanResponse: ScanResponse, - backupState: BackupState, -): ScanResponse { +private fun updateScanResponseAfterBackup(scanResponse: ScanResponse, backupState: BackupState): ScanResponse { val card = if (backupState.backupCardsNumber > 0) { val cardsCount = backupState.backupCardsNumber scanResponse.card.copy( @@ -412,10 +409,7 @@ private fun finishCardsActivationForDiscardedUnfinishedBackup(cardId: String) { /** * SaltPay state maybe not initialized if backup resumed from ResumeFoundUnfinishedBackup action */ -private fun initSaltPayOnBackupFinishedIfNeeded( - scanResponse: ScanResponse?, - state: OnboardingWalletState, -) { +private fun initSaltPayOnBackupFinishedIfNeeded(scanResponse: ScanResponse?, state: OnboardingWalletState) { if (state.backupState.isInterruptedBackup) return if (scanResponse == null) return diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt index dcb4044499..409ca000e6 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt @@ -131,9 +131,7 @@ class SaltPayActivationManager( .tryExtractError() } - suspend fun sendTransactions( - signedTransactions: List, - ): BlockchainResult> { + suspend fun sendTransactions(signedTransactions: List): BlockchainResult> { return gnosisRegistrator.sendTransactions(signedTransactions) } @@ -208,13 +206,12 @@ class SaltPayActivationManager( ) } - private fun makeRegisterKYCRequest(): RegisterKYCRequest = - RegisterKYCRequest( - cardId = cardId, - publicKey = cardPublicKey, - kycProvider = "UTORG", - kycRefId = kycUrlProvider.kycRefId, - ) + private fun makeRegisterKYCRequest(): RegisterKYCRequest = RegisterKYCRequest( + cardId = cardId, + publicKey = cardPublicKey, + kycProvider = "UTORG", + kycRefId = kycUrlProvider.kycRefId, + ) companion object { fun stub(): SaltPayActivationManager = SaltPayActivationManager( diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayRegistrationTask.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayRegistrationTask.kt index 11a0a30404..fb4bd50ed9 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayRegistrationTask.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayRegistrationTask.kt @@ -55,10 +55,7 @@ class SaltPayRegistrationTask( } } - private fun attestWallet( - session: CardSession, - callback: CompletionCallback, - ) { + private fun attestWallet(session: CardSession, callback: CompletionCallback) { val card = session.environment.card.guard { callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) return diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupAnimator.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupAnimator.kt index 368cb6a3a3..537ed92d90 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupAnimator.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupAnimator.kt @@ -166,14 +166,10 @@ class WalletBackupAnimator( private enum class State { TreeCards, - TwoCards + TwoCards, } - private fun BackupCardType.animateAlpha( - alpha: Float, - duration: Long = 0L, - startDelay: Long = 0L, - ) { + private fun BackupCardType.animateAlpha(alpha: Float, duration: Long = 0L, startDelay: Long = 0L) { when (this) { ORIGIN -> { cardsWidget.getOriginCardView().animate().apply { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupInfoAdapter.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupInfoAdapter.kt index 5b62611410..6ea3bf1a25 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupInfoAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupInfoAdapter.kt @@ -12,22 +12,20 @@ class BackupInfoAdapter : RecyclerView.Adapter() { private val data = backupInfoSnippets - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BackupInfoViewHolder = - BackupInfoViewHolder( - ItemBackupInfoAdapterBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ) - ) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BackupInfoViewHolder = BackupInfoViewHolder( + ItemBackupInfoAdapterBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false, + ), + ) override fun getItemCount(): Int = data.size - override fun onBindViewHolder(holder: BackupInfoViewHolder, position: Int) = - holder.binding.run { - tvHeader.text = root.getString(data[position].header) - tvBody.text = root.getString(data[position].body) - } + override fun onBindViewHolder(holder: BackupInfoViewHolder, position: Int) = holder.binding.run { + tvHeader.text = root.getString(data[position].header) + tvBody.text = root.getString(data[position].body) + } } private class BackupInfo( @@ -38,19 +36,19 @@ private class BackupInfo( private val backupInfoSnippets = listOf( BackupInfo( R.string.onboarding_wallet_info_title_first, - R.string.onboarding_wallet_info_subtitle_first + R.string.onboarding_wallet_info_subtitle_first, ), BackupInfo( R.string.onboarding_wallet_info_title_second, - R.string.onboarding_wallet_info_subtitle_second + R.string.onboarding_wallet_info_subtitle_second, ), BackupInfo( R.string.onboarding_wallet_info_title_third, - R.string.onboarding_wallet_info_subtitle_third + R.string.onboarding_wallet_info_subtitle_third, ), BackupInfo( R.string.onboarding_wallet_info_title_fourth, - R.string.onboarding_wallet_info_subtitle_fourth + R.string.onboarding_wallet_info_subtitle_fourth, ), ) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index 07939d2ad2..0f8715a237 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -47,8 +47,10 @@ import com.tangem.wallet.databinding.ViewOnboardingProgressBinding import org.rekotlin.StoreSubscriber @Suppress("LargeClass", "MagicNumber") -class OnboardingWalletFragment : BaseFragment(R.layout.fragment_onboarding_wallet), - StoreSubscriber, FragmentOnBackPressedHandler { +class OnboardingWalletFragment : + BaseFragment(R.layout.fragment_onboarding_wallet), + StoreSubscriber, + FragmentOnBackPressedHandler { private val pbBinding: ViewOnboardingProgressBinding by viewBinding(ViewOnboardingProgressBinding::bind) internal val binding: FragmentOnboardingWalletBinding by viewBinding(FragmentOnboardingWalletBinding::bind) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/WalletCardsWidget.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/WalletCardsWidget.kt index 64479ca66d..8f0bc94325 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/WalletCardsWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/WalletCardsWidget.kt @@ -21,10 +21,7 @@ class WalletCardsWidget( var currentState: WidgetState? = null private set - fun toWelcome( - animate: Boolean = true, - onEnd: () -> Unit = {}, - ) { + fun toWelcome(animate: Boolean = true, onEnd: () -> Unit = {}) { if (currentState == WidgetState.WELCOME) return currentState = WidgetState.WELCOME @@ -34,11 +31,7 @@ class WalletCardsWidget( leapfrogWidget.fold { animator.start() } } - fun toFolded( - animate: Boolean = true, - duration: Long = animDuration, - onEnd: () -> Unit = {}, - ) { + fun toFolded(animate: Boolean = true, duration: Long = animDuration, onEnd: () -> Unit = {}) { if (currentState == WidgetState.FOLDED) return currentState = WidgetState.FOLDED @@ -50,10 +43,7 @@ class WalletCardsWidget( animator.start() } - fun toFan( - animate: Boolean = true, - onEnd: () -> Unit = {}, - ) { + fun toFan(animate: Boolean = true, onEnd: () -> Unit = {}) { if (currentState == WidgetState.FAN) return currentState = WidgetState.FAN @@ -63,11 +53,7 @@ class WalletCardsWidget( leapfrogWidget.fold { animator.start() } } - fun toLeapfrog( - animate: Boolean = true, - onEndFold: () -> Unit = {}, - onEnd: () -> Unit = {}, - ) { + fun toLeapfrog(animate: Boolean = true, onEndFold: () -> Unit = {}, onEnd: () -> Unit = {}) { if (currentState == WidgetState.LEAPFROG) return currentState = WidgetState.LEAPFROG @@ -102,10 +88,7 @@ class WalletCardsWidget( } } - private fun createCardAnimator( - cardType: BackupCardType, - properties: CardProperties, - ): ObjectAnimator { + private fun createCardAnimator(cardType: BackupCardType, properties: CardProperties): ObjectAnimator { val view = getLeapViewByCard(cardType).view val animator = ObjectAnimator.ofPropertyValuesHolder( view, diff --git a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletReducer.kt index 89eefd41db..f2552462b6 100644 --- a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletReducer.kt @@ -7,7 +7,9 @@ internal object SaveWalletReducer { fun reduce(action: Action, state: AppState): SaveWalletState { return if (action is SaveWalletAction) { internalReduce(action, state.saveWalletState) - } else state.saveWalletState + } else { + state.saveWalletState + } } private fun internalReduce(action: SaveWalletAction, state: SaveWalletState): SaveWalletState { diff --git a/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt b/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt index 3f0f4f77c4..0a6a076bff 100644 --- a/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt @@ -39,10 +39,7 @@ internal class SaveWalletBottomSheetFragment : ComposeBottomSheetFragment Unit, - onCloseClick: () -> Unit, -) { +internal fun SaveWalletScreenContent(showProgress: Boolean, onSaveWalletClick: () -> Unit, onCloseClick: () -> Unit) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Header(onCloseClick = onCloseClick) SpacerHHalf() @@ -89,9 +85,7 @@ private fun Header(onCloseClick: () -> Unit) { } @Composable -private fun Title( - modifier: Modifier = Modifier, -) { +private fun Title(modifier: Modifier = Modifier) { Column( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally, @@ -113,9 +107,7 @@ private fun Title( } @Composable -private fun Description( - modifier: Modifier = Modifier, -) { +private fun Description(modifier: Modifier = Modifier) { Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing24), @@ -135,10 +127,7 @@ private fun Description( } @Composable -private fun Footer( - showProgress: Boolean, - onSaveWalletClick: () -> Unit, -) { +private fun Footer(showProgress: Boolean, onSaveWalletClick: () -> Unit) { Column( modifier = Modifier .padding(horizontal = TangemTheme.dimens.spacing16) @@ -163,11 +152,7 @@ private fun Footer( } @Composable -private fun DescriptionItem( - iconPainter: Painter, - title: String, - description: String, -) { +private fun DescriptionItem(iconPainter: Painter, title: String, description: String) { Row( verticalAlignment = Alignment.Top, horizontalArrangement = Arrangement.SpaceEvenly, @@ -197,9 +182,7 @@ private fun DescriptionItem( // region Preview @Composable -private fun SaveWalletScreenContentSample( - modifier: Modifier = Modifier, -) { +private fun SaveWalletScreenContentSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt index fcb9d013c1..00342aaddb 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt @@ -77,7 +77,7 @@ sealed class AddressPayIdVerifyAction : SendScreenAction { PAY_ID_NOT_REGISTERED, PAY_ID_REQUEST_FAILED, ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN, - ADDRESS_SAME_AS_WALLET + ADDRESS_SAME_AS_WALLET, } data class ChangePasteBtnEnableState(val isEnabled: Boolean) : AddressPayIdVerifyAction() diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt index 727964e0c4..9221d5ef60 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt @@ -41,7 +41,7 @@ class AmountReducer : SendInternalReducer { viewBalanceValue = rescaledBalance.stripZeroPlainString(), mainCurrency = state.createMainCurrency(currency, currencyCanBeSwitched), maxLengthOfAmount = sendState.getDecimals(currency), - cursorAtTheSamePosition = false + cursorAtTheSamePosition = false, ) } MainCurrencyType.CRYPTO -> { @@ -51,7 +51,7 @@ class AmountReducer : SendInternalReducer { viewBalanceValue = state.balanceCrypto.stripZeroPlainString(), mainCurrency = state.createMainCurrency(currency, currencyCanBeSwitched), maxLengthOfAmount = sendState.getDecimals(currency), - cursorAtTheSamePosition = false + cursorAtTheSamePosition = false, ) } } @@ -75,7 +75,7 @@ class AmountReducer : SendInternalReducer { viewAmountValue = InputViewValue(viewValue, action.isUserInput), amountToSendCrypto = action.amountCrypto, cursorAtTheSamePosition = true, - error = null + error = null, ) } is AmountAction.SetAmountError -> state.copy(error = action.error) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt index 6bca1e9649..7f918d72b3 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt @@ -70,11 +70,7 @@ class TransactionExtrasReducer : SendInternalReducer { return updateLastState(sendState.copy(transactionExtrasState = result), result) } - private fun handleXlmMemo( - action: XlmMemo, - sendState: SendState, - infoState: TransactionExtrasState, - ): SendState { + private fun handleXlmMemo(action: XlmMemo, sendState: SendState, infoState: TransactionExtrasState): SendState { fun clearMemo(memo: XlmMemoState): XlmMemoState = memo.copy(text = null, id = null, error = null) val result = when (action) { diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt index ad707474af..3ff920281d 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt @@ -108,5 +108,5 @@ data class TonMemoState( enum class TransactionExtraError { INVALID_DESTINATION_TAG, INVALID_XLM_MEMO, - INVALID_BINANCE_MEMO + INVALID_BINANCE_MEMO, } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt index 79b199a5e8..e9c9472bb4 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt @@ -21,7 +21,7 @@ data class FeeState( val controlsLayoutIsVisible: Boolean = false, val feeChipGroupIsVisible: Boolean = true, val includeFeeSwitcherIsEnabled: Boolean = true, - val progressState: ProgressState = ProgressState.Done + val progressState: ProgressState = ProgressState.Done, ) : SendScreenState { override val stateId: StateId = StateId.FEE diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/ReceiptState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/ReceiptState.kt index 29a6b2e210..5a9808ea69 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/ReceiptState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/ReceiptState.kt @@ -11,7 +11,7 @@ data class ReceiptState( val crypto: ReceiptCrypto? = null, val tokenFiat: ReceiptTokenFiat? = null, val tokenCrypto: ReceiptTokenCrypto? = null, - val mainCurrency: MainCurrency? = null + val mainCurrency: MainCurrency? = null, ) : SendScreenState { override val stateId: StateId = StateId.RECEIPT } @@ -19,7 +19,7 @@ data class ReceiptState( data class ReceiptSymbols( val fiat: String, val crypto: String, - val token: String? = null + val token: String? = null, ) data class ReceiptFiat( @@ -27,7 +27,7 @@ data class ReceiptFiat( val feeFiat: String, val totalFiat: String, val willSentCrypto: String, - val symbols: ReceiptSymbols + val symbols: ReceiptSymbols, ) data class ReceiptCrypto( @@ -36,14 +36,14 @@ data class ReceiptCrypto( val totalCrypto: String, val feeFiat: String, val willSentFiat: String, - val symbols: ReceiptSymbols + val symbols: ReceiptSymbols, ) data class ReceiptTokenCrypto( val amountToken: String, val feeCoin: String, val totalFiat: String, - val symbols: ReceiptSymbols + val symbols: ReceiptSymbols, ) data class ReceiptTokenFiat( @@ -52,5 +52,5 @@ data class ReceiptTokenFiat( val totalFiat: String, val willSentToken: String, val willSentFeeCoin: String, - val symbols: ReceiptSymbols + val symbols: ReceiptSymbols, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 635017f96b..e250ad075e 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -288,104 +288,101 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber } @Suppress("LongMethod", "ComplexMethod") - private fun handleReceiptState( - fg: SendFragment, - state: ReceiptState, - feeProgressState: ProgressState, - ) = with(fg.binding.clReceiptContainer) { - val mainLayout = clReceiptContainer as ViewGroup - val totalLayout = llTotalContainer.llTotal as ViewGroup - val totalTokenLayout = llTotalContainer.flTotalTokenCrypto as ViewGroup + private fun handleReceiptState(fg: SendFragment, state: ReceiptState, feeProgressState: ProgressState) = + with(fg.binding.clReceiptContainer) { + val mainLayout = clReceiptContainer as ViewGroup + val totalLayout = llTotalContainer.llTotal as ViewGroup + val totalTokenLayout = llTotalContainer.flTotalTokenCrypto as ViewGroup - fun getString(id: Int, vararg formatStrings: String): String = mainLayout.getString(id, *formatStrings) + fun getString(id: Int, vararg formatStrings: String): String = mainLayout.getString(id, *formatStrings) - fun roughOrEmpty(value: String): String { - return if (value == UNKNOWN_AMOUNT_SIGN) value else "$ROUGH_SIGN $value" - } - - when (feeProgressState) { - ProgressState.Loading -> { - tvReceiptFeeValue.hide() - pbReceiptFee.show() + fun roughOrEmpty(value: String): String { + return if (value == UNKNOWN_AMOUNT_SIGN) value else "$ROUGH_SIGN $value" } - ProgressState.Done -> { - pbReceiptFee.hide() - tvReceiptFeeValue.show() - } - else -> {} - } - when (state.visibleTypeOfReceipt) { - ReceiptLayoutType.FIAT -> { - val receipt = state.fiat ?: return - - totalLayout.show(true) - totalTokenLayout.show(false) - tvReceiptAmountValue.update("${receipt.amountFiat} ${receipt.symbols.fiat}") - tvReceiptFeeValue.update("${receipt.feeFiat} ${receipt.symbols.fiat}") - llTotalContainer.tvTotalValue.update("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}") - - val willSent = getString( - R.string.send_total_subtitle_format, - "${receipt.willSentCrypto} ${receipt.symbols.crypto}", - ) - llTotalContainer.tvWillBeSentValue.update(willSent) - } - ReceiptLayoutType.CRYPTO -> { - val receipt = state.crypto ?: return - - totalLayout.show(true) - totalTokenLayout.show(false) - tvReceiptAmountValue.update("${receipt.amountCrypto} ${receipt.symbols.crypto}") - tvReceiptFeeValue.update("${receipt.feeCrypto} ${receipt.symbols.crypto}") - llTotalContainer.tvTotalValue.update("${receipt.totalCrypto} ${receipt.symbols.crypto}") - - if (receipt.willSentFiat == UNKNOWN_AMOUNT_SIGN) { - llTotalContainer.tvWillBeSentValue.hide() - } else { - llTotalContainer.tvWillBeSentValue.show() - llTotalContainer.tvWillBeSentValue.update( - getString( - R.string.send_total_subtitle_fiat_format, - "${receipt.willSentFiat} ${receipt.symbols.fiat}", - "${receipt.feeFiat} ${receipt.symbols.fiat}", - ), - ) + when (feeProgressState) { + ProgressState.Loading -> { + tvReceiptFeeValue.hide() + pbReceiptFee.show() } + ProgressState.Done -> { + pbReceiptFee.hide() + tvReceiptFeeValue.show() + } + else -> {} } - ReceiptLayoutType.TOKEN_FIAT -> { - val receipt = state.tokenFiat ?: return - totalLayout.show(true) - totalTokenLayout.show(false) - tvReceiptAmountValue.update("${receipt.amountFiat} ${receipt.symbols.fiat}") - tvReceiptFeeValue.update("${receipt.feeFiat} ${receipt.symbols.fiat}") - llTotalContainer.tvTotalValue.update("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}") + when (state.visibleTypeOfReceipt) { + ReceiptLayoutType.FIAT -> { + val receipt = state.fiat ?: return - val willSent = getString( - R.string.send_total_subtitle_asset_format, - "${receipt.symbols.token ?: ""} ${receipt.willSentToken}", - "${receipt.symbols.crypto} ${receipt.willSentFeeCoin}", - ) - llTotalContainer.tvWillBeSentValue.update(willSent) - } - ReceiptLayoutType.TOKEN_CRYPTO -> { - val receipt = state.tokenCrypto ?: return + totalLayout.show(true) + totalTokenLayout.show(false) + tvReceiptAmountValue.update("${receipt.amountFiat} ${receipt.symbols.fiat}") + tvReceiptFeeValue.update("${receipt.feeFiat} ${receipt.symbols.fiat}") + llTotalContainer.tvTotalValue.update("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}") - totalLayout.show(false) - totalTokenLayout.show(true) + val willSent = getString( + R.string.send_total_subtitle_format, + "${receipt.willSentCrypto} ${receipt.symbols.crypto}", + ) + llTotalContainer.tvWillBeSentValue.update(willSent) + } + ReceiptLayoutType.CRYPTO -> { + val receipt = state.crypto ?: return - tvReceiptAmountValue.update("${receipt.amountToken} ${receipt.symbols.token}") - tvReceiptFeeValue.update("${receipt.feeCoin} ${receipt.symbols.crypto}") + totalLayout.show(true) + totalTokenLayout.show(false) + tvReceiptAmountValue.update("${receipt.amountCrypto} ${receipt.symbols.crypto}") + tvReceiptFeeValue.update("${receipt.feeCrypto} ${receipt.symbols.crypto}") + llTotalContainer.tvTotalValue.update("${receipt.totalCrypto} ${receipt.symbols.crypto}") - val willSent = SpannableStringBuilder() - .bold { - append(roughOrEmpty(receipt.totalFiat)).append(" ") - append(receipt.symbols.fiat) + if (receipt.willSentFiat == UNKNOWN_AMOUNT_SIGN) { + llTotalContainer.tvWillBeSentValue.hide() + } else { + llTotalContainer.tvWillBeSentValue.show() + llTotalContainer.tvWillBeSentValue.update( + getString( + R.string.send_total_subtitle_fiat_format, + "${receipt.willSentFiat} ${receipt.symbols.fiat}", + "${receipt.feeFiat} ${receipt.symbols.fiat}", + ), + ) } - llTotalContainer.tvTotalTokenCryptoValue.update(willSent.toString()) + } + ReceiptLayoutType.TOKEN_FIAT -> { + val receipt = state.tokenFiat ?: return + + totalLayout.show(true) + totalTokenLayout.show(false) + tvReceiptAmountValue.update("${receipt.amountFiat} ${receipt.symbols.fiat}") + tvReceiptFeeValue.update("${receipt.feeFiat} ${receipt.symbols.fiat}") + llTotalContainer.tvTotalValue.update("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}") + + val willSent = getString( + R.string.send_total_subtitle_asset_format, + "${receipt.symbols.token ?: ""} ${receipt.willSentToken}", + "${receipt.symbols.crypto} ${receipt.willSentFeeCoin}", + ) + llTotalContainer.tvWillBeSentValue.update(willSent) + } + ReceiptLayoutType.TOKEN_CRYPTO -> { + val receipt = state.tokenCrypto ?: return + + totalLayout.show(false) + totalTokenLayout.show(true) + + tvReceiptAmountValue.update("${receipt.amountToken} ${receipt.symbols.token}") + tvReceiptFeeValue.update("${receipt.feeCoin} ${receipt.symbols.crypto}") + + val willSent = SpannableStringBuilder() + .bold { + append(roughOrEmpty(receipt.totalFiat)).append(" ") + append(receipt.symbols.fiat) + } + llTotalContainer.tvTotalTokenCryptoValue.update(willSent.toString()) + } + else -> {} } - else -> {} } - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt index 8ec0fc117c..a27d16d2db 100644 --- a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt @@ -7,7 +7,9 @@ internal object SprinklrReducer { fun reduce(action: Action, state: AppState): SprinklrState { return if (action is SprinklrAction) { internalReduce(action, state.sprinklrState) - } else state.sprinklrState + } else { + state.sprinklrState + } } private fun internalReduce(action: SprinklrAction, state: SprinklrState): SprinklrState { diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrActivity.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrActivity.kt index 685a52d600..b567dce03b 100644 --- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrActivity.kt +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrActivity.kt @@ -30,10 +30,7 @@ internal class SprinklrActivity : ComposeActivity() { } @Composable - override fun ScreenContent( - state: SprinklrScreenState, - modifier: Modifier, - ) { + override fun ScreenContent(state: SprinklrScreenState, modifier: Modifier) { BackHandler(onBack = state.onNavigateBack) SprinklrScreenContent( modifier = modifier diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt index f80a4b43f3..5277ba0cea 100644 --- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt @@ -10,10 +10,7 @@ import com.tangem.tap.features.sprinklr.ui.webview.SprinklrWebViewClient @SuppressLint("SetJavaScriptEnabled") @Composable -internal fun SprinklrScreenContent( - state: SprinklrScreenState, - modifier: Modifier = Modifier, -) { +internal fun SprinklrScreenContent(state: SprinklrScreenState, modifier: Modifier = Modifier) { WebView( modifier = modifier, state = rememberWebViewState(url = state.initialUrl), diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt index 989b813d19..87c033582a 100644 --- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt @@ -52,9 +52,11 @@ internal class SprinklrViewModel : ViewModel(), StoreSubscriber { return if (isExternalUrl(url)) { store.dispatchOnMain(NavigationAction.OpenUrl(url)) this - } else when (this) { - is WebContent.Url -> copy(url = url) - else -> WebContent.Url(url) + } else { + when (this) { + is WebContent.Url -> copy(url = url) + else -> WebContent.Url(url) + } } } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt index 3dc5ab9c7b..d5c9bfe9c0 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt @@ -65,10 +65,7 @@ private class AddCustomTokenScreen // for simple search @OptIn(ExperimentalMaterialApi::class) @Composable -fun AddCustomTokenScreen( - state: MutableState, - closePopupTrigger: ClosePopupTrigger, -) { +fun AddCustomTokenScreen(state: MutableState, closePopupTrigger: ClosePopupTrigger) { val selectedTestCase = remember { mutableStateOf(TestCase.ContractAddress) } val bottomSheetScaffoldState = rememberBottomSheetScaffoldState( @@ -112,10 +109,7 @@ private suspend fun BottomSheetScaffoldState.toggle() { } @Composable -private fun ScreenContent( - state: MutableState, - closePopupTrigger: ClosePopupTrigger, -) { +private fun ScreenContent(state: MutableState, closePopupTrigger: ClosePopupTrigger) { val scaffoldState = rememberScaffoldState() Scaffold( @@ -158,10 +152,7 @@ private fun ScreenContent( } @Composable -private fun FormFields( - state: MutableState, - closePopupTrigger: ClosePopupTrigger, -) { +private fun FormFields(state: MutableState, closePopupTrigger: ClosePopupTrigger) { val context = LocalContext.current val errorConverter = remember { ModuleMessageConverter(context) } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/HangingOverKeyboardView.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/HangingOverKeyboardView.kt index 269a3177a6..a330583a8b 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/HangingOverKeyboardView.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/HangingOverKeyboardView.kt @@ -19,7 +19,7 @@ fun HangingOverKeyboardView( modifier: Modifier = Modifier, keyboardState: State, spaceBetweenKeyboard: Dp = 0.dp, - content: @Composable (BoxScope.() -> Unit) + content: @Composable (BoxScope.() -> Unit), ) { val padding = remember(keyboardState) { when (val state = keyboardState.value) { diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/test/ContractAddressTests.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/test/ContractAddressTests.kt index 2eb3b4923b..581af5a8df 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/test/ContractAddressTests.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/test/ContractAddressTests.kt @@ -21,9 +21,7 @@ import com.tangem.domain.redux.domainStore [REDACTED_AUTHOR] */ @Composable -fun ContractAddressTests( - onItemClick: VoidCallback, -) { +fun ContractAddressTests(onItemClick: VoidCallback) { val casesInfo = listOf( "USDC on ETH" to "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "BUSD on ETH" to "0x4fabb145d64652a948d72533023f6e7a623c7c53", @@ -37,9 +35,7 @@ fun ContractAddressTests( } @Composable -fun SolanaAddressTests( - onItemClick: VoidCallback, -) { +fun SolanaAddressTests(onItemClick: VoidCallback) { val casesInfo = listOf( "USDT (full)" to "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", "USDT (valid - 2/3 of address)" to "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8Ben", @@ -50,10 +46,7 @@ fun SolanaAddressTests( } @Composable -private fun CasesListContent( - casesList: List>, - onItemClick: VoidCallback, -) { +private fun CasesListContent(casesList: List>, onItemClick: VoidCallback) { LazyColumn( content = { item { @@ -96,9 +89,7 @@ fun ResetAllFieldsButton(onItemClick: VoidCallback) { } @Composable -fun ResetContractAddressButton( - onItemClick: VoidCallback, -) { +fun ResetContractAddressButton(onItemClick: VoidCallback) { ActionButton( name = "Set empty address", onClick = { @@ -109,11 +100,7 @@ fun ResetContractAddressButton( } @Composable -private fun ContractAddressButton( - name: String, - address: String, - onItemClick: VoidCallback, -) { +private fun ContractAddressButton(name: String, address: String, onItemClick: VoidCallback) { ActionButton( modifier = Modifier.fillMaxWidth(), name = name, @@ -125,11 +112,7 @@ private fun ContractAddressButton( } @Composable -fun ActionButton( - name: String, - onClick: () -> Unit, - modifier: Modifier = Modifier, -) { +fun ActionButton(name: String, onClick: () -> Unit, modifier: Modifier = Modifier) { Button( modifier = modifier.padding(horizontal = 8.dp), onClick = onClick, diff --git a/app/src/main/java/com/tangem/tap/features/tokens/api/featuretoggles/TokensListFeatureToggles.kt b/app/src/main/java/com/tangem/tap/features/tokens/api/featuretoggles/TokensListFeatureToggles.kt new file mode 100644 index 0000000000..286eb6d0e0 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/api/featuretoggles/TokensListFeatureToggles.kt @@ -0,0 +1,12 @@ +package com.tangem.tap.features.tokens.api.featuretoggles + +/** + * TokensList feature toggles + * +[REDACTED_AUTHOR] + */ +interface TokensListFeatureToggles { + + /** Availability of redesigned screen (internal feature) */ + val isRedesignedScreenEnabled: Boolean +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/data/DefaultTokensListRepository.kt b/app/src/main/java/com/tangem/tap/features/tokens/data/DefaultTokensListRepository.kt new file mode 100644 index 0000000000..ba522709c6 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/data/DefaultTokensListRepository.kt @@ -0,0 +1,53 @@ +package com.tangem.tap.features.tokens.data + +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.local.testnet.TestnetTokensStorage +import com.tangem.domain.common.TapWorkarounds.isTestCard +import com.tangem.tap.features.tokens.domain.TokensListRepository +import com.tangem.tap.features.tokens.domain.models.Token +import com.tangem.tap.proxy.AppStateHolder +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.Flow + +/** + * Default repository implementation of tokens list feature + * + * @property tangemTechApi Tangem Tech API + * @property dispatchers coroutine dispatchers provider + * @property reduxStateHolder redux state holder + * @property testnetTokensStorage storage for getting testnet tokens data + * +[REDACTED_AUTHOR] + */ +internal class DefaultTokensListRepository( + private val tangemTechApi: TangemTechApi, + private val dispatchers: CoroutineDispatcherProvider, + private val reduxStateHolder: AppStateHolder, + private val testnetTokensStorage: TestnetTokensStorage, +) : TokensListRepository { + + override fun getAvailableTokens(searchText: String?): Flow> { + return Pager( + config = PagingConfig( + pageSize = 100, + prefetchDistance = 70, + enablePlaceholders = false, + ), + pagingSourceFactory = { + if (reduxStateHolder.scanResponse?.card?.isTestCard == true) { + TestnetTokensPagingSource(testnetTokensStorage, searchText) + } else { + TangemApiTokensPagingSource( + api = tangemTechApi, + dispatchers = dispatchers, + reduxStateHolder = reduxStateHolder, + searchText = searchText, + ) + } + }, + ).flow + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/data/TangemApiTokensPagingSource.kt b/app/src/main/java/com/tangem/tap/features/tokens/data/TangemApiTokensPagingSource.kt new file mode 100644 index 0000000000..d9d63213bd --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/data/TangemApiTokensPagingSource.kt @@ -0,0 +1,62 @@ +package com.tangem.tap.features.tokens.data + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import com.tangem.blockchain.common.Blockchain +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.domain.common.extensions.supportedBlockchains +import com.tangem.domain.common.extensions.toNetworkId +import com.tangem.tap.features.tokens.data.converters.CoinsResponseConverter +import com.tangem.tap.features.tokens.domain.models.Token +import com.tangem.tap.proxy.AppStateHolder +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.runCatching + +/** + * Paging source that get tokens by Tangem Tech API + * + * @property api Tangem Tech API + * @property dispatchers coroutine dispatchers provider + * @property reduxStateHolder redux state holder + * @property searchText search text + */ +internal class TangemApiTokensPagingSource( + private val api: TangemTechApi, + private val dispatchers: CoroutineDispatcherProvider, + private val reduxStateHolder: AppStateHolder, + private val searchText: String?, +) : PagingSource() { + + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition?.let { anchorPosition -> + state.closestPageToPosition(anchorPosition)?.prevKey?.plus(other = 1) + ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(other = 1) + } + } + + override suspend fun load(params: LoadParams): LoadResult { + val page = params.key ?: 0 + + return runCatching(dispatchers.io) { + val supportedBlockchains = reduxStateHolder.scanResponse?.card?.supportedBlockchains() + ?: Blockchain.values().toList() + + api.getCoins( + networkIds = supportedBlockchains.joinToString(separator = ",", transform = Blockchain::toNetworkId), + active = true, + searchText = searchText, + offset = page * params.loadSize, + limit = params.loadSize, + ) + }.fold( + onSuccess = { response -> + LoadResult.Page( + data = CoinsResponseConverter.convert(response), + prevKey = if (page == 0) null else page.minus(other = 1), + nextKey = if (response.coins.isEmpty()) null else page.plus(other = 1), + ) + }, + onFailure = { LoadResult.Error(it) }, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/data/TestnetTokensPagingSource.kt b/app/src/main/java/com/tangem/tap/features/tokens/data/TestnetTokensPagingSource.kt new file mode 100644 index 0000000000..87943ee140 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/data/TestnetTokensPagingSource.kt @@ -0,0 +1,43 @@ +package com.tangem.tap.features.tokens.data + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import com.tangem.datasource.local.testnet.TestnetTokensStorage +import com.tangem.datasource.local.testnet.models.TestnetTokensConfig +import com.tangem.tap.features.tokens.data.converters.TestnetTokensConfigConverter +import com.tangem.tap.features.tokens.domain.models.Token + +/** + * Paging source that get tokens by testnet tokens config + * + * @property testnetTokensStorage testnet tokens config storage + * @property searchText search text + */ +internal class TestnetTokensPagingSource( + private val testnetTokensStorage: TestnetTokensStorage, + private val searchText: String?, +) : PagingSource() { + + override fun getRefreshKey(state: PagingState): Int? = null + + override suspend fun load(params: LoadParams): LoadResult { + return LoadResult.Page( + data = TestnetTokensConfigConverter.convert( + value = testnetTokensStorage.getConfig().searchByText(searchText), + ), + prevKey = null, + nextKey = null, + ) + } + + private fun TestnetTokensConfig.searchByText(searchText: String?): TestnetTokensConfig { + if (searchText.isNullOrBlank()) return this + + return copy( + tokens = tokens.filter { token -> + token.symbol.contains(other = searchText, ignoreCase = true) || + token.name.contains(other = searchText, ignoreCase = true) + }, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/data/converters/CoinsResponseConverter.kt b/app/src/main/java/com/tangem/tap/features/tokens/data/converters/CoinsResponseConverter.kt new file mode 100644 index 0000000000..9fa6492d80 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/data/converters/CoinsResponseConverter.kt @@ -0,0 +1,37 @@ +package com.tangem.tap.features.tokens.data.converters + +import com.tangem.blockchain.common.Blockchain +import com.tangem.datasource.api.tangemTech.models.CoinsResponse +import com.tangem.domain.common.extensions.fromNetworkId +import com.tangem.tap.domain.tokens.getIconUrl +import com.tangem.tap.features.tokens.domain.models.Token +import com.tangem.utils.converter.Converter + +/** + * Converter from data model [CoinsResponse] to list of domain models [Token] + * +[REDACTED_AUTHOR] + */ +internal object CoinsResponseConverter : Converter> { + + override fun convert(value: CoinsResponse): List { + return value.coins.map { token -> + Token( + id = token.id, + name = token.name, + symbol = token.symbol, + iconUrl = getIconUrl(token.id, value.imageHost), + networks = token.networks.mapNotNull { network -> + val blockchain = Blockchain.fromNetworkId(network.networkId) ?: return@mapNotNull null + + Token.Network( + id = network.networkId, + blockchain = blockchain, + address = network.contractAddress, + iconUrl = getIconUrl(network.networkId, value.imageHost), + ) + }, + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/data/converters/TestnetTokensConfigConverter.kt b/app/src/main/java/com/tangem/tap/features/tokens/data/converters/TestnetTokensConfigConverter.kt new file mode 100644 index 0000000000..6a3b684b51 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/data/converters/TestnetTokensConfigConverter.kt @@ -0,0 +1,37 @@ +package com.tangem.tap.features.tokens.data.converters + +import com.tangem.blockchain.common.Blockchain +import com.tangem.datasource.local.testnet.models.TestnetTokensConfig +import com.tangem.domain.common.extensions.fromNetworkId +import com.tangem.tap.domain.tokens.getIconUrl +import com.tangem.tap.features.tokens.domain.models.Token +import com.tangem.utils.converter.Converter + +/** + * Converter from data model [TestnetTokensConfig] to list of domain models [Token] + * +[REDACTED_AUTHOR] + */ +internal object TestnetTokensConfigConverter : Converter> { + + override fun convert(value: TestnetTokensConfig): List { + return value.tokens.map { token -> + Token( + id = token.id, + name = token.name, + symbol = token.symbol, + iconUrl = getIconUrl(id = token.id, imageHost = null), + networks = token.networks?.mapNotNull { network -> + val blockchain = Blockchain.fromNetworkId(network.id) ?: return@mapNotNull null + + Token.Network( + id = network.id, + blockchain = blockchain, + address = network.address, + iconUrl = getIconUrl(id = network.id, imageHost = null), + ) + }.orEmpty(), + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/di/TokensListFeatureTogglesModule.kt b/app/src/main/java/com/tangem/tap/features/tokens/di/TokensListFeatureTogglesModule.kt new file mode 100644 index 0000000000..be1a69cc5b --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/di/TokensListFeatureTogglesModule.kt @@ -0,0 +1,24 @@ +package com.tangem.tap.features.tokens.di + +import com.tangem.core.featuretoggle.manager.FeatureTogglesManager +import com.tangem.tap.features.tokens.api.featuretoggles.TokensListFeatureToggles +import com.tangem.tap.features.tokens.featuretoggles.DefaultTokensListFeatureToggles +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +/** +[REDACTED_AUTHOR] + */ +@Module +@InstallIn(SingletonComponent::class) +internal object TokensListFeatureTogglesModule { + + @Provides + @Singleton + fun providesTokensListFeatureToggles(featureTogglesManager: FeatureTogglesManager): TokensListFeatureToggles { + return DefaultTokensListFeatureToggles(featureTogglesManager) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/di/TokensListRepositoryModule.kt b/app/src/main/java/com/tangem/tap/features/tokens/di/TokensListRepositoryModule.kt new file mode 100644 index 0000000000..e71a3a6531 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/di/TokensListRepositoryModule.kt @@ -0,0 +1,37 @@ +package com.tangem.tap.features.tokens.di + +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.local.testnet.TestnetTokensStorage +import com.tangem.tap.features.tokens.data.DefaultTokensListRepository +import com.tangem.tap.features.tokens.domain.TokensListRepository +import com.tangem.tap.proxy.AppStateHolder +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +/** +[REDACTED_AUTHOR] + */ +@Module +@InstallIn(SingletonComponent::class) +internal object TokensListRepositoryModule { + + @Provides + @Singleton + fun providesTokensListRepository( + tangemTechApi: TangemTechApi, + dispatchers: CoroutineDispatcherProvider, + reduxStateHolder: AppStateHolder, + testnetTokensStorage: TestnetTokensStorage, + ): TokensListRepository { + return DefaultTokensListRepository( + tangemTechApi = tangemTechApi, + dispatchers = dispatchers, + reduxStateHolder = reduxStateHolder, + testnetTokensStorage = testnetTokensStorage, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/domain/TokensListRepository.kt b/app/src/main/java/com/tangem/tap/features/tokens/domain/TokensListRepository.kt new file mode 100644 index 0000000000..95fdde59ff --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/domain/TokensListRepository.kt @@ -0,0 +1,20 @@ +package com.tangem.tap.features.tokens.domain + +import androidx.paging.PagingData +import com.tangem.tap.features.tokens.domain.models.Token +import kotlinx.coroutines.flow.Flow + +/** + * Repository of tokens list feature + * +[REDACTED_AUTHOR] + */ +internal interface TokensListRepository { + + /** + * Get available tokens list + * + * @param searchText search text + */ + fun getAvailableTokens(searchText: String?): Flow> +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/domain/models/Token.kt b/app/src/main/java/com/tangem/tap/features/tokens/domain/models/Token.kt new file mode 100644 index 0000000000..d5724c314c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/domain/models/Token.kt @@ -0,0 +1,40 @@ +package com.tangem.tap.features.tokens.domain.models + +import com.tangem.blockchain.common.Blockchain + +/** + * Domain model of token for tokens list screen + * + * @property id token id + * @property name token name + * @property symbol token brief name. Example, "BTC" + * @property iconUrl token icon url + * @property networks token networks + * +[REDACTED_AUTHOR] + */ +internal data class Token( + val id: String, + val name: String, + val symbol: String, + val iconUrl: String, + val networks: List, +) { + + /** + * Domain model of network for tokens list screen + * + * @property id network id + * @property blockchain blockchain + * @property address address. If address equals null, it means it is the main network of token + * @property iconUrl network icon url + * +[REDACTED_AUTHOR] + */ + data class Network( + val id: String, + val blockchain: Blockchain, + val address: String?, + val iconUrl: String, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/featuretoggles/DefaultTokensListFeatureToggles.kt b/app/src/main/java/com/tangem/tap/features/tokens/featuretoggles/DefaultTokensListFeatureToggles.kt new file mode 100644 index 0000000000..eedb10b4a9 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/featuretoggles/DefaultTokensListFeatureToggles.kt @@ -0,0 +1,19 @@ +package com.tangem.tap.features.tokens.featuretoggles + +import com.tangem.core.featuretoggle.manager.FeatureTogglesManager +import com.tangem.tap.features.tokens.api.featuretoggles.TokensListFeatureToggles + +/** + * Default implementation of TokensList feature toggles + * + * @property featureTogglesManager manager for getting information about the availability of feature toggles + * +[REDACTED_AUTHOR] + */ +internal class DefaultTokensListFeatureToggles( + private val featureTogglesManager: FeatureTogglesManager, +) : TokensListFeatureToggles { + + override val isRedesignedScreenEnabled: Boolean + get() = featureTogglesManager.isFeatureEnabled(name = "REDESIGNED_TOKEN_LIST_SCREEN_ENABLED") +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/TokensListFragment.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/TokensListFragment.kt new file mode 100644 index 0000000000..0c66bbcbea --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/TokensListFragment.kt @@ -0,0 +1,49 @@ +package com.tangem.tap.features.tokens.presentation + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.core.view.WindowCompat +import androidx.fragment.app.Fragment +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.transition.TransitionInflater +import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.features.tokens.presentation.ui.AddTokensScreen +import com.tangem.tap.features.tokens.presentation.viewmodels.TokensListViewModel +import com.tangem.wallet.R +import dagger.hilt.android.AndroidEntryPoint + +/** + * Fragment with list of tokens + * +[REDACTED_AUTHOR] + */ +@AndroidEntryPoint +internal class TokensListFragment : Fragment() { + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) } + + with(TransitionInflater.from(requireContext())) { + enterTransition = inflateTransition(R.transition.fade) + exitTransition = inflateTransition(R.transition.fade) + } + + return ComposeView(inflater.context).apply { + setContent { + isTransitionGroup = true + + val viewModel = hiltViewModel().apply { + subscribeOnReduxEvents(lifecycle = LocalLifecycleOwner.current.lifecycle) + } + + TangemTheme { + AddTokensScreen(stateHolder = viewModel.uiState) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensNetworkItemState.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/NetworkItemState.kt similarity index 54% rename from app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensNetworkItemState.kt rename to app/src/main/java/com/tangem/tap/features/tokens/presentation/states/NetworkItemState.kt index c0df838d4d..c11142b85a 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensNetworkItemState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/NetworkItemState.kt @@ -1,11 +1,13 @@ package com.tangem.tap.features.tokens.presentation.states +import com.tangem.tap.features.tokens.redux.ContractAddress + /** * Network item state * [REDACTED_AUTHOR] */ -sealed interface AddTokensNetworkItemState { +sealed interface NetworkItemState { /** Network name */ val name: String @@ -23,6 +25,7 @@ sealed interface AddTokensNetworkItemState { * Network item state that is available for read * * @property name network name + * @property protocolName network protocol name * @property iconResId network icon id from resources * @property isMainNetwork flag that determines if the network is the main network for the token */ @@ -31,25 +34,30 @@ sealed interface AddTokensNetworkItemState { override val protocolName: String, override val iconResId: Int, override val isMainNetwork: Boolean, - ) : AddTokensNetworkItemState + ) : NetworkItemState /** * Network item state that is available for read and edit * - * @property name network name - * @property iconResId network icon id from resources - * @property isMainNetwork flag that determines if the network is the main network for the token - * @property isAdded flag that determines if the user has saved the token - * @property networkId network id - * @property onToggleClick lambda be invoked when switch is been toggled + * @property name network name + * @property protocolName network protocol name + * @property iconResId network icon id from resources + * @property isMainNetwork flag that determines if the network is the main network for the token + * @property isAdded flag that determines if the user has saved the token + * @property networkId network id + * @property contractAddress contract address + * @property onToggleClick lambda be invoked when switch is been toggled + * @property onNetworkClick lambda be invoked when network item is been clicked */ - data class EditAccess( + data class ManageAccess( override val name: String, override val protocolName: String, override val iconResId: Int, override val isMainNetwork: Boolean, val isAdded: Boolean, val networkId: String, - val onToggleClick: (String) -> Unit, - ) : AddTokensNetworkItemState + val contractAddress: ContractAddress?, + val onToggleClick: (String, String) -> Unit, + val onNetworkClick: () -> Unit, + ) : NetworkItemState } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokenItemModel.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokenItemModel.kt deleted file mode 100644 index 07e0af08f0..0000000000 --- a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokenItemModel.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.tangem.tap.features.tokens.presentation.states - -/** - * Token model - * - * @property name token name - * @property iconUrl token icon url - * @property networks list of networks - */ -data class TokenItemModel( - val name: String, - val iconUrl: String, - val networks: List, -) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokenItemState.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokenItemState.kt new file mode 100644 index 0000000000..5ce98ed4f0 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokenItemState.kt @@ -0,0 +1,48 @@ +package com.tangem.tap.features.tokens.presentation.states + +import kotlinx.collections.immutable.ImmutableList + +/** + * Network item state + * +[REDACTED_AUTHOR] + */ +sealed interface TokenItemState { + + /** Token name */ + val name: String + + /** Token icon url */ + val iconUrl: String + + /** List of networks */ + val networks: ImmutableList + + /** + * Token item state that is available for read + * + * @property name token name + * @property iconUrl token icon url + * @property networks list of networks that is available for read + */ + data class ReadAccess( + override val name: String, + override val iconUrl: String, + override val networks: ImmutableList, + ) : TokenItemState + + /** + * Token item state that is available for read and edit + * + * @property name token name + * @property iconUrl token icon url + * @property networks list of networks is available for read and edit + * @property id token id + */ + data class ManageAccess( + override val name: String, + override val iconUrl: String, + override val networks: ImmutableList, + val id: String, + ) : TokenItemState +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensStateHolder.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListStateHolder.kt similarity index 59% rename from app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensStateHolder.kt rename to app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListStateHolder.kt index 2db2b8bc59..0cf5c4d03a 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensStateHolder.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListStateHolder.kt @@ -1,21 +1,23 @@ package com.tangem.tap.features.tokens.presentation.states +import kotlinx.collections.immutable.ImmutableList + /** - * State holder for adding token screen + * State holder for screen with list of tokens * [REDACTED_AUTHOR] */ -internal sealed interface AddTokensStateHolder { +internal sealed interface TokensListStateHolder { /** Toolbar state */ - val toolbarState: AddTokensToolbarState + val toolbarState: TokensListToolbarState /** * Util function that allow to make a copy * * @param toolbarState toolbar state */ - fun copySealed(toolbarState: AddTokensToolbarState): AddTokensStateHolder { + fun copySealed(toolbarState: TokensListToolbarState): TokensListStateHolder { return when (this) { is ManageAccess -> copy(toolbarState = toolbarState) is Loading -> copy(toolbarState = toolbarState) @@ -28,7 +30,7 @@ internal sealed interface AddTokensStateHolder { * * @property toolbarState toolbar state */ - data class Loading(override val toolbarState: AddTokensToolbarState) : AddTokensStateHolder + data class Loading(override val toolbarState: TokensListToolbarState) : TokensListStateHolder /** * State screen that is available only for read @@ -37,9 +39,9 @@ internal sealed interface AddTokensStateHolder { * @property tokens tokens list */ data class ReadAccess( - override val toolbarState: AddTokensToolbarState, - override val tokens: List, - ) : AddTokensStateHolder, TokensListVisibility + override val toolbarState: TokensListToolbarState, + override val tokens: ImmutableList, + ) : TokensListStateHolder, TokensListVisibility /** * State screen that is available for read and edit @@ -49,8 +51,8 @@ internal sealed interface AddTokensStateHolder { * @property onSaveButtonClick callback to be invoked when SaveButton is being clicked */ data class ManageAccess( - override val toolbarState: AddTokensToolbarState, - override val tokens: List, + override val toolbarState: TokensListToolbarState, + override val tokens: ImmutableList, val onSaveButtonClick: () -> Unit, - ) : AddTokensStateHolder, TokensListVisibility + ) : TokensListStateHolder, TokensListVisibility } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensToolbarState.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListToolbarState.kt similarity index 93% rename from app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensToolbarState.kt rename to app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListToolbarState.kt index 8a21094acc..532c0739cf 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/AddTokensToolbarState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListToolbarState.kt @@ -1,7 +1,7 @@ package com.tangem.tap.features.tokens.presentation.states /** Toolbar state */ -sealed interface AddTokensToolbarState { +sealed interface TokensListToolbarState { /** Callback to be invoked when BackButton is being clicked */ val onBackButtonClick: () -> Unit @@ -10,7 +10,7 @@ sealed interface AddTokensToolbarState { val onSearchButtonClick: () -> Unit /** Toolbar state as title */ - sealed interface Title : AddTokensToolbarState { + sealed interface Title : TokensListToolbarState { /** Toolbar title id from resources */ val titleResId: Int @@ -36,7 +36,7 @@ sealed interface AddTokensToolbarState { * @property onSearchButtonClick callback to be invoked when SearchButton is being clicked * @property onAddCustomTokenClick callback to be invoked when AddCustomTokenButton is being clicked */ - data class EditAccess( + data class ManageAccess( override val titleResId: Int, override val onBackButtonClick: () -> Unit, override val onSearchButtonClick: () -> Unit, @@ -59,5 +59,5 @@ sealed interface AddTokensToolbarState { val value: String, val onValueChange: (String) -> Unit, val onCleanButtonClick: () -> Unit, - ) : AddTokensToolbarState + ) : TokensListToolbarState } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListVisibility.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListVisibility.kt index b1bd56a96e..4062066ad3 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListVisibility.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/states/TokensListVisibility.kt @@ -1,8 +1,10 @@ package com.tangem.tap.features.tokens.presentation.states +import kotlinx.collections.immutable.ImmutableList + /** Marker interface for states that have a list of tokens */ sealed interface TokensListVisibility { /** Tokens list */ - val tokens: List + val tokens: ImmutableList } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/AddTokensScreen.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/AddTokensScreen.kt new file mode 100644 index 0000000000..a691d057e6 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/AddTokensScreen.kt @@ -0,0 +1,180 @@ +package com.tangem.tap.features.tokens.presentation.ui + +import androidx.activity.compose.BackHandler +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.FabPosition +import androidx.compose.material.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.components.PrimaryButton +import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.common.compose.extensions.OnBottomReached +import com.tangem.tap.features.tokens.presentation.states.TokenItemState +import com.tangem.tap.features.tokens.presentation.states.TokensListStateHolder +import com.tangem.tap.features.tokens.presentation.states.TokensListToolbarState +import com.tangem.tap.features.tokens.presentation.states.TokensListVisibility +import com.tangem.tap.features.tokens.redux.TokensAction +import com.tangem.tap.store +import com.tangem.wallet.R +import kotlinx.collections.immutable.persistentListOf + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun AddTokensScreen(stateHolder: TokensListStateHolder) { + BackHandler(onBack = stateHolder.toolbarState.onBackButtonClick) + + Scaffold( + topBar = { AddTokensToolbar(state = stateHolder.toolbarState) }, + floatingActionButton = { + if (stateHolder is TokensListStateHolder.ManageAccess) { + SaveChangesButton(onClick = stateHolder.onSaveButtonClick) + } + }, + floatingActionButtonPosition = FabPosition.Center, + ) { scaffoldPadding -> + // This is a hack because AnimatedContent trigger recomposition if stateHolder content is changed + AnimatedVisibility( + visible = stateHolder is TokensListVisibility, + enter = fadeIn(), + exit = fadeOut(), + ) { + if (stateHolder is TokensListVisibility) { + TokensListContent( + stateHolder = stateHolder, + scaffoldPadding = scaffoldPadding, + ) + } + } + + AnimatedVisibility( + visible = stateHolder is TokensListStateHolder.Loading, + enter = fadeIn(), + exit = fadeOut(), + ) { + LoadingContent() + } + } +} + +@Composable +private fun LoadingContent() { + Box( + modifier = Modifier + .fillMaxSize() + .background(color = TangemColorPalette.White), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator(color = TangemColorPalette.Meadow) + } +} + +@Composable +private fun TokensListContent(stateHolder: TokensListVisibility, scaffoldPadding: PaddingValues) { + val state = rememberLazyListState().apply { + OnBottomReached(loadMoreThreshold = 40) { + store.dispatch(TokensAction.LoadMore(scanResponse = store.state.globalState.scanResponse)) + } + } + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(scaffoldPadding), + state, + ) { + items( + items = stateHolder.tokens, + key = TokenItemState::name, + itemContent = { TokenItem(model = it) }, + ) + } +} + +@Composable +private fun SaveChangesButton(onClick: () -> Unit) { + PrimaryButton( + modifier = Modifier + .imePadding() + .padding(horizontal = TangemTheme.dimens.spacing16) + .fillMaxWidth(), + text = stringResource(id = R.string.common_save_changes), + onClick = onClick, + ) +} + +@Preview +@Composable +private fun Preview_AddTokensScreen_Loading() { + TangemTheme { + AddTokensScreen( + stateHolder = TokensListStateHolder.Loading( + toolbarState = TokensListToolbarState.Title.ManageAccess( + titleResId = R.string.main_manage_tokens, + onBackButtonClick = {}, + onSearchButtonClick = {}, + onAddCustomTokenClick = {}, + ), + ), + ) + } +} + +@Preview +@Composable +private fun Preview_AddTokensScreen_ManageAccess() { + TangemTheme { + AddTokensScreen( + stateHolder = TokensListStateHolder.ManageAccess( + toolbarState = TokensListToolbarState.Title.ManageAccess( + titleResId = R.string.main_manage_tokens, + onBackButtonClick = {}, + onSearchButtonClick = {}, + onAddCustomTokenClick = {}, + ), + tokens = persistentListOf( + TokenListPreviewData.createManageToken(), + TokenListPreviewData.createManageToken(), + ), + onSaveButtonClick = {}, + ), + ) + } +} + +@Preview +@Composable +private fun Preview_AddTokensScreen_ReadAccess() { + TangemTheme { + AddTokensScreen( + stateHolder = TokensListStateHolder.ReadAccess( + toolbarState = TokensListToolbarState.Title.ReadAccess( + titleResId = R.string.search_tokens_title, + onBackButtonClick = {}, + onSearchButtonClick = {}, + ), + tokens = persistentListOf( + TokenListPreviewData.createReadToken(), + TokenListPreviewData.createReadToken(), + ), + ), + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/AddTokensToolbar.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/AddTokensToolbar.kt new file mode 100644 index 0000000000..a79d8cb8b4 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/AddTokensToolbar.kt @@ -0,0 +1,212 @@ +package com.tangem.tap.features.tokens.presentation.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Text +import androidx.compose.material.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.sp +import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.features.tokens.presentation.states.TokensListToolbarState +import com.tangem.tap.features.tokens.presentation.states.TokensListToolbarState.SearchInputField +import com.tangem.tap.features.tokens.presentation.states.TokensListToolbarState.Title +import com.tangem.wallet.R +import kotlinx.coroutines.delay + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun AddTokensToolbar(state: TokensListToolbarState) { + TopAppBar(backgroundColor = TangemTheme.colors.background.secondary) { + IconButton(onClick = state.onBackButtonClick) { + Icon( + painter = painterResource(id = R.drawable.ic_back_24), + contentDescription = "Go back", + tint = TangemTheme.colors.icon.secondary, + ) + } + + when (state) { + is Title -> TitleContent(state = state, modifier = Modifier.weight(1f)) + is SearchInputField -> InputContent(state = state, modifier = Modifier.weight(1f)) + } + } +} + +@Composable +private fun TitleContent(state: Title, modifier: Modifier = Modifier) { + Text( + text = stringResource(id = state.titleResId), + modifier = modifier.padding(horizontal = TangemTheme.dimens.spacing26), + color = TangemTheme.colors.text.primary1, + maxLines = 1, + style = TangemTheme.typography.h3, + ) + + IconButton(onClick = state.onSearchButtonClick) { + Icon( + painter = painterResource(id = R.drawable.ic_search_24), + contentDescription = "Search", + tint = TangemTheme.colors.icon.secondary, + ) + } + + if (state is Title.ManageAccess) { + IconButton(onClick = state.onAddCustomTokenClick) { + Icon( + painter = painterResource(id = R.drawable.ic_plus_24), + contentDescription = "Add custom token", + tint = TangemTheme.colors.icon.secondary, + ) + } + } +} + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +private fun InputContent(state: SearchInputField, modifier: Modifier = Modifier) { + val focusRequester = remember { FocusRequester() } + + BasicTextField( + value = state.value, + onValueChange = state.onValueChange, + modifier = modifier.focusRequester(focusRequester), + textStyle = TangemTheme.typography.subtitle1.copy(fontWeight = FontWeight.Normal), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text, imeAction = ImeAction.Search), + keyboardActions = KeyboardActions(onSearch = { state.onSearchButtonClick() }), + singleLine = true, + maxLines = 1, + cursorBrush = SolidColor(value = TangemTheme.colors.stroke.secondary), + ) { innerTextField -> + Row(verticalAlignment = Alignment.CenterVertically) { + Box( + modifier = Modifier + .weight(1f) + .padding( + start = TangemTheme.dimens.spacing28, + top = TangemTheme.dimens.spacing2, + end = TangemTheme.dimens.spacing16, + ), + ) { + Hint(value = state.value) + innerTextField() + } + + IconButton(onClick = state.onCleanButtonClick) { + Icon( + painter = painterResource(id = R.drawable.ic_cross_rounded_24), + contentDescription = "Clean entered value", + tint = TangemTheme.colors.icon.secondary, + ) + } + } + } + + // This is a hack because Compose can't show the keyboard if the input field is not found. + // So first I request focus and make a delay and then show the keyboard. + val keyboardManager = LocalSoftwareKeyboardController.current + LaunchedEffect(keyboardManager) { + focusRequester.requestFocus() + delay(timeMillis = 100) + keyboardManager?.show() + } +} + +@Composable +private fun Hint(value: String) { + if (value.isBlank()) { + Row( + modifier = Modifier.padding(start = TangemTheme.dimens.spacing4), + horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing4), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_search_24), + contentDescription = null, + tint = TangemColorPalette.Dark1, + ) + Text( + text = stringResource(id = R.string.common_search), + modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing2), + color = TangemTheme.colors.text.tertiary, + maxLines = 1, + // FIXME("Incorrect typography. Replace with typography from design system") + style = TangemTheme.typography.subtitle1.copy(fontSize = 18.sp, fontWeight = FontWeight.Normal), + ) + } + } +} + +@Preview +@Composable +private fun Preview_AddTokensToolbar_EditAccess() { + TangemTheme { + AddTokensToolbar( + state = Title.ManageAccess( + titleResId = R.string.main_manage_tokens, + onBackButtonClick = {}, + onSearchButtonClick = {}, + onAddCustomTokenClick = {}, + ), + ) + } +} + +@Preview +@Composable +private fun Preview_AddTokensToolbar_ReadAccess() { + TangemTheme { + AddTokensToolbar( + state = Title.ReadAccess( + titleResId = R.string.search_tokens_title, + onBackButtonClick = {}, + onSearchButtonClick = {}, + ), + ) + } +} + +@Preview +@Composable +private fun Preview_AddTokensToolbar_SearchInputField() { + var value by remember { mutableStateOf("") } + + TangemTheme { + AddTokensToolbar( + state = SearchInputField( + onBackButtonClick = {}, + onSearchButtonClick = {}, + value = value, + onValueChange = { value = it }, + onCleanButtonClick = { value = "" }, + ), + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/BriefNetworksList.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/BriefNetworksList.kt new file mode 100644 index 0000000000..e44b3def87 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/BriefNetworksList.kt @@ -0,0 +1,79 @@ +package com.tangem.tap.features.tokens.presentation.ui + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.key +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.features.tokens.presentation.states.NetworkItemState +import kotlinx.collections.immutable.ImmutableCollection + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun BriefNetworksList( + isCollapsed: Boolean, + networks: ImmutableCollection, + modifier: Modifier = Modifier, +) { + AnimatedVisibility( + visible = isCollapsed, + modifier = modifier, + enter = fadeIn(), + exit = fadeOut(), + ) { + Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4)) { + networks.forEach { + key(NetworkItemState::name) { + BriefNetworkItem(model = it) + } + } + } + } +} + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun BriefNetworkItem(model: NetworkItemState) { + Box(modifier = Modifier.size(size = TangemTheme.dimens.size20)) { + Image( + painter = painterResource(id = model.iconResId), + contentDescription = null, + modifier = Modifier.size(size = TangemTheme.dimens.size20), + ) + + if (model.isMainNetwork) { + Box( + modifier = Modifier + .align(Alignment.TopEnd) + .size(TangemTheme.dimens.size7) + .clip(CircleShape) + .background(TangemColorPalette.White), + contentAlignment = Alignment.Center, + ) { + Box( + modifier = Modifier + .size(TangemTheme.dimens.size5) + .clip(CircleShape) + .background(TangemColorPalette.Meadow), + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/DetailedNetworksList.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/DetailedNetworksList.kt new file mode 100644 index 0000000000..e404aec20e --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/DetailedNetworksList.kt @@ -0,0 +1,158 @@ +package com.tangem.tap.features.tokens.presentation.ui + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.Switch +import androidx.compose.material.SwitchDefaults +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.key +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.sp +import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.features.tokens.presentation.states.NetworkItemState +import kotlinx.collections.immutable.ImmutableCollection + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun DetailedNetworksList( + isExpanded: Boolean, + tokenId: String?, + networks: ImmutableCollection, + modifier: Modifier = Modifier, +) { + AnimatedVisibility( + visible = isExpanded, + modifier = modifier, + enter = fadeIn() + expandVertically(), + exit = shrinkVertically() + fadeOut(), + ) { + Column { + networks.forEachIndexed { index, network -> + key(network.name) { + DetailedNetworkItem(model = network, tokenId = tokenId, isLastItem = networks.size - 1 == index) + } + } + } + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +private fun DetailedNetworkItem(model: NetworkItemState, tokenId: String?, isLastItem: Boolean) { + val clipboardManager = LocalClipboardManager.current + val itemHeight = TangemTheme.dimens.size50 + + Row( + modifier = Modifier + .combinedClickable( + enabled = model is NetworkItemState.ManageAccess, + onLongClick = { + if (model is NetworkItemState.ManageAccess && model.contractAddress != null) { + clipboardManager.setText(AnnotatedString(text = model.contractAddress)) + model.onNetworkClick() + } + }, + onClick = {}, + indication = null, + interactionSource = remember { MutableInteractionSource() }, + ) + .fillMaxWidth() + .heightIn(min = itemHeight) + .padding(start = TangemTheme.dimens.spacing38), + verticalAlignment = Alignment.CenterVertically, + ) { + NetworkItemArrow(itemHeight = itemHeight, isLastItem = isLastItem) + Spacer(modifier = Modifier.width(TangemTheme.dimens.spacing16)) + BriefNetworkItem(model = model) + Spacer(modifier = Modifier.width(TangemTheme.dimens.spacing6)) + NetworkTitle(model = model) + + if (model is NetworkItemState.ManageAccess) { + Switch( + checked = model.isAdded, + onCheckedChange = { model.onToggleClick(requireNotNull(tokenId), model.networkId) }, + modifier = Modifier.padding(start = TangemTheme.dimens.spacing16, end = TangemTheme.dimens.spacing8), + colors = SwitchDefaults.colors( + checkedThumbColor = TangemColorPalette.Meadow, + ), + ) + } + } +} + +@Composable +private fun RowScope.NetworkTitle(model: NetworkItemState) { + Text( + modifier = Modifier.weight(1f), + text = buildAnnotatedString { + append(text = model.name) + append(text = " ") + withStyle( + style = SpanStyle( + fontWeight = FontWeight.Normal, + color = if (model.isMainNetwork) TangemColorPalette.Meadow else TangemColorPalette.Dark2, + ), + ) { + append(text = model.protocolName) + } + }, + fontWeight = FontWeight.SemiBold, + fontSize = 13.sp, + color = if (model is NetworkItemState.ManageAccess && model.isAdded) { + TangemColorPalette.Black + } else { + TangemColorPalette.Dark2 + }, + ) +} + +@Preview +@Composable +private fun Preview_DetailedNetworksList_ManageAccess() { + TangemTheme { + DetailedNetworksList( + isExpanded = true, + tokenId = null, + networks = TokenListPreviewData.createManageNetworksList(), + ) + } +} + +@Preview +@Composable +private fun Preview_DetailedNetworksList_ReadAccess() { + TangemTheme { + DetailedNetworksList( + isExpanded = true, + tokenId = null, + networks = TokenListPreviewData.createReadNetworksList(), + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/NetworkItemArrow.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/NetworkItemArrow.kt new file mode 100644 index 0000000000..5aadb66fa1 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/NetworkItemArrow.kt @@ -0,0 +1,60 @@ +package com.tangem.tap.features.tokens.presentation.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.res.TangemTheme +import com.tangem.wallet.R + +private const val SPECIAL_HEIGHT_3_5 = 3.5 + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun NetworkItemArrow(itemHeight: Dp, isLastItem: Boolean) { + Box(modifier = Modifier.height(height = itemHeight)) { + if (!isLastItem) { + Box( + modifier = Modifier + .padding(start = TangemTheme.dimens.spacing0_5) + .background(color = TangemTheme.colors.stroke.primary) + .size(width = TangemTheme.dimens.size1, height = itemHeight), + ) + } + + Icon( + painter = painterResource(id = R.drawable.ic_link), + contentDescription = null, + modifier = Modifier.height(height = itemHeight / 2 + SPECIAL_HEIGHT_3_5.dp), + tint = TangemTheme.colors.stroke.primary, + ) + } +} + +@Preview +@Composable +private fun Preview_NetworkItemArrow_Column() { + TangemTheme { + Column( + modifier = Modifier + .fillMaxWidth() + .background(color = TangemTheme.colors.background.primary) + .padding(start = TangemTheme.dimens.size36), + ) { + NetworkItemArrow(itemHeight = TangemTheme.dimens.size62, isLastItem = false) + NetworkItemArrow(itemHeight = TangemTheme.dimens.size62, isLastItem = true) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/TokenItem.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/TokenItem.kt new file mode 100644 index 0000000000..ba0b7959ec --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/TokenItem.kt @@ -0,0 +1,220 @@ +package com.tangem.tap.features.tokens.presentation.ui + +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.animation.with +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.Dimension +import coil.compose.SubcomposeAsyncImage +import coil.request.ImageRequest +import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.common.compose.extensions.toPx +import com.tangem.tap.features.tokens.presentation.states.TokenItemState +import com.tangem.wallet.R + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun TokenItem(model: TokenItemState) { + var isExpanded by rememberSaveable { mutableStateOf(false) } + + ConstraintLayout( + modifier = Modifier + .fillMaxWidth() + .padding(top = TangemTheme.dimens.spacing16), + ) { + val (icon, title, availableNetworksText) = createRefs() + val (briefNetworksList, detailedNetworksList, changeNetworksViewButton) = createRefs() + + val spacing16 = TangemTheme.dimens.spacing16 + val spacing6 = TangemTheme.dimens.spacing6 + + Icon( + name = model.name, + iconUrl = model.iconUrl, + modifier = Modifier.constrainAs(icon) { + top.linkTo(parent.top) + start.linkTo(anchor = parent.start, margin = spacing16) + }, + ) + + Title( + title = model.name, + modifier = Modifier.constrainAs(title) { + top.linkTo(parent.top) + start.linkTo(icon.end, margin = spacing16) + end.linkTo(anchor = changeNetworksViewButton.start, margin = spacing16) + width = Dimension.fillToConstraints + }, + ) + + Subtitle( + isExpanded = isExpanded, + modifier = Modifier.constrainAs(availableNetworksText) { + top.linkTo(title.bottom, margin = spacing6) + start.linkTo(icon.end, margin = spacing16) + end.linkTo(anchor = changeNetworksViewButton.start, margin = spacing16) + width = Dimension.fillToConstraints + }, + ) + + BriefNetworksList( + isCollapsed = !isExpanded, + networks = model.networks, + modifier = Modifier.constrainAs(briefNetworksList) { + top.linkTo(title.bottom, margin = spacing6) + start.linkTo(icon.end, margin = spacing16) + end.linkTo(anchor = changeNetworksViewButton.start, margin = spacing16) + width = Dimension.fillToConstraints + }, + ) + + DetailedNetworksList( + isExpanded = isExpanded, + tokenId = (model as? TokenItemState.ManageAccess)?.id, + networks = model.networks, + modifier = Modifier.constrainAs(detailedNetworksList) { + top.linkTo(anchor = availableNetworksText.bottom, margin = spacing16) + centerHorizontallyTo(parent) + width = Dimension.fillToConstraints + }, + ) + + ChangeNetworksViewButton( + isExpanded = isExpanded, + onClick = { isExpanded = !isExpanded }, + modifier = Modifier.constrainAs(changeNetworksViewButton) { + top.linkTo(parent.top) + end.linkTo(anchor = parent.end, margin = spacing6) + if (!isExpanded) bottom.linkTo(parent.bottom) + }, + ) + } +} + +@Composable +private fun Icon(name: String, iconUrl: String, modifier: Modifier = Modifier) { + val iconModifier = modifier.size(size = TangemTheme.dimens.size46) + + SubcomposeAsyncImage( + modifier = iconModifier, + model = ImageRequest.Builder(context = LocalContext.current) + .size(size = TangemTheme.dimens.size46.toPx().toInt()) + .data(data = iconUrl) + .crossfade(enable = true) + .build(), + contentDescription = null, + loading = { PlaceholderIcon(name = name, modifier = iconModifier) }, + error = { PlaceholderIcon(name = name, modifier = iconModifier) }, + ) +} + +@Composable +private fun PlaceholderIcon(name: String, modifier: Modifier = Modifier) { + Box( + contentAlignment = Alignment.Center, + modifier = modifier.background(TangemTheme.colors.icon.primary1, shape = CircleShape), + ) { + Text( + text = name.firstOrNull()?.titlecase() ?: "", + color = TangemTheme.colors.icon.primary2, + maxLines = 1, + // FIXME("Incorrect typography. Replace with typography from design system") + style = TangemTheme.typography.h3.copy(fontWeight = FontWeight.Bold), + ) + } +} + +@Composable +private fun Title(title: String, modifier: Modifier = Modifier) { + Text( + text = title, + modifier = modifier, + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Start, + maxLines = 1, + style = TangemTheme.typography.body1, + ) +} + +@Composable +private fun Subtitle(isExpanded: Boolean, modifier: Modifier = Modifier) { + AnimatedVisibility( + visible = isExpanded, + modifier = modifier, + enter = fadeIn() + expandVertically(), + exit = shrinkVertically() + fadeOut(), + ) { + Text( + text = stringResource(id = R.string.currency_subtitle_expanded), + color = TangemTheme.colors.text.secondary, + maxLines = 1, + style = TangemTheme.typography.body2, + ) + } +} + +@OptIn(ExperimentalAnimationApi::class) +@Composable +private fun ChangeNetworksViewButton(isExpanded: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) { + IconButton(onClick = onClick, modifier = modifier.size(size = TangemTheme.dimens.size46)) { + AnimatedContent( + targetState = isExpanded, + transitionSpec = { fadeIn() + scaleIn() with scaleOut() + fadeOut() }, + ) { isExpanded -> + Icon( + painter = painterResource( + id = if (isExpanded) R.drawable.ic_arrow_extended else R.drawable.ic_arrow_collapsed, + ), + contentDescription = null, + tint = TangemTheme.colors.icon.secondary, + ) + } + } +} + +@Preview +@Composable +private fun Preview_TokenItem_ManageAccess() { + TangemTheme { + TokenItem(model = TokenListPreviewData.createManageToken()) + } +} + +@Preview +@Composable +private fun Preview_TokenItem_ReadAccess() { + TangemTheme { + TokenItem(model = TokenListPreviewData.createReadToken()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/TokenListPreviewData.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/TokenListPreviewData.kt new file mode 100644 index 0000000000..8eb5cd50ee --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/ui/TokenListPreviewData.kt @@ -0,0 +1,74 @@ +package com.tangem.tap.features.tokens.presentation.ui + +import com.tangem.tap.features.tokens.presentation.states.NetworkItemState +import com.tangem.tap.features.tokens.presentation.states.TokenItemState +import com.tangem.wallet.R +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf + +/** +[REDACTED_AUTHOR] + */ +object TokenListPreviewData { + + fun createManageToken(): TokenItemState.ManageAccess { + return TokenItemState.ManageAccess( + name = "Tether (USDT)", + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/large/tether.png", + networks = createManageNetworksList(), + id = "", + ) + } + + fun createReadToken(): TokenItemState.ReadAccess { + return TokenItemState.ReadAccess( + name = "Tether (USDT)", + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/large/tether.png", + networks = createReadNetworksList(), + ) + } + + fun createManageNetworksList(): ImmutableList { + return persistentListOf( + NetworkItemState.ManageAccess( + name = "Ethereum", + protocolName = "MAIN", + iconResId = R.drawable.ic_eth_no_color, + isMainNetwork = true, + isAdded = true, + networkId = "", + contractAddress = null, + onToggleClick = { _, _ -> }, + onNetworkClick = {}, + ), + NetworkItemState.ManageAccess( + name = "BNB SMART CHAIN", + protocolName = "BEP20", + iconResId = R.drawable.ic_bsc_no_color, + isMainNetwork = false, + isAdded = false, + networkId = "", + contractAddress = null, + onToggleClick = { _, _ -> }, + onNetworkClick = {}, + ), + ) + } + + fun createReadNetworksList(): ImmutableList { + return persistentListOf( + NetworkItemState.ReadAccess( + name = "Ethereum", + protocolName = "MAIN", + iconResId = R.drawable.ic_eth_no_color, + isMainNetwork = true, + ), + NetworkItemState.ReadAccess( + name = "BNB SMART CHAIN", + protocolName = "BEP20", + iconResId = R.drawable.ic_bsc_no_color, + isMainNetwork = false, + ), + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/viewmodels/AddTokensViewModel.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/viewmodels/AddTokensViewModel.kt deleted file mode 100644 index 828ace57c6..0000000000 --- a/app/src/main/java/com/tangem/tap/features/tokens/presentation/viewmodels/AddTokensViewModel.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.tangem.tap.features.tokens.presentation.viewmodels - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.DefaultLifecycleObserver -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.ViewModel -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.features.tokens.presentation.router.AddTokensRouter -import com.tangem.tap.features.tokens.presentation.states.AddTokensStateHolder -import com.tangem.tap.features.tokens.presentation.states.AddTokensToolbarState -import com.tangem.tap.features.tokens.redux.TokensAction -import com.tangem.tap.features.tokens.redux.TokensState -import com.tangem.tap.store -import com.tangem.wallet.R -import dagger.hilt.android.lifecycle.HiltViewModel -import org.rekotlin.StoreSubscriber -import javax.inject.Inject - -/** - * ViewModel for add tokens screen - * - * @property router feature router - * -[REDACTED_AUTHOR] - */ -@HiltViewModel -internal class AddTokensViewModel @Inject constructor( - private val router: AddTokensRouter, -) : ViewModel(), DefaultLifecycleObserver, StoreSubscriber { - - var uiState by mutableStateOf(getInitialUiState()) - private set - - init { - loadContent() - } - - override fun onStop(owner: LifecycleOwner) { - store.unsubscribe(subscriber = this) - } - - override fun onDestroy(owner: LifecycleOwner) { - store.dispatch(TokensAction.ResetState) - } - - override fun newState(state: TokensState) { - uiState = uiState.copySealed( - toolbarState = getToolbarState(hasEditAccess = state.allowToAdd), - ) - } - - private fun loadContent() { - store.subscribe(subscriber = this) { state -> - state - .skipRepeats { old, new -> old.tokensState == new.tokensState } - .select(AppState::tokensState) - } - } - - private fun getInitialUiState(): AddTokensStateHolder { - return AddTokensStateHolder.Loading(toolbarState = getToolbarState(store.state.tokensState.allowToAdd)) - } - - private fun getToolbarState(hasEditAccess: Boolean): AddTokensToolbarState { - return if (hasEditAccess) { - AddTokensToolbarState.Title.EditAccess( - titleResId = R.string.main_manage_tokens, - onBackButtonClick = router::popBackStack, - onSearchButtonClick = ::onSearchButtonClick, - onAddCustomTokenClick = router::openAddCustomTokenScreen, - ) - } else { - AddTokensToolbarState.Title.ReadAccess( - titleResId = R.string.search_tokens_title, - onBackButtonClick = router::popBackStack, - onSearchButtonClick = ::onSearchButtonClick, - ) - } - } - - private fun onSearchButtonClick() { - uiState = when (val state = uiState.toolbarState) { - is AddTokensToolbarState.Title -> { - uiState.copySealed( - toolbarState = AddTokensToolbarState.SearchInputField( - onBackButtonClick = uiState.toolbarState.onBackButtonClick, - onSearchButtonClick = ::onSearchButtonClick, - value = "", - onValueChange = ::onValueChange, - onCleanButtonClick = { onValueChange(newValue = "") }, - ), - ) - } - is AddTokensToolbarState.SearchInputField -> { - store.dispatch(TokensAction.SetSearchInput(state.value)) - uiState.copySealed( - getToolbarState(store.state.tokensState.allowToAdd), - ) - } - } - } - - private fun onValueChange(newValue: String) { - val state = requireNotNull( - value = uiState.toolbarState as? AddTokensToolbarState.SearchInputField, - lazyMessage = { "Impossible to change value in another state" }, - ) - - uiState = uiState.copySealed(toolbarState = state.copy(value = newValue)) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/presentation/viewmodels/TokensListViewModel.kt b/app/src/main/java/com/tangem/tap/features/tokens/presentation/viewmodels/TokensListViewModel.kt new file mode 100644 index 0000000000..1b7c1fc3c0 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/tokens/presentation/viewmodels/TokensListViewModel.kt @@ -0,0 +1,453 @@ +package com.tangem.tap.features.tokens.presentation.viewmodels + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.Token +import com.tangem.core.analytics.Analytics +import com.tangem.core.ui.extensions.getActiveIconRes +import com.tangem.domain.common.extensions.fromNetworkId +import com.tangem.tap.common.analytics.events.AnalyticsParam +import com.tangem.tap.common.analytics.events.ManageTokens +import com.tangem.tap.common.extensions.dispatchDialogShow +import com.tangem.tap.common.extensions.dispatchNotification +import com.tangem.tap.common.extensions.fullNameWithoutTestnet +import com.tangem.tap.common.extensions.getGreyedOutIconRes +import com.tangem.tap.common.extensions.getNetworkName +import com.tangem.tap.common.redux.AppDialog +import com.tangem.tap.common.redux.AppState +import com.tangem.tap.domain.tokens.Contract +import com.tangem.tap.domain.tokens.Currency +import com.tangem.tap.features.tokens.presentation.router.AddTokensRouter +import com.tangem.tap.features.tokens.presentation.states.NetworkItemState +import com.tangem.tap.features.tokens.presentation.states.TokenItemState +import com.tangem.tap.features.tokens.presentation.states.TokensListStateHolder +import com.tangem.tap.features.tokens.presentation.states.TokensListToolbarState +import com.tangem.tap.features.tokens.redux.TokenWithBlockchain +import com.tangem.tap.features.tokens.redux.TokensAction +import com.tangem.tap.features.tokens.redux.TokensState +import com.tangem.tap.features.tokens.ui.compose.fullName +import com.tangem.tap.features.wallet.redux.models.WalletDialog +import com.tangem.tap.store +import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider +import com.tangem.wallet.R +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.rekotlin.StoreSubscriber +import javax.inject.Inject + +/** + * ViewModel for add tokens screen + * + * @property router feature router + * @property dispatchers coroutine dispatchers provider + * +[REDACTED_AUTHOR] + */ +@HiltViewModel +internal class TokensListViewModel @Inject constructor( + private val router: AddTokensRouter, + private val dispatchers: AppCoroutineDispatcherProvider, +) : ViewModel() { + + private val uiStateBuilder = UiStateBuilder() + + var uiState by mutableStateOf(uiStateBuilder.getInitialUiState()) + private set + + private val reduxSubscriber = ReduxSubscriber() + private var debounceJob: Job? = null + + private var originalAddedTokenList: List? = null + private var originalAddedBlockchainList: List? = null + private var addedTokenList: List? = null + private var addedBlockchainList: List? = null + + fun subscribeOnReduxEvents(lifecycle: Lifecycle) { + lifecycle.addObserver(reduxSubscriber) + } + + private object AnalyticsSender { + fun sendWhenTokenAdded(token: Token) { + Analytics.send( + event = ManageTokens.TokenSwitcherChanged( + type = AnalyticsParam.CurrencyType.Token(token), + state = AnalyticsParam.OnOffState.On, + ), + ) + } + + fun sendWhenBlockchainAdded(blockchain: Blockchain) { + Analytics.send( + event = ManageTokens.TokenSwitcherChanged( + type = AnalyticsParam.CurrencyType.Blockchain(blockchain), + state = AnalyticsParam.OnOffState.On, + ), + ) + } + + fun sendWhenTokenRemoved(token: Token) { + Analytics.send( + event = ManageTokens.TokenSwitcherChanged( + type = AnalyticsParam.CurrencyType.Token(token), + state = AnalyticsParam.OnOffState.Off, + ), + ) + } + + fun sendWhenBlockchainRemoved(blockchain: Blockchain) { + Analytics.send( + event = ManageTokens.TokenSwitcherChanged( + type = AnalyticsParam.CurrencyType.Blockchain(blockchain), + state = AnalyticsParam.OnOffState.Off, + ), + ) + } + + fun sendWhenSaveButtonClicked() { + Analytics.send(ManageTokens.ButtonSaveChanges()) + } + } + + private inner class ReduxSubscriber : DefaultLifecycleObserver, StoreSubscriber { + + override fun onStart(owner: LifecycleOwner) { + store.subscribe( + subscriber = this, + transform = { state -> + state + .skipRepeats { old, new -> old.tokensState == new.tokensState } + .select(AppState::tokensState) + }, + ) + } + + override fun onStop(owner: LifecycleOwner) { + store.unsubscribe(subscriber = this) + } + + override fun newState(state: TokensState) { + val isNotOriginalListsInitialized = originalAddedTokenList == null || originalAddedBlockchainList == null + val isNotCurrentListsInitialized = addedTokenList == null || addedBlockchainList == null + + if (isNotOriginalListsInitialized || isNotCurrentListsInitialized) { + originalAddedTokenList = state.addedTokens + originalAddedBlockchainList = state.addedBlockchains + addedTokenList = state.addedTokens + addedBlockchainList = state.addedBlockchains + } + + uiStateBuilder.updateStateByReduxState(state) + } + } + + private inner class UiStateBuilder { + + fun getInitialUiState(): TokensListStateHolder { + return TokensListStateHolder.Loading(toolbarState = getToolbarState()) + } + + fun updateStateByReduxState(state: TokensState) { + uiState = if (state.currencies.isEmpty()) { + TokensListStateHolder.Loading(toolbarState = getToolbarState(reduxState = state)) + } else if (state.allowToAdd) { + TokensListStateHolder.ManageAccess( + toolbarState = getToolbarState(reduxState = state), + tokens = state.currencies.map(::toManageTokenItemState).toImmutableList(), + onSaveButtonClick = { + val notNullAddedTokens = addedTokenList ?: return@ManageAccess + val notNullAddedBlockchains = addedBlockchainList ?: return@ManageAccess + + AnalyticsSender.sendWhenSaveButtonClicked() + store.dispatch(TokensAction.SaveChanges(notNullAddedTokens, notNullAddedBlockchains)) + }, + ) + } else { + TokensListStateHolder.ReadAccess( + toolbarState = getToolbarState(state), + tokens = state.currencies.map(::toReadTokenItemState).toImmutableList(), + ) + } + } + + private fun getToolbarState(reduxState: TokensState = store.state.tokensState): TokensListToolbarState { + val toolbarState = uiState.toolbarState + + return if (reduxState.searchInput != null && toolbarState is TokensListToolbarState.SearchInputField) { + TokensListToolbarState.SearchInputField( + onBackButtonClick = router::popBackStack, + onSearchButtonClick = ::onSearchButtonClick, + value = toolbarState.value, + onValueChange = ::onSearchValueChange, + onCleanButtonClick = ::onCleanButtonClick, + ) + } else if (reduxState.allowToAdd) { + TokensListToolbarState.Title.ManageAccess( + titleResId = R.string.main_manage_tokens, + onBackButtonClick = router::popBackStack, + onSearchButtonClick = ::onSearchButtonClick, + onAddCustomTokenClick = router::openAddCustomTokenScreen, + ) + } else { + TokensListToolbarState.Title.ReadAccess( + titleResId = R.string.search_tokens_title, + onBackButtonClick = router::popBackStack, + onSearchButtonClick = ::onSearchButtonClick, + ) + } + } + + private fun onSearchButtonClick() { + uiState = when (val state = uiState.toolbarState) { + is TokensListToolbarState.Title -> { + uiState.copySealed( + toolbarState = TokensListToolbarState.SearchInputField( + onBackButtonClick = uiState.toolbarState.onBackButtonClick, + onSearchButtonClick = uiState.toolbarState.onSearchButtonClick, + value = "", + onValueChange = ::onSearchValueChange, + onCleanButtonClick = ::onCleanButtonClick, + ), + ) + } + is TokensListToolbarState.SearchInputField -> { + store.dispatch(TokensAction.SetSearchInput(searchInput = state.value)) + uiState.copySealed(toolbarState = getToolbarState()) + } + } + } + + private fun onSearchValueChange(newValue: String) { + (uiState.toolbarState as? TokensListToolbarState.SearchInputField)?.let { state -> + uiState = uiState.copySealed(toolbarState = state.copy(value = newValue)) + } + + debounceJob?.cancel() + debounceJob = viewModelScope.launch(dispatchers.io) { + delay(timeMillis = 800L) + store.dispatch(TokensAction.SetSearchInput(searchInput = newValue)) + } + } + + private fun onCleanButtonClick() { + (uiState.toolbarState as? TokensListToolbarState.SearchInputField)?.let { state -> + if (state.value.isEmpty()) { + uiState = uiState.copySealed(toolbarState = getToolbarState()) + } else { + onSearchValueChange(newValue = "") + } + } + } + + private fun onToggleClick(tokenId: String, networkId: String) { + (uiState as? TokensListStateHolder.ManageAccess)?.let { state -> + val switchedToken = state.tokens.firstOrNull { it.id == tokenId } + val contractAddress = switchedToken?.networks + ?.firstOrNull { it.networkId == networkId } + ?.contractAddress + + val blockchain = Blockchain.fromNetworkId( + networkId = if (contractAddress == null) networkId else tokenId, + ) + + if (blockchain != null && contractAddress == null) { + onBlockchainToggleClick(blockchain) + } else if (contractAddress != null) { + onTokenToggleClick(tokenId, networkId, switchedToken, contractAddress) + } + + updateTokensList() + } + } + + private fun onBlockchainToggleClick(blockchain: Blockchain) { + val isRemoveAction = addedBlockchainList?.contains(blockchain) + + if (isRemoveAction == true) { + val isTokenWithSameBlockchainFound = addedTokenList?.any { it.blockchain == blockchain } + val isAddedOnMainScreen = originalAddedBlockchainList?.contains(blockchain) + + if (isTokenWithSameBlockchainFound == true) { + store.dispatchDialogShow( + WalletDialog.TokensAreLinkedDialog( + currencyTitle = blockchain.name, + currencySymbol = blockchain.currency, + ), + ) + } else if (isAddedOnMainScreen == true) { + store.dispatchDialogShow( + WalletDialog.RemoveWalletDialog( + currencyTitle = blockchain.name, + onOk = { + AnalyticsSender.sendWhenBlockchainAdded(blockchain) + addedBlockchainList = addedBlockchainList?.minus(blockchain) + updateTokensList() + }, + ), + ) + } else { + AnalyticsSender.sendWhenBlockchainRemoved(blockchain) + addedBlockchainList = addedBlockchainList?.minus(blockchain) + } + } else { + AnalyticsSender.sendWhenBlockchainAdded(blockchain) + addedBlockchainList = addedBlockchainList?.plus(blockchain) + } + } + + private fun onTokenToggleClick( + tokenId: String, + networkId: String, + switchedToken: TokenItemState.ManageAccess, + contractAddress: String, + ) { + val currency = store.state.tokensState.currencies.firstOrNull { it.id == tokenId } ?: return + val contract = currency.contracts.firstOrNull { it.networkId == networkId } ?: return + val token = TokenWithBlockchain( + token = Token( + id = switchedToken.id, + name = switchedToken.name, + symbol = currency.symbol, + contractAddress = contractAddress, + decimals = requireNotNull(contract.decimalCount), + ), + blockchain = contract.blockchain, + ) + val isUnsupportedToken = !store.state.tokensState.canHandleToken(token) + val isRemoveAction = addedTokenList?.contains(token) + val isAddedOnMainScreen = originalAddedTokenList?.contains(token) + if (isRemoveAction == true) { + if (isAddedOnMainScreen == true) { + store.dispatchDialogShow( + WalletDialog.RemoveWalletDialog( + currencyTitle = token.token.name, + onOk = { + AnalyticsSender.sendWhenTokenRemoved(token.token) + addedTokenList = addedTokenList?.minus(token) + updateTokensList() + }, + ), + ) + } else { + AnalyticsSender.sendWhenTokenRemoved(token.token) + addedTokenList = addedTokenList?.minus(token) + } + } else { + if (isUnsupportedToken) { + store.dispatchDialogShow( + AppDialog.SimpleOkDialogRes( + headerId = R.string.common_warning, + messageId = R.string.alert_manage_tokens_unsupported_message, + ), + ) + } else { + AnalyticsSender.sendWhenTokenAdded(token.token) + addedTokenList = addedTokenList?.plus(token) + } + } + } + + private fun updateTokensList() { + (uiState as? TokensListStateHolder.ManageAccess)?.let { state -> + val tokens = store.state.tokensState.currencies.mapNotNull { currency -> + state.tokens.firstOrNull { it.id == currency.id }?.copy( + networks = currency.contracts.mapNotNull { contract -> + state.tokens.firstOrNull { it.id == currency.id } + ?.networks?.firstOrNull { it.networkId == contract.networkId } + ?.copy( + isAdded = contract.isAdded(), + iconResId = if (contract.isAdded()) { + getActiveIconRes(contract.blockchain.id) + } else { + contract.blockchain.getGreyedOutIconRes() + }, + ) + }.toImmutableList(), + ) + }.toImmutableList() + + uiState = state.copy(tokens = tokens) + } + } + + private fun toManageTokenItemState(currency: Currency): TokenItemState.ManageAccess { + return TokenItemState.ManageAccess( + name = currency.fullName, + iconUrl = currency.iconUrl, + networks = currency.contracts.map(::toManageNetworkItemState).toImmutableList(), + id = currency.id, + ) + } + + private fun toManageNetworkItemState(contract: Contract): NetworkItemState.ManageAccess { + val isAdded = contract.isAdded() + return NetworkItemState.ManageAccess( + name = contract.blockchain.fullNameWithoutTestnet.uppercase(), + protocolName = if (contract.address == null) { + MAIN_NETWORK_LABEL + } else { + contract.blockchain.getNetworkName().uppercase() + }, + iconResId = if (isAdded) { + getActiveIconRes(contract.blockchain.id) + } else { + contract.blockchain.getGreyedOutIconRes() + }, + isMainNetwork = contract.address == null, + isAdded = isAdded, + networkId = contract.networkId, + contractAddress = contract.address, + onToggleClick = ::onToggleClick, + onNetworkClick = { store.dispatchNotification(R.string.contract_address_copied_message) }, + ) + } + + private fun toReadTokenItemState(currency: Currency): TokenItemState.ReadAccess { + return TokenItemState.ReadAccess( + name = currency.fullName, + iconUrl = currency.iconUrl, + networks = currency.contracts.map(::toReadNetworkItemState).toImmutableList(), + ) + } + + private fun toReadNetworkItemState(contract: Contract): NetworkItemState.ReadAccess { + return NetworkItemState.ReadAccess( + name = contract.blockchain.fullNameWithoutTestnet.uppercase(), + protocolName = if (contract.address == null) { + MAIN_NETWORK_LABEL + } else { + contract.blockchain.getNetworkName().uppercase() + }, + iconResId = if (contract.isAdded()) { + getActiveIconRes(contract.blockchain.id) + } else { + contract.blockchain.getGreyedOutIconRes() + }, + isMainNetwork = contract.address == null, + ) + } + + private fun Contract.isAdded(): Boolean { + return if (address != null) { + addedTokenList?.any { addedToken -> + address == addedToken.token.contractAddress && blockchain == addedToken.blockchain + } + } else { + addedBlockchainList?.contains(blockchain) + } ?: false + } + } + + private companion object { + const val MAIN_NETWORK_LABEL = "MAIN" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt index 39ac838653..78cfc5ac9e 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt @@ -13,26 +13,23 @@ sealed class TokensAction : Action { data class AllowToAddTokens(val allow: Boolean) : TokensAction() - data class LoadCurrencies( - val supportedBlockchains: List? = null, - val scanResponse: ScanResponse? = null - ) : TokensAction() { + data class LoadCurrencies(val scanResponse: ScanResponse? = null) : TokensAction() { data class Success(val currencies: List, val loadMore: Boolean) : TokensAction() object Failure : TokensAction() } data class LoadMore( - val scanResponse: ScanResponse? = null + val scanResponse: ScanResponse? = null, ) : TokensAction() data class SetAddedCurrencies( val wallets: List, - val derivationStyle: DerivationStyle? + val derivationStyle: DerivationStyle?, ) : TokensAction() data class SaveChanges( val addedTokens: List, - val addedBlockchains: List + val addedBlockchains: List, ) : TokensAction() object PrepareAndNavigateToAddCustomToken : TokensAction() diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index 305df3393e..9b3be6dca7 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -76,11 +76,8 @@ class TokensMiddleware { private fun handleLoadCurrencies(scanResponse: ScanResponse?, newSearchInput: String? = null) { val tokensState = store.state.tokensState - val isTestcard = scanResponse?.card?.isTestCard ?: false - - val supportedBlockchains: List = - scanResponse?.card?.supportedBlockchains() ?: Blockchain.values().toList() - .filter { !it.isTestnet() } + val supportedBlockchains: List = scanResponse?.card?.supportedBlockchains() + ?: Blockchain.values().toList().filterNot(Blockchain::isTestnet) val loadCoinsService = LoadAvailableCoinsService( tangemTechApi = store.state.domainNetworks.tangemTechService.api, @@ -89,34 +86,26 @@ class TokensMiddleware { ) scope.launch { - val loadCoinsResult = if (newSearchInput == null) { - loadCoinsService.getSupportedTokens( - isTestcard, - supportedBlockchains, - tokensState.pageToLoad, - tokensState.searchInput, - ) - } else { - loadCoinsService.getSupportedTokens( - isTestNet = isTestcard, - supportedBlockchains = supportedBlockchains, - page = 0, - searchInput = newSearchInput.ifBlank { null }, - ) - } - when (loadCoinsResult) { - is Result.Success -> { - val currencies = loadCoinsResult.data.currencies - .filter(supportedBlockchains.toSet()) - store.dispatchOnMain( + val result = loadCoinsService.getSupportedTokens( + isTestNet = scanResponse?.card?.isTestCard ?: false, + supportedBlockchains = supportedBlockchains, + page = if (newSearchInput == null) tokensState.pageToLoad else 0, + searchInput = if (newSearchInput == null) tokensState.searchInput else newSearchInput.ifBlank { null }, + ) + + store.dispatchOnMain( + action = when (result) { + is Result.Success -> { TokensAction.LoadCurrencies.Success( - currencies, - loadCoinsResult.data.moreAvailable, - ), - ) - } - is Result.Failure -> store.dispatchOnMain(TokensAction.LoadCurrencies.Failure) - } + currencies = result.data.currencies.filter(supportedBlockchains.toSet()), + loadMore = result.data.moreAvailable, + ) + } + is Result.Failure -> { + TokensAction.LoadCurrencies.Failure + } + }, + ) } } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt index e8ab2383d8..c792805d9b 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt @@ -37,7 +37,6 @@ private fun internalReduce(action: Action, state: AppState): TokensState { addedBlockchains = action.wallets.toNonCustomBlockchains(action.derivationStyle), addedTokens = action.wallets.toNonCustomTokensWithBlockchains(action.derivationStyle), addedWallets = action.wallets, - derivationStyle = action.derivationStyle, ) } is TokensAction.AllowToAddTokens -> { diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt index 5c4f723467..3cb59514c8 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt @@ -18,7 +18,6 @@ data class TokensState( val currencies: List = emptyList(), val searchInput: String? = null, val allowToAdd: Boolean = true, - val derivationStyle: DerivationStyle? = null, val scanResponse: ScanResponse? = null, val needToLoadMore: Boolean = true, val pageToLoad: Int = 0, @@ -67,19 +66,19 @@ data class TokenWithBlockchain( fun List.filter(supportedBlockchains: Set?): List { if (supportedBlockchains == null) return this - return map { - it.copy( - contracts = - it.contracts.filter { - supportedBlockchains.contains(it.blockchain) && - (it.blockchain.canHandleTokens() || it.address == null) + + return map { currency -> + currency.copy( + contracts = currency.contracts.filter { contract -> + supportedBlockchains.contains(contract.blockchain) && + (contract.blockchain.canHandleTokens() || contract.address == null) }, ) - }.filterNot { - it.contracts.isNullOrEmpty() && !supportedBlockchains.contains(Blockchain.fromNetworkId(it.id)) + }.filterNot { currency -> + currency.contracts.isEmpty() && !supportedBlockchains.contains(Blockchain.fromNetworkId(currency.id)) } } enum class LoadCoinsState { - LOADING, LOADED, ERROR + LOADING, LOADED, } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CurrencyPlaceholderIcon.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CurrencyPlaceholderIcon.kt index c62f31075e..188c75e57b 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CurrencyPlaceholderIcon.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CurrencyPlaceholderIcon.kt @@ -22,7 +22,7 @@ fun CurrencyPlaceholderIcon(id: String) { Box( contentAlignment = Alignment.Center, modifier = Modifier - .background(circleColor, shape = CircleShape) + .background(circleColor, shape = CircleShape), ) { Text( text = id.firstOrNull()?.titlecase() ?: "", diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/currencyItem/CurrencyItemArrow.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/currencyItem/CurrencyItemArrow.kt deleted file mode 100644 index 3c0c5655cc..0000000000 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/currencyItem/CurrencyItemArrow.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.tangem.tap.features.tokens.ui.compose.currencyItem - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -@Composable -fun CurrencyItemArrow( - rowHeight: Dp, - isLastArrow: Boolean, -) { - Box(Modifier.height(rowHeight)) { - if (!isLastArrow) { - MiddleArrowView(rowHeight) - } else { - LastArrowView(rowHeight) - } - } -} - -@Suppress("MagicNumber") -@Composable -private fun MiddleArrowView(rowHeight: Dp) { - Box { - Box( - modifier = Modifier - .padding(start = 0.5.dp), - ) { - Box( - modifier = Modifier - .background(color = Color(0xFFDEDEDE)) - .width(0.8.dp) - .fillMaxHeight(), - ) - } - - LastArrowView(rowHeight) - } -} - -@Composable -private fun LastArrowView(rowHeight: Dp) { - Image( - modifier = Modifier - .height(rowHeight / 2 + 3.5.dp), - painter = painterResource(id = R.drawable.ic_link), - contentDescription = null, - ) -} - -@Preview -@Composable -private fun ArrowViewPreview() { - Box(Modifier.background(color = Color.White)) { - Column( - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(start = 37.dp), - ) { - CurrencyItemArrow( - rowHeight = 62.dp, - isLastArrow = false, - ) - CurrencyItemArrow( - rowHeight = 62.dp, - isLastArrow = true, - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/currencyItem/NetworkItem.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/currencyItem/NetworkItem.kt index cf744085ba..ceb4e333c7 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/currencyItem/NetworkItem.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/currencyItem/NetworkItem.kt @@ -37,6 +37,7 @@ import com.tangem.tap.common.extensions.getGreyedOutIconRes import com.tangem.tap.common.extensions.getNetworkName import com.tangem.tap.domain.tokens.Contract import com.tangem.tap.domain.tokens.Currency +import com.tangem.tap.features.tokens.presentation.ui.NetworkItemArrow import com.tangem.tap.features.tokens.redux.ContractAddress import com.tangem.tap.features.tokens.redux.TokenWithBlockchain import com.tangem.tap.features.tokens.ui.compose.CurrencyPlaceholderIcon @@ -76,9 +77,9 @@ fun NetworkItem( .width(78.dp) .padding(start = 38.dp), ) { - CurrencyItemArrow( - rowHeight = rowHeight, - isLastArrow = index == size - 1, + NetworkItemArrow( + itemHeight = rowHeight, + isLastItem = index == size - 1, ) } Box( @@ -161,10 +162,7 @@ fun NetworkItem( @Suppress("MagicNumber") @Composable -private fun prepareNetworkNameSpannableText( - blockchain: Blockchain, - contractAddress: String?, -): AnnotatedString { +private fun prepareNetworkNameSpannableText(blockchain: Blockchain, contractAddress: String?): AnnotatedString { val blockchainName = blockchain.fullNameWithoutTestnet.uppercase() val additionalText = if (contractAddress == null) "MAIN" else blockchain.getNetworkName().uppercase() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt index c67c02d950..4c4079055c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt @@ -58,10 +58,7 @@ sealed interface Currency { fun isToken(): Boolean = this is Token companion object { - fun fromBlockchainNetwork( - blockchainNetwork: BlockchainNetwork, - token: SdkToken? = null, - ): Currency { + fun fromBlockchainNetwork(blockchainNetwork: BlockchainNetwork, token: SdkToken? = null): Currency { return if (token != null) { Token( token = token, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 45013512af..b55d54277d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -168,7 +168,9 @@ data class WalletState( state = walletsData.findProgressState(), error = this.error.takeIf { newProgressState == ProgressState.Error }, ) - } else this + } else { + this + } } companion object { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt index 974ef88df8..8c1847b11a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt @@ -41,7 +41,7 @@ class AppCurrencyMiddleware( WalletDialog.CurrencySelectionDialog( currenciesList = storedFiatCurrencies.mapToUiModel(), currentAppCurrency = appCurrencyProvider.invoke(), - ) + ), ) } @@ -55,7 +55,7 @@ class AppCurrencyMiddleware( WalletDialog.CurrencySelectionDialog( currenciesList = currenciesList.mapToUiModel(), currentAppCurrency = appCurrencyProvider.invoke(), - ) + ), ) } } @@ -82,7 +82,7 @@ class AppCurrencyMiddleware( FiatCurrency( code = it.code, name = it.name, - symbol = it.unit + symbol = it.unit, ) } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index f2cc59a816..d7c7bd6d85 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -30,10 +30,7 @@ import timber.log.Timber class MultiWalletMiddleware { @Suppress("LongMethod", "ComplexMethod") - fun handle( - action: WalletAction.MultiWallet, - walletState: WalletState?, - ) { + fun handle(action: WalletAction.MultiWallet, walletState: WalletState?) { when (action) { is WalletAction.MultiWallet.SelectWallet -> { if (action.currency != null) { @@ -105,29 +102,27 @@ class MultiWalletMiddleware { } } - private fun scanAndUpdateCard( - selectedUserWallet: UserWallet, - state: WalletState?, - ) = scope.launch(Dispatchers.Default) { - tangemSdkManager.scanProduct( - cardId = selectedUserWallet.cardId, - userTokensRepository = userTokensRepository, - additionalBlockchainsToDerive = state?.missingDerivations?.map { it.blockchain }, - allowsRequestAccessCodeFromRepository = true, - ) - .flatMap { scanResponse -> - userWalletsListManager.update( - userWalletId = selectedUserWallet.walletId, - update = { userWallet -> - userWallet.copy( - scanResponse = scanResponse, - ) - }, - ) - } - .doOnSuccess { updatedUserWallet -> - store.dispatchOnMain(WalletAction.MultiWallet.AddMissingDerivations(emptyList())) - store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true) - } - } + private fun scanAndUpdateCard(selectedUserWallet: UserWallet, state: WalletState?) = + scope.launch(Dispatchers.Default) { + tangemSdkManager.scanProduct( + cardId = selectedUserWallet.cardId, + userTokensRepository = userTokensRepository, + additionalBlockchainsToDerive = state?.missingDerivations?.map { it.blockchain }, + allowsRequestAccessCodeFromRepository = true, + ) + .flatMap { scanResponse -> + userWalletsListManager.update( + userWalletId = selectedUserWallet.walletId, + update = { userWallet -> + userWallet.copy( + scanResponse = scanResponse, + ) + }, + ) + } + .doOnSuccess { updatedUserWallet -> + store.dispatchOnMain(WalletAction.MultiWallet.AddMissingDerivations(emptyList())) + store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index ec7597b8c7..6020f4c151 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -46,10 +46,7 @@ class TradeCryptoMiddleware { } } - private fun proceedBuyAction( - state: () -> AppState?, - action: WalletAction.TradeCryptoAction.Buy, - ) { + private fun proceedBuyAction(state: () -> AppState?, action: WalletAction.TradeCryptoAction.Buy) { val selectedWalletData = store.state.walletState.selectedWalletData ?: return val currency = chooseAppropriateCurrency(store.state.walletState) ?: return @@ -164,7 +161,7 @@ class TradeCryptoMiddleware { val bundle = bundleOf( SwapFragment.CURRENCY_BUNDLE_KEY to Json.encodeToString(currency), - SwapFragment.DERIVATION_PATH to store.state.walletState.selectedWalletData?.currency?.derivationPath + SwapFragment.DERIVATION_PATH to store.state.walletState.selectedWalletData?.currency?.derivationPath, ) store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Swap, bundle = bundle)) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt index 1de96bac4b..9562b735fa 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt @@ -106,9 +106,7 @@ class WarningsMiddleware { } } - private fun checkIfWarningNeeded( - scanResponse: ScanResponse, - ): WarningMessage? { + private fun checkIfWarningNeeded(scanResponse: ScanResponse): WarningMessage? { if (scanResponse.cardTypesResolver.isTangemTwins() || scanResponse.isDemoCard()) return null if (scanResponse.cardTypesResolver.isMultiwalletAllowed()) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt index a098368d06..49ba3fa007 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt @@ -4,13 +4,11 @@ import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState class AppCurrencyReducer { - fun reduce( - action: WalletAction.AppCurrencyAction, - state: WalletState, - ): WalletState { + fun reduce(action: WalletAction.AppCurrencyAction, state: WalletState): WalletState { return when (action) { is WalletAction.AppCurrencyAction.SelectAppCurrency, - is WalletAction.AppCurrencyAction.ChooseAppCurrency -> state + is WalletAction.AppCurrencyAction.ChooseAppCurrency, + -> state } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index 78e56b7d93..d95339a75b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -210,10 +210,7 @@ fun Wallet.createAddressesData(): List { return listOfAddressData } -private fun handleCheckSignedHashesActions( - action: WalletAction.Warnings, - state: WalletState, -): WalletState { +private fun handleCheckSignedHashesActions(action: WalletAction.Warnings, state: WalletState): WalletState { return when (action) { WalletAction.Warnings.CheckHashesCount.ConfirmHashesCount -> state.copy(hashesCountVerified = true) WalletAction.Warnings.CheckHashesCount.NeedToCheckHashesCountOnline -> state.copy( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt index 16703319a4..0afeb7e3b0 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt @@ -152,14 +152,13 @@ class BalanceWidget( } } - private fun showBalanceWithoutToken(data: BalanceWidgetData, showAmount: Boolean) = - with(binding.lBalance) { - groupBaseCurrency.hide() - tvCurrency.text = data.currency - tvAmount.text = if (showAmount) data.amountFormatted else "" - if (showAmount) { - tvFiatAmount.show() - tvFiatAmount.text = data.fiatAmountFormatted - } + private fun showBalanceWithoutToken(data: BalanceWidgetData, showAmount: Boolean) = with(binding.lBalance) { + groupBaseCurrency.hide() + tvCurrency.text = data.currency + tvAmount.text = if (showAmount) data.amountFormatted else "" + if (showAmount) { + tvFiatAmount.show() + tvFiatAmount.text = data.fiatAmountFormatted } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 2668f1c79a..e070d1e5da 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -70,7 +70,8 @@ import javax.inject.Inject @Suppress("LargeClass", "MagicNumber") @AndroidEntryPoint -class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), +class WalletDetailsFragment : + Fragment(R.layout.fragment_wallet_details), StoreSubscriber { @Inject @@ -496,11 +497,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), setStatus(getString(mainMessage), R.color.darkGray4, null) } - private fun TextView.setStatus( - text: String, - @ColorRes color: Int, - @DrawableRes drawable: Int?, - ) { + private fun TextView.setStatus(text: String, @ColorRes color: Int, @DrawableRes drawable: Int?) { this.text = text setTextColor(getColor(color)) setCompoundDrawablesWithIntrinsicBounds(drawable ?: 0, 0, 0, 0) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt index 6d50e30035..0a59da666a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt @@ -20,7 +20,7 @@ class PendingTransactionsAdapter : val binding = ItemPendingTransactionBinding.inflate( LayoutInflater.from(parent.context), parent, - false + false, ) return TransactionsViewHolder(binding) } @@ -30,15 +30,9 @@ class PendingTransactionsAdapter : } object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame( - oldItem: PendingTransaction, - newItem: PendingTransaction - ) = oldItem == newItem + override fun areContentsTheSame(oldItem: PendingTransaction, newItem: PendingTransaction) = oldItem == newItem - override fun areItemsTheSame( - oldItem: PendingTransaction, - newItem: PendingTransaction - ) = oldItem == newItem + override fun areItemsTheSame(oldItem: PendingTransaction, newItem: PendingTransaction) = oldItem == newItem } class TransactionsViewHolder(val binding: ItemPendingTransactionBinding) : diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index 60c0d65fbc..98f4fbecee 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -40,15 +40,9 @@ class WalletAdapter : ListAdapter(D } object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame( - oldItem: WalletData, - newItem: WalletData, - ) = oldItem == newItem + override fun areContentsTheSame(oldItem: WalletData, newItem: WalletData) = oldItem == newItem - override fun areItemsTheSame( - oldItem: WalletData, - newItem: WalletData, - ) = oldItem == newItem + override fun areItemsTheSame(oldItem: WalletData, newItem: WalletData) = oldItem == newItem } class WalletsViewHolder(val binding: ItemCurrencyWalletBinding) : diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt index a96101b35a..95be9ce597 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt @@ -37,7 +37,7 @@ class WalletDetailWarningMessagesAdapter : } class WalletDetailsWarningMessageVH( - val binding: LayoutWarningCardBinding + val binding: LayoutWarningCardBinding, ) : RecyclerView.ViewHolder(binding.root) { fun bind(warning: WalletWarningDescription) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt index c22f00de55..762d6e818e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt @@ -40,11 +40,9 @@ class WarningMessagesAdapter : ListAdapter(Dif } object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame(oldItem: WarningMessage, newItem: WarningMessage) = - oldItem == newItem + override fun areContentsTheSame(oldItem: WarningMessage, newItem: WarningMessage) = oldItem == newItem - override fun areItemsTheSame(oldItem: WarningMessage, newItem: WarningMessage) = - oldItem == newItem + override fun areItemsTheSame(oldItem: WarningMessage, newItem: WarningMessage) = oldItem == newItem } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt index db783afc52..160d3fc40e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt @@ -44,7 +44,7 @@ class AmountToSendBottomSheetDialog( binding!!.rvAmountsToSend.layoutManager = LinearLayoutManager(context) val dividerItemDecoration = DividerItemDecoration( ContextThemeWrapper(binding!!.root.context, R.style.AppTheme), - DividerItemDecoration.VERTICAL + DividerItemDecoration.VERTICAL, ) binding!!.rvAmountsToSend.addItemDecoration(dividerItemDecoration) @@ -61,7 +61,7 @@ class ChooseAmountAdapter : ListAdapter() { - override fun areContentsTheSame( - oldItem: Amount, - newItem: Amount - ) = oldItem.currencySymbol == newItem.currencySymbol + override fun areContentsTheSame(oldItem: Amount, newItem: Amount) = + oldItem.currencySymbol == newItem.currencySymbol - override fun areItemsTheSame( - oldItem: Amount, - newItem: Amount - ) = oldItem == newItem + override fun areItemsTheSame(oldItem: Amount, newItem: Amount) = oldItem == newItem } class AmountViewHolder(val binding: ItemWalletAmountToSendBinding) : diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt index 4019726797..ee5b7dc3e2 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt @@ -47,10 +47,7 @@ class CurrencyIconView @JvmOverloads constructor( } } -fun CurrencyIconView.load( - currency: Currency, - derivationStyle: DerivationStyle?, -) { +fun CurrencyIconView.load(currency: Currency, derivationStyle: DerivationStyle?) { isCustomCurrencyBadgeVisible = currency.isCustomCurrency(derivationStyle) CurrencyIconRequest( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt index f17f324571..4efe5659b4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt @@ -101,10 +101,7 @@ internal class TotalBalanceCard @JvmOverloads constructor( } @Composable -private fun TotalBalanceCardContent( - state: TotalBalanceCardState, - modifier: Modifier = Modifier, -) { +private fun TotalBalanceCardContent(state: TotalBalanceCardState, modifier: Modifier = Modifier) { TotalBalanceCardScaffold( modifier = modifier, title = { @@ -199,9 +196,7 @@ private fun TotalBalanceCardScaffold( } @Composable -private fun LoadingAmount( - modifier: Modifier = Modifier, -) { +private fun LoadingAmount(modifier: Modifier = Modifier) { Box(modifier = modifier.shimmer()) { Box( modifier = Modifier @@ -216,10 +211,7 @@ private fun LoadingAmount( } @Composable -private fun LoadedAmount( - amount: AnnotatedString, - modifier: Modifier = Modifier, -) { +private fun LoadedAmount(amount: AnnotatedString, modifier: Modifier = Modifier) { Box(modifier = modifier) { Text( text = amount, @@ -232,10 +224,7 @@ private fun LoadedAmount( } @Composable -private fun buildAmountString( - amount: BigDecimal?, - fiatCurrencySymbol: String, -): AnnotatedString { +private fun buildAmountString(amount: BigDecimal?, fiatCurrencySymbol: String): AnnotatedString { if (amount == null) return AnnotatedString(text = UNKNOWN_AMOUNT_SIGN) val format = DecimalFormat.getInstance(Locale.getDefault()) as DecimalFormat @@ -290,9 +279,7 @@ private sealed interface TotalBalanceCardState { // region Preview @Composable -private fun TotalBalanceCardContentSample( - modifier: Modifier = Modifier, -) { +private fun TotalBalanceCardContentSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt index 30d48309a8..c7457f1158 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt @@ -42,7 +42,7 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( fun updateButtonsVisibility( actions: Set, exchangeServiceFeatureOn: Boolean, - sendAllowed: Boolean + sendAllowed: Boolean, ) = with(binding) { containerActionButtons.isVisible = exchangeServiceFeatureOn diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt index 6cce3b391b..835b547e6d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt @@ -8,10 +8,7 @@ import com.tangem.tap.store import com.tangem.wallet.R object CurrencySelectionDialog { - fun create( - dialog: WalletDialog.CurrencySelectionDialog, - context: Context - ): AlertDialog { + fun create(dialog: WalletDialog.CurrencySelectionDialog, context: Context): AlertDialog { val currenciesToShow = dialog.currenciesList .map { it.displayName } .toTypedArray() @@ -28,8 +25,8 @@ object CurrencySelectionDialog { dialog.currenciesList.getOrNull(which)?.let { selectedCurrency -> store.dispatch( WalletAction.AppCurrencyAction.SelectAppCurrency( - fiatCurrency = selectedCurrency - ) + fiatCurrency = selectedCurrency, + ), ) store.dispatch(WalletAction.DialogAction.Hide) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt index 4d2bdc1fdc..d735ef9615 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt @@ -6,7 +6,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.badoo.mvicore.modelWatcher import com.tangem.core.analytics.Analytics import com.tangem.domain.common.TapWorkarounds.derivationStyle -import com.tangem.domain.common.TapWorkarounds.isTestCard import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.ManageTokens import com.tangem.tap.common.analytics.events.Portfolio @@ -15,7 +14,6 @@ import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction -import com.tangem.tap.domain.tokens.CurrenciesRepository import com.tangem.tap.features.tokens.redux.TokensAction import com.tangem.tap.features.wallet.models.TotalBalance import com.tangem.tap.features.wallet.redux.WalletAction @@ -110,15 +108,7 @@ class MultiWalletView : WalletView() { binding.btnAddToken.setOnClickListener { val card = store.state.globalState.scanResponse!!.card Analytics.send(Portfolio.ButtonManageTokens()) - store.dispatch( - TokensAction.LoadCurrencies( - supportedBlockchains = CurrenciesRepository.getBlockchains( - card.firmwareVersion, - card.isTestCard, - ), - scanResponse = store.state.globalState.scanResponse, - ), - ) + store.dispatch(TokensAction.LoadCurrencies(scanResponse = store.state.globalState.scanResponse)) store.dispatch(TokensAction.AllowToAddTokens(true)) store.dispatch( TokensAction.SetAddedCurrencies( @@ -143,46 +133,35 @@ class MultiWalletView : WalletView() { } } - private fun handleBackupWarning( - binding: FragmentWalletBinding, - showBackupWarning: Boolean, - ) = with(binding.lWalletBackupWarning) { - root.isVisible = showBackupWarning - root.setOnClickListener { - Analytics.send(MainScreen.NoticeBackupYourWalletTapped()) - store.dispatch(WalletAction.MultiWallet.BackupWallet) + private fun handleBackupWarning(binding: FragmentWalletBinding, showBackupWarning: Boolean) = + with(binding.lWalletBackupWarning) { + root.isVisible = showBackupWarning + root.setOnClickListener { + Analytics.send(MainScreen.NoticeBackupYourWalletTapped()) + store.dispatch(WalletAction.MultiWallet.BackupWallet) + } } - } - private fun handleRescanWarning( - binding: FragmentWalletBinding, - showRescanWarning: Boolean, - ) = with(binding.lWalletRescanWarning) { - root.isVisible = showRescanWarning - root.setOnClickListener { - Analytics.send(MainScreen.NoticeScanYourCardTapped()) - store.dispatch(WalletAction.MultiWallet.ScanToGetDerivations) + private fun handleRescanWarning(binding: FragmentWalletBinding, showRescanWarning: Boolean) = + with(binding.lWalletRescanWarning) { + root.isVisible = showRescanWarning + root.setOnClickListener { + Analytics.send(MainScreen.NoticeScanYourCardTapped()) + store.dispatch(WalletAction.MultiWallet.ScanToGetDerivations) + } } - } - private fun handleTotalBalance( - binding: FragmentWalletBinding, - totalBalance: TotalBalance?, - walletsCount: Int, - ) = with(binding.lCardTotalBalance) { - isVisible = walletsCount > 0 + private fun handleTotalBalance(binding: FragmentWalletBinding, totalBalance: TotalBalance?, walletsCount: Int) = + with(binding.lCardTotalBalance) { + isVisible = walletsCount > 0 - onChangeFiatCurrencyClick = { - store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency) + onChangeFiatCurrencyClick = { + store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency) + } + status = totalBalance } - status = totalBalance - } - private fun handleErrorStates( - state: WalletState, - binding: FragmentWalletBinding, - fragment: WalletFragment, - ) { + private fun handleErrorStates(state: WalletState, binding: FragmentWalletBinding, fragment: WalletFragment) { when (state.primaryWalletData?.currencyData?.status) { BalanceStatus.EmptyCard -> { showErrorState( @@ -220,16 +199,15 @@ class MultiWalletView : WalletView() { } } - private fun configureButtonsForEmptyWalletState(binding: FragmentWalletBinding) = - with(binding) { - rowButtons.btnBuy.hide() - rowButtons.btnSell.hide() - rowButtons.btnTrade.hide() - rowButtons.show() + private fun configureButtonsForEmptyWalletState(binding: FragmentWalletBinding) = with(binding) { + rowButtons.btnBuy.hide() + rowButtons.btnSell.hide() + rowButtons.btnTrade.hide() + rowButtons.show() - rowButtons.btnSend.text = fragment?.getText(R.string.wallet_button_create_wallet) - rowButtons.onSendClick = { store.dispatch(WalletAction.CreateWallet) } - } + rowButtons.btnSend.text = fragment?.getText(R.string.wallet_button_create_wallet) + rowButtons.onSendClick = { store.dispatch(WalletAction.CreateWallet) } + } override fun onDestroyFragment() { super.onDestroyFragment() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt index a379f290a8..e999ee383a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt @@ -197,18 +197,16 @@ class SaltPayWalletView : WalletView() { groupShimmer.show() } - private fun handleTxSuccess( - txWidget: LayoutSaltPayTxHistoryBinding, - dataList: List, - ) = with(txWidget) { - Timber.d("handleTxSuccess") - groupShimmer.hide() - groupEmpty.hide() - groupError.hide() - // root.beginDelayedTransition() - updateTxHistoryWidget(txWidget, dataList) - groupSuccess.show() - } + private fun handleTxSuccess(txWidget: LayoutSaltPayTxHistoryBinding, dataList: List) = + with(txWidget) { + Timber.d("handleTxSuccess") + groupShimmer.hide() + groupEmpty.hide() + groupError.hide() + // root.beginDelayedTransition() + updateTxHistoryWidget(txWidget, dataList) + groupSuccess.show() + } private fun handleTxEmpty(txWidget: LayoutSaltPayTxHistoryBinding) = with(txWidget) { Timber.d("handleTxEmpty") @@ -230,12 +228,10 @@ class SaltPayWalletView : WalletView() { groupError.show() } - private fun updateTxHistoryWidget( - txWidget: LayoutSaltPayTxHistoryBinding, - dataList: List, - ) = with(txWidget) { - (rvTxHistory.adapter as TxHistoryAdapter).submitList(dataList) - } + private fun updateTxHistoryWidget(txWidget: LayoutSaltPayTxHistoryBinding, dataList: List) = + with(txWidget) { + (rvTxHistory.adapter as TxHistoryAdapter).submitList(dataList) + } override fun onViewDestroy() { Timber.d("onViewDestroy") diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index c93b07f234..9191b57a00 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -70,7 +70,7 @@ internal class WalletSelectorMiddleware { addWallet() } is WalletSelectorAction.SelectWallet -> { - selectWallet(action.userWalletId, action.sendAnalyticsEvent) + selectWallet(action.userWalletId) } is WalletSelectorAction.RemoveWallets -> { deleteWallets(action.userWalletsIds, state) @@ -189,7 +189,7 @@ internal class WalletSelectorMiddleware { } } - private fun selectWallet(userWalletId: UserWalletId, sendAnalyticsEvent: Boolean) { + private fun selectWallet(userWalletId: UserWalletId) { scope.launch { userWalletsListManager.get(userWalletId) .flatMap { userWallet -> diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt index e965a29794..c28a1e4ab1 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt @@ -10,7 +10,9 @@ internal object WalletSelectorReducer { fun reduce(action: Action, state: AppState): WalletSelectorState { return if (action is WalletSelectorAction) { internalReduce(action, state.walletSelectorState) - } else state.walletSelectorState + } else { + state.walletSelectorState + } } @Suppress("ComplexMethod") diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt index d22d12d85c..a00447b139 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt @@ -9,9 +9,7 @@ import com.tangem.tap.features.walletSelector.ui.model.MultiCurrencyUserWalletIt import com.tangem.tap.features.walletSelector.ui.model.SingleCurrencyUserWalletItem import com.tangem.tap.features.walletSelector.ui.model.UserWalletItem -internal fun List.toUiModels( - appCurrency: FiatCurrency, -): Sequence { +internal fun List.toUiModels(appCurrency: FiatCurrency): Sequence { return this.asSequence().map { userWalletModel -> with(userWalletModel) { val balance = when (fiatBalance) { diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt index b611289180..9f82671d66 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt @@ -51,10 +51,7 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment WarningModel.BiometricsLockoutWarning( isPermanent = error.isPermanent, diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/BiometricsLockoutWarningContent.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/BiometricsLockoutWarningContent.kt index 1416b5af61..3abfb1ade2 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/BiometricsLockoutWarningContent.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/BiometricsLockoutWarningContent.kt @@ -12,9 +12,7 @@ import com.tangem.tap.features.walletSelector.ui.model.WarningModel import com.tangem.wallet.R @Composable -internal fun BiometricsLockoutWarningContent( - warning: WarningModel.BiometricsLockoutWarning, -) { +internal fun BiometricsLockoutWarningContent(warning: WarningModel.BiometricsLockoutWarning) { BasicDialog( title = stringResource(id = R.string.biometric_lockout_warning_title), message = stringResource( @@ -34,9 +32,7 @@ internal fun BiometricsLockoutWarningContent( // region Preview @Composable -private fun BiometricsLockoutDialogSample( - modifier: Modifier = Modifier, -) { +private fun BiometricsLockoutDialogSample(modifier: Modifier = Modifier) { Column(modifier = modifier) { BiometricsLockoutWarningContent( warning = WarningModel.BiometricsLockoutWarning( @@ -64,9 +60,7 @@ private fun BiometricsLockoutDialogPreview_Dark() { } @Composable -private fun BiometricsLockoutDialog_Permanent_Sample( - modifier: Modifier = Modifier, -) { +private fun BiometricsLockoutDialog_Permanent_Sample(modifier: Modifier = Modifier) { Column(modifier = modifier) { BiometricsLockoutWarningContent( warning = WarningModel.BiometricsLockoutWarning( diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/KeyInvalidatedWarningContent.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/KeyInvalidatedWarningContent.kt index 0b31a73101..4459f55a1d 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/KeyInvalidatedWarningContent.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/KeyInvalidatedWarningContent.kt @@ -12,9 +12,7 @@ import com.tangem.tap.features.walletSelector.ui.model.WarningModel import com.tangem.wallet.R @Composable -internal fun KeyInvalidatedWarningContent( - warning: WarningModel.KeyInvalidatedWarning, -) { +internal fun KeyInvalidatedWarningContent(warning: WarningModel.KeyInvalidatedWarning) { BasicDialog( title = stringResource(id = R.string.common_attention), message = stringResource(id = R.string.key_invalidated_warning_description), @@ -28,9 +26,7 @@ internal fun KeyInvalidatedWarningContent( // region Preview @Composable -private fun KeyInvalidatedWarningSample( - modifier: Modifier = Modifier, -) { +private fun KeyInvalidatedWarningSample(modifier: Modifier = Modifier) { Column(modifier = modifier) { KeyInvalidatedWarningContent( warning = WarningModel.KeyInvalidatedWarning(onDismiss = {}), diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/RenameWalletDialogContent.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/RenameWalletDialogContent.kt index 97d465df54..64b69bad75 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/RenameWalletDialogContent.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/RenameWalletDialogContent.kt @@ -47,9 +47,7 @@ internal fun RenameWalletDialogContent(dialog: DialogModel.RenameWalletDialog) { // region Preview @Composable -private fun RenameWalletDialogContentSample( - modifier: Modifier = Modifier, -) { +private fun RenameWalletDialogContentSample(modifier: Modifier = Modifier) { Column( modifier = modifier, ) { diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt index d10ed293f0..ecf9cc83e9 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt @@ -266,9 +266,7 @@ private fun EditWalletsBar( // region Preview @Composable -private fun WalletSelectorScreenContentSample( - modifier: Modifier = Modifier, -) { +private fun WalletSelectorScreenContentSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(color = TangemTheme.colors.background.primary), @@ -303,9 +301,7 @@ private fun WalletSelectorScreenContentPreview_Dark() { } @Composable -private fun WalletSelectorScreenContent_EditWallets_Sample( - modifier: Modifier = Modifier, -) { +private fun WalletSelectorScreenContent_EditWallets_Sample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt index 385916f599..70c46cb0ce 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt @@ -84,11 +84,7 @@ internal fun WalletItem( } @Composable -private fun WalletCardImage( - cardImageUrl: String, - isChecked: Boolean, - isSelected: Boolean, -) { +private fun WalletCardImage(cardImageUrl: String, isChecked: Boolean, isSelected: Boolean) { Box( modifier = Modifier .width(TangemTheme.dimens.size62) @@ -107,7 +103,9 @@ private fun WalletCardImage( color = tintColor, blendMode = BlendMode.SrcOver, ) - } else null + } else { + null + } } SubcomposeAsyncImage( @@ -283,9 +281,7 @@ private fun LoadedTokensInfo( } @Composable -private fun LockedPlaceholder( - modifier: Modifier = Modifier, -) { +private fun LockedPlaceholder(modifier: Modifier = Modifier) { Box( modifier = modifier .padding(vertical = TangemTheme.dimens.spacing2) @@ -309,9 +305,7 @@ private fun LockedPlaceholder( } @Composable -private fun CardImagePlaceholder( - modifier: Modifier = Modifier, -) { +private fun CardImagePlaceholder(modifier: Modifier = Modifier) { Box(modifier = modifier) { Image( modifier = Modifier.matchParentSize(), @@ -322,9 +316,7 @@ private fun CardImagePlaceholder( } @Composable -private fun CardImageShimmer( - modifier: Modifier = Modifier, -) { +private fun CardImageShimmer(modifier: Modifier = Modifier) { Box(modifier = modifier.shimmer()) { Box( modifier = Modifier @@ -335,9 +327,7 @@ private fun CardImageShimmer( } @Composable -private fun SelectedWalletBadge( - modifier: Modifier = Modifier, -) { +private fun SelectedWalletBadge(modifier: Modifier = Modifier) { Box( modifier = modifier .size(TangemTheme.dimens.size18) @@ -357,9 +347,7 @@ private fun SelectedWalletBadge( } @Composable -private fun CheckedWalletMark( - modifier: Modifier = Modifier, -) { +private fun CheckedWalletMark(modifier: Modifier = Modifier) { Box( modifier = modifier, contentAlignment = Alignment.Center, diff --git a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt index 495b112f1d..e728d10a4a 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt @@ -106,9 +106,7 @@ internal class WelcomeMiddleware { } } - private suspend inline fun scanCardInternal( - crossinline onCardScanned: suspend (ScanResponse) -> Unit, - ) { + private suspend inline fun scanCardInternal(crossinline onCardScanned: suspend (ScanResponse) -> Unit) { tangemSdkManager.setAccessCodeRequestPolicy( useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes, ) diff --git a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeReducer.kt b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeReducer.kt index f44447f2a9..5f14d1744d 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeReducer.kt @@ -7,7 +7,9 @@ internal object WelcomeReducer { fun reduce(action: Action, state: AppState): WelcomeState { return if (action is WelcomeAction) { internalReduce(action, state.welcomeState) - } else state.welcomeState + } else { + state.welcomeState + } } private fun internalReduce(action: WelcomeAction, state: WelcomeState): WelcomeState { diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt index 81cad48aca..0554bdf27c 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt @@ -45,10 +45,7 @@ internal class WelcomeFragment : ComposeFragment() { } @Composable - override fun ScreenContent( - state: WelcomeScreenState, - modifier: Modifier, - ) { + override fun ScreenContent(state: WelcomeScreenState, modifier: Modifier) { val snackbarHostState = remember { SnackbarHostState() } val errorMessage by rememberUpdatedState(newValue = state.error?.resolveReference()) val warning by rememberUpdatedState(newValue = state.warning) diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WarningDialog.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WarningDialog.kt index fb974cc393..40ae13b0cb 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WarningDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WarningDialog.kt @@ -12,9 +12,7 @@ import com.tangem.tap.features.welcome.ui.model.WarningModel import com.tangem.wallet.R @Composable -internal fun WarningDialog( - warning: WarningModel?, -) { +internal fun WarningDialog(warning: WarningModel?) { when (warning) { null -> Unit is WarningModel.BiometricsLockoutWarning -> { @@ -50,9 +48,7 @@ internal fun WarningDialog( // region Preview @Composable -private fun BiometricsLockoutDialogSample( - modifier: Modifier = Modifier, -) { +private fun BiometricsLockoutDialogSample(modifier: Modifier = Modifier) { Column(modifier = modifier) { WarningDialog( warning = WarningModel.BiometricsLockoutWarning( @@ -80,9 +76,7 @@ private fun BiometricsLockoutDialogPreview_Dark() { } @Composable -private fun BiometricsLockoutDialog_Permanent_Sample( - modifier: Modifier = Modifier, -) { +private fun BiometricsLockoutDialog_Permanent_Sample(modifier: Modifier = Modifier) { Column(modifier = modifier) { WarningDialog( warning = WarningModel.BiometricsLockoutWarning( @@ -111,9 +105,7 @@ private fun BiometricsLockoutDialog_Permanent_Preview_Dark() { // region Preview @Composable -private fun KeyInvalidatedWarningSample( - modifier: Modifier = Modifier, -) { +private fun KeyInvalidatedWarningSample(modifier: Modifier = Modifier) { Column(modifier = modifier) { WarningDialog(warning = WarningModel.KeyInvalidatedWarning(onDismiss = {})) } diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt index 4cf55f6bcd..373d370eda 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt @@ -91,9 +91,7 @@ internal fun WelcomeScreenContent( // region Preview @Composable -private fun WelcomeScreenContentSample( - modifier: Modifier = Modifier, -) { +private fun WelcomeScreenContentSample(modifier: Modifier = Modifier) { Box( modifier = modifier .background(TangemTheme.colors.background.primary), diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt index 89308da1ce..5d9fece041 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt @@ -8,9 +8,7 @@ import retrofit2.http.Path interface MercuryoApi { @GET("{apiVersion}/lib/currencies") - suspend fun currencies( - @Path("apiVersion") apiVersion: String, - ): MercuryoCurrenciesResponse + suspend fun currencies(@Path("apiVersion") apiVersion: String): MercuryoCurrenciesResponse } data class MercuryoCurrenciesResponse( diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoEnvironment.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoEnvironment.kt index af3cda029a..36fd477bc5 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoEnvironment.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoEnvironment.kt @@ -16,11 +16,7 @@ data class MercuryoEnvironment( private const val BASE_URL = "https://api.mercuryo.io/" private const val API_VERSION = "v1.6" - fun prod( - widgetId: String, - secret: String, - apiVersion: String = API_VERSION, - ): MercuryoEnvironment { + fun prod(widgetId: String, secret: String, apiVersion: String = API_VERSION): MercuryoEnvironment { return MercuryoEnvironment( baseUrl = BASE_URL, apiVersion = apiVersion, diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt index 9561664182..8f76434576 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt @@ -125,10 +125,7 @@ class MercuryoService( return (address + environment.secret).calculateSha512().toHexString().lowercase() } - override fun getSellCryptoReceiptUrl( - action: CurrencyExchangeManager.Action, - transactionId: String, - ): String? = null + override fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String? = null private fun blockchainFromCurrencyName(currencyName: String): Blockchain? = when (currencyName) { "BNB" -> Blockchain.BSC diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayApi.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayApi.kt index 27dc8d0c3b..ce7c4c2a7f 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayApi.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayApi.kt @@ -8,14 +8,10 @@ import retrofit2.http.Query interface MoonPayApi { @GET(MOOONPAY_IP_ADDRESS_REQUEST_URL) - suspend fun getUserStatus( - @Query("apiKey") moonPayApiKey: String, - ): MoonPayUserStatus + suspend fun getUserStatus(@Query("apiKey") moonPayApiKey: String): MoonPayUserStatus @GET(MOOONPAY_CURRENCIES_REQUEST_URL) - suspend fun getCurrencies( - @Query("apiKey") moonPayApiKey: String, - ): List + suspend fun getCurrencies(@Query("apiKey") moonPayApiKey: String): List companion object { const val MOOONPAY_BASE_URL = "https://api.moonpay.com/" diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgEnvironment.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgEnvironment.kt index b31e8aa8bf..0aac5a8b43 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgEnvironment.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/UtorgEnvironment.kt @@ -25,15 +25,13 @@ data class UtorgEnvironment( private val STAGE_BASE_URL = Uri.parse("https://app-stage.utorg.pro") private const val STAGE_VERSION = "v1" - fun prod( - authProvider: UtorgAuthProvider, - apiVersion: String = PROD_VERSION, - ): UtorgEnvironment = UtorgEnvironment( - baseUri = PROD_BASE_URL, - sidValue = authProvider.sidValue, - apiVersion = apiVersion, - utorgApi = createApi(PROD_BASE_URL, authProvider, false), - ) + fun prod(authProvider: UtorgAuthProvider, apiVersion: String = PROD_VERSION): UtorgEnvironment = + UtorgEnvironment( + baseUri = PROD_BASE_URL, + sidValue = authProvider.sidValue, + apiVersion = apiVersion, + utorgApi = createApi(PROD_BASE_URL, authProvider, false), + ) fun stage( authProvider: UtorgAuthProvider, diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/UtorgApi.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/UtorgApi.kt index 6244d39a5e..b18618e38b 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/UtorgApi.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/utorg/api/UtorgApi.kt @@ -12,15 +12,10 @@ import retrofit2.http.Path interface UtorgApi { @POST("api/merchant/{apiVersion}/settings/currency") - suspend fun getCurrency( - @Path("apiVersion") apiVersion: String, - ): UtorgCurrencyResponse + suspend fun getCurrency(@Path("apiVersion") apiVersion: String): UtorgCurrencyResponse @POST("api/merchant/{apiVersion}/settings/successUrl") - suspend fun setSuccessUrl( - @Path("apiVersion") apiVersion: String, - @Body request: RequestSuccessUrl, - ) + suspend fun setSuccessUrl(@Path("apiVersion") apiVersion: String, @Body request: RequestSuccessUrl) } data class RequestSuccessUrl( diff --git a/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt b/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt index 8566c89a86..d9d00a663b 100644 --- a/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt +++ b/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt @@ -22,8 +22,7 @@ data class VerifyPayIdResponse( val addresses: List = mutableListOf(), val payId: String? = null, ) { - fun getAddressDetails(): PayIdAddressDetails? = - if (addresses.isNotEmpty()) addresses[0].addressDetails else null + fun getAddressDetails(): PayIdAddressDetails? = if (addresses.isNotEmpty()) addresses[0].addressDetails else null } @JsonClass(generateAdapter = true) diff --git a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt index 3f5c655ec2..5a2fddd325 100644 --- a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt @@ -158,11 +158,9 @@ class AppRatingLaunchObserver( editor.apply() } - private fun userWasInteractWithRating(): Boolean = - preferences.getBoolean(K_USER_WAS_INTERACT_WITH_RATING, false) + private fun userWasInteractWithRating(): Boolean = preferences.getBoolean(K_USER_WAS_INTERACT_WITH_RATING, false) - private fun getCounterOfNextShowing(): Int = - preferences.getInt(K_SHOW_RATING_AT_LAUNCH_COUNT, firstShowing) + private fun getCounterOfNextShowing(): Int = preferences.getInt(K_SHOW_RATING_AT_LAUNCH_COUNT, firstShowing) companion object { private const val K_SHOW_RATING_AT_LAUNCH_COUNT = "showRatingDialogAtLaunchCount" diff --git a/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt index 705cd2824f..0ef9bf082d 100644 --- a/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt @@ -42,7 +42,9 @@ class DerivationManagerImpl( contractAddress = currency.contractAddress, decimals = currency.decimalCount, ) - } else null + } else { + null + } val blockchainNetwork = BlockchainNetwork(blockchain, card) val appCurrency = com.tangem.tap.features.wallet.models.Currency.fromBlockchainNetwork( blockchainNetwork, diff --git a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt index b5225f4588..b49a4168c6 100644 --- a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt @@ -397,11 +397,7 @@ class TransactionManagerImpl( } } - private fun createAmount( - amount: BigDecimal, - currency: Currency, - blockchain: Blockchain, - ): Amount { + private fun createAmount(amount: BigDecimal, currency: Currency, blockchain: Blockchain): Amount { return when (currency) { is Currency.NativeToken -> { Amount(value = amount, blockchain = blockchain) @@ -412,11 +408,7 @@ class TransactionManagerImpl( } } - private fun createAmountForSwap( - amount: BigDecimal, - currency: Currency?, - blockchain: Blockchain, - ): Amount { + private fun createAmountForSwap(amount: BigDecimal, currency: Currency?, blockchain: Blockchain): Amount { return when (currency) { is Currency.NativeToken, null, diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt index cd392ae831..57cdad3cf3 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt @@ -3,6 +3,7 @@ package com.tangem.tap.proxy.redux import com.tangem.datasource.asset.AssetReader import com.tangem.datasource.connection.NetworkConnectionManager import com.tangem.features.tester.api.TesterRouter +import com.tangem.tap.features.tokens.api.featuretoggles.TokensListFeatureToggles import org.rekotlin.Action sealed interface DaggerGraphAction : Action { @@ -10,6 +11,7 @@ sealed interface DaggerGraphAction : Action { data class SetApplicationDependencies( val assetReader: AssetReader, val networkConnectionManager: NetworkConnectionManager, + val tokensListFeatureToggles: TokensListFeatureToggles, ) : DaggerGraphAction data class SetActivityDependencies(val testerRouter: TesterRouter) : DaggerGraphAction diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt index 34564599ac..65cfee1cf5 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt @@ -15,6 +15,7 @@ object DaggerGraphReducer { is DaggerGraphAction.SetApplicationDependencies -> state.daggerGraphState.copy( assetReader = action.assetReader, networkConnectionManager = action.networkConnectionManager, + tokensListFeatureToggles = action.tokensListFeatureToggles, ) is DaggerGraphAction.SetActivityDependencies -> state.daggerGraphState.copy( testerRouter = action.testerRouter, diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index 800182a67c..792009c602 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -3,12 +3,14 @@ package com.tangem.tap.proxy.redux import com.tangem.datasource.asset.AssetReader import com.tangem.datasource.connection.NetworkConnectionManager import com.tangem.features.tester.api.TesterRouter +import com.tangem.tap.features.tokens.api.featuretoggles.TokensListFeatureToggles import org.rekotlin.StateType data class DaggerGraphState( val assetReader: AssetReader? = null, val testerRouter: TesterRouter? = null, val networkConnectionManager: NetworkConnectionManager? = null, + val tokensListFeatureToggles: TokensListFeatureToggles? = null, ) : StateType { inline fun get(getDependency: DaggerGraphState.() -> T?): T { diff --git a/app/src/main/res/drawable/ic_back_24.xml b/app/src/main/res/drawable/ic_back_24.xml new file mode 100644 index 0000000000..fd06de4ca4 --- /dev/null +++ b/app/src/main/res/drawable/ic_back_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt b/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt index 0e0f40b6c9..8dda5adedf 100644 --- a/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt +++ b/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt @@ -18,7 +18,8 @@ import java.util.concurrent.Executors /** [REDACTED_AUTHOR] */ -interface GlobalAnalyticsEventHandler : AnalyticsEventHandler, +interface GlobalAnalyticsEventHandler : + AnalyticsEventHandler, AnalyticsHandlerHolder, AnalyticsFilterHolder, ParamsInterceptorHolder diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/api/ClientApi.kt b/core/analytics/src/main/java/com/tangem/core/analytics/api/ClientApi.kt index 0989dfaad4..f44a0133cd 100644 --- a/core/analytics/src/main/java/com/tangem/core/analytics/api/ClientApi.kt +++ b/core/analytics/src/main/java/com/tangem/core/analytics/api/ClientApi.kt @@ -4,15 +4,9 @@ package com.tangem.core.analytics.api [REDACTED_AUTHOR] */ interface EventLogger { - fun logEvent( - event: String, - params: Map = emptyMap(), - ) + fun logEvent(event: String, params: Map = emptyMap()) } interface ErrorEventLogger { - fun logErrorEvent( - error: Throwable, - params: Map = emptyMap(), - ) + fun logErrorEvent(error: Throwable, params: Map = emptyMap()) } \ No newline at end of file diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt b/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt index ca6721037c..49aadf88c3 100644 --- a/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt +++ b/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt @@ -22,10 +22,7 @@ interface AnalyticsHandler : AnalyticsEventHandler { } interface ErrorEventHandler { - fun send( - error: Throwable, - params: Map = emptyMap(), - ) + fun send(error: Throwable, params: Map = emptyMap()) } interface AnalyticsHandlerHolder { diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt index 711963d504..56963e7456 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt @@ -33,10 +33,7 @@ interface TangemTechApi { ): CoinsResponse @GET("rates") - suspend fun getRates( - @Query("currencyId") currencyId: String, - @Query("coinIds") coinIds: String, - ): RatesResponse + suspend fun getRates(@Query("currencyId") currencyId: String, @Query("coinIds") coinIds: String): RatesResponse @GET("currencies") suspend fun getCurrencyList(): CurrenciesResponse diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt index ab0752e212..4404533bf3 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt @@ -43,11 +43,13 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager { override fun resetToDefault(name: String) { when (name) { - IS_SENDING_TO_PAY_ID_ENABLED -> config = - config.copy(isSendingToPayIdEnabled = defaultConfig.isSendingToPayIdEnabled) + IS_SENDING_TO_PAY_ID_ENABLED -> + config = + config.copy(isSendingToPayIdEnabled = defaultConfig.isSendingToPayIdEnabled) IS_TOP_UP_ENABLED -> config = config.copy(isTopUpEnabled = defaultConfig.isTopUpEnabled) - IS_CREATING_TWIN_CARDS_ALLOWED -> config = - config.copy(isCreatingTwinCardsAllowed = defaultConfig.isCreatingTwinCardsAllowed) + IS_CREATING_TWIN_CARDS_ALLOWED -> + config = + config.copy(isCreatingTwinCardsAllowed = defaultConfig.isCreatingTwinCardsAllowed) } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/TestnetTokensStorageModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/TestnetTokensStorageModule.kt new file mode 100644 index 0000000000..229722e50d --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/di/TestnetTokensStorageModule.kt @@ -0,0 +1,27 @@ +package com.tangem.datasource.di + +import com.squareup.moshi.Moshi +import com.squareup.moshi.adapter +import com.tangem.datasource.asset.AssetReader +import com.tangem.datasource.local.testnet.DefaultTestnetTokensStorage +import com.tangem.datasource.local.testnet.TestnetTokensStorage +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +/** +[REDACTED_AUTHOR] + */ +@Module +@InstallIn(SingletonComponent::class) +object TestnetTokensStorageModule { + + @OptIn(ExperimentalStdlibApi::class) + @Provides + @Singleton + fun providesTestnetTokensStorage(assetReader: AssetReader, @SdkMoshi moshi: Moshi): TestnetTokensStorage { + return DefaultTestnetTokensStorage(assetReader = assetReader, adapter = moshi.adapter()) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/testnet/DefaultTestnetTokensStorage.kt b/core/datasource/src/main/java/com/tangem/datasource/local/testnet/DefaultTestnetTokensStorage.kt new file mode 100644 index 0000000000..d4a3a066e1 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/testnet/DefaultTestnetTokensStorage.kt @@ -0,0 +1,31 @@ +package com.tangem.datasource.local.testnet + +import com.squareup.moshi.JsonAdapter +import com.tangem.datasource.asset.AssetReader +import com.tangem.datasource.local.testnet.models.TestnetTokensConfig + +/** + * Default implementation for storing testnet tokens data + * + * @property assetReader file reader from assets + * @property adapter adapter for parsing testnet tokens config + * +[REDACTED_AUTHOR] + */ +internal class DefaultTestnetTokensStorage( + private val assetReader: AssetReader, + private val adapter: JsonAdapter, +) : TestnetTokensStorage { + + override fun getConfig(): TestnetTokensConfig { + return requireNotNull( + value = adapter.fromJson( + assetReader.readJson(fileName = LOCAL_CONFIG_PATH), + ), + ) + } + + private companion object { + const val LOCAL_CONFIG_PATH: String = "testnet_tokens" + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/testnet/TestnetTokensStorage.kt b/core/datasource/src/main/java/com/tangem/datasource/local/testnet/TestnetTokensStorage.kt new file mode 100644 index 0000000000..7f091e98e6 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/testnet/TestnetTokensStorage.kt @@ -0,0 +1,14 @@ +package com.tangem.datasource.local.testnet + +import com.tangem.datasource.local.testnet.models.TestnetTokensConfig + +/** + * Storage of testnet tokens data + * +[REDACTED_AUTHOR] + */ +interface TestnetTokensStorage { + + /** Get a testnet tokens data */ + fun getConfig(): TestnetTokensConfig +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/testnet/models/TestnetTokensConfig.kt b/core/datasource/src/main/java/com/tangem/datasource/local/testnet/models/TestnetTokensConfig.kt new file mode 100644 index 0000000000..1e619014cf --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/testnet/models/TestnetTokensConfig.kt @@ -0,0 +1,42 @@ +package com.tangem.datasource.local.testnet.models + +import com.squareup.moshi.Json + +/** + * Config model with testnet tokens list + * + * @property tokens testnet tokens list + */ +data class TestnetTokensConfig( + @Json(name = "coins") val tokens: List, +) { + + /** + * Testnet token model + * + * @property id token id + * @property name token name + * @property symbol token brief name. Example, "BTC" + * @property networks networks of testnet token + */ + data class Token( + @Json(name = "id") val id: String, + @Json(name = "name") val name: String, + @Json(name = "symbol") val symbol: String, + @Json(name = "networks") val networks: List? = null, + ) { + + /** + * Network model of testnet token + * + * @property id network id + * @property address network address + * @property decimalCount decimal count + */ + data class Network( + @Json(name = "networkId") val id: String, + @Json(name = "contractAddress") val address: String?, + @Json(name = "decimalCount") val decimalCount: Int?, + ) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt index 9e9e143cf2..66d6c0f90b 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt @@ -16,6 +16,6 @@ sealed class RequestHeader(vararg pairs: Pair) { class AuthenticationHeader(authProvider: AuthProvider) : RequestHeader( "card_public_key" to authProvider.getCardPublicKey(), - "card_id" to authProvider.getCardId() + "card_id" to authProvider.getCardId(), ) } \ No newline at end of file diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index 74e4d91915..b7661838a4 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -2,5 +2,9 @@ { "name": "OPTIMISM_SWAP_FEATURE_ENABLED", "version": "4.3.1" + }, + { + "name": "REDESIGNED_TOKEN_LIST_SCREEN_ENABLED", + "version": "4.5.0" } ] \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt index c720130f16..50651d2e35 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt @@ -42,12 +42,7 @@ import com.tangem.core.ui.res.TangemTheme * [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?node-id=97%3A103&t=TmfD6UBHPg9uYfev-4) * */ @Composable -fun TextButton( - text: String, - onClick: () -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, -) { +fun TextButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) { TangemButton( modifier = modifier, text = text, @@ -84,12 +79,7 @@ fun TextButtonIconLeft( } @Composable -fun WarningTextButton( - text: String, - onClick: () -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, -) { +fun WarningTextButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) { TangemButton( modifier = modifier, text = text, @@ -239,12 +229,7 @@ fun SecondaryButtonIconLeft( // region Other @Composable -fun SelectorButton( - text: String, - onClick: () -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, -) { +fun SelectorButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) { TangemButton( modifier = modifier, text = text, @@ -461,9 +446,7 @@ private open class TangemButtonColors( // region Preview @Composable -private fun PrimaryButtonSample( - modifier: Modifier = Modifier, -) { +private fun PrimaryButtonSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), @@ -537,9 +520,7 @@ private fun PrimaryButtonPreview_Dark() { } @Composable -private fun SecondaryButtonSample( - modifier: Modifier = Modifier, -) { +private fun SecondaryButtonSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), @@ -613,9 +594,7 @@ private fun SecondaryButtonPreview_Dark() { } @Composable -private fun TextButtonSample( - modifier: Modifier = Modifier, -) { +private fun TextButtonSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Cards.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Cards.kt index 0fc92ad614..b06cff2ece 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Cards.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Cards.kt @@ -43,11 +43,7 @@ import com.valentinilk.shimmer.shimmer * >Figma component */ @Composable -fun SmallInfoCard( - startText: String, - endText: String, - isLoading: Boolean = false, -) { +fun SmallInfoCard(startText: String, endText: String, isLoading: Boolean = false) { Surface( shape = RoundedCornerShape(TangemTheme.dimens.radius12), color = TangemTheme.colors.background.primary, @@ -74,12 +70,7 @@ fun SmallInfoCard( * >Figma component */ @Composable -fun SmallInfoCardWithDisclaimer( - startText: String, - endText: String, - disclaimer: String, - isLoading: Boolean = false, -) { +fun SmallInfoCardWithDisclaimer(startText: String, endText: String, disclaimer: String, isLoading: Boolean = false) { Surface( shape = RoundedCornerShape(TangemTheme.dimens.radius12), color = TangemTheme.colors.background.primary, @@ -106,12 +97,7 @@ fun SmallInfoCardWithDisclaimer( * >Figma component */ @Composable -fun SmallInfoCardWithWarning( - startText: String, - endText: String, - warningText: String, - disclaimer: String? = null, -) { +fun SmallInfoCardWithWarning(startText: String, endText: String, warningText: String, disclaimer: String? = null) { Surface( shape = RoundedCornerShape(TangemTheme.dimens.size12), color = TangemTheme.colors.background.primary, @@ -274,12 +260,7 @@ fun IconWithTitleAndDescription( // region elements @Composable -private fun CardInfoBox( - startText: String, - endText: String, - disclaimer: String?, - isLoading: Boolean = false, -) { +private fun CardInfoBox(startText: String, endText: String, disclaimer: String?, isLoading: Boolean = false) { val isOpened = remember { mutableStateOf(false) } Column { Row( diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Dialogs.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Dialogs.kt index aaf52b686e..36052e27f0 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Dialogs.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Dialogs.kt @@ -159,10 +159,7 @@ private fun TangemDialog( } @Composable -private fun DialogContent( - type: DialogType, - modifier: Modifier = Modifier, -) { +private fun DialogContent(type: DialogType, modifier: Modifier = Modifier) { Column( modifier = modifier, verticalArrangement = Arrangement.Center, @@ -196,11 +193,7 @@ private fun DialogContent( } @Composable -private fun DialogButtons( - confirmButton: DialogButton, - dismissButton: DialogButton?, - modifier: Modifier = Modifier, -) { +private fun DialogButtons(confirmButton: DialogButton, dismissButton: DialogButton?, modifier: Modifier = Modifier) { Row( modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy( @@ -315,9 +308,7 @@ private fun Preview_BasicDialog_InDarkTheme() { } @Composable -private fun WarningBasicDialogSample( - modifier: Modifier = Modifier, -) { +private fun WarningBasicDialogSample(modifier: Modifier = Modifier) { Column( modifier = modifier, ) { @@ -349,9 +340,7 @@ private fun WarningBasicDialogPreview_Dark() { } @Composable -private fun TextInputDialogSample( - modifier: Modifier = Modifier, -) { +private fun TextInputDialogSample(modifier: Modifier = Modifier) { Column( modifier = modifier, ) { diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/MiddleEllipsisText.kt b/core/ui/src/main/java/com/tangem/core/ui/components/MiddleEllipsisText.kt index 8d5527b5a6..9bdff5f987 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/MiddleEllipsisText.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/MiddleEllipsisText.kt @@ -153,21 +153,19 @@ private class BoundCounter( private var _nextCharWidth: Float? = null private var invalidCharsCount = 0 - fun widthWithNextChar(): Float = - width + nextCharWidth() + fun widthWithNextChar(): Float = width + nextCharWidth() - private fun nextCharWidth(): Float = - _nextCharWidth ?: run { - var boundingBox: Rect - // invalidCharsCount fixes this bug: https://issuetracker.google.com/issues/197146630 - invalidCharsCount-- - do { - boundingBox = textLayoutResult - .getBoundingBox(charPosition(string.count() + ++invalidCharsCount)) - } while (boundingBox.right == 0f) - _nextCharWidth = boundingBox.width - boundingBox.width - } + private fun nextCharWidth(): Float = _nextCharWidth ?: run { + var boundingBox: Rect + // invalidCharsCount fixes this bug: https://issuetracker.google.com/issues/197146630 + invalidCharsCount-- + do { + boundingBox = textLayoutResult + .getBoundingBox(charPosition(string.count() + ++invalidCharsCount)) + } while (boundingBox.right == 0f) + _nextCharWidth = boundingBox.width + boundingBox.width + } fun addNextChar() { string += text[charPosition(string.count())] diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt b/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt index 3e767ca2f5..ebab2d5145 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt @@ -106,10 +106,7 @@ fun ResultScreenContent( } @Composable -fun SuccessImage( - resultColor: Color, - @DrawableRes icon: Int, -) { +fun SuccessImage(resultColor: Color, @DrawableRes icon: Int) { Box( modifier = Modifier .background( diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsEffect.kt b/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsEffect.kt index 34ac768e47..ea843b7a7a 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsEffect.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/SystemBarsEffect.kt @@ -6,9 +6,7 @@ import com.google.accompanist.systemuicontroller.SystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController @Composable -fun SystemBarsEffect( - block: SystemUiController.() -> Unit, -) { +fun SystemBarsEffect(block: SystemUiController.() -> Unit) { val systemUiController = rememberSystemUiController() SideEffect { block(systemUiController) } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt b/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt index 6b9df80601..eafe741803 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt @@ -180,7 +180,7 @@ private fun TangemTextField( } private enum class TangemTextFieldSize { - Default + Default, } @Composable @@ -305,11 +305,7 @@ internal data class TangemTextFieldColors( } @Composable - override fun labelColor( - enabled: Boolean, - error: Boolean, - interactionSource: InteractionSource, - ): State { + override fun labelColor(enabled: Boolean, error: Boolean, interactionSource: InteractionSource): State { val focused by interactionSource.collectIsFocusedAsState() val targetValue = when { @@ -347,9 +343,7 @@ internal data class TangemTextFieldColors( // region Preview @Composable -private fun OutlineTextFieldSample( - modifier: Modifier = Modifier, -) { +private fun OutlineTextFieldSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt index d8293a9868..b6b858d2cd 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt @@ -24,11 +24,7 @@ import com.tangem.core.ui.res.TangemTheme * >Figma component */ @Composable -fun WarningCard( - title: String, - description: String, - icon: @Composable (() -> Unit)? = null, -) { +fun WarningCard(title: String, description: String, icon: @Composable (() -> Unit)? = null) { WarningCardSurface( content = { WarningBody( @@ -128,10 +124,7 @@ private fun WarningBody( @OptIn(ExperimentalMaterialApi::class) @Composable -private fun WarningCardSurface( - onClick: (() -> Unit)? = null, - content: @Composable () -> Unit, -) { +private fun WarningCardSurface(onClick: (() -> Unit)? = null, content: @Composable () -> Unit) { Card( shape = RoundedCornerShape(TangemTheme.dimens.size12), backgroundColor = TangemTheme.colors.background.primary, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/atoms/Hand.kt b/core/ui/src/main/java/com/tangem/core/ui/components/atoms/Hand.kt index e3ade6def9..cbb97ce8e1 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/atoms/Hand.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/atoms/Hand.kt @@ -18,9 +18,7 @@ import com.tangem.core.ui.res.TangemTheme * [Show in Figma](https://www.figma.com/file/17JyRbuUEZ42DluaFEuGQk/Atoms?node-id=135%3A25&t=Jo68S6ilyewVU8MV-4) * */ @Composable -fun Hand( - modifier: Modifier = Modifier, -) { +fun Hand(modifier: Modifier = Modifier) { Box( modifier = modifier .padding(vertical = TangemTheme.dimens.spacing8) @@ -41,9 +39,7 @@ fun Hand( // region Preview @Composable -private fun HandSample( - modifier: Modifier = Modifier, -) { +private fun HandSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary) diff --git a/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeBottomSheetFragment.kt b/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeBottomSheetFragment.kt index a88b3a2ff7..7e50223a02 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeBottomSheetFragment.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeBottomSheetFragment.kt @@ -26,11 +26,7 @@ abstract class ComposeBottomSheetFragment : BottomSheetDialogFragme override fun getTheme(): Int = R.style.AppTheme_TransparentBottomSheetDialog - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return createComposeView(inflater.context) } diff --git a/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeFragment.kt b/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeFragment.kt index d7ab04a268..cde4de5275 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeFragment.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeFragment.kt @@ -7,11 +7,7 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment abstract class ComposeFragment : Fragment(), ComposeScreen { - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return createComposeView(inflater.context) } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeScreen.kt b/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeScreen.kt index 20d6bf7bf1..987f29cd34 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeScreen.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/fragments/ComposeScreen.kt @@ -40,8 +40,5 @@ internal interface ComposeScreen { @Suppress("TopLevelComposableFunctions") @Composable - fun ScreenContent( - state: ScreenState, - modifier: Modifier, - ) + fun ScreenContent(state: ScreenState, modifier: Modifier) } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/ButtonColorType.kt b/core/ui/src/main/java/com/tangem/core/ui/res/ButtonColorType.kt index 5eb3a3fcff..2e45dc7577 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/ButtonColorType.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/ButtonColorType.kt @@ -17,7 +17,7 @@ enum class ButtonColorType(val lightColor: Color, val darkColor: Color) { SECONDARY(lightColor = Light2, darkColor = Dark5), DISABLED(lightColor = Light2, darkColor = Dark6), POSITIVE(lightColor = Meadow, darkColor = Meadow), - POSITIVE_DISABLED(lightColor = MagicMint, darkColor = DarkGreen) + POSITIVE_DISABLED(lightColor = MagicMint, darkColor = DarkGreen), } @Composable diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/IconColorType.kt b/core/ui/src/main/java/com/tangem/core/ui/res/IconColorType.kt index 9fa83581b6..f009843950 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/IconColorType.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/IconColorType.kt @@ -24,7 +24,7 @@ enum class IconColorType(val lightColor: Color, val darkColor: Color) { INACTIVE(lightColor = Light4, darkColor = Dark4), ACCENT(lightColor = Meadow, darkColor = Meadow), WARNING(lightColor = Amaranth, darkColor = Amaranth), - ATTENTION(lightColor = Tangerine, darkColor = Tangerine) + ATTENTION(lightColor = Tangerine, darkColor = Tangerine), } @Composable diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt index a681a0239b..7a5dcfec58 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt @@ -32,8 +32,11 @@ data class TangemDimens internal constructor( // region Size val size0: Dp = 0.dp, val size0_5: Dp = 0.5.dp, + val size1: Dp = 1.dp, val size2: Dp = 2.dp, val size4: Dp = 4.dp, + val size5: Dp = 5.dp, + val size7: Dp = 7.dp, val size8: Dp = 8.dp, val size11: Dp = 11.dp, val size12: Dp = 12.dp, @@ -77,9 +80,11 @@ data class TangemDimens internal constructor( val spacing18: Dp = 18.dp, val spacing20: Dp = 20.dp, val spacing24: Dp = 24.dp, + val spacing26: Dp = 26.dp, val spacing28: Dp = 28.dp, val spacing32: Dp = 32.dp, val spacing34: Dp = 34.dp, + val spacing38: Dp = 38.dp, val spacing44: Dp = 44.dp, val spacing50: Dp = 50.dp, val spacing52: Dp = 52.dp, diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt index 8239973f6a..139dc810c6 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt @@ -69,10 +69,7 @@ object TangemTheme { @Stable @Composable -private fun materialThemeColors( - colors: TangemColors, - isDark: Boolean, -): Colors { +private fun materialThemeColors(colors: TangemColors, isDark: Boolean): Colors { return Colors( primary = colors.background.primary, primaryVariant = colors.background.secondary, diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TextColorType.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TextColorType.kt index 5b726844aa..39f85b8fa1 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TextColorType.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TextColorType.kt @@ -24,7 +24,7 @@ enum class TextColorType(val lightColor: Color, val darkColor: Color) { ACCENT(lightColor = Meadow, darkColor = Meadow), WARNING(lightColor = Amaranth, darkColor = Amaranth), ATTENTION(lightColor = Tangerine, darkColor = Tangerine), - CONSTANT_WHITE(lightColor = White, darkColor = White) + CONSTANT_WHITE(lightColor = White, darkColor = White), } @Composable diff --git a/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt b/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt index b9ed8ee566..59452dbf7a 100644 --- a/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt +++ b/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt @@ -25,11 +25,7 @@ class Debouncer { private var debounceJob: Job? = null - fun debounce( - waitMs: Long = 300L, - coroutineScope: CoroutineScope, - destinationFunction: () -> Unit, - ) { + fun debounce(waitMs: Long = 300L, coroutineScope: CoroutineScope, destinationFunction: () -> Unit) { debounceJob?.cancel() debounceJob = coroutineScope.launch { delay(waitMs) diff --git a/core/utils/src/main/java/com/tangem/utils/detekt/UnusedRequiredComponent.kt b/core/utils/src/main/java/com/tangem/utils/detekt/UnusedRequiredComponent.kt index 273d9dc981..3ee986c4d2 100644 --- a/core/utils/src/main/java/com/tangem/utils/detekt/UnusedRequiredComponent.kt +++ b/core/utils/src/main/java/com/tangem/utils/detekt/UnusedRequiredComponent.kt @@ -22,7 +22,7 @@ package com.tangem.utils.detekt AnnotationTarget.TYPE, AnnotationTarget.EXPRESSION, AnnotationTarget.FILE, - AnnotationTarget.TYPEALIAS + AnnotationTarget.TYPEALIAS, ) @Retention(AnnotationRetention.SOURCE) annotation class UnusedRequiredComponent(val description: String) \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/DomainModuleMessage.kt b/domain/src/main/java/com/tangem/domain/DomainModuleMessage.kt index 6eb55484ca..27d7606e7f 100644 --- a/domain/src/main/java/com/tangem/domain/DomainModuleMessage.kt +++ b/domain/src/main/java/com/tangem/domain/DomainModuleMessage.kt @@ -52,9 +52,11 @@ sealed class AddCustomTokenError( object UnsupportedSolanaToken : Warning() } - data class SelectTokeNetworkError(val networkId: String) : AddCustomTokenError( - message = "Unknown network [$networkId] should not be included in the network selection dialog.", - ), FbConsumeException + data class SelectTokeNetworkError(val networkId: String) : + AddCustomTokenError( + message = "Unknown network [$networkId] should not be included in the network selection dialog.", + ), + FbConsumeException data class UnAppropriateInitialization( val of: String, diff --git a/domain/src/main/java/com/tangem/domain/DomainWrapped.kt b/domain/src/main/java/com/tangem/domain/DomainWrapped.kt index 1b41d0e9cd..a94866c343 100644 --- a/domain/src/main/java/com/tangem/domain/DomainWrapped.kt +++ b/domain/src/main/java/com/tangem/domain/DomainWrapped.kt @@ -19,14 +19,14 @@ sealed interface DomainWrapped { data class Token( val token: com.tangem.blockchain.common.Token, override val blockchain: com.tangem.blockchain.common.Blockchain, - override val derivationPath: String? + override val derivationPath: String?, ) : Currency { override val currencySymbol = token.symbol } data class Blockchain( override val blockchain: com.tangem.blockchain.common.Blockchain, - override val derivationPath: String? + override val derivationPath: String?, ) : Currency { override val currencySymbol: String = blockchain.currency } diff --git a/domain/src/main/java/com/tangem/domain/common/CardDTO.kt b/domain/src/main/java/com/tangem/domain/common/CardDTO.kt index 63695e8fdc..630a017700 100644 --- a/domain/src/main/java/com/tangem/domain/common/CardDTO.kt +++ b/domain/src/main/java/com/tangem/domain/common/CardDTO.kt @@ -267,7 +267,8 @@ data class CardDTO( enum class LinkedTerminalStatus { Current, Other, - None; + None, + ; companion object { internal fun fromSdkStatus(sdkStatus: Card.LinkedTerminalStatus): LinkedTerminalStatus { diff --git a/domain/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt b/domain/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt index b84051a3c1..5d9f6fafa7 100644 --- a/domain/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt +++ b/domain/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt @@ -32,8 +32,10 @@ class TangemCardTypesResolver( override fun isMultiwalletAllowed(): Boolean = !isTangemTwins() && !card.isStart2Coin && !isTangemNote() && !isSaltPay() && - (card.firmwareVersion >= FirmwareVersion.MultiWalletAvailable || - card.wallets.firstOrNull()?.curve == EllipticCurve.Secp256k1) + ( + card.firmwareVersion >= FirmwareVersion.MultiWalletAvailable || + card.wallets.firstOrNull()?.curve == EllipticCurve.Secp256k1 + ) override fun getBlockchain(): Blockchain { return when (productType) { diff --git a/domain/src/main/java/com/tangem/domain/common/Throttling.kt b/domain/src/main/java/com/tangem/domain/common/Throttling.kt index b7ef3d7783..e0344ec362 100644 --- a/domain/src/main/java/com/tangem/domain/common/Throttling.kt +++ b/domain/src/main/java/com/tangem/domain/common/Throttling.kt @@ -31,7 +31,7 @@ open class Throttler( } class ThrottlerWithValues( - duration: Long + duration: Long, ) : Throttler(duration), ValuesHolder { private val valuesHolder: MutableMap = mutableMapOf() diff --git a/domain/src/main/java/com/tangem/domain/common/form/Form.kt b/domain/src/main/java/com/tangem/domain/common/form/Form.kt index b63423436e..cca8b72a5f 100644 --- a/domain/src/main/java/com/tangem/domain/common/form/Form.kt +++ b/domain/src/main/java/com/tangem/domain/common/form/Form.kt @@ -38,7 +38,7 @@ interface Field { data class Data( val value: Data, - val isUserInput: Boolean + val isUserInput: Boolean, ) } diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt index ba47bee24f..1a533426fc 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt @@ -81,11 +81,7 @@ internal class AddCustomTokenHub : BaseStoreHub("AddCustomT } @Suppress("ComplexMethod") - override suspend fun handleAction( - action: Action, - storeState: DomainState, - cancel: ValueCallback, - ) { + override suspend fun handleAction(action: Action, storeState: DomainState, cancel: ValueCallback) { if (action !is AddCustomTokenAction) return when (action) { diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/Models.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/Models.kt index 3dba21a577..444255ef7f 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/Models.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/Models.kt @@ -11,7 +11,7 @@ data class ScreenState( val symbol: ViewStates.TokenField, val decimals: ViewStates.TokenField, val derivationPath: ViewStates.TokenField, - val addButton: ViewStates.AddButton + val addButton: ViewStates.AddButton, ) sealed class ViewStates { @@ -22,6 +22,6 @@ sealed class ViewStates { ) : ViewStates() data class AddButton( - val isEnabled: Boolean = true + val isEnabled: Boolean = true, ) : ViewStates() } \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/redux/ReStoreHub.kt b/domain/src/main/java/com/tangem/domain/redux/ReStoreHub.kt index fc2f0df299..fcef0871d2 100644 --- a/domain/src/main/java/com/tangem/domain/redux/ReStoreHub.kt +++ b/domain/src/main/java/com/tangem/domain/redux/ReStoreHub.kt @@ -3,7 +3,13 @@ package com.tangem.domain.redux import android.webkit.ValueCallback import com.tangem.domain.redux.global.DomainGlobalState import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.job +import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.DispatchFunction import org.rekotlin.Middleware @@ -38,14 +44,14 @@ internal interface ReStoreReducer { */ internal abstract class BaseStoreHub( private val name: String, - private val dispatcher: CoroutineDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher() + private val dispatcher: CoroutineDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher(), ) : ReStoreHub { val globalState: DomainGlobalState get() = domainStore.state.globalState val hubScope = CoroutineScope( - Job() + dispatcher + CoroutineName(name) + FeatureCoroutineExceptionHandler.create(name) + Job() + dispatcher + CoroutineName(name) + FeatureCoroutineExceptionHandler.create(name), ) private val actionsAndJobs = mutableMapOf() diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralRepository.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralRepository.kt index 2c477d67e3..ad770f8c2e 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralRepository.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralRepository.kt @@ -10,10 +10,5 @@ interface ReferralRepository { suspend fun getReferralStatus(walletId: String): ReferralData /** Starts user referral program */ - suspend fun startReferral( - walletId: String, - networkId: String, - tokenId: String, - address: String, - ): ReferralData + suspend fun startReferral(walletId: String, networkId: String, tokenId: String, address: String): ReferralData } \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt index e0671b7ffd..09e9cea01c 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt @@ -102,8 +102,11 @@ internal class SwapRepositoryImpl @Inject constructor( } } - override suspend fun checkTokensSpendAllowance(networkId: String, tokenAddress: String, walletAddress: String): - AggregatedSwapDataModel { + override suspend fun checkTokensSpendAllowance( + networkId: String, + tokenAddress: String, + walletAddress: String, + ): AggregatedSwapDataModel { return withContext(coroutineDispatcher.io) { try { val response = oneInchErrorsHandler.handleOneInchResponse( diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 60fcbfece5..cdca70f863 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -305,11 +305,7 @@ internal class SwapInteractorImpl @Inject constructor( return allowance.error == DataError.NoError && allowance.dataModel != ZERO_BALANCE } - private fun createEmptyAmountState( - networkId: String, - fromToken: Currency, - toToken: Currency, - ): SwapState { + private fun createEmptyAmountState(networkId: String, fromToken: Currency, toToken: Currency): SwapState { val appCurrency = userWalletManager.getUserAppCurrency() val fromTokenBalance = cache.getBalanceForToken(networkId, derivationPath, fromToken.symbol) val toTokenBalance = cache.getBalanceForToken(networkId, derivationPath, toToken.symbol) @@ -372,10 +368,7 @@ internal class SwapInteractorImpl @Inject constructor( } } - private suspend fun getFormattedFiatFee( - networkId: String, - fee: BigDecimal, - ): String { + private suspend fun getFormattedFiatFee(networkId: String, fee: BigDecimal): String { val appCurrency = userWalletManager.getUserAppCurrency() val nativeToken = userWalletManager.getNativeTokenForNetwork(networkId) val rates = repository.getRates(appCurrency.code, listOf(nativeToken.id)) diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt index 932a45fd4e..70289f0c3f 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt @@ -32,11 +32,7 @@ interface SwapRepository { * @param tokenAddress token you want to exchange * @param amount number of tokens is allowed. By default infinite */ - suspend fun dataToApprove( - networkId: String, - tokenAddress: String, - amount: String? = null, - ): ApproveModel + suspend fun dataToApprove(networkId: String, tokenAddress: String, amount: String? = null): ApproveModel /** * Get the number of tokens that the 1inch router is allowed to spend diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt index 7f65454b85..572c5484ac 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt @@ -37,9 +37,7 @@ class SwapDomainModule { @Provides @Singleton - fun provideBlockchainInteractor( - transactionManager: TransactionManager, - ): BlockchainInteractor { + fun provideBlockchainInteractor(transactionManager: TransactionManager): BlockchainInteractor { return BlockchainInteractorImpl( transactionManager = transactionManager, ) diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt index fee4466f54..fbcbeb51b0 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt @@ -9,9 +9,11 @@ sealed class DataError { fun mapErrors(error: String?): DataError { return if (error == null) { DataError.NoError - } else when (error) { - INSUFFICIENT_LIQUIDITY_ERROR -> DataError.InsufficientLiquidity - else -> DataError.UnknownError(error) + } else { + when (error) { + INSUFFICIENT_LIQUIDITY_ERROR -> DataError.InsufficientLiquidity + else -> DataError.UnknownError(error) + } } } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index c5924121b8..11d2617601 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -290,11 +290,7 @@ internal class StateBuilder(val actions: UiActions) { ) } - fun createErrorTransaction( - uiState: SwapStateHolder, - txState: TxState, - onAlertClick: () -> Unit, - ): SwapStateHolder { + fun createErrorTransaction(uiState: SwapStateHolder, txState: TxState, onAlertClick: () -> Unit): SwapStateHolder { return uiState.copy( alert = SwapWarning.GenericWarning( message = null, diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt index 78df67253d..9862a5b00b 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt @@ -293,9 +293,7 @@ private fun FeeItem(feeState: FeeState, currency: String) { } @Composable -private fun SwapWarnings( - warnings: List, -) { +private fun SwapWarnings(warnings: List) { Column( modifier = Modifier .background(color = TangemTheme.colors.background.secondary) diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt index 382986835c..b10aac1300 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt @@ -198,10 +198,7 @@ private fun TokenItem(token: TokenToSelect, network: Network, onTokenClick: () - @Suppress("MagicNumber") @Composable -private fun TokenIcon( - token: TokenToSelect, - @DrawableRes iconPlaceholder: Int?, -) { +private fun TokenIcon(token: TokenToSelect, @DrawableRes iconPlaceholder: Int?) { val data = token.iconUrl.ifEmpty { iconPlaceholder } @@ -233,9 +230,7 @@ private fun TokenIcon( } @Composable -private fun TokenImageShimmer( - modifier: Modifier = Modifier, -) { +private fun TokenImageShimmer(modifier: Modifier = Modifier) { Box(modifier = modifier.shimmer()) { Box( modifier = Modifier diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt index 1e886b5303..761a8f9448 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt @@ -121,11 +121,7 @@ fun TransactionCard( } @Composable -private fun Header( - type: TransactionCardType, - balance: String, - modifier: Modifier = Modifier, -) { +private fun Header(type: TransactionCardType, balance: String, modifier: Modifier = Modifier) { Row( modifier = modifier .fillMaxWidth() @@ -383,9 +379,7 @@ private fun makePriceImpactBalanceWarning(value: String, priceImpactPercents: In } @Composable -private fun TokenImageShimmer( - modifier: Modifier = Modifier, -) { +private fun TokenImageShimmer(modifier: Modifier = Modifier) { Box(modifier = modifier.shimmer()) { Box( modifier = Modifier diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index e441f3bf63..1c1ea1538f 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -159,11 +159,7 @@ internal class SwapViewModel @Inject constructor( } } - private fun loadQuotesTask( - fromToken: Currency, - toToken: Currency, - amount: String, - ): PeriodicTask { + private fun loadQuotesTask(fromToken: Currency, toToken: Currency, amount: String): PeriodicTask { return PeriodicTask( UPDATE_DELAY, task = { diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/actions/TesterActionsScreen.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/actions/TesterActionsScreen.kt index 31b45f81f9..341b2879e7 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/actions/TesterActionsScreen.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/actions/TesterActionsScreen.kt @@ -20,10 +20,7 @@ import com.tangem.feature.tester.impl.R @OptIn(ExperimentalFoundationApi::class) @Composable -internal fun TesterActionsScreen( - state: TesterActionsContentState, - modifier: Modifier = Modifier, -) { +internal fun TesterActionsScreen(state: TesterActionsContentState, modifier: Modifier = Modifier) { LazyColumn( modifier = modifier .fillMaxSize() @@ -48,11 +45,7 @@ internal fun TesterActionsScreen( } @Composable -private fun TesterActionItem( - progress: Boolean, - onClick: () -> Unit, - modifier: Modifier = Modifier, -) { +private fun TesterActionItem(progress: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) { Box(modifier = modifier.padding(all = TangemTheme.dimens.spacing16)) { PrimaryButton( modifier = Modifier.fillMaxWidth(), @@ -65,9 +58,7 @@ private fun TesterActionItem( // region Preview @Composable -private fun TesterActionsScreenSample( - modifier: Modifier = Modifier, -) { +private fun TesterActionsScreenSample(modifier: Modifier = Modifier) { Column( modifier = modifier .background(TangemTheme.colors.background.primary), diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 69151488bc..f6c1447110 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -17,6 +17,7 @@ androidxConstraintLayout = "2.1.4" androidxCore = "1.9.0" androidxFragment = "1.5.3" androidxLifecycle = "2.5.1" +androidx-paging = "3.1.1" # endregion AndroidX # region Compose @@ -27,6 +28,7 @@ compose-material = "1.3.1" compose-constraint = "1.0.1" compose-navigation = "2.5.3" compose-accompanist = "0.28.0" +compose-paging = "1.0.0-alpha18" # endregion Compose # region Other libraries @@ -46,6 +48,7 @@ hilt = "2.44" hilt-navigation = "1.0.0" jodatime = "2.12.1" krateSharedPref = "2.0.0" +kotlin-immutable-collections = "0.3.5" kotsonGsonExt = "2.5.0" lottie = "3.4.0" moshi = "1.12.0" @@ -76,7 +79,7 @@ tangemCardSdk = "develop-209" # region Tools detektComposeRules = "1.2.2" -detekt = "1.21.0" +detekt = "1.22.0" # endregion Tools # region Testing @@ -115,6 +118,7 @@ androidx-browser = { module = "androidx.browser:browser", version.ref = "android androidx-constraintLayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidxConstraintLayout" } androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidxCore" } androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "androidxFragment" } +androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "androidx-paging" } lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "androidxLifecycle" } lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycle" } lifecycle-viewModel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidxLifecycle" } @@ -134,6 +138,7 @@ compose-navigation-hilt = { module = "androidx.hilt:hilt-navigation-compose", ve compose-accompanist-appCompatTheme = { module = "com.google.accompanist:accompanist-appcompat-theme", version.ref = "compose-accompanist" } compose-accompanist-systemUiController = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "compose-accompanist" } compose-accompanist-webView = { module = "com.google.accompanist:accompanist-webview", version.ref = "compose-accompanist" } +compose-paging = { module = "androidx.paging:paging-compose", version.ref = "compose-paging" } # endregion Compose # region Firebase @@ -168,6 +173,7 @@ appsflyer = { module = "com.appsflyer:af-android-sdk", version.ref = "appsflyer" armadillo = { module = "at.favre.lib:armadillo", version.ref = "armadillo" } coil = { module = "io.coil-kt:coil", version.ref = "coil" } kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutine" } +kotlin-immutable-collections = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlin-immutable-collections" } desugar = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdkLibs" } googlePlay-core = { module = "com.google.android.play:core", version.ref = "googlePlayCore" } googlePlay-core-ktx = { module = "com.google.android.play:core-ktx", version.ref = "googlePlayCoreKtx" } diff --git a/plugins/configuration/detekt.yml b/plugins/configuration/detekt.yml index f26f48c71c..51dbfc0927 100644 --- a/plugins/configuration/detekt.yml +++ b/plugins/configuration/detekt.yml @@ -66,7 +66,7 @@ comments: complexity: active: true - ComplexMethod: + CyclomaticComplexMethod: active: true ComplexCondition: active: true @@ -84,7 +84,7 @@ complexity: threshold: 300 LongMethod: active: true - threshold: 60 + threshold: 70 LongParameterList: active: true functionThreshold: 6 @@ -550,7 +550,7 @@ style: NestedClassesVisibility: active: true NewLineAtEndOfFile: - active: false # This rules overlaps with style>NewLineAtEndOfFile from the standard rules + active: false # Same as FinalNewline NoTabs: active: true NullableBooleanCheck: @@ -690,8 +690,8 @@ formatting: Filename: active: true # This rules overlaps with naming>MatchingDeclarationName from the standard rules mustBeFirst: true - FinalNewline: - active: false + FinalNewline: # This rules overlaps with style>NewLineAtEndOfFile from the standard rules + active: true insertFinalNewLine: true FunKeywordSpacing: active: true @@ -797,10 +797,10 @@ formatting: active: true TrailingCommaOnCallSite: active: true - useTrailingCommaOnCallSite: false + useTrailingCommaOnCallSite: true TrailingCommaOnDeclarationSite: active: true - useTrailingCommaOnCallSite: false + useTrailingCommaOnDeclarationSite: true TypeArgumentListSpacing: active: true TypeParameterListSpacing: @@ -808,7 +808,7 @@ formatting: UnnecessaryParenthesesBeforeTrailingLambda: active: true Wrapping: - active: false + active: true indentSize: 4 compose: