Updated on 2026-08-14
This commit is contained in:
parent
3595fdbf9a
commit
36871cc5c9
17 changed files with 152 additions and 10 deletions
|
|
@ -140,6 +140,8 @@ dependencies {
|
||||||
implementation(projects.features.disclaimer.impl)
|
implementation(projects.features.disclaimer.impl)
|
||||||
implementation(projects.features.pushNotifications.api)
|
implementation(projects.features.pushNotifications.api)
|
||||||
implementation(projects.features.pushNotifications.impl)
|
implementation(projects.features.pushNotifications.impl)
|
||||||
|
implementation(projects.features.walletSettings.api)
|
||||||
|
implementation(projects.features.walletSettings.impl)
|
||||||
|
|
||||||
/** AndroidX libraries */
|
/** AndroidX libraries */
|
||||||
implementation(deps.androidx.core.ktx)
|
implementation(deps.androidx.core.ktx)
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,17 @@ package com.tangem.tap
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
import com.tangem.core.decompose.factory.ComponentFactory
|
import com.tangem.core.decompose.factory.ComponentFactory
|
||||||
import com.tangem.core.ui.ComposableContentComponent
|
|
||||||
import com.tangem.core.ui.UiDependencies
|
import com.tangem.core.ui.UiDependencies
|
||||||
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.core.ui.message.EventMessageEffect
|
import com.tangem.core.ui.message.EventMessageEffect
|
||||||
import com.tangem.core.ui.screen.ComposeFragment
|
import com.tangem.core.ui.screen.ComposeFragment
|
||||||
import com.tangem.utils.Provider
|
import com.tangem.utils.Provider
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import java.util.WeakHashMap
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
|
|
@ -20,7 +22,10 @@ internal class DecomposeFragment : ComposeFragment() {
|
||||||
override lateinit var uiDependencies: UiDependencies
|
override lateinit var uiDependencies: UiDependencies
|
||||||
|
|
||||||
private val component by lazy(mode = LazyThreadSafetyMode.NONE) {
|
private val component by lazy(mode = LazyThreadSafetyMode.NONE) {
|
||||||
requireNotNull(componentBuilder?.build()) {
|
val tag = requireArguments().getString(TAG_KEY)
|
||||||
|
val builder = componentsBuilders[tag]
|
||||||
|
|
||||||
|
requireNotNull(builder?.build()) {
|
||||||
"Component builder is not set, call newInstance() for DecomposeFragment creation first."
|
"Component builder is not set, call newInstance() for DecomposeFragment creation first."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -46,16 +51,21 @@ internal class DecomposeFragment : ComposeFragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private var componentBuilder: ComponentBuilder<*, *, *>? = null
|
private const val TAG_KEY = "tag"
|
||||||
|
|
||||||
|
private val componentsBuilders = WeakHashMap<String, ComponentBuilder<*, *, *>>()
|
||||||
|
|
||||||
fun <C : ComposableContentComponent, P : Any, F : ComponentFactory<P, C>> newInstance(
|
fun <C : ComposableContentComponent, P : Any, F : ComponentFactory<P, C>> newInstance(
|
||||||
|
tag: String,
|
||||||
contextProvider: Provider<AppComponentContext>,
|
contextProvider: Provider<AppComponentContext>,
|
||||||
params: P,
|
params: P,
|
||||||
componentFactory: F,
|
componentFactory: F,
|
||||||
): Fragment {
|
): Fragment {
|
||||||
this@Companion.componentBuilder = ComponentBuilder(contextProvider, params, componentFactory)
|
this@Companion.componentsBuilders[tag] = ComponentBuilder(contextProvider, params, componentFactory)
|
||||||
|
|
||||||
return DecomposeFragment()
|
return DecomposeFragment().apply {
|
||||||
|
this.arguments = bundleOf(TAG_KEY to tag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import com.arkivanov.decompose.router.stack.ChildStack
|
||||||
import com.arkivanov.decompose.router.stack.childStack
|
import com.arkivanov.decompose.router.stack.childStack
|
||||||
import com.arkivanov.decompose.value.Value
|
import com.arkivanov.decompose.value.Value
|
||||||
import com.arkivanov.essenty.backhandler.BackCallback
|
import com.arkivanov.essenty.backhandler.BackCallback
|
||||||
|
import com.arkivanov.essenty.lifecycle.doOnDestroy
|
||||||
import com.tangem.common.routing.AppRoute
|
import com.tangem.common.routing.AppRoute
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
import com.tangem.core.decompose.context.childByContext
|
import com.tangem.core.decompose.context.childByContext
|
||||||
|
|
@ -34,6 +35,10 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
backHandler.register(backCallback)
|
backHandler.register(backCallback)
|
||||||
|
|
||||||
|
lifecycle.doOnDestroy {
|
||||||
|
childFactory.doOnDestroy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInitialRoute(): AppRoute = AppRoute.Initial
|
private fun getInitialRoute(): AppRoute = AppRoute.Initial
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,10 @@ internal class ChildFactory @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun doOnDestroy() {
|
||||||
|
componentContexts.clear()
|
||||||
|
}
|
||||||
|
|
||||||
private fun contextProvider(
|
private fun contextProvider(
|
||||||
appRoute: AppRoute,
|
appRoute: AppRoute,
|
||||||
contextFactory: (route: AppRoute) -> AppComponentContext,
|
contextFactory: (route: AppRoute) -> AppComponentContext,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import com.tangem.common.routing.AppRoute
|
||||||
import com.tangem.common.routing.bundle.RouteBundleParams
|
import com.tangem.common.routing.bundle.RouteBundleParams
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
import com.tangem.core.decompose.factory.ComponentFactory
|
import com.tangem.core.decompose.factory.ComponentFactory
|
||||||
import com.tangem.core.ui.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.tap.DecomposeFragment
|
import com.tangem.tap.DecomposeFragment
|
||||||
import com.tangem.tap.routing.RoutingComponent.Child
|
import com.tangem.tap.routing.RoutingComponent.Child
|
||||||
import com.tangem.utils.Provider
|
import com.tangem.utils.Provider
|
||||||
|
|
@ -29,6 +29,7 @@ internal fun <C : ComposableContentComponent, P : Any, F : ComponentFactory<P, C
|
||||||
): Child {
|
): Child {
|
||||||
val fragmentProvider = Provider {
|
val fragmentProvider = Provider {
|
||||||
DecomposeFragment.newInstance(
|
DecomposeFragment.newInstance(
|
||||||
|
tag = path,
|
||||||
contextProvider = contextProvider,
|
contextProvider = contextProvider,
|
||||||
params = params,
|
params = params,
|
||||||
componentFactory = componentFactory,
|
componentFactory = componentFactory,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.tangem.core.ui
|
package com.tangem.core.ui.decompose
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.tangem.core.ui.decompose
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
interface ComposableDialogComponent {
|
||||||
|
|
||||||
|
val doOnDismiss: () -> Unit
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Suppress("TopLevelComposableFunctions") // TODO: Remove this check
|
||||||
|
fun Dialog()
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.tangem.features.details.component
|
package com.tangem.features.details.component
|
||||||
|
|
||||||
import com.tangem.core.decompose.factory.ComponentFactory
|
import com.tangem.core.decompose.factory.ComponentFactory
|
||||||
import com.tangem.core.ui.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
||||||
interface DetailsComponent : ComposableContentComponent {
|
interface DetailsComponent : ComposableContentComponent {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.tangem.features.details.component
|
package com.tangem.features.details.component
|
||||||
|
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
import com.tangem.core.ui.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
|
|
||||||
interface UserWalletListComponent : ComposableContentComponent {
|
interface UserWalletListComponent : ComposableContentComponent {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import com.tangem.core.ui.ComposableContentComponent
|
|
||||||
import com.tangem.core.ui.components.appbar.models.TopAppBarMedium
|
import com.tangem.core.ui.components.appbar.models.TopAppBarMedium
|
||||||
import com.tangem.core.ui.components.block.BlockItem
|
import com.tangem.core.ui.components.block.BlockItem
|
||||||
import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
|
import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
|
||||||
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.res.LocalSnackbarHostState
|
import com.tangem.core.ui.res.LocalSnackbarHostState
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
|
|
||||||
1
features/wallet-settings/api/.gitignore
vendored
Normal file
1
features/wallet-settings/api/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
19
features/wallet-settings/api/build.gradle.kts
Normal file
19
features/wallet-settings/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
plugins {
|
||||||
|
alias(deps.plugins.android.library)
|
||||||
|
alias(deps.plugins.kotlin.android)
|
||||||
|
id("configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.tangem.feature.walletsettings.api"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
/* Project - Domain */
|
||||||
|
implementation(projects.domain.wallets.models)
|
||||||
|
|
||||||
|
/* Project - Core */
|
||||||
|
implementation(projects.core.decompose)
|
||||||
|
implementation(projects.core.ui)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.tangem.feature.walletsettings.component
|
||||||
|
|
||||||
|
import com.tangem.core.decompose.factory.ComponentFactory
|
||||||
|
import com.tangem.core.ui.decompose.ComposableDialogComponent
|
||||||
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
||||||
|
interface RenameWalletComponent : ComposableDialogComponent {
|
||||||
|
|
||||||
|
data class Params(
|
||||||
|
val userWalletId: UserWalletId,
|
||||||
|
val currentName: String,
|
||||||
|
val onDismiss: () -> Unit,
|
||||||
|
)
|
||||||
|
|
||||||
|
interface Factory : ComponentFactory<Params, RenameWalletComponent>
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.tangem.feature.walletsettings.component
|
||||||
|
|
||||||
|
import com.tangem.core.decompose.factory.ComponentFactory
|
||||||
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
||||||
|
interface WalletSettingsComponent : ComposableContentComponent {
|
||||||
|
|
||||||
|
data class Params(
|
||||||
|
val userWalletId: UserWalletId,
|
||||||
|
)
|
||||||
|
|
||||||
|
interface Factory : ComponentFactory<Params, WalletSettingsComponent>
|
||||||
|
}
|
||||||
1
features/wallet-settings/impl/.gitignore
vendored
Normal file
1
features/wallet-settings/impl/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
52
features/wallet-settings/impl/build.gradle.kts
Normal file
52
features/wallet-settings/impl/build.gradle.kts
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
plugins {
|
||||||
|
alias(deps.plugins.android.library)
|
||||||
|
alias(deps.plugins.kotlin.android)
|
||||||
|
alias(deps.plugins.kotlin.kapt)
|
||||||
|
alias(deps.plugins.kotlin.serialization)
|
||||||
|
alias(deps.plugins.hilt.android)
|
||||||
|
id("configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.tangem.feature.walletsettings.impl"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
/* Project - API */
|
||||||
|
implementation(projects.features.walletSettings.api)
|
||||||
|
|
||||||
|
/* Project - Core */
|
||||||
|
implementation(projects.core.decompose)
|
||||||
|
implementation(projects.core.ui)
|
||||||
|
implementation(projects.core.featuretoggles)
|
||||||
|
implementation(projects.core.navigation)
|
||||||
|
implementation(projects.core.analytics.models)
|
||||||
|
implementation(projects.common.routing)
|
||||||
|
|
||||||
|
/* Project - Domain */
|
||||||
|
implementation(projects.domain.wallets)
|
||||||
|
implementation(projects.domain.wallets.models)
|
||||||
|
|
||||||
|
/* AndroidX */
|
||||||
|
implementation(deps.androidx.fragment.ktx)
|
||||||
|
implementation(deps.androidx.activity.compose)
|
||||||
|
implementation(deps.lifecycle.compose)
|
||||||
|
|
||||||
|
/* Compose */
|
||||||
|
implementation(deps.compose.ui)
|
||||||
|
implementation(deps.compose.ui.tooling)
|
||||||
|
implementation(deps.compose.accompanist.systemUiController)
|
||||||
|
implementation(deps.compose.foundation)
|
||||||
|
implementation(deps.compose.material3)
|
||||||
|
implementation(deps.compose.shimmer)
|
||||||
|
implementation(deps.decompose.ext.compose)
|
||||||
|
|
||||||
|
/* DI */
|
||||||
|
implementation(deps.hilt.android)
|
||||||
|
kapt(deps.hilt.kapt)
|
||||||
|
|
||||||
|
/* Other */
|
||||||
|
implementation(deps.kotlin.immutable.collections)
|
||||||
|
implementation(deps.timber)
|
||||||
|
}
|
||||||
|
|
@ -183,6 +183,9 @@ include(":features:disclaimer:impl")
|
||||||
|
|
||||||
include(":features:push-notifications:api")
|
include(":features:push-notifications:api")
|
||||||
include(":features:push-notifications:impl")
|
include(":features:push-notifications:impl")
|
||||||
|
|
||||||
|
include(":features:wallet-settings:api")
|
||||||
|
include(":features:wallet-settings:impl")
|
||||||
// endregion Feature modules
|
// endregion Feature modules
|
||||||
|
|
||||||
// region Domain modules
|
// region Domain modules
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue