From 87ae4d34f33f7befd742a2d12e2ae56489150fe6 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 13 Aug 2022 01:49:33 +0200 Subject: [PATCH] NF: simplify catchingLifecycleScope My understanding is that this method will often be called either on fragments, and using the fragment's activity. So it seems to make sense to simplify it, ensuring that we avoid a parameter that will probably never change. Actually, since activities are also LifecycleOwner, it may be possible to ensure this method is even simpler, by defining it on activities instead of defining it on LifecycleOwner. Unless we have a reason to use an activity distinct from the LifecycleOwner. Also cleaning from function I viewed at the same time --- .../java/com/ichi2/anki/CoroutineHelpers.kt | 33 ++++++++++++ .../main/java/com/ichi2/anki/Statistics.kt | 3 +- .../src/main/java/com/ichi2/anki/UIUtils.kt | 4 +- .../java/com/ichi2/async/CoroutineHelpers.kt | 54 ------------------- 4 files changed, 36 insertions(+), 58 deletions(-) delete mode 100644 AnkiDroid/src/main/java/com/ichi2/async/CoroutineHelpers.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CoroutineHelpers.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CoroutineHelpers.kt index 70c5b5f6c6eb..1915188d1d9e 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CoroutineHelpers.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CoroutineHelpers.kt @@ -16,8 +16,11 @@ package com.ichi2.anki +import android.app.Activity import android.content.Context import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.Fragment +import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.coroutineScope import anki.collection.Progress import com.ichi2.anki.UIUtils.showSimpleSnackbar @@ -232,3 +235,33 @@ suspend fun AnkiActivity.userAcceptsSchemaChange(col: Collection): Boolean { .show() } } + +/** + * Launch a job that catches any uncaught errors, informs the user and prints it to Log. + * Errors from the backend contain localized text that is often suitable to show to the user as-is. + * Other errors should ideally be handled in the block. + */ +fun LifecycleOwner.catchingLifecycleScope( + activity: Activity, + errorMessage: String? = null, + block: suspend CoroutineScope.() -> Unit +): Job = lifecycle.coroutineScope.launch { + try { + block() + } catch (e: CancellationException) { + throw e + } catch (e: Exception) { + // TODO: localize + Timber.w(e, errorMessage) + UIUtils.showDismissibleSnackbar(activity, "An error occurred: $e", R.string.close) + CrashReportService.sendExceptionReport(e, activity::class.java.simpleName) + } +} + +/** + * @see [LifecycleOwner.catchingLifecycleScope] + */ +fun Fragment.catchingLifecycleScope( + errorMessage: String? = null, + block: suspend CoroutineScope.() -> Unit +) = (this as LifecycleOwner).catchingLifecycleScope(requireActivity(), errorMessage, block) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Statistics.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Statistics.kt index 81a331c53382..092e3ee56c1b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Statistics.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Statistics.kt @@ -44,7 +44,6 @@ import com.ichi2.anki.stats.AnkiStatsTaskHandler import com.ichi2.anki.stats.AnkiStatsTaskHandler.Companion.getInstance import com.ichi2.anki.stats.ChartView import com.ichi2.anki.widgets.DeckDropDownAdapter.SubtitleListener -import com.ichi2.async.catchingLifecycleScope import com.ichi2.libanki.Collection import com.ichi2.libanki.DeckId import com.ichi2.libanki.Decks @@ -451,7 +450,7 @@ class Statistics : NavigationDrawerActivity(), DeckSelectionListener, SubtitleLi private fun createStatisticOverview() { val handler = (requireActivity() as Statistics).taskHandler - statisticsJob = catchingLifecycleScope(requireActivity(), "createStatisticOverview failed with error") { + statisticsJob = catchingLifecycleScope("createStatisticOverview failed with error") { handler.createStatisticsOverview(mWebView, mProgressBar) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/UIUtils.kt b/AnkiDroid/src/main/java/com/ichi2/anki/UIUtils.kt index 4773de51d8c1..8bd4d016261f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/UIUtils.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/UIUtils.kt @@ -141,7 +141,7 @@ object UIUtils { } @JvmStatic - fun getDismissibleSnackbar(activity: Activity?, mainText: String, length: Int, dismissTextResource: Int, root: View): Snackbar { + fun getDismissibleSnackbar(context: Context, mainText: String, length: Int, dismissTextResource: Int, root: View): Snackbar { val sb = Snackbar.make(root, mainText, length) sb.setAction(dismissTextResource) { sb.dismiss() @@ -152,7 +152,7 @@ object UIUtils { val action = view.findViewById(com.google.android.material.R.id.snackbar_action) if (tv != null && action != null) { tv.setTextColor(Color.WHITE) - action.setTextColor(ContextCompat.getColor(activity!!, R.color.material_light_blue_500)) + action.setTextColor(ContextCompat.getColor(context, R.color.material_light_blue_500)) tv.maxLines = 2 // prevent tablets from truncating to 1 line } return sb diff --git a/AnkiDroid/src/main/java/com/ichi2/async/CoroutineHelpers.kt b/AnkiDroid/src/main/java/com/ichi2/async/CoroutineHelpers.kt deleted file mode 100644 index c1ade807f1df..000000000000 --- a/AnkiDroid/src/main/java/com/ichi2/async/CoroutineHelpers.kt +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2022 Divyansh Kushwaha * - * * - * 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 . * - ****************************************************************************************/ - -/* -* This file contains extension functions for different coroutine related actions. -*/ -package com.ichi2.async - -import android.app.Activity -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.coroutineScope -import com.ichi2.anki.CrashReportService -import com.ichi2.anki.R -import com.ichi2.anki.UIUtils.showDismissibleSnackbar -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import timber.log.Timber - -/* - * Launch a job that catches any uncaught errors, informs the user and prints it to Log. - * Errors from the backend contain localized text that is often suitable to show to the user as-is. - * Other errors should ideally be handled in the block. - */ -fun LifecycleOwner.catchingLifecycleScope( - activity: Activity, - errorMessage: String? = null, - block: suspend CoroutineScope.() -> Unit -): Job = lifecycle.coroutineScope.launch { - try { - block() - } catch (e: CancellationException) { - throw e - } catch (e: Exception) { - // TODO: localize - Timber.w(e, errorMessage) - showDismissibleSnackbar(activity, "An error occurred: $e", R.string.close) - CrashReportService.sendExceptionReport(e, activity::class.java.simpleName) - } -}