From 110b5cfcb4ff48931973a9e11d05c9eb54640c8a Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Wed, 12 Apr 2023 14:35:01 +0200 Subject: [PATCH] Add pills for permalink supported hosts (#8324) --- changelog.d/8307.bugfix | 2 ++ .../session/room/send/TestPermalinkService.kt | 4 ++++ .../matrix/android/sdk/api/MatrixPatterns.kt | 2 +- .../session/permalinks/PermalinkService.kt | 11 ++++++++++ .../permalinks/DefaultPermalinkService.kt | 6 ++++++ .../timeline/render/EventTextRenderer.kt | 6 ++++-- .../app/features/html/PillsPostProcessor.kt | 20 +++++++++++++------ .../features/permalink/PermalinkHandler.kt | 11 ++-------- 8 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 changelog.d/8307.bugfix diff --git a/changelog.d/8307.bugfix b/changelog.d/8307.bugfix new file mode 100644 index 0000000000..b548287ee7 --- /dev/null +++ b/changelog.d/8307.bugfix @@ -0,0 +1,2 @@ + The new permalink rendering is not applied on permalink created with the potential clientPermalinkBaseUrl + \ No newline at end of file diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt index 3a267ec694..a0986cc55a 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/TestPermalinkService.kt @@ -48,4 +48,8 @@ class TestPermalinkService : PermalinkService { MARKDOWN -> "[%2\$s](https://matrix.to/#/%1\$s)" } } + + override fun isPermalinkSupported(supportedHosts: Array, url: String): Boolean { + return false + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt index 2de95850b0..0f7e9ca6a8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt @@ -62,7 +62,7 @@ object MatrixPatterns { // regex pattern to find permalink with message id. // Android does not support in URL so extract it. private const val PERMALINK_BASE_REGEX = "https://matrix\\.to/#/" - private const val APP_BASE_REGEX = "https://[A-Z0-9.-]+\\.[A-Z]{2,}/[A-Z]{3,}/#/room/" + private const val APP_BASE_REGEX = "https://[A-Z0-9.-]+\\.[A-Z]{2,}/#/(room|user)/" const val SEP_REGEX = "/" private val PATTERN_CONTAIN_MATRIX_TO_PERMALINK = PERMALINK_BASE_REGEX.toRegex(RegexOption.IGNORE_CASE) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt index 1788bf7bd2..0733ac0bc1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt @@ -97,4 +97,15 @@ interface PermalinkService { * @return the created template */ fun createMentionSpanTemplate(type: SpanTemplateType, forceMatrixTo: Boolean = false): String + + /** + * Check if the url is a permalink. It must be a matrix.to link + * or a link with host provided by the string-array `permalink_supported_hosts` in the config file + * + * @param supportedHosts the list of hosts supported for permalinks + * @param url the link to check, Ex: "https://matrix.to/#/@benoit:matrix.org" + * + * @return true when url is a permalink + */ + fun isPermalinkSupported(supportedHosts: Array, url: String): Boolean } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/DefaultPermalinkService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/DefaultPermalinkService.kt index 196a8c122d..270676ff6d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/DefaultPermalinkService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/DefaultPermalinkService.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.internal.session.permalinks +import androidx.core.net.toUri import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.permalinks.PermalinkService import javax.inject.Inject @@ -47,4 +48,9 @@ internal class DefaultPermalinkService @Inject constructor( override fun createMentionSpanTemplate(type: PermalinkService.SpanTemplateType, forceMatrixTo: Boolean): String { return permalinkFactory.createMentionSpanTemplate(type, forceMatrixTo) } + + override fun isPermalinkSupported(supportedHosts: Array, url: String): Boolean { + return url.startsWith(PermalinkService.MATRIX_TO_URL_BASE) || + supportedHosts.any { url.toUri().host == it } + } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt index cc09ea0296..79e8690c91 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt @@ -29,7 +29,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.html.PillImageSpan -import org.matrix.android.sdk.api.MatrixPatterns +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.getUserOrDefault import org.matrix.android.sdk.api.session.permalinks.PermalinkData @@ -99,7 +99,9 @@ class EventTextRenderer @AssistedInject constructor( private fun addPermalinksSpans(text: Spannable) { for (match in Patterns.WEB_URL.toRegex().findAll(text)) { val url = text.substring(match.range) - val matrixItem = if (MatrixPatterns.isPermalink(url)) { + val supportedHosts = context.resources.getStringArray(R.array.permalink_supported_hosts) + val isPermalinkSupported = sessionHolder.getSafeActiveSession()?.permalinkService()?.isPermalinkSupported(supportedHosts, url).orFalse() + val matrixItem = if (isPermalinkSupported) { when (val permalinkData = PermalinkParser.parse(url)) { is PermalinkData.UserLink -> permalinkData.toMatrixItem() is PermalinkData.RoomLink -> permalinkData.toMatrixItem() diff --git a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt index 6b23d68e80..92d5b16998 100644 --- a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt +++ b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt @@ -22,10 +22,12 @@ import android.text.Spanned import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.AvatarRenderer import io.noties.markwon.core.spans.LinkSpan +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.getUser import org.matrix.android.sdk.api.session.permalinks.PermalinkData @@ -105,12 +107,18 @@ class PillsPostProcessor @AssistedInject constructor( PillImageSpan(GlideApp.with(context), avatarRenderer, context, matrixItem) private fun LinkSpan.createPillSpan(): PillImageSpan? { - val matrixItem = when (val permalinkData = PermalinkParser.parse(url)) { - is PermalinkData.UserLink -> permalinkData.toMatrixItem() - is PermalinkData.RoomLink -> permalinkData.toMatrixItem() - else -> null - } ?: return null - return createPillImageSpan(matrixItem) + val supportedHosts = context.resources.getStringArray(R.array.permalink_supported_hosts) + val isPermalinkSupported = sessionHolder.getSafeActiveSession()?.permalinkService()?.isPermalinkSupported(supportedHosts, url).orFalse() + if (isPermalinkSupported) { + val matrixItem = when (val permalinkData = PermalinkParser.parse(url)) { + is PermalinkData.UserLink -> permalinkData.toMatrixItem() + is PermalinkData.RoomLink -> permalinkData.toMatrixItem() + else -> null + } ?: return null + return createPillImageSpan(matrixItem) + } else { + return null + } } private fun PermalinkData.UserLink.toMatrixItem(): MatrixItem? = diff --git a/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt b/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt index 304bfa6d43..f15375c09f 100644 --- a/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt +++ b/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt @@ -18,7 +18,6 @@ package im.vector.app.features.permalink import android.content.Context import android.net.Uri -import androidx.core.net.toUri import androidx.fragment.app.FragmentActivity import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder @@ -38,7 +37,6 @@ import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.permalinks.PermalinkData import org.matrix.android.sdk.api.session.permalinks.PermalinkParser -import org.matrix.android.sdk.api.session.permalinks.PermalinkService import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -68,10 +66,11 @@ class PermalinkHandler @Inject constructor( navigationInterceptor: NavigationInterceptor? = null, buildTask: Boolean = false ): Boolean { + val supportedHosts = fragmentActivity.resources.getStringArray(R.array.permalink_supported_hosts) return when { deepLink == null -> false deepLink.isIgnored() -> true - !isPermalinkSupported(fragmentActivity, deepLink.toString()) -> false + !activeSessionHolder.getSafeActiveSession()?.permalinkService()?.isPermalinkSupported(supportedHosts, deepLink.toString()).orFalse() -> false else -> { tryOrNull { withContext(Dispatchers.Default) { @@ -167,12 +166,6 @@ class PermalinkHandler @Inject constructor( } } - private fun isPermalinkSupported(context: Context, url: String): Boolean { - return url.startsWith(PermalinkService.MATRIX_TO_URL_BASE) || - context.resources.getStringArray(R.array.permalink_supported_hosts) - .any { url.toUri().host == it } - } - private suspend fun PermalinkData.RoomLink.getRoomId(): String? { val session = activeSessionHolder.getSafeActiveSession() return if (isRoomAlias && session != null) {