diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 0b349f013a..78c6c7dbd6 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -6,7 +6,9 @@ import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Bundle import android.util.Log +import android.view.View import androidx.appcompat.app.AppCompatActivity +import com.google.android.material.snackbar.Snackbar import com.tangem.CardFilter import com.tangem.Config import com.tangem.TangemSdk @@ -52,6 +54,9 @@ private fun initCoroutineExceptionHandler(): CoroutineExceptionHandler { } class MainActivity : AppCompatActivity() { + + private var snackbar: Snackbar? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) @@ -104,4 +109,21 @@ class MainActivity : AppCompatActivity() { store.dispatch(NavigationAction.ActivityDestroyed) super.onDestroy() } + + fun showSnackbar(text: Int, buttonTitle: Int? = null, action: View.OnClickListener? = null) { + if (snackbar != null) return + + snackbar = Snackbar.make( + fragment_container, getString(text), Snackbar.LENGTH_INDEFINITE + ) + if (buttonTitle != null && action != null) { + snackbar?.setAction(getString(buttonTitle), action) + } + snackbar?.show() + } + + fun dismissSnackbar() { + snackbar?.dismiss() + snackbar = null + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index b471168b8b..3782d4a7fb 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -143,10 +143,6 @@ class TapWalletManager { store.dispatch(WalletAction.Warnings.CheckIfNeeded) val artworkId = data.verifyResponse?.artworkInfo?.id if (data.walletManager != null) { - if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) { - store.dispatch(WalletAction.LoadData.Failure(TapError.NoInternetConnection)) - return@withContext - } val config = store.state.globalState.configManager?.config ?: return@withContext val primaryWalletManager = data.walletManager @@ -218,6 +214,10 @@ class TapWalletManager { when (result) { is Result.Success -> store.dispatch(WalletAction.LoadWallet.Success(result.data)) is Result.Failure -> { + if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) { + store.dispatch(WalletAction.LoadData.Failure(TapError.NoInternetConnection)) + return@withContext + } val error = result.error val blockchain = walletManager.wallet.blockchain if (error != null && blockchain.isNoAccountError(error)) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt index 24fb8d843a..1b3442c812 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt @@ -88,7 +88,7 @@ class OnWalletLoadedReducer { ProgressState.Done } return walletState.copy( - state = state, wallets = wallets + state = state, wallets = wallets, error = null ) } @@ -143,7 +143,7 @@ class OnWalletLoadedReducer { ) val wallets = walletData?.let { listOf(walletData) } ?: emptyList() return walletState.copy( - state = ProgressState.Done, wallets = wallets + state = ProgressState.Done, wallets = wallets, error = null ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index 59e50c8820..051594b368 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -57,9 +57,16 @@ private fun internalReduce(action: Action, state: AppState): WalletState { is WalletAction.LoadData.Failure -> { when (action.error) { is TapError.NoInternetConnection -> { + val wallets = newState.wallets + .map { + it.copy(currencyData = it.currencyData.copy( + status = BalanceStatus.Unreachable + )) + } newState = newState.copy( state = ProgressState.Error, error = ErrorType.NoInternetConnection, + wallets = wallets ) } is TapError.UnknownBlockchain -> { @@ -100,7 +107,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ) } else { val walletManager = newState.getWalletManager(action.currency) ?: return newState - val currencies = listOf(walletManager.wallet.blockchain.currency + walletManager.presetTokens.map { it.symbol }) + val currencies = listOf(walletManager.wallet.blockchain.currency) + walletManager.presetTokens.map { it.symbol } val newWallets = newState.wallets.filter { currencies.contains(it.currencyData.currencySymbol) } .map { wallet -> wallet.copy( @@ -146,22 +153,35 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ) } is WalletAction.LoadWallet.Failure -> { + val message = if (newState.error == ErrorType.NoInternetConnection) { + null + } else { + action.errorMessage + } val walletData = newState.getWalletData(action.wallet.blockchain.currency) val newWalletData = walletData?.copy( currencyData = walletData.currencyData.copy( status = BalanceStatus.Unreachable, - errorMessage = action.errorMessage + errorMessage = message ), topUpState = TopUpState(false) ) - val wallets = newState.replaceWalletInWallets(newWalletData) - val state = if (wallets.any { it.currencyData.status == BalanceStatus.Loading }) { + val tokenWallets = action.wallet.getTokens() + .mapNotNull { newState.getWalletData(it.symbol) } + .map { + it.copy(currencyData = it.currencyData.copy( + status = BalanceStatus.Unreachable, errorMessage = message + )) + } + val wallets = newState.replaceSomeWallets(listOfNotNull(newWalletData) + tokenWallets) + + val progressState = if (wallets.any { it.currencyData.status == BalanceStatus.Loading }) { ProgressState.Loading } else { ProgressState.Done } newState = newState.copy( - state = state, wallets = wallets + state = progressState, wallets = wallets ) } is WalletAction.SetArtworkId -> { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 8913acc643..3998eee99b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -10,22 +10,18 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.transition.TransitionInflater import com.tangem.blockchain.common.Blockchain +import com.tangem.tap.MainActivity import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.global.StateDialog import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.wallet.models.PendingTransaction -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletData -import com.tangem.tap.features.wallet.redux.WalletDialog -import com.tangem.tap.features.wallet.redux.WalletState +import com.tangem.tap.features.wallet.redux.* import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter import com.tangem.tap.features.wallet.ui.dialogs.AmountToSendDialog import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.fragment_details_twin_cards.* -import kotlinx.android.synthetic.main.fragment_wallet.* import kotlinx.android.synthetic.main.fragment_wallet_details.* -import kotlinx.android.synthetic.main.fragment_wallet_details.rv_pending_transaction import kotlinx.android.synthetic.main.fragment_wallet_details.toolbar import kotlinx.android.synthetic.main.item_currency_wallet.view.* import kotlinx.android.synthetic.main.layout_balance_error.* @@ -105,6 +101,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS showPendingTransactionsIfPresent(selectedWallet.pendingTransactions) setupAddressCard(selectedWallet) + setupNoInternetHandling(state) setupBalanceData(selectedWallet.currencyData) btn_confirm.isEnabled = selectedWallet.mainButton.enabled @@ -183,6 +180,20 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS } } + private fun setupNoInternetHandling(state: WalletState) { + if (state.state == ProgressState.Error) { + if (state.error == ErrorType.NoInternetConnection) { + srl_wallet_details?.isRefreshing = false + (activity as? MainActivity)?.showSnackbar( + text = R.string.wallet_notification_no_internet, + buttonTitle = R.string.common_retry + ) { store.dispatch(WalletAction.LoadData) } + } + } else { + (activity as? MainActivity)?.dismissSnackbar() + } + } + private fun setupBalanceData(data: BalanceWidgetData) { when (data.status) { BalanceStatus.Loading -> { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index ec1c7cdf74..580bb34141 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -12,9 +12,9 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.transition.TransitionInflater -import com.google.android.material.snackbar.Snackbar import com.squareup.picasso.Picasso import com.tangem.tangem_sdk_new.extensions.dpToPx +import com.tangem.tap.MainActivity import com.tangem.tap.common.extensions.show import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction @@ -30,13 +30,13 @@ import com.tangem.tap.features.wallet.ui.wallet.WalletView import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.fragment_wallet.* +import kotlinx.android.synthetic.main.fragment_wallet.toolbar +import kotlinx.android.synthetic.main.fragment_wallet_details.* import org.rekotlin.StoreSubscriber class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber { - private var snackbar: Snackbar? = null - private lateinit var warningsAdapter: WarningMessagesAdapter private var walletView: WalletView = SingleWalletView() @@ -133,15 +133,14 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber