From af5501fb9b9b21563847de5569fa63f598c46527 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 18 Apr 2025 19:22:02 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../di/domain/WalletConnectDomainModule.kt | 8 +++ .../connections/entity/WcConnectionsState.kt | 2 +- .../connections/model/WcConnectionsModel.kt | 54 ++++++++++++++++--- .../transformers/WcSessionsTransformer.kt | 38 +++++++++++++ .../connections/ui/WcConnectionsContent.kt | 10 ++-- .../ui/preview/WcConnectionsPreviewData.kt | 26 ++------- .../configurations/KotlinConfigurations.kt | 10 ++-- 7 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsTransformer.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletConnectDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletConnectDomainModule.kt index e542ddc5fd..fd5d2491d3 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/WalletConnectDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/WalletConnectDomainModule.kt @@ -2,6 +2,8 @@ package com.tangem.tap.di.domain import com.tangem.domain.walletconnect.CheckIsWalletConnectAvailableUseCase import com.tangem.domain.walletconnect.repository.WalletConnectRepository +import com.tangem.domain.walletconnect.repository.WcSessionsManager +import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -19,4 +21,10 @@ internal object WalletConnectDomainModule { ): CheckIsWalletConnectAvailableUseCase { return CheckIsWalletConnectAvailableUseCase(walletConnectRepository = walletConnectRepository) } + + @Provides + @Singleton + fun providesWcSessionsUseCase(sessionsManager: WcSessionsManager): WcSessionsUseCase { + return WcSessionsUseCase(sessionsManager) + } } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcConnectionsState.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcConnectionsState.kt index 62474e35b9..0eb7c4e19b 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcConnectionsState.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/entity/WcConnectionsState.kt @@ -14,7 +14,7 @@ internal data class WcConnectionsState( internal data class WcConnectionsTopAppBarConfig( val startButtonUM: TopAppBarButtonUM, - val endActions: ImmutableList, + val disconnectAllItem: TangemDropdownMenuItem, ) internal data class WcConnectionsUM( diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt index ada41bf7d8..a0b6c6aa91 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcConnectionsModel.kt @@ -6,15 +6,22 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM +import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenuItem 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.res.TangemTheme import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase +import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase import com.tangem.features.walletconnect.connections.entity.WcConnectionsState -import com.tangem.features.walletconnect.connections.ui.preview.WcConnectionsPreviewData +import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppBarConfig +import com.tangem.features.walletconnect.connections.model.transformers.WcSessionsTransformer import com.tangem.features.walletconnect.impl.R import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.transformer.update +import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.* import timber.log.Timber import javax.inject.Inject @@ -24,19 +31,16 @@ internal class WcConnectionsModel @Inject constructor( private val router: Router, private val uiMessageSender: UiMessageSender, private val listenToQrScanningUseCase: ListenToQrScanningUseCase, + private val wcSessionsUseCase: WcSessionsUseCase, override val dispatchers: CoroutineDispatcherProvider, ) : Model() { - val uiState: StateFlow = MutableStateFlow( - WcConnectionsPreviewData.stateForModel( - onBackClicked = router::pop, - openQrScanScreen = ::openQrScanScreen, - disconnectAll = ::disconnectAll, - ), - ).asStateFlow() + val uiState: StateFlow + field = MutableStateFlow(getInitialState()) init { listenQrUpdates() + listenWcSessions() } private fun listenQrUpdates() { @@ -49,6 +53,21 @@ internal class WcConnectionsModel @Inject constructor( .launchIn(modelScope) } + private fun listenWcSessions() { + wcSessionsUseCase.invoke() + .conflate() + .distinctUntilChanged() + .onEach { sessionsMap -> + uiState.update( + WcSessionsTransformer( + sessionsMap = sessionsMap, + openAppInfoModal = { Timber.d("Open app info for session: $it") }, + ), + ) + } + .launchIn(modelScope) + } + private fun openQrScanScreen() { router.push(AppRoute.QrScanning(source = AppRoute.QrScanning.Source.WalletConnect)) } @@ -69,4 +88,23 @@ internal class WcConnectionsModel @Inject constructor( ) uiMessageSender.send(message) } + + private fun getInitialState(): WcConnectionsState { + return WcConnectionsState( + topAppBarConfig = WcConnectionsTopAppBarConfig( + startButtonUM = TopAppBarButtonUM( + iconRes = R.drawable.ic_back_24, + onIconClicked = router::pop, + enabled = true, + ), + disconnectAllItem = TangemDropdownMenuItem( + title = resourceReference(R.string.wc_disconnect_all), + textColorProvider = { TangemTheme.colors.text.warning }, + onClick = ::disconnectAll, + ), + ), + connections = persistentListOf(), + onNewConnectionClick = ::openQrScanScreen, + ) + } } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsTransformer.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsTransformer.kt new file mode 100644 index 0000000000..1f3b8a9ebc --- /dev/null +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/transformers/WcSessionsTransformer.kt @@ -0,0 +1,38 @@ +package com.tangem.features.walletconnect.connections.model.transformers + +import com.tangem.core.ui.extensions.stringReference +import com.tangem.domain.walletconnect.model.WcSession +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.features.walletconnect.connections.entity.WcConnectedAppInfo +import com.tangem.features.walletconnect.connections.entity.WcConnectionsState +import com.tangem.features.walletconnect.connections.entity.WcConnectionsUM +import com.tangem.utils.transformer.Transformer +import kotlinx.collections.immutable.toPersistentList + +internal class WcSessionsTransformer( + private val sessionsMap: Map>, + private val openAppInfoModal: (WcSession) -> Unit, +) : Transformer { + + override fun transform(prevState: WcConnectionsState): WcConnectionsState { + return prevState.copy( + connections = sessionsMap.map { (wallet, sessions) -> + WcConnectionsUM( + userWalletId = wallet.walletId.stringValue, + walletName = wallet.name, + connectedApps = sessions.map { session -> + with(session.sdkModel) { + WcConnectedAppInfo( + name = appMetaData.name, + iconUrl = appMetaData.icons.firstOrNull().orEmpty(), + subtitle = stringReference(appMetaData.description), + isVerified = false, + onClick = { openAppInfoModal(session) }, + ) + } + }.toPersistentList(), + ) + }.toPersistentList(), + ) + } +} \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcConnectionsContent.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcConnectionsContent.kt index 005ff5c7a4..e529ec9d02 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcConnectionsContent.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/WcConnectionsContent.kt @@ -259,12 +259,10 @@ private fun ConnectionsTopBar( modifier = Modifier.background(TangemTheme.colors.background.primary), onDismissRequest = { showDropdownMenu = false }, content = { - config.endActions.fastForEach { - TangemDropdownItem( - item = it, - dismissParent = { showDropdownMenu = false }, - ) - } + TangemDropdownItem( + item = config.disconnectAllItem, + dismissParent = { showDropdownMenu = false }, + ) }, ) }, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/preview/WcConnectionsPreviewData.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/preview/WcConnectionsPreviewData.kt index 57ce635a39..31759bb4d4 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/preview/WcConnectionsPreviewData.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/ui/preview/WcConnectionsPreviewData.kt @@ -10,7 +10,6 @@ import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppB import com.tangem.features.walletconnect.connections.entity.WcConnectionsUM import com.tangem.features.walletconnect.impl.R import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableList import timber.log.Timber internal object WcConnectionsPreviewData { @@ -111,31 +110,14 @@ internal object WcConnectionsPreviewData { onIconClicked = {}, enabled = true, ), - endActions = persistentListOf( - TangemDropdownMenuItem( - title = resourceReference(R.string.wc_disconnect_all), - textColorProvider = { TangemTheme.colors.text.warning }, - onClick = { }, - ), + disconnectAllItem = TangemDropdownMenuItem( + title = resourceReference(R.string.wc_disconnect_all), + textColorProvider = { TangemTheme.colors.text.warning }, + onClick = { }, ), ), connections = persistentListOf(), onNewConnectionClick = {}, ) val fullState = stateWithEmptyConnections.copy(connections = connections) - fun stateForModel( - onBackClicked: () -> Unit, - openQrScanScreen: () -> Unit, - disconnectAll: () -> Unit, - ): WcConnectionsState { - return fullState.copy( - topAppBarConfig = fullState.topAppBarConfig.copy( - startButtonUM = fullState.topAppBarConfig.startButtonUM.copy(onIconClicked = onBackClicked), - endActions = fullState.topAppBarConfig.endActions - .map { it.copy(onClick = disconnectAll) } - .toImmutableList(), - ), - onNewConnectionClick = openQrScanScreen, - ) - } } \ No newline at end of file diff --git a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/KotlinConfigurations.kt b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/KotlinConfigurations.kt index ae7e54965a..1ff0e4258f 100644 --- a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/KotlinConfigurations.kt +++ b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/KotlinConfigurations.kt @@ -1,15 +1,15 @@ package com.tangem.plugin.configuration.configurations import org.gradle.api.Project -import org.gradle.kotlin.dsl.getByType import org.gradle.kotlin.dsl.withType -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension -import org.jetbrains.kotlin.gradle.model.KotlinAndroidExtension +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile internal fun Project.configureKotlinCompilerOptions() { + kotlinExtension.sourceSets.all { + // https://github.com/Kotlin/KEEP/blob/explicit-backing-fields-re/proposals/explicit-backing-fields.md + languageSettings.enableLanguageFeature("ExplicitBackingFields") + } project.tasks.withType { kotlinOptions { jvmTarget = "17"