From 1deed59d5be5d455a99d9b3aeb6a23e68a28840e Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 12 Feb 2024 16:03:37 -0500 Subject: [PATCH] Fixes: https://github.com/vitorpamplona/amethyst/issues/740 Displays error messages when the URI sent to Amethyst is invalid --- .../amethyst/ui/navigation/AppNavigation.kt | 62 ++++++++++++++----- .../ui/screen/loggedIn/AccountViewModel.kt | 14 ++++- .../amethyst/ui/screen/loggedIn/MainScreen.kt | 20 ++++-- app/src/main/res/values/strings.xml | 3 + .../vitorpamplona/quartz/encoders/Nip19.kt | 7 ++- 5 files changed, 83 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index 35a453b64..3d7a696fc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -39,6 +39,7 @@ import androidx.core.util.Consumer import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.ui.MainActivity import com.vitorpamplona.amethyst.ui.note.UserReactionsViewModel import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel @@ -359,31 +360,60 @@ fun AppNavigation( } val activity = LocalContext.current.getActivity() - var actionableNextPage by remember { - mutableStateOf(uriToRoute(activity.intent?.data?.toString()?.ifBlank { null })) + + var currentIntentNextPage by remember { + mutableStateOf(activity.intent?.data?.toString()?.ifBlank { null }) } - actionableNextPage?.let { - LaunchedEffect(it) { - navController.navigate(it) { - popUpTo(Route.Home.route) - launchSingleTop = true - } + + currentIntentNextPage?.let { intentNextPage -> + var actionableNextPage by remember { + mutableStateOf(uriToRoute(intentNextPage)) + } + + LaunchedEffect(intentNextPage) { + if (actionableNextPage != null) { + actionableNextPage?.let { + navController.navigate(it) { + popUpTo(Route.Home.route) + launchSingleTop = true + } + actionableNextPage = null + } + } else { + accountViewModel.toast( + R.string.invalid_nip19_uri, + R.string.invalid_nip19_uri_description, + intentNextPage, + ) + } + + currentIntentNextPage = null } - actionableNextPage = null } DisposableEffect(activity) { val consumer = Consumer { intent -> val uri = intent?.data?.toString() - val newPage = uriToRoute(uri) + if (!uri.isNullOrBlank()) { + val newPage = uriToRoute(uri) - newPage?.let { route -> - val currentRoute = getRouteWithArguments(navController) - if (!isSameRoute(currentRoute, route)) { - navController.navigate(route) { - popUpTo(Route.Home.route) - launchSingleTop = true + if (newPage != null) { + val currentRoute = getRouteWithArguments(navController) + if (!isSameRoute(currentRoute, newPage)) { + navController.navigate(newPage) { + popUpTo(Route.Home.route) + launchSingleTop = true + } + } + } else { + scope.launch { + delay(1000) + accountViewModel.toast( + R.string.invalid_nip19_uri, + R.string.invalid_nip19_uri_description, + uri, + ) } } } 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 e5b295140..adbed38b5 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 @@ -105,7 +105,11 @@ import kotlin.time.measureTimedValue @Immutable class StringToastMsg(val title: String, val msg: String) : ToastMsg() -@Immutable class ResourceToastMsg(val titleResId: Int, val resourceId: Int) : ToastMsg() +@Immutable class ResourceToastMsg( + val titleResId: Int, + val resourceId: Int, + val params: Array? = null, +) : ToastMsg() @Stable class AccountViewModel(val account: Account, val settings: SettingsState) : ViewModel(), Dao { @@ -141,6 +145,14 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View viewModelScope.launch { toasts.emit(ResourceToastMsg(titleResId, resourceId)) } } + fun toast( + titleResId: Int, + resourceId: Int, + vararg params: String, + ) { + viewModelScope.launch { toasts.emit(ResourceToastMsg(titleResId, resourceId, params)) } + } + fun isWriteable(): Boolean { return account.isWriteable() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt index 9dfea373e..cbe5114e6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt @@ -473,12 +473,22 @@ private fun DisplayErrorMessages(accountViewModel: AccountViewModel) { openDialogMsg.value?.let { obj -> when (obj) { is ResourceToastMsg -> - InformationDialog( - context.getString(obj.titleResId), - context.getString(obj.resourceId), - ) { - accountViewModel.clearToasts() + if (obj.params != null) { + InformationDialog( + context.getString(obj.titleResId), + context.getString(obj.resourceId, *obj.params), + ) { + accountViewModel.clearToasts() + } + } else { + InformationDialog( + context.getString(obj.titleResId), + context.getString(obj.resourceId), + ) { + accountViewModel.clearToasts() + } } + is StringToastMsg -> InformationDialog( obj.title, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c8c0655a4..6ad75e819 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -753,4 +753,7 @@ Add content warning Remove content warning Show npub as a QR code + + Invalid address + Amethyst received a URI to open but that uri was invalid: %1$s diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Nip19.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Nip19.kt index 7e1d2418e..03f638351 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Nip19.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/Nip19.kt @@ -97,7 +97,12 @@ object Nip19 { "naddr1" -> naddr(bytes) else -> null } - parsed?.copy(additionalChars = additionalChars ?: "") + + if (parsed?.hex?.isBlank() == true) { + null + } else { + parsed?.copy(additionalChars = additionalChars ?: "") + } } catch (e: Throwable) { Log.w("NIP19 Parser", "Issue trying to Decode NIP19 $key: ${e.message}", e) null