Loading app/src/main/java/foundation/e/apps/domain/errors/CentralErrorHandler.kt 0 → 100644 +131 −0 Original line number Diff line number Diff line /* * Copyright MURENA SAS 2023 * Apps Quickly and easily install Android apps onto your device! * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.domain.errors import android.app.Activity import android.content.Intent import android.graphics.Paint import android.net.Uri import android.view.View import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import foundation.e.apps.R import foundation.e.apps.data.enums.User import foundation.e.apps.databinding.DialogErrorLogBinding class CentralErrorHandler { private var lastDialog: AlertDialog? = null fun getDialogForTimeout( context: Activity, logToDisplay: String = "", retryAction: () -> Unit, ): AlertDialog.Builder { val customDialogView = getDialogCustomView(context, logToDisplay) val dialog = AlertDialog.Builder(context).apply { setTitle(R.string.timeout_title) setMessage(R.string.timeout_desc_cleanapk) setView(customDialogView) setPositiveButton(R.string.retry) { _, _ -> retryAction() } setNegativeButton(R.string.close, null) setCancelable(true) } return dialog } fun getDialogForUnauthorized( context: Activity, logToDisplay: String = "", user: User, retryAction: () -> Unit, logoutAction: () -> Unit, ): AlertDialog.Builder { val customDialogView = getDialogCustomView(context, logToDisplay) val dialog = AlertDialog.Builder(context).apply { if (user == User.GOOGLE) { setTitle(R.string.sign_in_failed_title) setMessage(R.string.sign_in_failed_desc) } else { setTitle(R.string.anonymous_login_failed) setMessage(R.string.anonymous_login_failed_desc) } setView(customDialogView) setPositiveButton(R.string.retry) { _, _ -> retryAction() } setNegativeButton(R.string.logout) { _, _ -> logoutAction() } setCancelable(true) } return dialog } private fun getDialogCustomView( context: Activity, logToDisplay: String, ): View { val dialogLayout = DialogErrorLogBinding.inflate(context.layoutInflater) dialogLayout.apply { moreInfo.setOnClickListener { logDisplay.isVisible = true moreInfo.isVisible = false } setTextviewUnderlined(troubleshootingLink) troubleshootingLink.setOnClickListener { openTroubleshootingPage(context) } if (logToDisplay.isNotBlank()) { logDisplay.text = logToDisplay moreInfo.isVisible = true } } return dialogLayout.root } fun dismissAllAndShow(alertDialogBuilder: AlertDialog.Builder) { if (lastDialog?.isShowing == true) { lastDialog?.dismiss() } alertDialogBuilder.create().run { this.show() lastDialog = this } } private fun setTextviewUnderlined(textView: TextView) { textView.paintFlags = textView.paintFlags or Paint.UNDERLINE_TEXT_FLAG } private fun openTroubleshootingPage(context: Activity) { context.run { val troubleshootUrl = getString(R.string.troubleshootURL) val openUrlIntent = Intent(Intent.ACTION_VIEW) openUrlIntent.data = Uri.parse(troubleshootUrl) startActivity(openUrlIntent) } } } No newline at end of file app/src/main/java/foundation/e/apps/domain/errors/RetryMechanism.kt 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright MURENA SAS 2023 * Apps Quickly and easily install Android apps onto your device! * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.domain.errors class RetryMechanism { private var autoRetryCount = 0 /** * Wrap the code to code to retry execution. */ fun wrapWithRetry( retryBlock: () -> Unit, retryFailureBlock: () -> Unit, ) { if (!retryEvaluator(retryBlock)) { retryFailureBlock() } } /** * Example of where this function can be called: * - If user presses "Log out" or "Retry" from an error dialog. */ fun resetRetryCondition() { autoRetryCount = 0 } /** * The actual block to do multiple retries. * We can do some fancy stuff like exponential back-off using recursions. * * @return true if retry conditions have not expired, false otherwise. */ private fun retryEvaluator( retryBlock: () -> Unit, ): Boolean { if (shouldFailRetry()) return false retryBlock() updateAutoRetryCondition() return true } private fun updateAutoRetryCondition() { autoRetryCount++ } private fun shouldFailRetry(): Boolean { return autoRetryCount > 0 } } No newline at end of file Loading
app/src/main/java/foundation/e/apps/domain/errors/CentralErrorHandler.kt 0 → 100644 +131 −0 Original line number Diff line number Diff line /* * Copyright MURENA SAS 2023 * Apps Quickly and easily install Android apps onto your device! * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.domain.errors import android.app.Activity import android.content.Intent import android.graphics.Paint import android.net.Uri import android.view.View import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import foundation.e.apps.R import foundation.e.apps.data.enums.User import foundation.e.apps.databinding.DialogErrorLogBinding class CentralErrorHandler { private var lastDialog: AlertDialog? = null fun getDialogForTimeout( context: Activity, logToDisplay: String = "", retryAction: () -> Unit, ): AlertDialog.Builder { val customDialogView = getDialogCustomView(context, logToDisplay) val dialog = AlertDialog.Builder(context).apply { setTitle(R.string.timeout_title) setMessage(R.string.timeout_desc_cleanapk) setView(customDialogView) setPositiveButton(R.string.retry) { _, _ -> retryAction() } setNegativeButton(R.string.close, null) setCancelable(true) } return dialog } fun getDialogForUnauthorized( context: Activity, logToDisplay: String = "", user: User, retryAction: () -> Unit, logoutAction: () -> Unit, ): AlertDialog.Builder { val customDialogView = getDialogCustomView(context, logToDisplay) val dialog = AlertDialog.Builder(context).apply { if (user == User.GOOGLE) { setTitle(R.string.sign_in_failed_title) setMessage(R.string.sign_in_failed_desc) } else { setTitle(R.string.anonymous_login_failed) setMessage(R.string.anonymous_login_failed_desc) } setView(customDialogView) setPositiveButton(R.string.retry) { _, _ -> retryAction() } setNegativeButton(R.string.logout) { _, _ -> logoutAction() } setCancelable(true) } return dialog } private fun getDialogCustomView( context: Activity, logToDisplay: String, ): View { val dialogLayout = DialogErrorLogBinding.inflate(context.layoutInflater) dialogLayout.apply { moreInfo.setOnClickListener { logDisplay.isVisible = true moreInfo.isVisible = false } setTextviewUnderlined(troubleshootingLink) troubleshootingLink.setOnClickListener { openTroubleshootingPage(context) } if (logToDisplay.isNotBlank()) { logDisplay.text = logToDisplay moreInfo.isVisible = true } } return dialogLayout.root } fun dismissAllAndShow(alertDialogBuilder: AlertDialog.Builder) { if (lastDialog?.isShowing == true) { lastDialog?.dismiss() } alertDialogBuilder.create().run { this.show() lastDialog = this } } private fun setTextviewUnderlined(textView: TextView) { textView.paintFlags = textView.paintFlags or Paint.UNDERLINE_TEXT_FLAG } private fun openTroubleshootingPage(context: Activity) { context.run { val troubleshootUrl = getString(R.string.troubleshootURL) val openUrlIntent = Intent(Intent.ACTION_VIEW) openUrlIntent.data = Uri.parse(troubleshootUrl) startActivity(openUrlIntent) } } } No newline at end of file
app/src/main/java/foundation/e/apps/domain/errors/RetryMechanism.kt 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright MURENA SAS 2023 * Apps Quickly and easily install Android apps onto your device! * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.domain.errors class RetryMechanism { private var autoRetryCount = 0 /** * Wrap the code to code to retry execution. */ fun wrapWithRetry( retryBlock: () -> Unit, retryFailureBlock: () -> Unit, ) { if (!retryEvaluator(retryBlock)) { retryFailureBlock() } } /** * Example of where this function can be called: * - If user presses "Log out" or "Retry" from an error dialog. */ fun resetRetryCondition() { autoRetryCount = 0 } /** * The actual block to do multiple retries. * We can do some fancy stuff like exponential back-off using recursions. * * @return true if retry conditions have not expired, false otherwise. */ private fun retryEvaluator( retryBlock: () -> Unit, ): Boolean { if (shouldFailRetry()) return false retryBlock() updateAutoRetryCondition() return true } private fun updateAutoRetryCondition() { autoRetryCount++ } private fun shouldFailRetry(): Boolean { return autoRetryCount > 0 } } No newline at end of file