From eae07e2fe0bb886ec7ef26823c2d9318b2c5b6ce Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 30 Jan 2024 17:27:48 -0500 Subject: [PATCH] Making sure Cancellation of coroutines stops long processes. --- .../amethyst/service/notifications/PushMessageReceiver.kt | 2 ++ .../service/notifications/PushNotificationUtils.kt | 2 ++ .../java/com/vitorpamplona/amethyst/LocalPreferences.kt | 7 +++++++ .../java/com/vitorpamplona/amethyst/ServiceManager.kt | 2 ++ .../java/com/vitorpamplona/amethyst/model/LocalCache.kt | 5 +++++ .../main/java/com/vitorpamplona/amethyst/model/Note.kt | 4 ++++ .../amethyst/service/CachedRichTextParser.kt | 3 +++ .../com/vitorpamplona/amethyst/service/CashuProcessor.kt | 4 ++++ .../java/com/vitorpamplona/amethyst/service/FileHeader.kt | 3 +++ .../com/vitorpamplona/amethyst/service/LocationUtil.kt | 2 ++ .../amethyst/service/Nip05NostrAddressVerifier.kt | 7 +++++-- .../amethyst/service/Nip11RelayInfoRetriever.kt | 3 +++ .../com/vitorpamplona/amethyst/service/Nip44UrlParser.kt | 2 ++ .../amethyst/service/Nip47WalletConnectParser.kt | 2 ++ .../vitorpamplona/amethyst/service/Nip96MediaServers.kt | 2 ++ .../amethyst/service/NostrSearchEventOrUserDataSource.kt | 2 ++ .../com/vitorpamplona/amethyst/service/OnlineCheck.kt | 2 ++ .../amethyst/service/lnurl/LightningAddressResolver.kt | 4 ++++ .../amethyst/service/notifications/RegisterAccounts.kt | 2 ++ .../amethyst/service/playback/PlaybackClientController.kt | 3 +++ .../amethyst/service/previews/BahaUrlPreview.kt | 2 ++ .../com/vitorpamplona/amethyst/service/relays/Relay.kt | 8 ++++++-- .../java/com/vitorpamplona/amethyst/ui/MainActivity.kt | 2 ++ .../vitorpamplona/amethyst/ui/actions/ImageDownloader.kt | 2 ++ .../com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt | 4 ++++ .../vitorpamplona/amethyst/ui/actions/NewMediaModel.kt | 2 ++ .../com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt | 2 ++ .../vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt | 2 ++ .../vitorpamplona/amethyst/ui/actions/NewPollClosing.kt | 2 ++ .../amethyst/ui/actions/NewPollConsensusThreshold.kt | 2 ++ .../com/vitorpamplona/amethyst/ui/actions/NewPostView.kt | 2 ++ .../vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt | 4 ++++ .../amethyst/ui/actions/NewUserMetadataViewModel.kt | 2 ++ .../amethyst/ui/actions/UrlUserTagTransformation.kt | 2 ++ .../vitorpamplona/amethyst/ui/components/CashuRedeem.kt | 3 +++ .../amethyst/ui/components/ClickableEmail.kt | 2 ++ .../amethyst/ui/components/InvoicePreview.kt | 2 ++ .../amethyst/ui/components/MarkdownParser.kt | 3 +++ .../amethyst/ui/components/MediaCompressor.kt | 2 ++ .../com/vitorpamplona/amethyst/ui/components/VideoView.kt | 2 ++ .../amethyst/ui/components/ZoomableContentView.kt | 2 ++ .../amethyst/ui/navigation/AccountSwitchBottomSheet.kt | 2 ++ .../amethyst/ui/note/UpdateZapAmountDialog.kt | 3 +++ .../com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt | 3 +++ .../com/vitorpamplona/amethyst/ui/qrcode/QrCodeScanner.kt | 2 ++ .../com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt | 2 ++ .../amethyst/ui/screen/AccountStateViewModel.kt | 2 ++ .../amethyst/ui/screen/loggedIn/AccountViewModel.kt | 2 ++ .../amethyst/ui/screen/loggedIn/ConnectOrbotDialog.kt | 4 +++- .../amethyst/ui/screen/loggedOff/LoginScreen.kt | 2 ++ .../amethyst/service/lang/LanguageTranslatorService.kt | 7 +++++-- .../service/notifications/PushNotificationUtils.kt | 2 ++ 52 files changed, 141 insertions(+), 7 deletions(-) diff --git a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt index 951f6e8c6..a10656414 100644 --- a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt +++ b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt @@ -32,6 +32,7 @@ import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrC import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrCreateZapChannel import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.GiftWrapEvent +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -60,6 +61,7 @@ class PushMessageReceiver : MessagingReceiver() { try { parseMessage(messageStr)?.let { receiveIfNew(it) } } catch (e: Exception) { + if (e is CancellationException) throw e Log.d(TAG, "Message could not be parsed: ${e.message}") } } diff --git a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt index 6a25767b0..7405779aa 100644 --- a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt +++ b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt @@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.service.notifications import android.util.Log import com.vitorpamplona.amethyst.AccountInfo +import kotlinx.coroutines.CancellationException object PushNotificationUtils { var hasInit: Boolean = false @@ -36,6 +37,7 @@ object PushNotificationUtils { RegisterAccounts(accounts).go(pushHandler.getSavedEndpoint()) } } catch (e: Exception) { + if (e is CancellationException) throw e Log.d("Amethyst-OSSPushUtils", "Failed to get endpoint.") } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index af3201fb3..b553a33d2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -53,6 +53,7 @@ import com.vitorpamplona.quartz.events.LnZapEvent import com.vitorpamplona.quartz.signers.ExternalSignerLauncher import com.vitorpamplona.quartz.signers.NostrSignerExternal import com.vitorpamplona.quartz.signers.NostrSignerInternal +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.sync.Mutex @@ -368,6 +369,7 @@ object LocalPreferences { return try { getString(PrefKeys.SHARED_SETTINGS, "{}")?.let { Event.mapper.readValue(it) } } catch (e: Throwable) { + if (e is CancellationException) throw e Log.w( "LocalPreferences", "Unable to decode shared preferences: ${getString(PrefKeys.SHARED_SETTINGS, null)}", @@ -510,6 +512,7 @@ object LocalPreferences { } ?: Nip96MediaServers.DEFAULT[0] } catch (e: Exception) { + if (e is CancellationException) throw e Log.w("LocalPreferences", "Failed to decode saved File Server", e) e.printStackTrace() Nip96MediaServers.DEFAULT[0] @@ -521,6 +524,7 @@ object LocalPreferences { Event.mapper.readValue(it) } } catch (e: Throwable) { + if (e is CancellationException) throw e Log.w( "LocalPreferences", "Error Decoding Zap Payment Request Server ${getString(PrefKeys.ZAP_PAYMENT_REQUEST_SERVER, null)}", @@ -541,6 +545,7 @@ object LocalPreferences { } } } catch (e: Throwable) { + if (e is CancellationException) throw e Log.w( "LocalPreferences", "Error Decoding Contact List ${getString(PrefKeys.LATEST_CONTACT_LIST, null)}", @@ -556,6 +561,7 @@ object LocalPreferences { } ?: mapOf() } catch (e: Throwable) { + if (e is CancellationException) throw e Log.w( "LocalPreferences", "Error Decoding Language Preferences ${getString(PrefKeys.LANGUAGE_PREFS, null)}", @@ -588,6 +594,7 @@ object LocalPreferences { } ?: mapOf() } catch (e: Throwable) { + if (e is CancellationException) throw e Log.w( "LocalPreferences", "Error Decoding Last Read per route ${getString(PrefKeys.LAST_READ_PER_ROUTE, null)}", diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt index 7b332b5df..4cf478185 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt @@ -51,6 +51,7 @@ import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.quartz.encoders.bechToBytes import com.vitorpamplona.quartz.encoders.decodePublicKeyAsHexOrNull import com.vitorpamplona.quartz.encoders.toHexKey +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -126,6 +127,7 @@ class ServiceManager { try { it.npub.bechToBytes().toHexKey() } catch (e: Exception) { + if (e is CancellationException) throw e null } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 2122b7a99..7c530058f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -98,6 +98,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableSet +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.MutableSharedFlow @@ -1397,6 +1398,7 @@ object LocalCache { try { Nip19.uriToRoute(text)?.hex ?: Hex.decode(text).toHexKey() } catch (e: Exception) { + if (e is CancellationException) throw e null } @@ -1446,6 +1448,7 @@ object LocalCache { try { Nip19.uriToRoute(text)?.hex ?: Hex.decode(text).toHexKey() } catch (e: Exception) { + if (e is CancellationException) throw e null } @@ -1738,6 +1741,7 @@ object LocalCache { try { event.checkSignature() } catch (e: Exception) { + if (e is CancellationException) throw e Log.w("Event failed retest ${event.kind}", (e.message ?: "") + event.toJson()) } false @@ -1831,6 +1835,7 @@ object LocalCache { } } } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt index 5d2a49f9a..4fae595d6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt @@ -63,6 +63,7 @@ import com.vitorpamplona.quartz.events.WrappedEvent import com.vitorpamplona.quartz.signers.NostrSigner import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.containsAny +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import java.math.BigDecimal @@ -644,6 +645,7 @@ open class Note(val idHex: String) { try { LnInvoiceUtil.getAmountInSats(invoice) } catch (e: java.lang.Exception) { + if (e is CancellationException) throw e null } @@ -694,6 +696,7 @@ open class Note(val idHex: String) { try { BigDecimal(it.event?.content()) } catch (e: Exception) { + if (e is CancellationException) throw e null // do nothing if it can't convert to bigdecimal } @@ -709,6 +712,7 @@ open class Note(val idHex: String) { try { BigDecimal(it.event?.content()) } catch (e: Exception) { + if (e is CancellationException) throw e null // do nothing if it can't convert to bigdecimal } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/CachedRichTextParser.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/CachedRichTextParser.kt index bc420f8d2..6f3046af9 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/CachedRichTextParser.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/CachedRichTextParser.kt @@ -42,6 +42,7 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableMap import kotlinx.collections.immutable.toImmutableSet +import kotlinx.coroutines.CancellationException import java.util.regex.Pattern @Immutable @@ -285,6 +286,7 @@ class RichTextParser() { } } } catch (e: Exception) { + if (e is CancellationException) throw e Log.w("Tag Parser", "Couldn't link tag $word", e) } @@ -299,6 +301,7 @@ class RichTextParser() { } } } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Hashtag Parser", "Couldn't link hashtag $word", e) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt index 3762505aa..ced0fa315 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt @@ -32,6 +32,7 @@ import okhttp3.MediaType.Companion.toMediaType import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import java.util.Base64 +import kotlin.coroutines.cancellation.CancellationException @Immutable data class CashuToken( @@ -59,6 +60,7 @@ class CashuProcessor { return GenericLoadable.Loaded(CashuToken(cashuToken, mint, totalAmount, proofs)) } catch (e: Exception) { + if (e is CancellationException) throw e return GenericLoadable.Error("Could not parse this cashu token") } } @@ -154,6 +156,7 @@ class CashuProcessor { } } } catch (e: Exception) { + if (e is CancellationException) throw e onError( context.getString(R.string.cashu_successful_redemption), context.getString(R.string.cashu_failed_redemption_explainer_error_msg, e.message), @@ -211,6 +214,7 @@ class CashuProcessor { } } } catch (e: Exception) { + if (e is CancellationException) throw e onError( context.getString(R.string.cashu_successful_redemption), context.getString(R.string.cashu_failed_redemption_explainer_error_msg, e.message), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt index f763482d0..de73fc0f5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt @@ -32,6 +32,7 @@ import com.vitorpamplona.amethyst.ui.actions.ImageDownloader import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.encoders.toHexKey import io.trbl.blurhash.BlurHash +import kotlinx.coroutines.CancellationException import java.io.IOException import kotlin.math.roundToInt @@ -59,6 +60,7 @@ class FileHeader( onError(null) } } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("ImageDownload", "Couldn't download image from server: ${e.message}") onError(e.message) } @@ -174,6 +176,7 @@ class FileHeader( onReady(FileHeader(mimeType, hash, size, dim, blurHash)) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("ImageDownload", "Couldn't convert image in to File Header: ${e.message}") onError(e.message) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/LocationUtil.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/LocationUtil.kt index f634b08a6..67ce8bc03 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/LocationUtil.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/LocationUtil.kt @@ -29,6 +29,7 @@ import android.location.LocationManager import android.os.HandlerThread import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow class LocationUtil(context: Context) { @@ -105,6 +106,7 @@ class ReverseGeoLocationUtil { .joinToString(", ") } } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() return null } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt index 3498f9518..4ba8c34ac 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt @@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.service import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.vitorpamplona.amethyst.BuildConfig +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okhttp3.Call @@ -96,7 +97,8 @@ class Nip05NostrAddressVerifier() { } }, ) - } catch (e: java.lang.Exception) { + } catch (e: Exception) { + if (e is CancellationException) throw e onError("Could not resolve '$url': ${e.message}") } } @@ -122,7 +124,8 @@ class Nip05NostrAddressVerifier() { val nip05url = try { mapper.readTree(it.lowercase()) - } catch (t: Throwable) { + } catch (e: Throwable) { + if (e is CancellationException) throw e onError("Error Parsing JSON from Lightning Address. Check the user's lightning setup") null } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt index 07fb77fe5..db98738df 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt @@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.service import android.util.Log import android.util.LruCache import com.vitorpamplona.amethyst.model.RelayInformation +import kotlinx.coroutines.CancellationException import okhttp3.Call import okhttp3.Callback import okhttp3.Request @@ -102,6 +103,7 @@ class Nip11Retriever { onError(dirtyUrl, ErrorCode.FAIL_WITH_HTTP_STATUS, it.code.toString()) } } catch (e: Exception) { + if (e is CancellationException) throw e Log.e( "RelayInfoFail", "Resulting Message from Relay $dirtyUrl in not parseable: $body", @@ -122,6 +124,7 @@ class Nip11Retriever { }, ) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("RelayInfoFail", "Invalid URL $dirtyUrl", e) onError(dirtyUrl, ErrorCode.FAIL_TO_ASSEMBLE_URL, e.message) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip44UrlParser.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip44UrlParser.kt index a3297527f..d203c9d8d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip44UrlParser.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip44UrlParser.kt @@ -22,12 +22,14 @@ package com.vitorpamplona.amethyst.service import java.net.URI import java.net.URLDecoder +import kotlin.coroutines.cancellation.CancellationException class Nip44UrlParser { fun parse(url: String): Map { return try { fragments(URI(url)) } catch (e: Exception) { + if (e is CancellationException) throw e emptyMap() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip47WalletConnectParser.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip47WalletConnectParser.kt index 075b537cc..d7186895d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip47WalletConnectParser.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip47WalletConnectParser.kt @@ -24,6 +24,7 @@ import android.net.Uri import com.vitorpamplona.amethyst.model.Nip47URI import com.vitorpamplona.quartz.encoders.decodePublicKey import com.vitorpamplona.quartz.encoders.toHexKey +import kotlinx.coroutines.CancellationException // Rename to the corect nip number when ready. object Nip47WalletConnectParser { @@ -42,6 +43,7 @@ object Nip47WalletConnectParser { try { decodePublicKey(pubkey).toHexKey() } catch (e: Exception) { + if (e is CancellationException) throw e throw IllegalArgumentException("Hostname is not a valid Nostr Pubkey") } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt index d024bb748..f45d59b9f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt @@ -24,6 +24,7 @@ import android.util.Log import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import kotlinx.coroutines.CancellationException import okhttp3.Request object Nip96MediaServers { @@ -100,6 +101,7 @@ class Nip96Retriever { ) } } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("RelayInfoFail", "Resulting Message from $baseUrl in not parseable: $body", e) throw e } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt index a4a3a39ec..64804f126 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt @@ -46,6 +46,7 @@ import com.vitorpamplona.quartz.events.PeopleListEvent import com.vitorpamplona.quartz.events.PinListEvent import com.vitorpamplona.quartz.events.PollNoteEvent import com.vitorpamplona.quartz.events.TextNoteEvent +import kotlin.coroutines.cancellation.CancellationException object NostrSearchEventOrUserDataSource : NostrDataSource("SearchEventFeed") { private var searchString: String? = null @@ -67,6 +68,7 @@ object NostrSearchEventOrUserDataSource : NostrDataSource("SearchEventFeed") { Nip19.uriToRoute(mySearchString)?.hex ?: isAStraightHex } catch (e: Exception) { + if (e is CancellationException) throw e null } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt index fae525ad6..cc6e4ed71 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt @@ -25,6 +25,7 @@ import android.util.LruCache import androidx.compose.runtime.Immutable import com.vitorpamplona.amethyst.BuildConfig import okhttp3.Request +import kotlin.coroutines.cancellation.CancellationException @Immutable data class OnlineCheckResult(val timeInMs: Long, val online: Boolean) @@ -66,6 +67,7 @@ object OnlineChecker { checkOnlineCache.put(url, OnlineCheckResult(System.currentTimeMillis(), result)) result } catch (e: Exception) { + if (e is CancellationException) throw e checkOnlineCache.put(url, OnlineCheckResult(System.currentTimeMillis(), false)) Log.e("LiveActivities", "Failed to check streaming url $url", e) false diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt index 0b5f9a5c9..fb471d86d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt @@ -33,6 +33,7 @@ import okhttp3.Request import java.math.BigDecimal import java.math.RoundingMode import java.net.URLEncoder +import kotlin.coroutines.cancellation.CancellationException class LightningAddressResolver() { val client = HttpClientManager.getHttpClient() @@ -96,6 +97,7 @@ class LightningAddressResolver() { } } } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() onError( context.getString(R.string.error_unable_to_fetch_invoice), @@ -184,6 +186,7 @@ class LightningAddressResolver() { try { mapper.readTree(lnAddressJson) } catch (t: Throwable) { + if (t is CancellationException) throw t onError( context.getString(R.string.error_unable_to_fetch_invoice), context.getString( @@ -219,6 +222,7 @@ class LightningAddressResolver() { try { mapper.readTree(it) } catch (t: Throwable) { + if (t is CancellationException) throw t onError( context.getString(R.string.error_unable_to_fetch_invoice), context.getString( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt index 903b94f95..8d0bac6ee 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt @@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.service.HttpClientManager import com.vitorpamplona.quartz.events.RelayAuthEvent +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okhttp3.MediaType.Companion.toMediaType @@ -110,6 +111,7 @@ class RegisterAccounts( val isSucess = client.newCall(request).execute().use { it.isSuccessful } } catch (e: java.lang.Exception) { + if (e is CancellationException) throw e val tag = if (BuildConfig.FLAVOR == "play") { "FirebaseMsgService" diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackClientController.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackClientController.kt index 94499d3c9..13616eeac 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackClientController.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackClientController.kt @@ -28,6 +28,7 @@ import android.util.LruCache import androidx.media3.session.MediaController import androidx.media3.session.SessionToken import com.google.common.util.concurrent.MoreExecutors +import kotlinx.coroutines.CancellationException object PlaybackClientController { val cache = LruCache(1) @@ -62,12 +63,14 @@ object PlaybackClientController { try { onReady(controllerFuture.get()) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Playback Client", "Failed to load Playback Client for $videoUri", e) } }, MoreExecutors.directExecutor(), ) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Playback Client", "Failed to load Playback Client for $videoUri", e) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/previews/BahaUrlPreview.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/previews/BahaUrlPreview.kt index aedb40df6..e794100cb 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/previews/BahaUrlPreview.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/previews/BahaUrlPreview.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.amethyst.service.previews +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -29,6 +30,7 @@ class BahaUrlPreview(val url: String, var callback: IUrlPreviewCallback?) { try { fetch(timeOut) } catch (t: Throwable) { + if (t is CancellationException) throw t callback?.onFailed(t) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt index e8a2b632e..fed6828b6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt @@ -31,6 +31,7 @@ import com.vitorpamplona.quartz.events.EventInterface import com.vitorpamplona.quartz.events.RelayAuthEvent import com.vitorpamplona.quartz.events.bytesUsedInMemory import com.vitorpamplona.quartz.utils.TimeUtils +import kotlinx.coroutines.CancellationException import okhttp3.Request import okhttp3.Response import okhttp3.WebSocket @@ -128,6 +129,8 @@ class Relay( socket = httpClient.newWebSocket(request, RelayListener(onConnected)) } catch (e: Exception) { + if (e is CancellationException) throw e + errorCounter++ markConnectionAsClosed() Log.e("Relay", "Relay Invalid $url") @@ -167,8 +170,9 @@ class Relay( try { processNewRelayMessage(text) - } catch (t: Throwable) { - t.printStackTrace() + } catch (e: Throwable) { + if (e is CancellationException) throw e + e.printStackTrace() text.chunked(2000) { chunked -> listeners.forEach { it.onError(this@Relay, "", Error("Problem with $chunked")) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index 0303adc68..85fef8da5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -64,6 +64,7 @@ import com.vitorpamplona.quartz.events.ChannelMetadataEvent import com.vitorpamplona.quartz.events.CommunityDefinitionEvent import com.vitorpamplona.quartz.events.LiveActivitiesEvent import com.vitorpamplona.quartz.events.PrivateDmEvent +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -341,6 +342,7 @@ fun uriToRoute(uri: String?): String? { Route.Home.base + "?nip47=" + encodedUri } } catch (e: Exception) { + if (e is CancellationException) throw e null } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt index e37758f29..674108bf4 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.amethyst.ui.actions +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.delay import java.net.HttpURLConnection import java.net.URL @@ -57,6 +58,7 @@ class ImageDownloader { null } } catch (e: Exception) { + if (e is CancellationException) throw e tentatives++ delay(1000) null diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt index ad83dc860..11a989a60 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt @@ -31,6 +31,7 @@ import android.webkit.MimeTypeMap import androidx.annotation.RequiresApi import com.vitorpamplona.amethyst.BuildConfig import com.vitorpamplona.amethyst.service.HttpClientManager +import kotlinx.coroutines.CancellationException import okhttp3.Call import okhttp3.Callback import okhttp3.Request @@ -102,6 +103,7 @@ object ImageSaver { } onSuccess() } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() onError(e) } @@ -138,6 +140,7 @@ object ImageSaver { } onSuccess() } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() onError(e) } @@ -176,6 +179,7 @@ object ImageSaver { outputStream.use { contentSource.readAll(it.sink()) } } catch (e: Exception) { + if (e is CancellationException) throw e contentResolver.delete(uri, null, null) throw e } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt index 985915881..703938397 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt @@ -36,6 +36,7 @@ import com.vitorpamplona.amethyst.service.Nip96MediaServers import com.vitorpamplona.amethyst.service.Nip96Uploader import com.vitorpamplona.amethyst.service.relays.Relay import com.vitorpamplona.amethyst.ui.components.MediaCompressor +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -148,6 +149,7 @@ open class NewMediaModel : ViewModel() { context, ) } catch (e: Exception) { + if (e is CancellationException) throw e isUploadingImage = false uploadingPercentage.value = 0.00f uploadingDescription.value = null diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt index 52f2d77b8..847131e4f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt @@ -72,6 +72,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner import com.vitorpamplona.amethyst.ui.screen.loggedIn.TitleExplainer import com.vitorpamplona.amethyst.ui.theme.placeholderText import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -231,6 +232,7 @@ fun ImageVideoPost( try { bitmap = resolver.loadThumbnail(it, Size(1200, 1000), null) } catch (e: Exception) { + if (e is CancellationException) throw e Log.w("NewPostView", "Couldn't create thumbnail, but the video can be uploaded", e) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt index 8299421e9..86f531645 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.Nip19 import com.vitorpamplona.quartz.encoders.bechToBytes import com.vitorpamplona.quartz.encoders.toNpub +import kotlinx.coroutines.CancellationException class NewMessageTagger( var message: String, @@ -196,6 +197,7 @@ class NewMessageTagger( ) // no way to know when they address ends and dirt begins } } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollClosing.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollClosing.kt index 39f16194c..7f6145daf 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollClosing.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollClosing.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel import com.vitorpamplona.amethyst.ui.theme.placeholderText +import kotlinx.coroutines.CancellationException @Composable fun NewPollClosing(pollViewModel: NewPostViewModel) { @@ -58,6 +59,7 @@ fun NewPollClosing(pollViewModel: NewPostViewModel) { pollViewModel.closedAt = int } } catch (e: Exception) { + if (e is CancellationException) throw e pollViewModel.isValidClosedAt.value = false } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollConsensusThreshold.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollConsensusThreshold.kt index 271c0f346..51c1f65c8 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollConsensusThreshold.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPollConsensusThreshold.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel import com.vitorpamplona.amethyst.ui.theme.placeholderText +import kotlinx.coroutines.CancellationException @Composable fun NewPollConsensusThreshold(pollViewModel: NewPostViewModel) { @@ -58,6 +59,7 @@ fun NewPollConsensusThreshold(pollViewModel: NewPostViewModel) { pollViewModel.consensusThreshold = int } } catch (e: Exception) { + if (e is CancellationException) throw e pollViewModel.isValidConsensusThreshold.value = false } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt index e756677d1..2429a2990 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt @@ -179,6 +179,7 @@ import com.vitorpamplona.quartz.events.ClassifiedsEvent import com.vitorpamplona.quartz.events.toImmutableListOfLists import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow @@ -1674,6 +1675,7 @@ fun ImageVideoDescription( try { bitmap = resolver.loadThumbnail(uri, Size(1200, 1000), null) } catch (e: Exception) { + if (e is CancellationException) throw e onError("Unable to load thumbnail") Log.w("NewPostView", "Couldn't create thumbnail, but the video can be uploaded", e) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt index 20f7c59ff..1bc8a5fbd 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt @@ -63,6 +63,7 @@ import com.vitorpamplona.quartz.events.PrivateDmEvent import com.vitorpamplona.quartz.events.TextNoteEvent import com.vitorpamplona.quartz.events.ZapSplitSetup import com.vitorpamplona.quartz.events.findURLs +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.BufferOverflow @@ -476,6 +477,7 @@ open class NewPostViewModel() : ViewModel() { ) } } catch (e: Exception) { + if (e is CancellationException) throw e Log.e( "ImageUploader", "Failed to upload ${e.message}", @@ -942,6 +944,7 @@ open class NewPostViewModel() : ViewModel() { valueMinimum = int } } catch (e: Exception) { + if (e is CancellationException) throw e } } else { valueMinimum = null @@ -960,6 +963,7 @@ open class NewPostViewModel() : ViewModel() { valueMaximum = int } } catch (e: Exception) { + if (e is CancellationException) throw e } } else { valueMaximum = null diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt index 1824dbbc5..86695c9b6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt @@ -37,6 +37,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.launch +import kotlin.coroutines.cancellation.CancellationException class NewUserMetadataViewModel : ViewModel() { private lateinit var account: Account @@ -197,6 +198,7 @@ class NewUserMetadataViewModel : ViewModel() { } } } catch (e: Exception) { + if (e is CancellationException) throw e onUploading(false) viewModelScope.launch { imageUploadingError.emit("Failed to upload the image / video") diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt index 32218b39a..f239f4af0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.text.style.TextDecoration import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.quartz.encoders.decodePublicKey import com.vitorpamplona.quartz.encoders.toHexKey +import kotlin.coroutines.cancellation.CancellationException import kotlin.math.roundToInt data class RangesChanges(val original: TextRange, val modified: TextRange) @@ -113,6 +114,7 @@ fun buildAnnotatedStringWithUrlHighlighting( word } } catch (e: Exception) { + if (e is CancellationException) throw e // if it can't parse the key, don't try to change. builderBefore.append("$word ") builderAfter.append("$word ") diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/CashuRedeem.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/CashuRedeem.kt index d71e64e82..b318a4a3f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/CashuRedeem.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/CashuRedeem.kt @@ -83,6 +83,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size20Modifier import com.vitorpamplona.amethyst.ui.theme.SmallishBorder import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.amethyst.ui.theme.subtleBorder +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -238,6 +239,7 @@ fun CashuPreview( startActivity(context, intent, null) } catch (e: Exception) { + if (e is CancellationException) throw e toast("Cashu", context.getString(R.string.cashu_no_wallet_found)) } }, @@ -354,6 +356,7 @@ fun CashuPreviewNew( startActivity(context, intent, null) } catch (e: Exception) { + if (e is CancellationException) throw e toast("Cashu", context.getString(R.string.cashu_no_wallet_found)) } }, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt index 7faddad2f..841e35864 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableEmail.kt @@ -30,6 +30,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.AnnotatedString +import kotlinx.coroutines.CancellationException @Composable fun ClickableEmail(email: String) { @@ -58,6 +59,7 @@ fun Context.sendMail( } catch (e: ActivityNotFoundException) { // TODO: Handle case where no email app is available } catch (t: Throwable) { + if (t is CancellationException) throw t // TODO: Handle potential other type of exceptions } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoicePreview.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoicePreview.kt index 3f1213cee..5ed03955b 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoicePreview.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoicePreview.kt @@ -58,6 +58,7 @@ import com.vitorpamplona.amethyst.ui.theme.QuoteBorder import com.vitorpamplona.amethyst.ui.theme.Size20Modifier import com.vitorpamplona.amethyst.ui.theme.subtleBorder import com.vitorpamplona.quartz.encoders.LnInvoiceUtil +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.text.NumberFormat @@ -79,6 +80,7 @@ fun LoadValueFromInvoice( try { NumberFormat.getInstance().format(LnInvoiceUtil.getAmountInSats(myInvoice)) } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() null } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MarkdownParser.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MarkdownParser.kt index eabab7c90..e3518a55b 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MarkdownParser.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MarkdownParser.kt @@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.service.startsWithNIP19Scheme import com.vitorpamplona.quartz.encoders.Nip19 import com.vitorpamplona.quartz.events.ImmutableListOfLists +import kotlinx.coroutines.CancellationException class MarkdownParser { private fun getDisplayNameAndNIP19FromTag( @@ -39,6 +40,7 @@ class MarkdownParser { matcher.find() Pair(matcher.group(1)?.toInt(), matcher.group(2) ?: "") } catch (e: Exception) { + if (e is CancellationException) throw e Log.w("Tag Parser", "Couldn't link tag $tag", e) Pair(null, null) } @@ -161,6 +163,7 @@ class MarkdownParser { hashtagMatcher.find() Pair(hashtagMatcher.group(1), hashtagMatcher.group(2)) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Hashtag Parser", "Couldn't link hashtag $word", e) Pair(null, null) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MediaCompressor.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MediaCompressor.kt index 0e9d5377c..176e5c14e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MediaCompressor.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/MediaCompressor.kt @@ -33,6 +33,7 @@ import com.abedelazizshe.lightcompressorlibrary.config.Configuration import com.vitorpamplona.amethyst.service.checkNotInMainThread import id.zelory.compressor.Compressor import id.zelory.compressor.constraint.default +import kotlinx.coroutines.CancellationException import java.io.File import java.io.FileOutputStream import java.util.UUID @@ -115,6 +116,7 @@ class MediaCompressor { } onReady(compressedImageFile.toUri(), contentType, compressedImageFile.length()) } catch (e: Exception) { + if (e is CancellationException) throw e e.printStackTrace() onReady(uri, contentType, null) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index ddd58eede..530c95c08 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -106,6 +106,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size75dp import com.vitorpamplona.amethyst.ui.theme.VolumeBottomIconSize import com.vitorpamplona.amethyst.ui.theme.imageModifier import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay @@ -356,6 +357,7 @@ fun GetMediaItem( null } } catch (e: Exception) { + if (e is CancellationException) throw e null }, ) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt index 9b89696d9..504136bbb 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt @@ -131,6 +131,7 @@ import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.encoders.toHexKey import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -650,6 +651,7 @@ fun aspectRatio(dim: String?): Float? { width / height } } catch (e: Exception) { + if (e is CancellationException) throw e null } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt index 61b3bd706..82d50cf33 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt @@ -80,6 +80,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size55dp import com.vitorpamplona.quartz.encoders.decodePublicKey import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.events.toImmutableListOfLists +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -166,6 +167,7 @@ fun DisplayAccount( decodePublicKey(acc.npub).toHexKey(), ) } catch (e: Exception) { + if (e is CancellationException) throw e null } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt index bcd0ce310..2d5a0fd78 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt @@ -103,6 +103,7 @@ import com.vitorpamplona.quartz.encoders.decodePublicKey import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.events.LnZapEvent import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CancellationException class UpdateZapAmountViewModel(val account: Account) : ViewModel() { var nextAmount by mutableStateOf(TextFieldValue("")) @@ -149,6 +150,7 @@ class UpdateZapAmountViewModel(val account: Account) : ViewModel() { try { decodePublicKey(walletConnectPubkey.text.trim()).toHexKey() } catch (e: Exception) { + if (e is CancellationException) throw e null } @@ -168,6 +170,7 @@ class UpdateZapAmountViewModel(val account: Account) : ViewModel() { try { unverifiedPrivKey?.let { decodePublicKey(it).toHexKey() } } catch (e: Exception) { + if (e is CancellationException) throw e null } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt index 15b5cec1c..94ab5037b 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt @@ -88,6 +88,7 @@ import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.quartz.events.LnZapEvent import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CancellationException class ZapOptionstViewModel : ViewModel() { private var account: Account? = null @@ -107,6 +108,7 @@ class ZapOptionstViewModel : ViewModel() { return try { customAmount.text.trim().toLongOrNull() } catch (e: Exception) { + if (e is CancellationException) throw e null } } @@ -446,6 +448,7 @@ fun payViaIntent( ContextCompat.startActivity(context, intent, null) } catch (e: Exception) { + if (e is CancellationException) throw e if (e.message != null) { onError(context.getString(R.string.no_wallet_found_with_error, e.message!!)) } else { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/QrCodeScanner.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/QrCodeScanner.kt index fec70d41c..abca33706 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/QrCodeScanner.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/QrCodeScanner.kt @@ -30,6 +30,7 @@ import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanOptions import com.vitorpamplona.amethyst.R import com.vitorpamplona.quartz.encoders.Nip19 +import kotlinx.coroutines.CancellationException @Composable fun NIP19QrCodeScanner(onScan: (String?) -> Unit) { @@ -51,6 +52,7 @@ fun NIP19QrCodeScanner(onScan: (String?) -> Unit) { onScan(null) } } catch (e: Throwable) { + if (e is CancellationException) throw e Log.e("NIP19 Scanner", "Error parsing $it", e) // QR can be anything, do not throw errors. onScan(null) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt index 5555a2932..29134685d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt @@ -52,6 +52,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.MainScreen import com.vitorpamplona.amethyst.ui.screen.loggedOff.LoginOrSignupScreen import com.vitorpamplona.quartz.signers.NostrSignerExternal +import kotlinx.coroutines.CancellationException @Composable fun AccountScreen( @@ -143,6 +144,7 @@ fun LoggedInPage( activity.prepareToLaunchSigner() launcher.launch(it) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Signer", "Error opening Signer app", e) accountViewModel.toast( R.string.error_opening_external_signer, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt index 3d2a3caca..484943d4a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt @@ -40,6 +40,7 @@ import com.vitorpamplona.quartz.encoders.toNpub import com.vitorpamplona.quartz.signers.ExternalSignerLauncher import com.vitorpamplona.quartz.signers.NostrSignerExternal import com.vitorpamplona.quartz.signers.NostrSignerInternal +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -204,6 +205,7 @@ class AccountStateViewModel() : ViewModel() { try { loginAndStartUI(key, useProxy, proxyPort, loginWithExternalSigner, packageName) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Login", "Could not sign in", e) onError() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 20561019b..36671804d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -87,6 +87,7 @@ import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableSet +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.channels.BufferOverflow @@ -1102,6 +1103,7 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View val myCover = context.imageLoader.execute(request).drawable onReady(myCover) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("VideoView", "Fail to load cover $thumbUri", e) onError(e.message) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ConnectOrbotDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ConnectOrbotDialog.kt index 64b2536c4..9fe64bdf7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ConnectOrbotDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ConnectOrbotDialog.kt @@ -54,6 +54,7 @@ import com.vitorpamplona.amethyst.ui.actions.CloseButton import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.RichTextDefaults import com.vitorpamplona.amethyst.ui.theme.placeholderText +import kotlinx.coroutines.CancellationException @Composable fun ConnectOrbotDialog( @@ -83,7 +84,8 @@ fun ConnectOrbotDialog( onPost = { try { Integer.parseInt(portNumber.value) - } catch (_: Exception) { + } catch (e: Exception) { + if (e is CancellationException) throw e onError(toastMessage) return@UseOrbotButton } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedOff/LoginScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedOff/LoginScreen.kt index 5fb180f8f..3fec84763 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedOff/LoginScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedOff/LoginScreen.kt @@ -101,6 +101,7 @@ import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonRow import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.quartz.signers.ExternalSignerLauncher import com.vitorpamplona.quartz.signers.SignerType +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.UUID @@ -173,6 +174,7 @@ fun LoginPage( activity.prepareToLaunchSigner() launcher.launch(it) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Signer", "Error opening Signer app", e) scope.launch(Dispatchers.Main) { Toast.makeText( diff --git a/app/src/play/java/com/vitorpamplona/amethyst/service/lang/LanguageTranslatorService.kt b/app/src/play/java/com/vitorpamplona/amethyst/service/lang/LanguageTranslatorService.kt index 4d9bcc839..3c020b888 100644 --- a/app/src/play/java/com/vitorpamplona/amethyst/service/lang/LanguageTranslatorService.kt +++ b/app/src/play/java/com/vitorpamplona/amethyst/service/lang/LanguageTranslatorService.kt @@ -33,6 +33,7 @@ import com.google.mlkit.nl.translate.TranslatorOptions import com.linkedin.urls.detection.UrlDetector import com.linkedin.urls.detection.UrlDetectorOptions import com.vitorpamplona.amethyst.service.checkNotInMainThread +import kotlinx.coroutines.CancellationException import java.util.concurrent.Executors import java.util.regex.Pattern @@ -161,7 +162,8 @@ object LanguageTranslatorService { val short = "A$counter" counter++ returningList.put(short, tag) - } catch (_: Exception) { + } catch (e: Exception) { + if (e is CancellationException) throw e } } return returningList @@ -177,7 +179,8 @@ object LanguageTranslatorService { val short = "A$counter" counter++ returningList.put(short, lnInvoice) - } catch (_: Exception) { + } catch (e: Exception) { + if (e is CancellationException) throw e } } return returningList diff --git a/app/src/play/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt b/app/src/play/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt index cd1aadf00..03721e0b0 100644 --- a/app/src/play/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt +++ b/app/src/play/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt @@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.service.notifications import android.util.Log import com.google.firebase.messaging.FirebaseMessaging import com.vitorpamplona.amethyst.AccountInfo +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.tasks.await @@ -38,6 +39,7 @@ object PushNotificationUtils { try { RegisterAccounts(accounts).go(FirebaseMessaging.getInstance().token.await()) } catch (e: Exception) { + if (e is CancellationException) throw e Log.e("Firebase token", "failed to get firebase token", e) } }