Updated on 2026-08-14
This commit is contained in:
parent
6f62e15621
commit
6f4d7d2ce4
11 changed files with 120 additions and 43 deletions
|
|
@ -21,6 +21,6 @@ class TapApplication : Application() {
|
|||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(Timber.DebugTree())
|
||||
}
|
||||
NetworkConnectivity(store, this)
|
||||
NetworkConnectivity.createInstance(store, this)
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import com.tangem.tap.common.redux.global.GlobalAction
|
|||
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
||||
import com.tangem.tap.features.wallet.redux.PayIdState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.network.NetworkConnectivity
|
||||
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
|
||||
import com.tangem.tap.store
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -71,6 +72,10 @@ class TapWalletManager {
|
|||
withContext(Dispatchers.Main) {
|
||||
store.dispatch(GlobalAction.SaveScanNoteResponse(data))
|
||||
if (data.walletManager != null) {
|
||||
if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) {
|
||||
store.dispatch(WalletAction.LoadData.NoInternetConnection)
|
||||
return@withContext
|
||||
}
|
||||
data.verifyResponse?.artworkInfo?.id?.let {
|
||||
store.dispatch(WalletAction.LoadArtwork(data.card, it))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,42 +12,51 @@ import java.math.BigDecimal
|
|||
|
||||
sealed class WalletAction : Action {
|
||||
|
||||
object LoadData : WalletAction()
|
||||
object LoadData : WalletAction() {
|
||||
object NoInternetConnection : WalletAction()
|
||||
}
|
||||
|
||||
object LoadWallet : WalletAction() {
|
||||
data class Success(val wallet: Wallet): WalletAction()
|
||||
data class NoAccount(val amountToCreateAccount: Int): WalletAction()
|
||||
data class Failure(val errorMessage: String? = null): WalletAction()
|
||||
data class Success(val wallet: Wallet) : WalletAction()
|
||||
data class NoAccount(val amountToCreateAccount: Int) : WalletAction()
|
||||
data class Failure(val errorMessage: String? = null) : WalletAction()
|
||||
}
|
||||
|
||||
object LoadFiatRate : WalletAction() {
|
||||
data class Success(val fiatRates: Pair<String, BigDecimal>) : WalletAction()
|
||||
object Failure: WalletAction()
|
||||
object Failure : WalletAction()
|
||||
}
|
||||
|
||||
object LoadPayId : WalletAction() {
|
||||
data class Success(val payId: String): WalletAction()
|
||||
object NotCreated: WalletAction()
|
||||
object Failure: WalletAction()
|
||||
data class Success(val payId: String) : WalletAction()
|
||||
object NotCreated : WalletAction()
|
||||
object Failure : WalletAction()
|
||||
}
|
||||
|
||||
data class LoadArtwork(val card: Card, val artworkId: String) : WalletAction() {
|
||||
data class Success(val artworkId: String, val artwork: ByteArray) : WalletAction()
|
||||
object Failure: WalletAction()
|
||||
object Failure : WalletAction()
|
||||
}
|
||||
|
||||
object Scan : WalletAction()
|
||||
object Send : WalletAction()
|
||||
object CreatePayId : WalletAction() {
|
||||
data class CompleteCreatingPayId(val payId: String): WalletAction()
|
||||
data class Success(val payId: String): WalletAction()
|
||||
object EmptyField: WalletAction(), ErrorAction {
|
||||
data class CompleteCreatingPayId(val payId: String) : WalletAction()
|
||||
data class Success(val payId: String) : WalletAction()
|
||||
object EmptyField : WalletAction(), ErrorAction {
|
||||
override val error = TapError.PayIdEmptyField
|
||||
}
|
||||
|
||||
class Failure(override val error: TapError) : WalletAction(), ErrorAction
|
||||
object Cancel: WalletAction()
|
||||
object Cancel : WalletAction()
|
||||
}
|
||||
|
||||
data class CopyAddress(val context: Context) : WalletAction() {
|
||||
object Success : WalletAction(), NotificationAction {
|
||||
override val messageResource = R.string.notification_address_copied
|
||||
}
|
||||
}
|
||||
|
||||
object ShowQrCode : WalletAction()
|
||||
object HideQrCode : WalletAction()
|
||||
data class ExploreAddress(val context: Context) : WalletAction()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.tap.common.extensions.copyToClipboard
|
|||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.PayIdManager
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.network.NetworkStateChanged
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
|
|
@ -90,7 +91,7 @@ val walletMiddleware: Middleware<AppState> = { dispatch, state ->
|
|||
}
|
||||
}
|
||||
}
|
||||
is WalletAction.LoadData -> {
|
||||
is WalletAction.LoadData, is NetworkStateChanged -> {
|
||||
scope.launch {
|
||||
store.state.globalState.scanNoteResponse?.let {
|
||||
store.state.globalState.tapWalletManager.onCardScanned(it)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,23 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
currencyData = BalanceWidgetData(BalanceStatus.EmptyCard),
|
||||
mainButton = WalletMainButton.CreateWalletButton(true)
|
||||
)
|
||||
is WalletAction.LoadData.NoInternetConnection -> {
|
||||
val wallet = state.globalState.scanNoteResponse?.walletManager?.wallet
|
||||
val addressData = if (wallet == null) {
|
||||
null
|
||||
} else {
|
||||
AddressData(wallet.address, wallet.shareUrl, wallet.exploreUrl)
|
||||
}
|
||||
newState = WalletState(
|
||||
state = ProgressState.Error,
|
||||
error = ErrorType.NoInternetConnection,
|
||||
addressData = addressData,
|
||||
currencyData = BalanceWidgetData(
|
||||
status = BalanceStatus.Unreachable,
|
||||
currency = wallet?.blockchain?.fullName),
|
||||
mainButton = WalletMainButton.SendButton(false)
|
||||
)
|
||||
}
|
||||
is WalletAction.LoadWallet -> {
|
||||
val wallet = state.globalState.scanNoteResponse?.walletManager?.wallet
|
||||
val addressData = if (wallet == null) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import org.rekotlin.StateType
|
|||
|
||||
data class WalletState(
|
||||
val state: ProgressState = ProgressState.Done,
|
||||
val error: ErrorType? = null,
|
||||
val cardImage: Artwork? = null,
|
||||
val wallet: Wallet? = null,
|
||||
val pendingTransactions: List<PendingTransaction> = emptyList(),
|
||||
|
|
@ -23,6 +24,8 @@ data class WalletState(
|
|||
|
||||
enum class ProgressState { Loading, Done, Error }
|
||||
|
||||
enum class ErrorType { NoInternetConnection }
|
||||
|
||||
enum class PayIdState { Disabled, Loading, NotCreated, Created, ErrorLoading }
|
||||
|
||||
data class PayIdData(
|
||||
|
|
|
|||
|
|
@ -10,13 +10,6 @@ import kotlinx.android.synthetic.main.layout_balance.*
|
|||
import kotlinx.android.synthetic.main.layout_balance_error.*
|
||||
import kotlinx.android.synthetic.main.layout_token.view.*
|
||||
|
||||
enum class PayIdState {
|
||||
Loading,
|
||||
NotCreated,
|
||||
Loaded,
|
||||
Error
|
||||
}
|
||||
|
||||
enum class BalanceStatus {
|
||||
VerifiedOnline,
|
||||
Unreachable,
|
||||
|
|
@ -54,12 +47,14 @@ class BalanceWidget(
|
|||
BalanceStatus.Loading -> {
|
||||
fragment.l_balance.show()
|
||||
fragment.l_balance_error.hide()
|
||||
fragment.tv_fiat_amount.hide()
|
||||
fragment.l_token.hide()
|
||||
|
||||
fragment.tv_currency.text = data.currency
|
||||
fragment.tv_currency_symbol.text = "-"
|
||||
fragment.tv_amount.text = ""
|
||||
fragment.tv_fiat_amount.hide()
|
||||
|
||||
showStatus(R.id.tv_status_loading)
|
||||
fragment.l_token.hide()
|
||||
}
|
||||
BalanceStatus.VerifiedOnline -> {
|
||||
fragment.l_balance.show()
|
||||
|
|
@ -78,14 +73,18 @@ class BalanceWidget(
|
|||
fragment.l_token.tv_token_fiat_amount.text = data.token.fiatAmount
|
||||
} else {
|
||||
fragment.l_token.hide()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
BalanceStatus.Unreachable -> {
|
||||
fragment.l_balance.show()
|
||||
fragment.l_balance_error.hide()
|
||||
fragment.l_token.hide()
|
||||
fragment.tv_fiat_amount.hide()
|
||||
|
||||
fragment.tv_currency.text = data.currency
|
||||
fragment.tv_currency_symbol.text = "-"
|
||||
fragment.tv_amount.text = ""
|
||||
|
||||
showStatus(R.id.tv_status_error)
|
||||
}
|
||||
BalanceStatus.EmptyCard -> {
|
||||
|
|
@ -112,15 +111,4 @@ class BalanceWidget(
|
|||
fragment.tv_status_loading.show(viewRes == R.id.tv_status_loading)
|
||||
fragment.tv_status_verified.show(viewRes == R.id.tv_status_verified)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum class BalanceErrorWidgetState {
|
||||
NoAccount,
|
||||
NoWallet,
|
||||
BlockchainError
|
||||
}
|
||||
|
||||
class BalanceErrorWidget(
|
||||
|
||||
)
|
||||
}
|
||||
|
|
@ -7,13 +7,13 @@ import androidx.activity.OnBackPressedCallback
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.tap.common.extensions.getDrawable
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.PayIdState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.card_balance.*
|
||||
|
|
@ -26,6 +26,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
|
||||
private var qrDialog: QrDialog? = null
|
||||
private var payIdDialog: PayIdDialog? = null
|
||||
private var snackbar: Snackbar? = null
|
||||
|
||||
private lateinit var viewAdapter: PendingTransactionsAdapter
|
||||
|
||||
|
|
@ -84,6 +85,8 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
store.dispatch(WalletAction.LoadData)
|
||||
}
|
||||
|
||||
setupNoInternetHandling(state)
|
||||
|
||||
setupButtons(state)
|
||||
setupAddressCard(state)
|
||||
setupCardImage(state.cardImage?.artwork)
|
||||
|
|
@ -137,6 +140,22 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupNoInternetHandling(state: WalletState) {
|
||||
if (state.state == ProgressState.Error) {
|
||||
if (state.error == ErrorType.NoInternetConnection) {
|
||||
srl_wallet?.isRefreshing = false
|
||||
snackbar = Snackbar.make(
|
||||
coordinator_wallet, getString(R.string.notification_no_internet),
|
||||
Snackbar.LENGTH_INDEFINITE
|
||||
).setAction(getString(R.string.notification_no_internet_retry))
|
||||
{ store.dispatch(WalletAction.LoadData) }
|
||||
.also { it.show() }
|
||||
}
|
||||
} else {
|
||||
snackbar?.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupButtons(state: WalletState) {
|
||||
btn_copy.setOnClickListener { store.dispatch(WalletAction.CopyAddress(requireContext())) }
|
||||
btn_show_qr.setOnClickListener { store.dispatch(WalletAction.ShowQrCode) }
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.os.Build
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.Store
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -15,7 +18,8 @@ class NetworkConnectivity(
|
|||
private val store: Store<*>,
|
||||
context: Context
|
||||
) {
|
||||
private val connectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
|
||||
private val wContext: WeakReference<Context> = WeakReference(context)
|
||||
|
||||
private val receiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(c: Context?, intent: Intent?) {
|
||||
|
|
@ -26,14 +30,42 @@ class NetworkConnectivity(
|
|||
init {
|
||||
val intentFilter = IntentFilter()
|
||||
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
context.registerReceiver(receiver, intentFilter)
|
||||
wContext.get()?.registerReceiver(receiver, intentFilter)
|
||||
store.dispatch(NetworkStateChanged(isOnlineOrConnecting()))
|
||||
}
|
||||
|
||||
|
||||
fun isOnlineOrConnecting(): Boolean {
|
||||
val netInfo = connectivityManager.activeNetworkInfo
|
||||
return netInfo != null && netInfo.isConnectedOrConnecting
|
||||
val connectivityManager = getConnectivityManager() ?: return false
|
||||
|
||||
return if (Build.VERSION.SDK_INT >= 23) {
|
||||
val capabilities =
|
||||
connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
|
||||
(capabilities != null) &&
|
||||
(capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET))
|
||||
|
||||
} else {
|
||||
val networkInfo = connectivityManager.activeNetworkInfo
|
||||
networkInfo != null && networkInfo.isConnectedOrConnecting
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConnectivityManager(): ConnectivityManager? {
|
||||
return wContext.get()?.applicationContext
|
||||
?.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
|
||||
}
|
||||
|
||||
companion object {
|
||||
private lateinit var instance: NetworkConnectivity
|
||||
|
||||
fun createInstance(store: Store<*>, context: Context): NetworkConnectivity {
|
||||
instance = NetworkConnectivity(store, context)
|
||||
return instance
|
||||
}
|
||||
|
||||
fun getInstance(): NetworkConnectivity = instance
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/coordinator_wallet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/backgroundLightGray"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
<string name="app_name" translatable="false">Tangem Tap</string>
|
||||
|
||||
<string name="notification_address_copied">Address was successfully copied</string>
|
||||
<string name="notification_no_internet">No internet connection</string>
|
||||
<string name="notification_no_internet_retry">Retry</string>
|
||||
<string name="generic_done">Done</string>
|
||||
|
||||
<string name="home_do_you_have_card">Welcome to Tangem.\nDo you have one of our cards?</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue