Hush lite wallet for Android
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
8.5 KiB

package cash.z.ecc.android.ext
import android.app.ActivityManager
import android.app.Dialog
import android.content.Context
import android.text.Html
import android.util.Log
import androidx.annotation.StringRes
import androidx.core.content.getSystemService
import cash.z.ecc.android.R
import cash.z.ecc.android.feedback.Report
import cash.z.ecc.android.ui.scan.ScanFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlin.system.exitProcess
fun Context.showClearDataConfirmation(onDismiss: () -> Unit = {}, onCancel: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_nuke_wallet_title)
.setMessage(R.string.dialog_nuke_wallet_message)
.setCancelable(false)
.setPositiveButton(R.string.dialog_nuke_wallet_button_positive) { dialog, _ ->
dialog.dismiss()
onDismiss()
onCancel()
}
.setNegativeButton(R.string.dialog_nuke_wallet_button_negative) { dialog, _ ->
dialog.dismiss()
onDismiss()
getSystemService<ActivityManager>()?.clearApplicationUserData()
}
.show()
}
fun Context.showUninitializedError(error: Throwable? = null, onDismiss: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_error_uninitialized_title)
.setMessage(R.string.dialog_error_uninitialized_message)
.setCancelable(false)
.setPositiveButton(getString(R.string.dialog_error_uninitialized_button_positive)) { dialog, _ ->
dialog.dismiss()
onDismiss()
if (error != null) throw error
}
.setNegativeButton(getString(R.string.dialog_error_uninitialized_button_negative)) { dialog, _ ->
showClearDataConfirmation(
onDismiss,
onCancel = {
// do not let the user back into the app because we cannot recover from this case
showUninitializedError(error, onDismiss)
}
)
}
.show()
}
fun Context.showInvalidSeedPhraseError(error: Throwable? = null, onDismiss: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_error_invalid_seed_phrase_title)
.setMessage(getString(R.string.dialog_error_invalid_seed_phrase_message, error?.message ?: ""))
.setCancelable(false)
.setPositiveButton(getString(R.string.dialog_error_invalid_seed_phrase_button_positive)) { dialog, _ ->
dialog.dismiss()
onDismiss()
}
.show()
}
fun Context.showScanFailure(error: Throwable?, onCancel: () -> Unit = {}, onDismiss: () -> Unit = {}): Dialog {
val message = if (error == null) {
"Unknown error"
} else {
"${error.message}${if (error.cause != null) "\n\nCaused by: ${error.cause}" else ""}"
}
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_error_scan_failure_title)
.setMessage(message)
.setCancelable(true)
.setPositiveButton(R.string.dialog_error_scan_failure_button_positive) { d, _ ->
d.dismiss()
onDismiss()
}
.setNegativeButton(R.string.dialog_error_scan_failure_button_negative) { d, _ ->
d.dismiss()
onCancel()
onDismiss()
}
.show()
}
fun Context.showCriticalMessage(@StringRes titleResId: Int, @StringRes messageResId: Int, onDismiss: () -> Unit = {}): Dialog {
return showCriticalMessage(titleResId.toAppString(), messageResId.toAppString(), onDismiss)
}
fun Context.showCriticalMessage(title: String, message: String, onDismiss: () -> Unit = {}): Dialog {
Log.d("SilentDragon", "showCriticalMessage called: $message")
var delimiter = ":"
val splitError = message.split(delimiter)
var pluckedError = splitError[0]
if(pluckedError == "UNAVAILABLE"){
return MaterialAlertDialogBuilder(this)
.setTitle("Server Unavailable")
.setMessage("Please close and restart the app to try another random server.")
.setCancelable(false)
.setNegativeButton("Exit") { dialog, _ ->
dialog.dismiss()
exitProcess(0)
}
.show()
}
return MaterialAlertDialogBuilder(this)
.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setPositiveButton(android.R.string.ok) { d, _ ->
d.dismiss()
onDismiss()
}
.show()
}
fun Context.showCriticalProcessorError(error: Throwable?, onRetry: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_error_processor_critical_title)
.setMessage(error?.message ?: getString(R.string.dialog_error_processor_critical_message))
.setCancelable(false)
.setPositiveButton(R.string.dialog_error_processor_critical_button_positive) { d, _ ->
d.dismiss()
onRetry()
}
.setNegativeButton(R.string.dialog_error_processor_critical_button_negative) { dialog, _ ->
dialog.dismiss()
throw error ?: RuntimeException("Critical error while processing blocks and the user chose to exit.")
}
.show()
}
fun Context.showUpdateServerCriticalError(userFacingMessage: String, onConfirm: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_error_change_server_title)
.setMessage(userFacingMessage)
.setCancelable(false)
.setPositiveButton(R.string.dialog_error_change_server_button_positive) { d, _ ->
d.dismiss()
onConfirm()
}
.show()
}
fun Context.showUpdateServerDialog(positiveResId: Int = R.string.dialog_modify_server_button_positive, onCancel: () -> Unit = {}, onUpdate: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_modify_server_title)
.setMessage(R.string.dialog_modify_server_message)
.setCancelable(false)
.setPositiveButton(positiveResId) { dialog, _ ->
dialog.dismiss()
onUpdate()
}
.setNegativeButton(R.string.dialog_modify_server_button_negative) { dialog, _ ->
dialog.dismiss()
onCancel()
}
.show()
}
fun Context.showRescanWalletDialog(quickDistance: String, quickEstimate: String, fullDistance: String, fullEstimate: String, onWipe: () -> Unit = {}, onFullRescan: () -> Unit = {}, onQuickRescan: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_rescan_wallet_title)
.setMessage(Html.fromHtml(getString(R.string.dialog_rescan_wallet_message, quickDistance, quickEstimate, fullDistance, fullEstimate)))
.setCancelable(true)
.setPositiveButton(R.string.dialog_rescan_wallet_button_positive) { dialog, _ ->
dialog.dismiss()
onQuickRescan()
}
.setNeutralButton(R.string.dialog_rescan_wallet_button_neutral) { dialog, _ ->
dialog.dismiss()
onWipe()
}
.setNegativeButton(R.string.dialog_rescan_wallet_button_negative) { dialog, _ ->
dialog.dismiss()
onFullRescan()
}
.show()
}
fun Context.showConfirmation(title: String, message: String, positiveButton: String, negativeButton: String = "Cancel", onPositive: () -> Unit = {}): Dialog {
return MaterialAlertDialogBuilder(this)
.setTitle(title)
.setMessage(message)
.setPositiveButton(positiveButton) { dialog, _ ->
dialog.dismiss()
onPositive()
}
.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
.show()
}
/**
* Error to show when the Rust libraries did not properly link. This problem can happen pretty often
* during development when a build of the SDK failed to compile and resulted in an AAR file with no
* shared libraries (*.so files) inside. In theory, this should never be seen by an end user but if
* it does occur it is better to show a clean message explaining the situation. Nothing can be done
* other than rebuilding the SDK or switching to a functional version.
* As a developer, this error probably means that you need to comment out mavenLocal() as a repo.
*/
fun Context.showSharedLibraryCriticalError(e: Throwable): Dialog = showCriticalMessage(
titleResId = R.string.dialog_error_critical_link_title,
messageResId = R.string.dialog_error_critical_link_message,
onDismiss = { throw e }
)