Updated on 2026-08-14
This commit is contained in:
parent
c55274f40f
commit
efcb0dea79
20 changed files with 477 additions and 17 deletions
|
|
@ -1,10 +1,7 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
||||
import com.tangem.domain.notifications.GetApplicationIdUseCase
|
||||
import com.tangem.domain.notifications.GetTronFeeNotificationShowCountUseCase
|
||||
import com.tangem.domain.notifications.IncrementNotificationsShowCountUseCase
|
||||
import com.tangem.domain.notifications.SendPushTokenUseCase
|
||||
import com.tangem.domain.notifications.*
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
|
||||
import com.tangem.tap.domain.notifications.DefaultNotificationsFeatureToggles
|
||||
|
|
@ -64,4 +61,12 @@ internal object NotificationsDomainModule {
|
|||
fun provideNotificationsFeatureToggles(featureTogglesManager: FeatureTogglesManager): NotificationsFeatureToggles {
|
||||
return DefaultNotificationsFeatureToggles(featureTogglesManager = featureTogglesManager)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetNetworksAvailableForNotifications(
|
||||
notificationsRepository: NotificationsRepository,
|
||||
): GetNetworksAvailableForNotificationsUseCase {
|
||||
return GetNetworksAvailableForNotificationsUseCase(notificationsRepository = notificationsRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.tangem.core.ui.components.items
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
@Composable
|
||||
fun NetworkNameAndSymbolItem(icon: Int, name: String, symbol: String, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier.padding(14.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.size(24.dp),
|
||||
painter = painterResource(icon),
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.weight(1f, fill = false),
|
||||
text = name,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Text(text = symbol, style = TangemTheme.typography.caption1, color = TangemTheme.colors.text.tertiary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NetworkNameAndSymbolItemShimmer(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier.padding(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
CircleShimmer(
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.size(24.dp),
|
||||
)
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
modifier = Modifier.width(70.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun ContentPreview() {
|
||||
TangemThemePreview {
|
||||
Column {
|
||||
NetworkNameAndSymbolItemShimmer()
|
||||
NetworkNameAndSymbolItem(
|
||||
icon = R.drawable.ic_solana_16,
|
||||
name = "Solana",
|
||||
symbol = "SOL",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
31
core/ui/src/main/res/drawable/ic_notification_48.xml
Normal file
31
core/ui/src/main/res/drawable/ic_notification_48.xml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M25,6H23C14.043,6 9.565,6 6.782,8.782C4,11.565 4,16.043 4,25C4,33.957 4,38.435 6.782,41.217C9.565,44 14.043,44 23,44C31.957,44 36.435,44 39.217,41.217C42,38.435 42,33.957 42,25V23"
|
||||
android:strokeWidth="3"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#0099FF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M44,11C44,14.866 40.866,18 37,18C33.134,18 30,14.866 30,11C30,7.134 33.134,4 37,4C40.866,4 44,7.134 44,11Z"
|
||||
android:strokeWidth="3"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#0099FF"/>
|
||||
<path
|
||||
android:pathData="M14,22H22"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#0099FF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M14,32H30"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#0099FF"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
@ -10,6 +10,9 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
// region sdk
|
||||
implementation(tangemDeps.blockchain)
|
||||
// endregion
|
||||
|
||||
// region AndroidX libraries
|
||||
implementation(deps.androidx.datastore)
|
||||
|
|
@ -28,6 +31,8 @@ dependencies {
|
|||
// region Core modules
|
||||
implementation(projects.core.datasource)
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
// endregion
|
||||
|
||||
// region Domain modules
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ internal class DefaultNotificationsRepository @Inject constructor(
|
|||
}
|
||||
|
||||
override suspend fun getEligibleNetworks(): List<NotificationsEligibleNetwork> = withContext(dispatchers.io) {
|
||||
tangemTechApi.getEligibleNetworksForPushNotifications().getOrThrow().map {
|
||||
tangemTechApi.getEligibleNetworksForPushNotifications().getOrThrow().mapNotNull {
|
||||
NotificationsEligibleNetworkConverter.convert(it)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
package com.tangem.data.notifications.converters
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.core.ui.extensions.getActiveIconRes
|
||||
import com.tangem.datasource.api.tangemTech.models.CryptoNetworkResponse
|
||||
import com.tangem.domain.notifications.models.NotificationsEligibleNetwork
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal object NotificationsEligibleNetworkConverter : Converter<CryptoNetworkResponse, NotificationsEligibleNetwork> {
|
||||
override fun convert(value: CryptoNetworkResponse): NotificationsEligibleNetwork {
|
||||
internal object NotificationsEligibleNetworkConverter {
|
||||
fun convert(value: CryptoNetworkResponse): NotificationsEligibleNetwork? {
|
||||
val blockchain: Blockchain = Blockchain.fromNetworkId(value.networkId) ?: return null
|
||||
return NotificationsEligibleNetwork(
|
||||
id = value.id.toString(),
|
||||
networkId = value.networkId,
|
||||
name = value.name,
|
||||
id = value.networkId,
|
||||
name = blockchain.fullName,
|
||||
symbol = blockchain.currency,
|
||||
icon = getActiveIconRes(blockchain.id),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ class DefaultNotificationsRepositoryTest {
|
|||
CryptoNetworkResponse(
|
||||
id = 1,
|
||||
name = "Ethereum",
|
||||
networkId = "Ethereum",
|
||||
networkId = "ethereum",
|
||||
),
|
||||
CryptoNetworkResponse(
|
||||
id = 2,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.notifications.models
|
|||
|
||||
data class NotificationsEligibleNetwork(
|
||||
val id: String,
|
||||
val networkId: String,
|
||||
val name: String,
|
||||
val symbol: String,
|
||||
val icon: Int,
|
||||
)
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.domain.notifications
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.notifications.models.NotificationsEligibleNetwork
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
|
||||
class GetNetworksAvailableForNotificationsUseCase(
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(): Either<Throwable, List<NotificationsEligibleNetwork>> = Either.catch {
|
||||
notificationsRepository.getEligibleNetworks()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.feature.walletsettings.component
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
|
||||
interface NetworksAvailableForNotificationsComponent : ComposableBottomSheetComponent {
|
||||
|
||||
data class Params(
|
||||
val onDismiss: () -> Unit,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Params, NetworksAvailableForNotificationsComponent>
|
||||
}
|
||||
|
|
@ -37,6 +37,8 @@ dependencies {
|
|||
implementation(projects.domain.demo)
|
||||
implementation(projects.domain.nft)
|
||||
implementation(projects.domain.notifications.toggles)
|
||||
implementation(projects.domain.notifications.models)
|
||||
implementation(projects.domain.notifications)
|
||||
|
||||
/* AndroidX */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package com.tangem.feature.walletsettings.component.impl
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.feature.walletsettings.component.NetworksAvailableForNotificationsComponent
|
||||
import com.tangem.feature.walletsettings.component.impl.model.NetworksAvailableForNotificationsModel
|
||||
import com.tangem.feature.walletsettings.ui.NetworksAvailableForNotificationsListBS
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultNetworksAvailableForNotificationsComponent @AssistedInject constructor(
|
||||
@Assisted context: AppComponentContext,
|
||||
@Assisted private val params: NetworksAvailableForNotificationsComponent.Params,
|
||||
) : NetworksAvailableForNotificationsComponent, AppComponentContext by context {
|
||||
|
||||
private val model: NetworksAvailableForNotificationsModel = getOrCreateModel(params)
|
||||
|
||||
override fun dismiss() {
|
||||
params.onDismiss()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun BottomSheet() {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
|
||||
NetworksAvailableForNotificationsListBS(state = state, onBack = ::dismiss, onDismiss = ::dismiss)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : NetworksAvailableForNotificationsComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: NetworksAvailableForNotificationsComponent.Params,
|
||||
): DefaultNetworksAvailableForNotificationsComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -11,10 +11,13 @@ import com.arkivanov.decompose.router.slot.dismiss
|
|||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableDialogComponent
|
||||
import com.tangem.feature.walletsettings.component.NetworksAvailableForNotificationsComponent
|
||||
import com.tangem.feature.walletsettings.component.RenameWalletComponent
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.feature.walletsettings.entity.DialogConfig
|
||||
import com.tangem.feature.walletsettings.entity.NetworksAvailableForNotificationBSConfig
|
||||
import com.tangem.feature.walletsettings.model.WalletSettingsModel
|
||||
import com.tangem.feature.walletsettings.ui.WalletSettingsScreen
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -25,14 +28,24 @@ internal class DefaultWalletSettingsComponent @AssistedInject constructor(
|
|||
@Assisted context: AppComponentContext,
|
||||
@Assisted params: WalletSettingsComponent.Params,
|
||||
private val renameWalletComponentFactory: RenameWalletComponent.Factory,
|
||||
private val networksAvailableForNotificationsComponent: NetworksAvailableForNotificationsComponent.Factory,
|
||||
) : WalletSettingsComponent, AppComponentContext by context {
|
||||
|
||||
private val model: WalletSettingsModel = getOrCreateModel(params)
|
||||
|
||||
private val bottomSheetSlot = childSlot(
|
||||
source = model.bottomSheetNavigation,
|
||||
serializer = null,
|
||||
handleBackButton = false,
|
||||
key = "bottomSheetSlot",
|
||||
childFactory = ::bottomSheetChild,
|
||||
)
|
||||
|
||||
private val dialog = childSlot(
|
||||
source = model.dialogNavigation,
|
||||
serializer = DialogConfig.serializer(),
|
||||
handleBackButton = true,
|
||||
key = "dialogSlot",
|
||||
childFactory = ::dialogChild,
|
||||
)
|
||||
|
||||
|
|
@ -40,12 +53,15 @@ internal class DefaultWalletSettingsComponent @AssistedInject constructor(
|
|||
override fun Content(modifier: Modifier) {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
val dialog by dialog.subscribeAsState()
|
||||
val bottomSheet by bottomSheetSlot.subscribeAsState()
|
||||
|
||||
WalletSettingsScreen(
|
||||
modifier = modifier,
|
||||
state = state,
|
||||
dialog = { dialog.child?.instance?.Dialog() },
|
||||
)
|
||||
|
||||
bottomSheet.child?.instance?.BottomSheet()
|
||||
}
|
||||
|
||||
private fun dialogChild(
|
||||
|
|
@ -64,6 +80,18 @@ internal class DefaultWalletSettingsComponent @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private fun bottomSheetChild(
|
||||
config: NetworksAvailableForNotificationBSConfig,
|
||||
componentContext: ComponentContext,
|
||||
): ComposableBottomSheetComponent = networksAvailableForNotificationsComponent.create(
|
||||
context = childByContext(componentContext),
|
||||
params = NetworksAvailableForNotificationsComponent.Params(
|
||||
onDismiss = model
|
||||
.bottomSheetNavigation::dismiss,
|
||||
),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : WalletSettingsComponent.Factory {
|
||||
override fun create(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package com.tangem.feature.walletsettings.component.impl.model
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.domain.notifications.GetNetworksAvailableForNotificationsUseCase
|
||||
import com.tangem.feature.walletsettings.ui.state.NetworksAvailableForNotificationsUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
internal class NetworksAvailableForNotificationsModel @Inject constructor(
|
||||
private val getNetworksAvailableForNotificationsUseCase: GetNetworksAvailableForNotificationsUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
val state: StateFlow<NetworksAvailableForNotificationsUM> get() = _state
|
||||
|
||||
private val _state = MutableStateFlow(
|
||||
value = NetworksAvailableForNotificationsUM(
|
||||
networks = persistentListOf(),
|
||||
isLoading = true,
|
||||
),
|
||||
)
|
||||
|
||||
init {
|
||||
modelScope.launch {
|
||||
getNetworksAvailableForNotificationsUseCase().onRight { networks ->
|
||||
_state.update {
|
||||
it.copy(networks = networks.toImmutableList(), isLoading = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,10 @@ package com.tangem.feature.walletsettings.di
|
|||
|
||||
import com.tangem.feature.walletsettings.component.RenameWalletComponent
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.feature.walletsettings.component.impl.DefaultNetworksAvailableForNotificationsComponent
|
||||
import com.tangem.feature.walletsettings.component.impl.DefaultRenameWalletComponent
|
||||
import com.tangem.feature.walletsettings.component.impl.DefaultWalletSettingsComponent
|
||||
import com.tangem.feature.walletsettings.component.NetworksAvailableForNotificationsComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -23,4 +25,10 @@ internal interface WalletSettingsComponentModule {
|
|||
@Binds
|
||||
@Singleton
|
||||
fun bindRenameWalletComponentFactory(factory: DefaultRenameWalletComponent.Factory): RenameWalletComponent.Factory
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindNetworksComponentFactory(
|
||||
factory: DefaultNetworksAvailableForNotificationsComponent.Factory,
|
||||
): NetworksAvailableForNotificationsComponent.Factory
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.walletsettings.di
|
|||
|
||||
import com.tangem.core.decompose.di.ModelComponent
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.feature.walletsettings.component.impl.model.NetworksAvailableForNotificationsModel
|
||||
import com.tangem.feature.walletsettings.component.impl.model.RenameWalletModel
|
||||
import com.tangem.feature.walletsettings.model.WalletSettingsModel
|
||||
import dagger.Binds
|
||||
|
|
@ -23,4 +24,9 @@ internal interface WalletSettingsModelModule {
|
|||
@IntoMap
|
||||
@ClassKey(RenameWalletModel::class)
|
||||
fun bindRenameWalletModel(model: RenameWalletModel): Model
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(NetworksAvailableForNotificationsModel::class)
|
||||
fun bindNetworksAvailableForNotificationsModel(model: NetworksAvailableForNotificationsModel): Model
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.feature.walletsettings.entity
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
internal object NetworksAvailableForNotificationBSConfig
|
||||
|
|
@ -13,9 +13,7 @@ import com.tangem.core.decompose.navigation.Router
|
|||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.navigation.settings.SettingsManager
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.core.ui.message.*
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
|
|
@ -31,6 +29,7 @@ import com.tangem.domain.wallets.usecase.*
|
|||
import com.tangem.feature.walletsettings.analytics.Settings
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.feature.walletsettings.entity.DialogConfig
|
||||
import com.tangem.feature.walletsettings.entity.NetworksAvailableForNotificationBSConfig
|
||||
import com.tangem.feature.walletsettings.entity.WalletSettingsItemUM
|
||||
import com.tangem.feature.walletsettings.entity.WalletSettingsUM
|
||||
import com.tangem.feature.walletsettings.impl.R
|
||||
|
|
@ -70,6 +69,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
|
||||
val params: WalletSettingsComponent.Params = paramsContainer.require()
|
||||
val dialogNavigation = SlotNavigation<DialogConfig>()
|
||||
val bottomSheetNavigation: SlotNavigation<NetworksAvailableForNotificationBSConfig> = SlotNavigation()
|
||||
|
||||
val state: MutableStateFlow<WalletSettingsUM> = MutableStateFlow(
|
||||
value = WalletSettingsUM(
|
||||
|
|
@ -215,7 +215,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onNotificationsDescriptionClick() {
|
||||
// TODO [REDACTED_JIRA]
|
||||
bottomSheetNavigation.activate(NetworksAvailableForNotificationBSConfig)
|
||||
}
|
||||
|
||||
private fun openPushSystemSettings() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,171 @@
|
|||
package com.tangem.feature.walletsettings.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.SpacerH24
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetWithFooter
|
||||
import com.tangem.core.ui.components.items.NetworkNameAndSymbolItem
|
||||
import com.tangem.core.ui.components.items.NetworkNameAndSymbolItemShimmer
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.notifications.models.NotificationsEligibleNetwork
|
||||
import com.tangem.feature.walletsettings.ui.state.NetworksAvailableForNotificationsUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun NetworksAvailableForNotificationsListBS(
|
||||
state: NetworksAvailableForNotificationsUM,
|
||||
onBack: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
TangemModalBottomSheetWithFooter<TangemBottomSheetConfigContent.Empty>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = onDismiss,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
onBack = onBack,
|
||||
title = {
|
||||
TangemModalBottomSheetTitle(
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = onDismiss,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
NetworksAvailableForNotificationsListBottomSheetContent(
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
state = state,
|
||||
)
|
||||
},
|
||||
footer = {
|
||||
SecondaryButton(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.balance_hidden_got_it_button),
|
||||
onClick = onDismiss,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NetworksAvailableForNotificationsListBottomSheetContent(
|
||||
state: NetworksAvailableForNotificationsUM,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.background(TangemTheme.colors.background.primary),
|
||||
) {
|
||||
Header()
|
||||
SpacerH24()
|
||||
Networks(networks = state.networks, isLoading = state.isLoading)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.Header() {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_notification_48),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.size(TangemTheme.dimens.size56),
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.push_transactions_notifications_title),
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing34,
|
||||
end = TangemTheme.dimens.spacing34,
|
||||
top = TangemTheme.dimens.spacing28,
|
||||
),
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.push_transactions_notifications_description),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing34,
|
||||
end = TangemTheme.dimens.spacing34,
|
||||
top = TangemTheme.dimens.spacing8,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Networks(
|
||||
networks: ImmutableList<NotificationsEligibleNetwork>,
|
||||
modifier: Modifier = Modifier,
|
||||
isLoading: Boolean = false,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
modifier = Modifier.padding(top = 12.dp, bottom = 4.dp, start = 12.dp, end = 12.dp),
|
||||
text = stringResourceSafe(R.string.common_supported_networks),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
if (isLoading) {
|
||||
repeat(SHIMMERS_COUNT) {
|
||||
NetworkNameAndSymbolItemShimmer()
|
||||
}
|
||||
} else {
|
||||
networks.fastForEach { network ->
|
||||
key(network.id) {
|
||||
NetworkNameAndSymbolItem(
|
||||
icon = network.icon,
|
||||
name = network.name,
|
||||
symbol = network.symbol,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val SHIMMERS_COUNT = 10
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_CustomTokenNetworkSelectorContent() {
|
||||
TangemThemePreview {
|
||||
NetworksAvailableForNotificationsListBS(
|
||||
state = NetworksAvailableForNotificationsUM(
|
||||
networks = persistentListOf(),
|
||||
isLoading = true,
|
||||
),
|
||||
onDismiss = {},
|
||||
onBack = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.feature.walletsettings.ui.state
|
||||
|
||||
import com.tangem.domain.notifications.models.NotificationsEligibleNetwork
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class NetworksAvailableForNotificationsUM(
|
||||
val networks: ImmutableList<NotificationsEligibleNetwork>,
|
||||
val isLoading: Boolean,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue