error handling: using new error handling functionality in the sdk

This commit is contained in:
Kevin Gorham 2019-02-24 19:03:04 -05:00 committed by Kevin Gorham
parent d66ead2e24
commit 69e159ff2b
7 changed files with 78 additions and 10 deletions

View File

@ -4,15 +4,49 @@ import android.content.Context
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
internal inline fun Context.alert(@StringRes messageResId: Int, crossinline block: () -> Unit = {}) { internal val NO_ACTION = {}
AlertDialog.Builder(this)
.setMessage(messageResId) /**
.setPositiveButton(android.R.string.ok) { dialog, _ -> * Calls context.alert with the given string.
*/
internal fun Context.alert(
@StringRes messageResId: Int,
@StringRes positiveButtonResId: Int = android.R.string.ok,
@StringRes negativeButtonResId: Int = android.R.string.cancel,
positiveAction: () -> Unit = NO_ACTION,
negativeAction: () -> Unit = NO_ACTION
) {
alert(
message = getString(messageResId),
positiveButtonResId = positiveButtonResId,
negativeButtonResId = negativeButtonResId,
positiveAction = positiveAction,
negativeAction = negativeAction
)
}
/**
* Show an alert with the given message, if the block exists, it will execute after the user clicks the positive button,
* while clicking the negative button will abort the block. If no block exists, there will only be a positive button.
*/
internal fun Context.alert(
message: String,
@StringRes positiveButtonResId: Int = android.R.string.ok,
@StringRes negativeButtonResId: Int = android.R.string.cancel,
positiveAction: (() -> Unit) = NO_ACTION,
negativeAction: (() -> Unit) = NO_ACTION
) {
val builder = AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton(positiveButtonResId) { dialog, _ ->
dialog.dismiss() dialog.dismiss()
block() positiveAction()
} }
.setNegativeButton(android.R.string.cancel) { dialog, _ -> if (positiveAction !== NO_ACTION || negativeAction !== NO_ACTION) {
builder.setNegativeButton(negativeButtonResId) { dialog, _ ->
dialog.dismiss() dialog.dismiss()
negativeAction()
} }
.show() }
builder.show()
} }

View File

@ -180,6 +180,16 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
snackbar = snackbar.showOk(view!!, "Oops! It was too late to cancel!") snackbar = snackbar.showOk(view!!, "Oops! It was too late to cancel!")
} }
override fun onSynchronizerError(error: Throwable?): Boolean {
context?.alert(
message = "WARNING: A critical error has occurred and " +
"this app will not function properly until that is corrected!",
positiveButtonResId = R.string.ignore,
negativeButtonResId = R.string.details,
negativeAction = { context?.alert("Synchronization error:\n\n$error") }
)
return false
}
// //
// View API // View API

View File

@ -90,7 +90,7 @@ class ReceiveFragment : BaseFragment() {
// TODO: replace with tiered load. First check memory reference (textview contents?) then check DB, then load from JNI and write to DB // TODO: replace with tiered load. First check memory reference (textview contents?) then check DB, then load from JNI and write to DB
private fun loadAddress(): String { private fun loadAddress(): String {
return synchronizer.getAddress() return synchronizer.address
} }
} }

View File

@ -10,8 +10,13 @@ import androidx.navigation.NavOptions
import androidx.transition.TransitionInflater import androidx.transition.TransitionInflater
import cash.z.android.wallet.R import cash.z.android.wallet.R
import cash.z.android.wallet.databinding.FragmentSyncBinding import cash.z.android.wallet.databinding.FragmentSyncBinding
import cash.z.android.wallet.extention.alert
import cash.z.android.wallet.extention.showOk
import cash.z.android.wallet.ui.presenter.Presenter import cash.z.android.wallet.ui.presenter.Presenter
import cash.z.android.wallet.ui.presenter.ProgressPresenter import cash.z.android.wallet.ui.presenter.ProgressPresenter
import cash.z.wallet.sdk.data.Synchronizer
import cash.z.wallet.sdk.data.twig
import com.google.android.material.snackbar.Snackbar
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
@ -21,6 +26,7 @@ import javax.inject.Singleton
class SyncFragment : ProgressFragment(R.id.progress_sync) { class SyncFragment : ProgressFragment(R.id.progress_sync) {
private lateinit var binding: FragmentSyncBinding private lateinit var binding: FragmentSyncBinding
// //
@ -59,6 +65,7 @@ class SyncFragment : ProgressFragment(R.id.progress_sync) {
(view?.parent as? ViewGroup)?.doOnPreDraw { (view?.parent as? ViewGroup)?.doOnPreDraw {
startPostponedEnterTransition() startPostponedEnterTransition()
} }
synchronizer.onSynchronizerErrorListener = ::onSynchronizerError
} }
override fun onResume() { override fun onResume() {
@ -93,6 +100,17 @@ class SyncFragment : ProgressFragment(R.id.progress_sync) {
} }
} }
fun onSynchronizerError(error: Throwable?): Boolean {
context?.alert(
message = "WARNING: A critical error has occurred and " +
"this app will not function properly until that is corrected!",
positiveButtonResId = R.string.ignore,
negativeButtonResId = R.string.details,
negativeAction = { context?.alert("Synchronization error:\n\n$error") }
)
return false
}
} }
@Module @Module

View File

@ -1,15 +1,17 @@
package cash.z.android.wallet.ui.presenter package cash.z.android.wallet.ui.presenter
import cash.z.android.wallet.di.annotation.FragmentScope import cash.z.android.wallet.di.annotation.FragmentScope
import cash.z.android.wallet.extention.alert
import cash.z.android.wallet.ui.fragment.HomeFragment import cash.z.android.wallet.ui.fragment.HomeFragment
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
import cash.z.wallet.sdk.dao.WalletTransaction import cash.z.wallet.sdk.dao.WalletTransaction
import cash.z.wallet.sdk.data.* import cash.z.wallet.sdk.data.*
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import kotlinx.coroutines.* import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.ReceiveChannel import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class HomePresenter @Inject constructor( class HomePresenter @Inject constructor(
@ -24,6 +26,7 @@ class HomePresenter @Inject constructor(
fun updateBalance(old: Long, new: Long) fun updateBalance(old: Long, new: Long)
fun setActiveTransactions(activeTransactionMap: Map<ActiveTransaction, TransactionState>) fun setActiveTransactions(activeTransactionMap: Map<ActiveTransaction, TransactionState>)
fun onCancelledTooLate() fun onCancelledTooLate()
fun onSynchronizerError(error: Throwable?): Boolean
} }
override suspend fun start() { override suspend fun start() {
@ -35,6 +38,7 @@ class HomePresenter @Inject constructor(
launchTransactionBinder(synchronizer.allTransactions()) launchTransactionBinder(synchronizer.allTransactions())
launchActiveTransactionMonitor(synchronizer.activeTransactions()) launchActiveTransactionMonitor(synchronizer.activeTransactions())
} }
synchronizer.onSynchronizerErrorListener = view::onSynchronizerError
} }
override fun stop() { override fun stop() {

View File

@ -10,6 +10,8 @@
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<!-- General --> <!-- General -->
<string name="ignore">ignore</string>
<string name="details">details</string>
<string name="cancel">cancel</string> <string name="cancel">cancel</string>
<string name="cancelled">cancelled</string> <string name="cancelled">cancelled</string>
<string name="ok_allcaps">OK</string> <string name="ok_allcaps">OK</string>