Add pills for permalink supported hosts (#8324)

This commit is contained in:
Yoan Pintas 2023-04-12 14:35:01 +02:00 committed by GitHub
parent fb837fed5a
commit 110b5cfcb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 44 additions and 18 deletions

2
changelog.d/8307.bugfix Normal file
View file

@ -0,0 +1,2 @@
The new permalink rendering is not applied on permalink created with the potential clientPermalinkBaseUrl

View file

@ -48,4 +48,8 @@ class TestPermalinkService : PermalinkService {
MARKDOWN -> "[%2\$s](https://matrix.to/#/%1\$s)" MARKDOWN -> "[%2\$s](https://matrix.to/#/%1\$s)"
} }
} }
override fun isPermalinkSupported(supportedHosts: Array<String>, url: String): Boolean {
return false
}
} }

View file

@ -62,7 +62,7 @@ object MatrixPatterns {
// regex pattern to find permalink with message id. // regex pattern to find permalink with message id.
// Android does not support in URL so extract it. // Android does not support in URL so extract it.
private const val PERMALINK_BASE_REGEX = "https://matrix\\.to/#/" 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 = "/" const val SEP_REGEX = "/"
private val PATTERN_CONTAIN_MATRIX_TO_PERMALINK = PERMALINK_BASE_REGEX.toRegex(RegexOption.IGNORE_CASE) private val PATTERN_CONTAIN_MATRIX_TO_PERMALINK = PERMALINK_BASE_REGEX.toRegex(RegexOption.IGNORE_CASE)

View file

@ -97,4 +97,15 @@ interface PermalinkService {
* @return the created template * @return the created template
*/ */
fun createMentionSpanTemplate(type: SpanTemplateType, forceMatrixTo: Boolean = false): String 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<String>, url: String): Boolean
} }

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.session.permalinks 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.events.model.Event
import org.matrix.android.sdk.api.session.permalinks.PermalinkService import org.matrix.android.sdk.api.session.permalinks.PermalinkService
import javax.inject.Inject import javax.inject.Inject
@ -47,4 +48,9 @@ internal class DefaultPermalinkService @Inject constructor(
override fun createMentionSpanTemplate(type: PermalinkService.SpanTemplateType, forceMatrixTo: Boolean): String { override fun createMentionSpanTemplate(type: PermalinkService.SpanTemplateType, forceMatrixTo: Boolean): String {
return permalinkFactory.createMentionSpanTemplate(type, forceMatrixTo) return permalinkFactory.createMentionSpanTemplate(type, forceMatrixTo)
} }
override fun isPermalinkSupported(supportedHosts: Array<String>, url: String): Boolean {
return url.startsWith(PermalinkService.MATRIX_TO_URL_BASE) ||
supportedHosts.any { url.toUri().host == it }
}
} }

View file

@ -29,7 +29,7 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.glide.GlideApp import im.vector.app.core.glide.GlideApp
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.html.PillImageSpan 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.getRoomSummary
import org.matrix.android.sdk.api.session.getUserOrDefault import org.matrix.android.sdk.api.session.getUserOrDefault
import org.matrix.android.sdk.api.session.permalinks.PermalinkData import org.matrix.android.sdk.api.session.permalinks.PermalinkData
@ -99,7 +99,9 @@ class EventTextRenderer @AssistedInject constructor(
private fun addPermalinksSpans(text: Spannable) { private fun addPermalinksSpans(text: Spannable) {
for (match in Patterns.WEB_URL.toRegex().findAll(text)) { for (match in Patterns.WEB_URL.toRegex().findAll(text)) {
val url = text.substring(match.range) 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)) { when (val permalinkData = PermalinkParser.parse(url)) {
is PermalinkData.UserLink -> permalinkData.toMatrixItem() is PermalinkData.UserLink -> permalinkData.toMatrixItem()
is PermalinkData.RoomLink -> permalinkData.toMatrixItem() is PermalinkData.RoomLink -> permalinkData.toMatrixItem()

View file

@ -22,10 +22,12 @@ import android.text.Spanned
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.glide.GlideApp import im.vector.app.core.glide.GlideApp
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import io.noties.markwon.core.spans.LinkSpan 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.getRoomSummary
import org.matrix.android.sdk.api.session.getUser import org.matrix.android.sdk.api.session.getUser
import org.matrix.android.sdk.api.session.permalinks.PermalinkData import org.matrix.android.sdk.api.session.permalinks.PermalinkData
@ -105,12 +107,18 @@ class PillsPostProcessor @AssistedInject constructor(
PillImageSpan(GlideApp.with(context), avatarRenderer, context, matrixItem) PillImageSpan(GlideApp.with(context), avatarRenderer, context, matrixItem)
private fun LinkSpan.createPillSpan(): PillImageSpan? { private fun LinkSpan.createPillSpan(): PillImageSpan? {
val matrixItem = when (val permalinkData = PermalinkParser.parse(url)) { val supportedHosts = context.resources.getStringArray(R.array.permalink_supported_hosts)
is PermalinkData.UserLink -> permalinkData.toMatrixItem() val isPermalinkSupported = sessionHolder.getSafeActiveSession()?.permalinkService()?.isPermalinkSupported(supportedHosts, url).orFalse()
is PermalinkData.RoomLink -> permalinkData.toMatrixItem() if (isPermalinkSupported) {
else -> null val matrixItem = when (val permalinkData = PermalinkParser.parse(url)) {
} ?: return null is PermalinkData.UserLink -> permalinkData.toMatrixItem()
return createPillImageSpan(matrixItem) is PermalinkData.RoomLink -> permalinkData.toMatrixItem()
else -> null
} ?: return null
return createPillImageSpan(matrixItem)
} else {
return null
}
} }
private fun PermalinkData.UserLink.toMatrixItem(): MatrixItem? = private fun PermalinkData.UserLink.toMatrixItem(): MatrixItem? =

View file

@ -18,7 +18,6 @@ package im.vector.app.features.permalink
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.core.net.toUri
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder 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.getRoomSummary
import org.matrix.android.sdk.api.session.permalinks.PermalinkData 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.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.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
@ -68,10 +66,11 @@ class PermalinkHandler @Inject constructor(
navigationInterceptor: NavigationInterceptor? = null, navigationInterceptor: NavigationInterceptor? = null,
buildTask: Boolean = false buildTask: Boolean = false
): Boolean { ): Boolean {
val supportedHosts = fragmentActivity.resources.getStringArray(R.array.permalink_supported_hosts)
return when { return when {
deepLink == null -> false deepLink == null -> false
deepLink.isIgnored() -> true deepLink.isIgnored() -> true
!isPermalinkSupported(fragmentActivity, deepLink.toString()) -> false !activeSessionHolder.getSafeActiveSession()?.permalinkService()?.isPermalinkSupported(supportedHosts, deepLink.toString()).orFalse() -> false
else -> { else -> {
tryOrNull { tryOrNull {
withContext(Dispatchers.Default) { 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? { private suspend fun PermalinkData.RoomLink.getRoomId(): String? {
val session = activeSessionHolder.getSafeActiveSession() val session = activeSessionHolder.getSafeActiveSession()
return if (isRoomAlias && session != null) { return if (isRoomAlias && session != null) {