Updated on 2026-08-14
This commit is contained in:
parent
2a3a59c0aa
commit
2782d8a846
26 changed files with 662 additions and 251 deletions
|
|
@ -37,6 +37,8 @@ dependencies {
|
|||
implementation(project(":features:swap:data"))
|
||||
implementation(project(":features:tester:api"))
|
||||
implementation(project(":features:tester:impl"))
|
||||
implementation(project(":features:wallet:api"))
|
||||
implementation(project(":features:wallet:impl"))
|
||||
|
||||
/** AndroidX libraries */
|
||||
implementation(deps.androidx.core.ktx)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.tangem.datasource.config.models.Config
|
|||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
import com.tangem.domain.DomainLayer
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.tap.common.IntentHandler
|
||||
import com.tangem.tap.common.analytics.AnalyticsFactory
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
|
@ -133,6 +134,9 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
@Inject
|
||||
lateinit var preferencesDataSource: PreferencesDataSource
|
||||
|
||||
@Inject
|
||||
lateinit var walletFeatureToggles: WalletFeatureToggles
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
|
|
@ -146,6 +150,7 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
assetReader = assetReader,
|
||||
networkConnectionManager = networkConnectionManager,
|
||||
customTokenFeatureToggles = customTokenFeatureToggles,
|
||||
walletFeatureToggles = walletFeatureToggles,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
package com.tangem.tap.common.extensions
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.fragment.app.*
|
||||
import com.tangem.feature.referral.ReferralFragment
|
||||
import com.tangem.feature.swap.presentation.SwapFragment
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
|
|
@ -37,6 +33,7 @@ import com.tangem.tap.proxy.redux.DaggerGraphState
|
|||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import timber.log.Timber
|
||||
import com.tangem.feature.wallet.presentation.WalletFragment as RedesignedWalletFragment
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.AddCustomTokenFragment as RedesignedAddCustomTokenFragment
|
||||
|
||||
fun FragmentActivity.openFragment(
|
||||
|
|
@ -138,7 +135,16 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
|
|||
AppScreen.OnboardingWallet -> OnboardingWalletFragment()
|
||||
AppScreen.OnboardingTwins -> TwinsCardsFragment()
|
||||
AppScreen.OnboardingOther -> OnboardingOtherCardsFragment()
|
||||
AppScreen.Wallet -> WalletFragment()
|
||||
AppScreen.Wallet -> {
|
||||
val featureToggles = store.state.daggerGraphState.get(
|
||||
getDependency = DaggerGraphState::walletFeatureToggles,
|
||||
)
|
||||
if (featureToggles.isRedesignedScreenEnabled) {
|
||||
RedesignedWalletFragment()
|
||||
} else {
|
||||
WalletFragment()
|
||||
}
|
||||
}
|
||||
AppScreen.Send -> SendFragment()
|
||||
AppScreen.Details -> DetailsFragment()
|
||||
AppScreen.DetailsSecurity -> SecurityModeFragment()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.datasource.asset.AssetReader
|
|||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
|
||||
import org.rekotlin.StateType
|
||||
|
||||
|
|
@ -13,6 +14,7 @@ data class DaggerGraphState(
|
|||
val networkConnectionManager: NetworkConnectionManager? = null,
|
||||
val customTokenFeatureToggles: CustomTokenFeatureToggles? = null,
|
||||
val scanCardUseCase: ScanCardUseCase? = null,
|
||||
val walletFeatureToggles: WalletFeatureToggles? = null,
|
||||
) : StateType {
|
||||
|
||||
inline fun <reified T> get(getDependency: DaggerGraphState.() -> T?): T {
|
||||
|
|
|
|||
|
|
@ -10,5 +10,9 @@
|
|||
{
|
||||
"name": "NEW_CARD_SCANNING_ENABLED",
|
||||
"version": "4.7.0"
|
||||
},
|
||||
{
|
||||
"name": "REDESIGNED_WALLET_SCREEN_ENABLED",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.features.wallet.featuretoggles
|
||||
|
||||
/**
|
||||
* Wallet feature toggles
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface WalletFeatureToggles {
|
||||
|
||||
/** Availability of redesigned screen */
|
||||
val isRedesignedScreenEnabled: Boolean
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ dependencies {
|
|||
implementation(deps.compose.constraintLayout)
|
||||
implementation(deps.compose.material)
|
||||
implementation(deps.compose.foundation)
|
||||
implementation(deps.compose.material3)
|
||||
implementation(deps.compose.navigation)
|
||||
implementation(deps.compose.navigation.hilt)
|
||||
implementation(deps.compose.ui)
|
||||
|
|
@ -32,5 +33,4 @@ dependencies {
|
|||
|
||||
/** Feature Apis */
|
||||
implementation(project(":features:wallet:api"))
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.feature.wallet.di
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import com.tangem.feature.wallet.featuretoggles.DefaultWalletFeatureToggles
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object WalletFeatureTogglesModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWalletFeatureToggles(featureTogglesManager: FeatureTogglesManager): WalletFeatureToggles {
|
||||
return DefaultWalletFeatureToggles(featureTogglesManager = featureTogglesManager)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.feature.wallet.featuretoggles
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
|
||||
/**
|
||||
* Default implementation of CustomToken feature toggles
|
||||
*
|
||||
* @property featureTogglesManager manager for getting information about the availability of feature toggles
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultWalletFeatureToggles(
|
||||
private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : WalletFeatureToggles {
|
||||
|
||||
override val isRedesignedScreenEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "REDESIGNED_WALLET_SCREEN_ENABLED")
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.tangem.feature.wallet.presentation
|
||||
|
||||
import android.os.Bundle
|
||||
import android.transition.TransitionInflater
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
/**
|
||||
* Wallet fragment
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class WalletFragment : 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.slide_right)
|
||||
exitTransition = inflateTransition(R.transition.fade)
|
||||
}
|
||||
|
||||
return ComposeView(inflater.context).apply {
|
||||
setContent {
|
||||
isTransitionGroup = true
|
||||
|
||||
TangemTheme {
|
||||
// TODO: [REDACTED_TASK_KEY] Call WalletScreen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.state
|
||||
|
||||
internal enum class TokenUIState {
|
||||
LOADED, LOADING
|
||||
}
|
||||
|
||||
internal enum class TokenOptionsUIState {
|
||||
VISIBLE, HIDDEN, DRAG, UNREACHABLE
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.ui.config
|
||||
package com.tangem.feature.wallet.presentation.state
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.feature.wallet.presentation.ui.state.TokenOptionsUIState
|
||||
import com.tangem.feature.wallet.presentation.ui.state.TokenUIState
|
||||
|
||||
/**
|
||||
* Token config
|
||||
|
|
@ -18,7 +16,7 @@ import com.tangem.feature.wallet.presentation.ui.state.TokenUIState
|
|||
* @property tokenOptionsUIState state for token options like 'unreachable', 'hidden' etc
|
||||
* @property hasPending pending tx in blockchain
|
||||
*/
|
||||
data class TokenV2Config(
|
||||
internal data class TokenV2Config(
|
||||
val name: String,
|
||||
val amount: String,
|
||||
val fiatAmount: String,
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package com.tangem.feature.wallet.presentation.state
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
|
||||
/** Wallet card state */
|
||||
internal sealed interface WalletCardState {
|
||||
/** Id */
|
||||
val id: String
|
||||
|
||||
/** Title */
|
||||
val title: String
|
||||
|
||||
/** Additional wallet information */
|
||||
val additionalInfo: String
|
||||
|
||||
/** Wallet image resource id */
|
||||
@get:DrawableRes
|
||||
val imageResId: Int
|
||||
|
||||
/** Lambda be invoked when card is clicked */
|
||||
val onClick: (() -> Unit)?
|
||||
|
||||
/**
|
||||
* Wallet card content state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property title wallet name
|
||||
* @property additionalInfo wallet additional info
|
||||
* @property imageResId wallet image resource id
|
||||
* @property onClick lambda be invoked when wallet card is clicked
|
||||
* @property balance wallet balance
|
||||
*/
|
||||
data class Content(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val additionalInfo: String,
|
||||
override val imageResId: Int,
|
||||
override val onClick: (() -> Unit)? = null,
|
||||
val balance: String,
|
||||
) : WalletCardState
|
||||
|
||||
/**
|
||||
* Wallet card loading state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property title wallet name
|
||||
* @property additionalInfo wallet additional info
|
||||
* @property imageResId wallet image resource id
|
||||
* @property onClick lambda be invoked when wallet card is clicked
|
||||
*/
|
||||
data class Loading(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val additionalInfo: String,
|
||||
override val imageResId: Int,
|
||||
override val onClick: (() -> Unit)?,
|
||||
) : WalletCardState
|
||||
|
||||
/**
|
||||
* Wallet card hidden content state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property title wallet name
|
||||
* @property additionalInfo wallet additional info
|
||||
* @property imageResId wallet image resource id
|
||||
* @property onClick lambda be invoked when wallet card is clicked
|
||||
*/
|
||||
data class HiddenContent(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val additionalInfo: String,
|
||||
override val imageResId: Int,
|
||||
override val onClick: (() -> Unit)?,
|
||||
) : WalletCardState
|
||||
|
||||
/**
|
||||
* Wallet card error state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property title wallet name
|
||||
* @property additionalInfo wallet additional info
|
||||
* @property imageResId wallet image resource id
|
||||
* @property onClick lambda be invoked when wallet card is clicked
|
||||
*/
|
||||
data class Error(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val additionalInfo: String,
|
||||
override val imageResId: Int,
|
||||
override val onClick: (() -> Unit)?,
|
||||
) : WalletCardState
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.feature.wallet.presentation.state
|
||||
|
||||
/**
|
||||
* Wallet state holder
|
||||
*
|
||||
* @property onBackClick lambda be invoked when back button is clicked
|
||||
* @property headerConfig header config
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal data class WalletStateHolder(
|
||||
val onBackClick: () -> Unit,
|
||||
val headerConfig: HeaderConfig,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Header config
|
||||
*
|
||||
* @property wallets list of wallets states
|
||||
* @property onScanCardClick lambda be invoked when scan card button is clicked
|
||||
* @property onMoreClick lambda be invoked when more button is clicked
|
||||
*/
|
||||
data class HeaderConfig(
|
||||
val wallets: List<WalletCardState>,
|
||||
val onScanCardClick: () -> Unit,
|
||||
val onMoreClick: () -> Unit,
|
||||
)
|
||||
}
|
||||
|
|
@ -5,10 +5,9 @@ import androidx.compose.foundation.Image
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -21,20 +20,16 @@ import androidx.constraintlayout.compose.ConstraintLayout
|
|||
import androidx.constraintlayout.compose.Dimension
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.presentation.ui.config.PriceChange
|
||||
import com.tangem.feature.wallet.presentation.ui.config.PriceChangeType
|
||||
import com.tangem.feature.wallet.presentation.ui.config.TokenV2Config
|
||||
import com.tangem.feature.wallet.presentation.ui.state.TokenOptionsUIState
|
||||
import com.tangem.feature.wallet.presentation.ui.state.TokenUIState
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.state.*
|
||||
|
||||
private const val DOTS = "•••"
|
||||
|
||||
@Composable
|
||||
fun TokenItemV2(config: TokenV2Config) {
|
||||
internal fun TokenItemV2(config: TokenV2Config) {
|
||||
when (config.tokenUIState) {
|
||||
TokenUIState.LOADED -> LoadedTokenState(config)
|
||||
TokenUIState.LOADING -> LoadingTokenState()
|
||||
|
|
@ -167,7 +162,6 @@ private fun LoadingTokenState() {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun BaseSurface(onClick: (() -> Unit)? = null, content: @Composable () -> Unit) {
|
||||
Surface(
|
||||
|
|
@ -224,12 +218,15 @@ private fun TokenFiatPercentageBlock(fiatAmount: String, priceChange: PriceChang
|
|||
) {
|
||||
val iconChangeArrow: Int
|
||||
val changeTextColor: Color
|
||||
if (priceChange.type == PriceChangeType.UP) {
|
||||
iconChangeArrow = R.drawable.img_arrow_up_8
|
||||
changeTextColor = TangemTheme.colors.text.accent
|
||||
} else {
|
||||
iconChangeArrow = R.drawable.img_arrow_down_8
|
||||
changeTextColor = TangemTheme.colors.text.warning
|
||||
when (priceChange.type) {
|
||||
PriceChangeType.UP -> {
|
||||
iconChangeArrow = R.drawable.img_arrow_up_8
|
||||
changeTextColor = TangemTheme.colors.text.accent
|
||||
}
|
||||
PriceChangeType.DOWN -> {
|
||||
iconChangeArrow = R.drawable.img_arrow_down_8
|
||||
changeTextColor = TangemTheme.colors.text.warning
|
||||
}
|
||||
}
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
|
|
|
|||
|
|
@ -1,193 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.ui
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.ui.config.WalletHeaderConfig
|
||||
import com.tangem.feature.wallet.presentation.ui.state.BalanceUIState
|
||||
|
||||
private const val DOTS = "•••"
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun WalletHeaderCard(config: WalletHeaderConfig, modifier: Modifier = Modifier) {
|
||||
Surface(
|
||||
modifier = modifier.defaultMinSize(minHeight = TangemTheme.dimens.size108),
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
color = TangemTheme.colors.background.primary,
|
||||
onClick = config.onClick ?: {},
|
||||
enabled = config.onClick != null,
|
||||
) {
|
||||
ConstraintLayout(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
val (balanceBlock, imageItem) = createRefs()
|
||||
Column(
|
||||
modifier = Modifier.constrainAs(balanceBlock) {
|
||||
centerVerticallyTo(parent)
|
||||
start.linkTo(parent.start)
|
||||
end.linkTo(imageItem.start)
|
||||
width = Dimension.fillToConstraints
|
||||
},
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
HeaderWalletName(
|
||||
walletName = config.walletName,
|
||||
balanceState = config.balanceState,
|
||||
)
|
||||
HeaderBalanceTitle(
|
||||
balance = config.balance,
|
||||
balanceState = config.balanceState,
|
||||
)
|
||||
Text(
|
||||
text = config.additionalInfo,
|
||||
color = TangemTheme.colors.text.disabled,
|
||||
style = TangemTheme.typography.caption,
|
||||
)
|
||||
}
|
||||
val imageWidth = TangemTheme.dimens.size120
|
||||
Image(
|
||||
modifier = Modifier.constrainAs(imageItem) {
|
||||
centerVerticallyTo(parent)
|
||||
top.linkTo(parent.top)
|
||||
end.linkTo(parent.end)
|
||||
height = Dimension.fillToConstraints
|
||||
width = Dimension.value(imageWidth)
|
||||
},
|
||||
painter = config.cardImage,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.FillWidth,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HeaderWalletName(walletName: String, balanceState: BalanceUIState) {
|
||||
if (balanceState == BalanceUIState.HIDDEN) {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4)) {
|
||||
Text(
|
||||
text = walletName,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
maxLines = 1,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.size(size = TangemTheme.dimens.size20),
|
||||
painter = painterResource(id = R.drawable.ic_eye_off_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Text(
|
||||
text = walletName,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HeaderBalanceTitle(balance: String, balanceState: BalanceUIState) {
|
||||
when (balanceState) {
|
||||
BalanceUIState.VISIBLE -> {
|
||||
ResizableText(
|
||||
text = balance,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.h2,
|
||||
fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
|
||||
modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size32),
|
||||
)
|
||||
}
|
||||
BalanceUIState.LOADING -> {
|
||||
ShimmerRectangle(
|
||||
modifier = Modifier.size(
|
||||
width = TangemTheme.dimens.size102,
|
||||
height = TangemTheme.dimens.size24,
|
||||
),
|
||||
)
|
||||
}
|
||||
BalanceUIState.HIDDEN -> {
|
||||
Text(
|
||||
text = DOTS,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.h2,
|
||||
)
|
||||
}
|
||||
BalanceUIState.NONE -> {
|
||||
Text(
|
||||
text = "—",
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.h2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
|
||||
@Composable
|
||||
private fun WarningsPreview() {
|
||||
val walletHeaderConfig = WalletHeaderConfig(
|
||||
walletName = "Wallet 1",
|
||||
balance = "8923,05 $",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
balanceState = BalanceUIState.VISIBLE,
|
||||
cardImage = painterResource(id = R.drawable.ill_businessman_3d),
|
||||
onClick = {},
|
||||
)
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
WalletHeaderCard(
|
||||
config = walletHeaderConfig,
|
||||
)
|
||||
SpacerH32()
|
||||
WalletHeaderCard(
|
||||
config = walletHeaderConfig.copy(balanceState = BalanceUIState.HIDDEN),
|
||||
)
|
||||
SpacerH32()
|
||||
WalletHeaderCard(
|
||||
config = walletHeaderConfig.copy(balanceState = BalanceUIState.LOADING),
|
||||
)
|
||||
SpacerH32()
|
||||
WalletHeaderCard(
|
||||
config = walletHeaderConfig.copy(balanceState = BalanceUIState.NONE),
|
||||
)
|
||||
SpacerH32()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_Warning_InLightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
WarningsPreview()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_Warning_InDarkTheme() {
|
||||
TangemTheme(isDark = true) {
|
||||
WarningsPreview()
|
||||
}
|
||||
}
|
||||
|
||||
// endregion Preview
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.tangem.feature.wallet.presentation.ui
|
||||
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.feature.wallet.presentation.state.WalletCardState
|
||||
import java.util.UUID
|
||||
|
||||
internal object WalletPreviewData {
|
||||
|
||||
val walletCardContent = WalletCardState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
title = "Wallet 1",
|
||||
balance = "8923,05 $",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
val walletCardLoading = WalletCardState.Loading(
|
||||
id = UUID.randomUUID().toString(),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
val walletCardHiddenContent = WalletCardState.HiddenContent(
|
||||
id = UUID.randomUUID().toString(),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
val walletCardError = WalletCardState.Error(
|
||||
id = UUID.randomUUID().toString(),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.feature.wallet.presentation.ui
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.tangem.feature.wallet.presentation.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.ui.components.WalletHeader
|
||||
|
||||
/**
|
||||
* Wallet screen
|
||||
*
|
||||
* @param state screen state
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
internal fun WalletScreen(state: WalletStateHolder) {
|
||||
BackHandler(onBack = state.onBackClick)
|
||||
|
||||
Scaffold(
|
||||
topBar = { WalletHeader(config = state.headerConfig) },
|
||||
) {
|
||||
// TODO: [REDACTED_TASK_KEY] Design a body with tokens and transactions
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
package com.tangem.feature.wallet.presentation.ui.components
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import com.tangem.core.ui.components.FontSizeRange
|
||||
import com.tangem.core.ui.components.ResizableText
|
||||
import com.tangem.core.ui.components.ShimmerRectangle
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.state.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.ui.WalletPreviewData
|
||||
|
||||
private const val DOTS = "•••"
|
||||
|
||||
/**
|
||||
* Wallet card
|
||||
*
|
||||
* @param state state
|
||||
* @param modifier modifier
|
||||
*/
|
||||
@Composable
|
||||
internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
|
||||
Surface(
|
||||
modifier = modifier.defaultMinSize(minHeight = TangemTheme.dimens.size108),
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
color = TangemTheme.colors.background.primary,
|
||||
onClick = state.onClick ?: {},
|
||||
enabled = state.onClick != null,
|
||||
) {
|
||||
ConstraintLayout(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
val (balanceBlock, imageItem) = createRefs()
|
||||
Column(
|
||||
modifier = Modifier.constrainAs(balanceBlock) {
|
||||
centerVerticallyTo(parent)
|
||||
start.linkTo(parent.start)
|
||||
end.linkTo(imageItem.start)
|
||||
width = Dimension.fillToConstraints
|
||||
},
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
Title(state)
|
||||
Balance(state)
|
||||
AdditionalInfo(description = state.additionalInfo)
|
||||
}
|
||||
|
||||
val imageWidth = TangemTheme.dimens.size120
|
||||
WalletImage(
|
||||
id = state.imageResId,
|
||||
modifier = Modifier.constrainAs(imageItem) {
|
||||
centerVerticallyTo(parent)
|
||||
top.linkTo(parent.top)
|
||||
end.linkTo(parent.end)
|
||||
height = Dimension.fillToConstraints
|
||||
width = Dimension.value(imageWidth)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Title(state: WalletCardState) {
|
||||
when (state) {
|
||||
is WalletCardState.HiddenContent -> {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4)) {
|
||||
Text(
|
||||
text = state.title,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
maxLines = 1,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.size(size = TangemTheme.dimens.size20),
|
||||
painter = painterResource(id = R.drawable.ic_eye_off_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Text(
|
||||
text = state.title,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Balance(state: WalletCardState) {
|
||||
when (state) {
|
||||
is WalletCardState.Content -> {
|
||||
ResizableText(
|
||||
text = state.balance,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.h2,
|
||||
fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
|
||||
modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size32),
|
||||
)
|
||||
}
|
||||
is WalletCardState.Loading -> {
|
||||
ShimmerRectangle(
|
||||
modifier = Modifier.size(
|
||||
width = TangemTheme.dimens.size102,
|
||||
height = TangemTheme.dimens.size24,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletCardState.HiddenContent -> {
|
||||
Text(
|
||||
text = DOTS,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.h2,
|
||||
)
|
||||
}
|
||||
is WalletCardState.Error -> {
|
||||
Text(
|
||||
text = "—",
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.h2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AdditionalInfo(description: String) {
|
||||
Text(
|
||||
text = description,
|
||||
color = TangemTheme.colors.text.disabled,
|
||||
style = TangemTheme.typography.caption,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WalletImage(@DrawableRes id: Int, modifier: Modifier = Modifier) {
|
||||
Image(
|
||||
painter = painterResource(id),
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
contentScale = ContentScale.FillWidth,
|
||||
)
|
||||
}
|
||||
|
||||
// region Preview
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_WalletCard_LightTheme(@PreviewParameter(WalletCardStateProvider::class) state: WalletCardState) {
|
||||
TangemTheme(isDark = false) {
|
||||
WalletCard(state)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_WalletCard_DarkTheme(@PreviewParameter(WalletCardStateProvider::class) state: WalletCardState) {
|
||||
TangemTheme(isDark = true) {
|
||||
WalletCard(state)
|
||||
}
|
||||
}
|
||||
|
||||
private class WalletCardStateProvider : CollectionPreviewParameterProvider<WalletCardState>(
|
||||
collection = listOf(
|
||||
WalletPreviewData.walletCardContent,
|
||||
WalletPreviewData.walletCardLoading,
|
||||
WalletPreviewData.walletCardHiddenContent,
|
||||
WalletPreviewData.walletCardError,
|
||||
),
|
||||
)
|
||||
|
||||
// endregion Preview
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package com.tangem.feature.wallet.presentation.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.state.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.ui.WalletPreviewData
|
||||
|
||||
/**
|
||||
* Wallet screen header
|
||||
*
|
||||
* @param config config
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
internal fun WalletHeader(config: WalletStateHolder.HeaderConfig) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(color = TangemTheme.colors.background.secondary)
|
||||
.padding(bottom = TangemTheme.dimens.spacing14),
|
||||
) {
|
||||
TopBar(onScanCardClick = config.onScanCardClick, onMoreClick = config.onMoreClick)
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
items(items = config.wallets, key = WalletCardState::id) { state ->
|
||||
WalletCard(
|
||||
state = state,
|
||||
modifier = Modifier.width(LocalConfiguration.current.screenWidthDp.dp - TangemTheme.dimens.size32),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TopBar(onScanCardClick: () -> Unit, onMoreClick: () -> Unit) {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Icon(painter = painterResource(id = R.drawable.img_tangem_logo_90_24), contentDescription = null)
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = onScanCardClick) {
|
||||
Icon(painter = painterResource(id = R.drawable.ic_tap_card_24), contentDescription = "Scan card")
|
||||
}
|
||||
IconButton(onClick = onMoreClick) {
|
||||
Icon(painter = painterResource(id = R.drawable.ic_more_vertical_24), contentDescription = "More")
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = TangemTheme.colors.background.secondary,
|
||||
titleContentColor = TangemTheme.colors.icon.primary1,
|
||||
actionIconContentColor = TangemTheme.colors.icon.primary1,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_WalletHeader_LightTheme(
|
||||
@PreviewParameter(WalletHeaderProvider::class) state: WalletStateHolder.HeaderConfig,
|
||||
) {
|
||||
TangemTheme(isDark = false) {
|
||||
WalletHeader(state)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_WalletHeader_DarkTheme(
|
||||
@PreviewParameter(WalletHeaderProvider::class) state: WalletStateHolder.HeaderConfig,
|
||||
) {
|
||||
TangemTheme(isDark = true) {
|
||||
WalletHeader(state)
|
||||
}
|
||||
}
|
||||
|
||||
private class WalletHeaderProvider : CollectionPreviewParameterProvider<WalletStateHolder.HeaderConfig>(
|
||||
collection = listOf(
|
||||
WalletStateHolder.HeaderConfig(
|
||||
wallets = listOf(
|
||||
WalletPreviewData.walletCardContent,
|
||||
WalletPreviewData.walletCardLoading,
|
||||
WalletPreviewData.walletCardHiddenContent,
|
||||
WalletPreviewData.walletCardError,
|
||||
),
|
||||
onScanCardClick = {},
|
||||
onMoreClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.ui.config
|
||||
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import com.tangem.feature.wallet.presentation.ui.state.BalanceUIState
|
||||
|
||||
data class WalletHeaderConfig(
|
||||
val walletName: String,
|
||||
val balance: String,
|
||||
val additionalInfo: String,
|
||||
val balanceState: BalanceUIState,
|
||||
val cardImage: Painter,
|
||||
val onClick: (() -> Unit)?,
|
||||
)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.ui.state
|
||||
|
||||
enum class BalanceUIState {
|
||||
VISIBLE, LOADING, HIDDEN, NONE
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.ui.state
|
||||
|
||||
enum class TokenUIState {
|
||||
LOADED, LOADING
|
||||
}
|
||||
|
||||
enum class TokenOptionsUIState {
|
||||
VISIBLE, HIDDEN, DRAG, UNREACHABLE
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="90dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="90"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M20,7.5H4V5.5C4,3.843 5.343,2.5 7,2.5H17C18.657,2.5 20,3.843 20,5.5V7.5ZM9,21.5H7C5.343,21.5 4,20.157 4,18.5V11.5H9V21.5ZM15,21.5H17C18.657,21.5 20,20.157 20,18.5V11.5H15V21.5Z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M32.063,18.693C31.148,18.693 30.447,18.452 29.96,17.97C29.485,17.488 29.247,16.795 29.247,15.892V10.723H28V9.078H29.247V7H31.404V9.078H33.453V10.723H31.404V15.693C31.404,16.5 31.76,16.904 32.473,16.904C32.889,16.904 33.239,16.843 33.525,16.723V18.458C33.109,18.615 32.622,18.693 32.063,18.693Z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M37.642,18.711C36.727,18.711 35.978,18.482 35.396,18.024C34.814,17.554 34.523,16.849 34.523,15.91C34.523,14.873 34.957,14.115 35.824,13.632C36.691,13.151 37.85,12.91 39.299,12.91H40.457V12.422C40.457,11.771 40.327,11.295 40.065,10.994C39.816,10.681 39.382,10.524 38.764,10.524C37.683,10.524 37.089,11.018 36.982,12.006H34.897C34.98,10.958 35.384,10.175 36.109,9.657C36.846,9.139 37.772,8.88 38.889,8.88C41.372,8.88 42.614,10.03 42.614,12.331V18.53H40.493V17.374C39.828,18.265 38.877,18.711 37.642,18.711ZM38.159,17.139C38.836,17.139 39.388,16.97 39.816,16.632C40.244,16.283 40.457,15.813 40.457,15.223V14.283H39.353C37.558,14.283 36.661,14.795 36.661,15.819C36.661,16.699 37.16,17.139 38.159,17.139Z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M44.729,18.53V9.078H46.885V10.578C47.123,10.084 47.503,9.681 48.026,9.367C48.549,9.042 49.172,8.88 49.897,8.88C50.883,8.88 51.661,9.187 52.232,9.801C52.802,10.404 53.087,11.331 53.087,12.584V18.53H50.931V12.783C50.931,12.072 50.782,11.548 50.485,11.211C50.188,10.873 49.719,10.705 49.077,10.705C48.436,10.705 47.907,10.904 47.491,11.301C47.087,11.687 46.885,12.241 46.885,12.964V18.53H44.729Z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M59.189,22C57.799,22 56.736,21.717 55.999,21.151C55.263,20.584 54.829,19.819 54.698,18.855H56.872C57.062,19.843 57.829,20.337 59.171,20.337C60.906,20.337 61.773,19.488 61.773,17.789V16.398C61.5,16.879 61.084,17.295 60.526,17.645C59.979,17.982 59.379,18.151 58.726,18.151C57.538,18.151 56.551,17.735 55.767,16.904C54.983,16.072 54.591,14.988 54.591,13.651V13.524C54.591,12.199 54.989,11.096 55.785,10.217C56.581,9.325 57.579,8.88 58.779,8.88C60.157,8.88 61.155,9.428 61.773,10.524V9.078H63.93V17.825C63.918,19.187 63.49,20.223 62.646,20.934C61.815,21.645 60.662,22 59.189,22ZM59.26,16.47C60.021,16.47 60.639,16.211 61.114,15.693C61.601,15.175 61.844,14.47 61.844,13.578V13.452C61.844,12.56 61.619,11.861 61.167,11.355C60.716,10.849 60.104,10.596 59.332,10.596C58.548,10.596 57.93,10.861 57.478,11.392C57.027,11.922 56.801,12.62 56.801,13.488V13.632C56.801,14.488 57.033,15.175 57.496,15.693C57.959,16.211 58.548,16.47 59.26,16.47Z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M70.235,18.711C68.845,18.711 67.71,18.277 66.831,17.41C65.952,16.542 65.512,15.373 65.512,13.904V13.759C65.512,12.313 65.946,11.139 66.813,10.235C67.692,9.331 68.803,8.88 70.146,8.88C71.405,8.88 72.451,9.277 73.282,10.072C74.126,10.868 74.548,12.06 74.548,13.651V14.283H67.722C67.758,15.187 67.995,15.88 68.435,16.361C68.874,16.843 69.492,17.084 70.288,17.084C71.548,17.084 72.261,16.602 72.427,15.639H74.512C74.357,16.626 73.906,17.385 73.158,17.916C72.409,18.446 71.435,18.711 70.235,18.711ZM67.758,12.819H72.409C72.302,11.253 71.548,10.47 70.146,10.47C69.504,10.47 68.97,10.681 68.542,11.102C68.126,11.512 67.865,12.084 67.758,12.819Z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M76.117,18.53V9.078H78.274V10.524C78.511,10.054 78.88,9.663 79.379,9.349C79.878,9.036 80.454,8.88 81.107,8.88C82.414,8.88 83.293,9.446 83.745,10.578C84.089,10.024 84.547,9.602 85.117,9.313C85.687,9.024 86.281,8.88 86.899,8.88C87.814,8.88 88.557,9.187 89.127,9.801C89.709,10.404 90,11.319 90,12.548V18.53H87.844V12.693C87.844,11.368 87.291,10.705 86.186,10.705C85.616,10.705 85.129,10.898 84.725,11.283C84.333,11.657 84.137,12.187 84.137,12.873V18.53H81.98V12.693C81.98,11.368 81.428,10.705 80.323,10.705C79.753,10.705 79.266,10.898 78.862,11.283C78.47,11.657 78.274,12.187 78.274,12.873V18.53H76.117Z" />
|
||||
</vector>
|
||||
|
|
@ -25,6 +25,7 @@ compose-compiler = "1.4.3"
|
|||
compose-runtime = "1.3.3"
|
||||
compose-foundation = "1.3.1"
|
||||
compose-material = "1.4.2"
|
||||
compose-material3 = "1.1.0"
|
||||
compose-constraint = "1.0.1"
|
||||
compose-navigation = "2.5.3"
|
||||
compose-accompanist = "0.28.0"
|
||||
|
|
@ -132,6 +133,7 @@ compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref =
|
|||
compose-animation = { module = "androidx.compose.animation:animation", version.ref = "compose-runtime" }
|
||||
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose-foundation" }
|
||||
compose-material = { module = "androidx.compose.material:material", version.ref = "compose-material" }
|
||||
compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "compose-material3" }
|
||||
compose-constraintLayout = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "compose-constraint" }
|
||||
compose-shimmer = { module = "com.valentinilk.shimmer:compose-shimmer", version.ref = "compose-shimmer" }
|
||||
compose-coil = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
|
||||
|
|
@ -211,5 +213,5 @@ mviCore-watcher = { module = "com.github.badoo.mvicore:mvicore-diff", version.re
|
|||
kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinSerialization" }
|
||||
arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" }
|
||||
arrow-fx = { module = "io.arrow-kt:arrow-fx-coroutines", version.ref = "arrow" }
|
||||
reactive-network = { module = "com.github.pwittchen:reactivenetwork-rx2", version.ref = "reactiveNetwork" }
|
||||
reactive-network = { module = "com.github.pwittchen:reactivenetwork-rx2", version.ref = "reactiveNetwork" }
|
||||
# endregion Other
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue