From 7686228e016b38ca13718f1d3b49ee6bf523c388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sun, 25 Nov 2018 15:03:47 +0100 Subject: [PATCH] Add details to error message (#186) --- .../io/github/wulkanowy/data/ErrorHandler.kt | 17 ++--- .../github/wulkanowy/ui/base/BaseActivity.kt | 7 ++ .../github/wulkanowy/ui/base/BaseFragment.kt | 13 +++- .../github/wulkanowy/ui/base/BasePresenter.kt | 3 +- .../io/github/wulkanowy/ui/base/BaseView.kt | 2 + .../github/wulkanowy/ui/base/ErrorDialog.kt | 60 ++++++++++++++++ .../ui/modules/account/AccountDialog.kt | 4 ++ .../ui/modules/login/LoginErrorHandler.kt | 4 +- .../login/options/LoginOptionsPresenter.kt | 5 +- .../ui/modules/settings/SettingsFragment.kt | 8 ++- app/src/main/res/layout/dialog_error.xml | 70 +++++++++++++++++++ app/src/main/res/values-pl/strings.xml | 13 ++-- app/src/main/res/values/strings.xml | 13 ++-- 13 files changed, 193 insertions(+), 26 deletions(-) create mode 100644 app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt create mode 100644 app/src/main/res/layout/dialog_error.xml diff --git a/app/src/main/java/io/github/wulkanowy/data/ErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/data/ErrorHandler.kt index deefbd72..8e7fbdea 100644 --- a/app/src/main/java/io/github/wulkanowy/data/ErrorHandler.kt +++ b/app/src/main/java/io/github/wulkanowy/data/ErrorHandler.kt @@ -2,29 +2,30 @@ package io.github.wulkanowy.data import android.content.res.Resources import io.github.wulkanowy.R +import io.github.wulkanowy.api.interceptor.ServiceUnavailableException import io.github.wulkanowy.api.login.NotLoggedInException import timber.log.Timber -import java.io.IOException import java.net.SocketTimeoutException import java.net.UnknownHostException import javax.inject.Inject open class ErrorHandler @Inject constructor(protected val resources: Resources) { - var showErrorMessage: (String) -> Unit = {} + var showErrorMessage: (String, Throwable) -> Unit = { _, _ -> } open fun proceed(error: Throwable) { Timber.e(error, "An exception occurred while the Wulkanowy was running") showErrorMessage((when (error) { - is UnknownHostException -> resources.getString(R.string.all_no_internet) - is SocketTimeoutException -> resources.getString(R.string.all_timeout) - is NotLoggedInException, is IOException -> resources.getString(R.string.all_login_failed) - else -> error.localizedMessage - })) + is UnknownHostException -> resources.getString(R.string.error_no_internet) + is SocketTimeoutException -> resources.getString(R.string.error_timeout) + is NotLoggedInException -> resources.getString(R.string.error_login_failed) + is ServiceUnavailableException -> resources.getString(R.string.error_service_unavaible) + else -> resources.getString(R.string.error_unknown) + }), error) } open fun clear() { - showErrorMessage = {} + showErrorMessage = { _, _ -> } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt index f02b6488..f227dc19 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt @@ -6,6 +6,7 @@ import androidx.appcompat.app.AppCompatDelegate import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar.LENGTH_LONG import dagger.android.support.DaggerAppCompatActivity +import io.github.wulkanowy.R abstract class BaseActivity : DaggerAppCompatActivity(), BaseView { @@ -16,6 +17,12 @@ abstract class BaseActivity : DaggerAppCompatActivity(), BaseView { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) } + override fun showError(text: String, error: Throwable) { + Snackbar.make(messageContainer, text, LENGTH_LONG).setAction(R.string.all_details) { + ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString()) + }.show() + } + override fun showMessage(text: String) { Snackbar.make(messageContainer, text, LENGTH_LONG).show() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt index b0d6178e..667b46ff 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt @@ -2,15 +2,24 @@ package io.github.wulkanowy.ui.base import android.view.View import com.google.android.material.snackbar.Snackbar -import com.google.android.material.snackbar.Snackbar.LENGTH_LONG import dagger.android.support.DaggerFragment +import io.github.wulkanowy.R abstract class BaseFragment : DaggerFragment(), BaseView { protected var messageContainer: View? = null + override fun showError(text: String, error: Throwable) { + if (messageContainer == null) (activity as? BaseActivity)?.showError(text, error) + else messageContainer?.also { + Snackbar.make(it, text, Snackbar.LENGTH_LONG).setAction(R.string.all_details) { + ErrorDialog.newInstance(error).show(fragmentManager, error.toString()) + }.show() + } + } + override fun showMessage(text: String) { if (messageContainer == null) (activity as? BaseActivity)?.showMessage(text) - else messageContainer?.also { Snackbar.make(it, text, LENGTH_LONG).show() } + else messageContainer?.also { Snackbar.make(it, text, Snackbar.LENGTH_LONG).show() } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt index 9a0b5eda..5606a51f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt @@ -1,7 +1,6 @@ package io.github.wulkanowy.ui.base import io.github.wulkanowy.data.ErrorHandler -import io.github.wulkanowy.ui.modules.main.MainView import io.reactivex.disposables.CompositeDisposable open class BasePresenter(private val errorHandler: ErrorHandler) { @@ -12,7 +11,7 @@ open class BasePresenter(private val errorHandler: ErrorHandler) { open fun onAttachView(view: T) { this.view = view - errorHandler.showErrorMessage = { view.showMessage(it) } + errorHandler.showErrorMessage = { text, error -> view.showError(text, error) } } open fun onDetachView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt index 6352ca83..d2470fd1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt @@ -2,5 +2,7 @@ package io.github.wulkanowy.ui.base interface BaseView { + fun showError(text: String, error: Throwable) + fun showMessage(text: String) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt new file mode 100644 index 00000000..db3918b9 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt @@ -0,0 +1,60 @@ +package io.github.wulkanowy.ui.base + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context.CLIPBOARD_SERVICE +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import android.widget.Toast.LENGTH_LONG +import androidx.fragment.app.DialogFragment +import io.github.wulkanowy.R +import kotlinx.android.synthetic.main.dialog_error.* +import java.io.PrintWriter +import java.io.StringWriter + +class ErrorDialog : DialogFragment() { + + private lateinit var error: Throwable + + companion object { + private const val ARGUMENT_KEY = "Data" + + fun newInstance(error: Throwable): ErrorDialog { + return ErrorDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, error) } + } + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + error = getSerializable(ARGUMENT_KEY) as Throwable + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.dialog_error, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + StringWriter().let { writer -> + error.printStackTrace(PrintWriter(writer)) + + errorDialogContent.text = writer.toString() + errorDialogCopy.setOnClickListener { + ClipData.newPlainText("wulkanowyError", writer.toString()).let { clip -> + (activity?.getSystemService(CLIPBOARD_SERVICE) as? ClipboardManager)?.primaryClip = clip + } + Toast.makeText(context, R.string.all_copied, LENGTH_LONG).show() + } + } + errorDialogCancel.setOnClickListener { dismiss() } + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt index 040bfd3a..3c3c0a7a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt @@ -59,6 +59,10 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView { accountAdapter.updateDataSet(data) } + override fun showError(text: String, error: Throwable) { + showMessage(text) + } + override fun showMessage(text: String) { Toast.makeText(context, text, LENGTH_LONG).show() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt index 1763f8d4..507ef5fe 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt @@ -10,10 +10,12 @@ class LoginErrorHandler(resources: Resources) : ErrorHandler(resources) { var onBadCredentials: () -> Unit = {} + var onStudentDuplicate: (String) -> Unit = {} + override fun proceed(error: Throwable) { when (error) { is BadCredentialsException -> onBadCredentials() - is SQLiteConstraintException -> showErrorMessage(resources.getString(R.string.login_duplicate_student)) + is SQLiteConstraintException -> onStudentDuplicate(resources.getString(R.string.login_duplicate_student)) else -> super.proceed(error) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/options/LoginOptionsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/options/LoginOptionsPresenter.kt index ba16072d..eb9d981f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/options/LoginOptionsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/options/LoginOptionsPresenter.kt @@ -20,7 +20,10 @@ class LoginOptionsPresenter @Inject constructor( override fun onAttachView(view: LoginOptionsView) { super.onAttachView(view) - view.initView() + view.run { + initView() + errorHandler.onStudentDuplicate = { showMessage(it) } + } } fun onParentViewLoadData() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt index 7a24a10d..7273e8e9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt @@ -3,11 +3,11 @@ package io.github.wulkanowy.ui.modules.settings import android.content.Context import android.content.SharedPreferences import android.os.Bundle -import android.widget.Toast import androidx.appcompat.app.AppCompatDelegate import com.takisoft.preferencex.PreferenceFragmentCompat import dagger.android.support.AndroidSupportInjection import io.github.wulkanowy.R +import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.main.MainView import javax.inject.Inject @@ -54,8 +54,12 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP } } + override fun showError(text: String, error: Throwable) { + (activity as? BaseActivity)?.showError(text, error) + } + override fun showMessage(text: String) { - Toast.makeText(context, text, Toast.LENGTH_SHORT).show() + (activity as? BaseActivity)?.showMessage(text) } override fun onResume() { diff --git a/app/src/main/res/layout/dialog_error.xml b/app/src/main/res/layout/dialog_error.xml new file mode 100644 index 00000000..904d04eb --- /dev/null +++ b/app/src/main/res/layout/dialog_error.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + +