forked from github/wulkanowy-mirror
Add details to error message (#186)
This commit is contained in:
parent
7a3c0de7ad
commit
7686228e01
@ -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 = { _, _ -> }
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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() }
|
||||
}
|
||||
}
|
||||
|
@ -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<T : BaseView>(private val errorHandler: ErrorHandler) {
|
||||
@ -12,7 +11,7 @@ open class BasePresenter<T : BaseView>(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() {
|
||||
|
@ -2,5 +2,7 @@ package io.github.wulkanowy.ui.base
|
||||
|
||||
interface BaseView {
|
||||
|
||||
fun showError(text: String, error: Throwable)
|
||||
|
||||
fun showMessage(text: String)
|
||||
}
|
||||
|
60
app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
Normal file
60
app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
Normal file
@ -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() }
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
70
app/src/main/res/layout/dialog_error.xml
Normal file
70
app/src/main/res/layout/dialog_error.xml
Normal file
@ -0,0 +1,70 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="300dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:overScrollMode="ifContentScrolls"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="350dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingTop="24dp"
|
||||
android:paddingRight="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errorDialogContent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollHorizontally="true"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
</HorizontalScrollView>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="end"
|
||||
android:minHeight="52dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/errorDialogCancel"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@android:string/cancel"
|
||||
android:textColor="@color/colorPrimary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/errorDialogCopy"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@android:string/copy"
|
||||
android:textColor="@color/colorPrimary" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -205,9 +205,12 @@
|
||||
|
||||
|
||||
<!--Others-->
|
||||
<string name="all_no_internet">Brak połączenia z internetem</string>
|
||||
<string name="all_sync_finish">Synchronizacja zakończona</string>
|
||||
<string name="all_sync_fail">Podczas synchronizacji wystąpił błąd</string>
|
||||
<string name="all_timeout">Zbyt długie oczekiwanie na połączenie</string>
|
||||
<string name="all_login_failed">Logowanie nie powiodło się. Spróbuj ponownie lub zrestartuj aplikację</string>
|
||||
<string name="all_copied">Skopiowano</string>
|
||||
|
||||
<!--Errors-->
|
||||
<string name="error_no_internet">Brak połączenia z internetem</string>
|
||||
<string name="error_timeout">Zbyt długie oczekiwanie na połączenie</string>
|
||||
<string name="error_login_failed">Logowanie nie powiodło się. Spróbuj ponownie lub zrestartuj aplikację</string>
|
||||
<string name="error_service_unavaible">Dziennik jest niedostępny. Spróbuj ponownie później</string>
|
||||
<string name="error_unknown">Wystąpił nieoczekiwany błąd</string>
|
||||
</resources>
|
||||
|
@ -190,9 +190,12 @@
|
||||
|
||||
|
||||
<!--Others-->
|
||||
<string name="all_no_internet">No internet connection</string>
|
||||
<string name="all_sync_finish">Synchronization complete</string>
|
||||
<string name="all_sync_fail">There was an error during synchronization</string>
|
||||
<string name="all_timeout">Too long wait for connection</string>
|
||||
<string name="all_login_failed">Login is failed. Try again or restart the app</string>
|
||||
<string name="all_copied">Copied</string>
|
||||
|
||||
<!--Errors-->
|
||||
<string name="error_no_internet">No internet connection</string>
|
||||
<string name="error_timeout">Too long wait for connection</string>
|
||||
<string name="error_login_failed">Login is failed. Try again or restart the app</string>
|
||||
<string name="error_service_unavaible">The log is not available. Try again later</string>
|
||||
<string name="error_unknown">An unexpected error occurred</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user