diff --git a/app/src/main/kotlin/io/element/android/x/MainActivity.kt b/app/src/main/kotlin/io/element/android/x/MainActivity.kt index 7c0f91f1e9..be9f6134ba 100644 --- a/app/src/main/kotlin/io/element/android/x/MainActivity.kt +++ b/app/src/main/kotlin/io/element/android/x/MainActivity.kt @@ -26,6 +26,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalUriHandler import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.WindowCompat import com.bumble.appyx.core.integration.NodeHost @@ -36,6 +37,7 @@ import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.designsystem.utils.LocalSnackbarDispatcher import io.element.android.x.di.AppBindings +import io.element.android.x.intent.SafeUriHandler import timber.log.Timber private val loggerTag = LoggerTag("MainActivity") @@ -63,6 +65,7 @@ class MainActivity : NodeComponentActivity() { ElementTheme { CompositionLocalProvider( LocalSnackbarDispatcher provides appBindings.snackbarDispatcher(), + LocalUriHandler provides SafeUriHandler(this), ) { Box( modifier = Modifier diff --git a/app/src/main/kotlin/io/element/android/x/intent/SafeUriHandler.kt b/app/src/main/kotlin/io/element/android/x/intent/SafeUriHandler.kt new file mode 100644 index 0000000000..582cd3b7d5 --- /dev/null +++ b/app/src/main/kotlin/io/element/android/x/intent/SafeUriHandler.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.x.intent + +import android.app.Activity +import androidx.compose.ui.platform.UriHandler +import io.element.android.libraries.androidutils.system.openUrlInExternalApp + +class SafeUriHandler(private val activity: Activity) : UriHandler { + override fun openUri(uri: String) { + activity.openUrlInExternalApp(uri) + } +} diff --git a/changelog.d/517.bugfix b/changelog.d/517.bugfix new file mode 100644 index 0000000000..34840b4252 --- /dev/null +++ b/changelog.d/517.bugfix @@ -0,0 +1 @@ +Crash when clicking on a link with associated text. diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt index afe4e61fa8..cb0264cf5d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt @@ -535,7 +535,7 @@ private fun AnnotatedString.Builder.appendLink(link: Element) { val permalinkData = PermalinkParser.parse(uriString) when (permalinkData) { is PermalinkData.FallbackLink -> { - pushStringAnnotation(tag = "URL", annotation = link.ownText()) + pushStringAnnotation(tag = "URL", annotation = permalinkData.uri.toString()) withStyle( style = SpanStyle(color = LinkColor) ) { diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt index a6c3f93ecf..c48d52a1fc 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt @@ -242,6 +242,19 @@ fun startImportTextFromFileIntent( } } +@Suppress("SwallowedException") +fun Context.openUrlInExternalApp( + url: String, + errorMessage: String = getString(R.string.error_no_compatible_app_found), +) { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + try { + startActivity(intent) + } catch (activityNotFoundException: ActivityNotFoundException) { + toast(errorMessage) + } +} + // Not in KTX anymore fun Context.toast(resId: Int) { Toast.makeText(this, resId, Toast.LENGTH_SHORT).show()