Updated on 2026-08-14
This commit is contained in:
parent
6fd17ffb31
commit
11f7775787
21 changed files with 319 additions and 18 deletions
|
|
@ -7,6 +7,7 @@ import com.tangem.tap.common.redux.navigation.AppScreen
|
|||
import com.tangem.tap.features.details.ui.DetailsConfirmFragment
|
||||
import com.tangem.tap.features.details.ui.DetailsFragment
|
||||
import com.tangem.tap.features.details.ui.DetailsSecurityFragment
|
||||
import com.tangem.tap.features.disclaimer.ui.DisclaimerFragment
|
||||
import com.tangem.tap.features.home.HomeFragment
|
||||
import com.tangem.tap.features.send.ui.SendFragment
|
||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||
|
|
@ -42,5 +43,6 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
|
|||
AppScreen.Details -> DetailsFragment()
|
||||
AppScreen.DetailsConfirm -> DetailsConfirmFragment()
|
||||
AppScreen.DetailsSecurity -> DetailsSecurityFragment()
|
||||
AppScreen.Disclaimer -> DisclaimerFragment()
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.common.redux
|
|||
import com.tangem.tap.common.redux.global.globalReducer
|
||||
import com.tangem.tap.common.redux.navigation.NavigationReducer
|
||||
import com.tangem.tap.features.details.redux.DetailsReducer
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerReducer
|
||||
import com.tangem.tap.features.home.redux.HomeReducer
|
||||
import com.tangem.tap.features.send.redux.reducers.SendScreenReducer
|
||||
import com.tangem.tap.features.wallet.redux.WalletReducer
|
||||
|
|
@ -18,7 +19,8 @@ fun appReducer(action: Action, state: AppState?): AppState {
|
|||
homeState = HomeReducer.reduce(action, state),
|
||||
walletState = WalletReducer.reduce(action, state),
|
||||
sendState = SendScreenReducer.reduce(action, state.sendState),
|
||||
detailsState = DetailsReducer.reduce(action, state)
|
||||
detailsState = DetailsReducer.reduce(action, state),
|
||||
disclaimerState = DisclaimerReducer.reduce(action, state)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import com.tangem.tap.common.redux.navigation.NavigationState
|
|||
import com.tangem.tap.common.redux.navigation.navigationMiddleware
|
||||
import com.tangem.tap.features.details.redux.DetailsMiddleware
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerMiddleware
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerState
|
||||
import com.tangem.tap.features.home.redux.HomeState
|
||||
import com.tangem.tap.features.home.redux.homeMiddleware
|
||||
import com.tangem.tap.features.send.redux.middlewares.sendMiddleware
|
||||
|
|
@ -21,7 +23,8 @@ data class AppState(
|
|||
val homeState: HomeState = HomeState(),
|
||||
val walletState: WalletState = WalletState(),
|
||||
val sendState: SendState = SendState(),
|
||||
val detailsState: DetailsState = DetailsState()
|
||||
val detailsState: DetailsState = DetailsState(),
|
||||
val disclaimerState: DisclaimerState = DisclaimerState()
|
||||
) : StateType {
|
||||
|
||||
companion object {
|
||||
|
|
@ -29,7 +32,8 @@ data class AppState(
|
|||
return listOf(
|
||||
logMiddleware, navigationMiddleware, notificationsMiddleware, globalMiddleware,
|
||||
homeMiddleware, walletMiddleware, sendMiddleware,
|
||||
DetailsMiddleware().detailsMiddleware
|
||||
DetailsMiddleware().detailsMiddleware,
|
||||
DisclaimerMiddleware().disclaimerMiddleware
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ sealed class GlobalAction : Action {
|
|||
object RestoreAppCurrency : GlobalAction() {
|
||||
data class Success(val appCurrency: FiatCurrencyName) : GlobalAction()
|
||||
}
|
||||
data class UpdateWalletSignedHashes(val walletSignedHashes: Int) : GlobalAction()
|
||||
data class UpdateWalletSignedHashes(val walletSignedHashes: Int?) : GlobalAction()
|
||||
}
|
||||
|
|
@ -9,4 +9,4 @@ data class NavigationState(
|
|||
val activity: WeakReference<FragmentActivity>? = null
|
||||
) : StateType
|
||||
|
||||
enum class AppScreen { Home, Wallet, Send, Details, DetailsConfirm, DetailsSecurity }
|
||||
enum class AppScreen { Home, Wallet, Send, Details, DetailsConfirm, DetailsSecurity, Disclaimer }
|
||||
|
|
@ -17,6 +17,8 @@ sealed class DetailsAction : Action {
|
|||
val fiatCurrencies: List<FiatCurrencyName>? = null,
|
||||
): DetailsAction()
|
||||
|
||||
object ShowDisclaimer : DetailsAction()
|
||||
|
||||
|
||||
sealed class EraseWallet : DetailsAction() {
|
||||
object Check : EraseWallet()
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.tap.common.redux.AppState
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
|
||||
import com.tangem.tap.preferencesStorage
|
||||
|
|
@ -29,6 +30,10 @@ class DetailsMiddleware {
|
|||
is DetailsAction.EraseWallet -> eraseWalletMiddleware.handle(action)
|
||||
is DetailsAction.AppCurrencyAction -> appCurrencyMiddleware.handle(action)
|
||||
is DetailsAction.ManageSecurity -> manageSecurityMiddleware.handle(action)
|
||||
is DetailsAction.ShowDisclaimer -> {
|
||||
store.dispatch(DisclaimerAction.ShowAcceptedDisclaimer)
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
|
||||
}
|
||||
}
|
||||
next(action)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ private fun internalReduce(action: Action, state: AppState): DetailsState {
|
|||
is DetailsAction.ManageSecurity -> {
|
||||
handleSecurityAction(action, detailsState)
|
||||
}
|
||||
else -> detailsState
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ class DetailsFragment : Fragment(R.layout.fragment_details), StoreSubscriber<Det
|
|||
tv_signed_hashes.text = state.cardInfo.signedHashes.toString()
|
||||
}
|
||||
|
||||
tv_disclaimer.setOnClickListener { store.dispatch(DetailsAction.ShowDisclaimer) }
|
||||
|
||||
tv_erase_wallet.setOnClickListener {
|
||||
store.dispatch(DetailsAction.EraseWallet.Check)
|
||||
store.dispatch(DetailsAction.EraseWallet.Proceed)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import org.rekotlin.Action
|
||||
|
||||
sealed class DisclaimerAction: Action {
|
||||
object AcceptDisclaimer : DisclaimerAction()
|
||||
object ShowAcceptedDisclaimer : DisclaimerAction()
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.Middleware
|
||||
|
||||
class DisclaimerMiddleware {
|
||||
val disclaimerMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||
{ next ->
|
||||
{ action ->
|
||||
when (action) {
|
||||
is DisclaimerAction.AcceptDisclaimer -> {
|
||||
preferencesStorage.saveDisclaimerAccepted()
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
}
|
||||
}
|
||||
next(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import org.rekotlin.Action
|
||||
|
||||
class DisclaimerReducer {
|
||||
companion object {
|
||||
fun reduce(action: Action, state: AppState): DisclaimerState = internalReduce(action, state)
|
||||
}
|
||||
}
|
||||
|
||||
private fun internalReduce(action: Action, state: AppState): DisclaimerState {
|
||||
if (action !is DisclaimerAction) return state.disclaimerState
|
||||
|
||||
val disclaimerState = state.disclaimerState
|
||||
return when (action) {
|
||||
is DisclaimerAction.AcceptDisclaimer, DisclaimerAction.ShowAcceptedDisclaimer -> {
|
||||
disclaimerState.copy(accepted = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import org.rekotlin.StateType
|
||||
|
||||
data class DisclaimerState(
|
||||
val accepted: Boolean = false
|
||||
) : StateType
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package com.tangem.tap.features.disclaimer.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.fragment_disclaimer.*
|
||||
import org.rekotlin.StoreSubscriber
|
||||
|
||||
class DisclaimerFragment : Fragment(R.layout.fragment_disclaimer),
|
||||
StoreSubscriber<DisclaimerState> {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
})
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(R.transition.slide_right)
|
||||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
store.subscribe(this) { state ->
|
||||
state.skipRepeats { oldState, newState ->
|
||||
oldState.disclaimerState == newState.disclaimerState
|
||||
}.select { it.disclaimerState }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
store.unsubscribe(this)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
toolbar.setNavigationOnClickListener {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
setOnClickListeners()
|
||||
}
|
||||
|
||||
private fun setOnClickListeners() {
|
||||
btn_accept.setOnClickListener { store.dispatch(DisclaimerAction.AcceptDisclaimer) }
|
||||
}
|
||||
|
||||
override fun newState(state: DisclaimerState) {
|
||||
if (activity == null) return
|
||||
|
||||
if (state.accepted) btn_accept.hide()
|
||||
}
|
||||
}
|
||||
|
|
@ -54,6 +54,4 @@ class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber<HomeState
|
|||
val inflater = TransitionInflater.from(requireContext())
|
||||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ val homeMiddleware: Middleware<AppState> = { dispatch, state ->
|
|||
is CompletionResult.Success -> {
|
||||
store.dispatch(GlobalAction.RestoreAppCurrency)
|
||||
store.state.globalState.tapWalletManager.onCardScanned(result.data)
|
||||
navigateToWallet()
|
||||
showDisclaimerOrNavigateToWallet()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,6 +51,15 @@ val homeMiddleware: Middleware<AppState> = { dispatch, state ->
|
|||
}
|
||||
}
|
||||
|
||||
private fun showDisclaimerOrNavigateToWallet() {
|
||||
if (preferencesStorage.wasDisclaimerAccepted()) {
|
||||
navigateToWallet()
|
||||
} else {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun navigateToWallet() {
|
||||
if (store.state.navigationState.backStack.isNotEmpty()) {
|
||||
val currentScreen = store.state.navigationState.backStack.last()
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
setHasOptionsMenu(true)
|
||||
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
})
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
|
|
@ -72,7 +72,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
(activity as? AppCompatActivity)?.setSupportActionBar(toolbar)
|
||||
|
||||
toolbar.setNavigationOnClickListener {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
|
||||
btn_scan.setOnClickListener {
|
||||
|
|
|
|||
|
|
@ -65,12 +65,22 @@ class PreferencesStorage(applicationContext: Application) {
|
|||
private fun restoreScannedCardIds(): String =
|
||||
preferences.getString(SCANNED_CARDS_IDS_KEY, "") ?: ""
|
||||
|
||||
|
||||
fun saveDisclaimerAccepted() {
|
||||
preferences.edit().putBoolean(DISCLAIMER_ACCEPTED_KEY, true).apply()
|
||||
}
|
||||
|
||||
fun wasDisclaimerAccepted(): Boolean {
|
||||
return preferences.getBoolean(DISCLAIMER_ACCEPTED_KEY, false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PREFERENCES_NAME = "tapPrefs"
|
||||
private const val APP_CURRENCY_KEY = "appCurrency"
|
||||
private const val FIAT_CURRENCIES_KEY = "fiatCurrencies"
|
||||
private const val FIRST_LAUNCH_CHECK_KEY = "firstLaunchCheck"
|
||||
private const val SCANNED_CARDS_IDS_KEY = "scannedCardIds"
|
||||
private const val DISCLAIMER_ACCEPTED_KEY = "disclaimerAccepted"
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue