diff --git a/changelog.d/8219.feature b/changelog.d/8219.feature
new file mode 100644
index 0000000000..648bc7c624
--- /dev/null
+++ b/changelog.d/8219.feature
@@ -0,0 +1 @@
+Permalinks to a room/space are pillified
diff --git a/changelog.d/8220.feature b/changelog.d/8220.feature
new file mode 100644
index 0000000000..e7862bb5fe
--- /dev/null
+++ b/changelog.d/8220.feature
@@ -0,0 +1 @@
+Permalinks to a matrix user are pillified
diff --git a/changelog.d/8221.feature b/changelog.d/8221.feature
new file mode 100644
index 0000000000..f542012bc1
--- /dev/null
+++ b/changelog.d/8221.feature
@@ -0,0 +1 @@
+Permalinks to messages are pillified
diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index 62f061f009..439479151c 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3539,4 +3539,11 @@
Access Token
Your access token gives full access to your account. Do not share it with anyone.
+
+
+ Message from %s
+ Message
+ Message in %s
+ Message in room
+ Room/Space
diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml
index 4c911c9e97..55cbddf78c 100644
--- a/library/ui-styles/src/main/res/values/dimens.xml
+++ b/library/ui-styles/src/main/res/values/dimens.xml
@@ -18,8 +18,8 @@
- 0.75
- 16dp
- 20dp
+ 20sp
+ 26sp
4dp
128dp
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 bae4b06a05..2de95850b0 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
@@ -65,27 +65,14 @@ object MatrixPatterns {
private const val APP_BASE_REGEX = "https://[A-Z0-9.-]+\\.[A-Z]{2,}/[A-Z]{3,}/#/room/"
const val SEP_REGEX = "/"
- private const val LINK_TO_ROOM_ID_REGEXP = PERMALINK_BASE_REGEX + MATRIX_ROOM_IDENTIFIER_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
- private val PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ID = LINK_TO_ROOM_ID_REGEXP.toRegex(RegexOption.IGNORE_CASE)
-
- private const val LINK_TO_ROOM_ALIAS_REGEXP = PERMALINK_BASE_REGEX + MATRIX_ROOM_ALIAS_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
- private val PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ALIAS = LINK_TO_ROOM_ALIAS_REGEXP.toRegex(RegexOption.IGNORE_CASE)
-
- private const val LINK_TO_APP_ROOM_ID_REGEXP = APP_BASE_REGEX + MATRIX_ROOM_IDENTIFIER_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
- private val PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ID = LINK_TO_APP_ROOM_ID_REGEXP.toRegex(RegexOption.IGNORE_CASE)
-
- private const val LINK_TO_APP_ROOM_ALIAS_REGEXP = APP_BASE_REGEX + MATRIX_ROOM_ALIAS_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
- private val PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ALIAS = LINK_TO_APP_ROOM_ALIAS_REGEXP.toRegex(RegexOption.IGNORE_CASE)
+ private val PATTERN_CONTAIN_MATRIX_TO_PERMALINK = PERMALINK_BASE_REGEX.toRegex(RegexOption.IGNORE_CASE)
+ private val PATTERN_CONTAIN_APP_PERMALINK = APP_BASE_REGEX.toRegex(RegexOption.IGNORE_CASE)
// ascii characters in the range \x20 (space) to \x7E (~)
val ORDER_STRING_REGEX = "[ -~]+".toRegex()
// list of patterns to find some matrix item.
val MATRIX_PATTERNS = listOf(
- PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ID,
- PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ALIAS,
- PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ID,
- PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ALIAS,
PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER,
PATTERN_CONTAIN_MATRIX_ALIAS,
PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER,
@@ -146,6 +133,12 @@ object MatrixPatterns {
return str != null && str matches PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
}
+ fun isPermalink(str: String?): Boolean {
+ return str != null &&
+ (PATTERN_CONTAIN_MATRIX_TO_PERMALINK.containsMatchIn(str) ||
+ PATTERN_CONTAIN_APP_PERMALINK.containsMatchIn(str))
+ }
+
/**
* Extract server name from a matrix id.
*
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt
index c428e40203..060b93ed0f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt
@@ -17,6 +17,7 @@
package org.matrix.android.sdk.api.session.permalinks
import android.text.Spannable
+import android.util.Patterns
import org.matrix.android.sdk.api.MatrixPatterns
/**
@@ -44,22 +45,26 @@ object MatrixLinkify {
}
val text = spannable.toString()
var hasMatch = false
- for (pattern in MatrixPatterns.MATRIX_PATTERNS) {
+ for (pattern in listOf(Patterns.WEB_URL.toRegex()).plus(MatrixPatterns.MATRIX_PATTERNS)) {
for (match in pattern.findAll(spannable)) {
hasMatch = true
val startPos = match.range.first
if (startPos == 0 || text[startPos - 1] != '/') {
val endPos = match.range.last + 1
var url = text.substring(match.range)
- if (MatrixPatterns.isUserId(url) ||
+ val isPermalink = MatrixPatterns.isPermalink(url)
+ if (isPermalink ||
+ MatrixPatterns.isUserId(url) ||
MatrixPatterns.isRoomAlias(url) ||
MatrixPatterns.isRoomId(url) ||
MatrixPatterns.isGroupId(url) ||
MatrixPatterns.isEventId(url)) {
- url = PermalinkService.MATRIX_TO_URL_BASE + url
+ if (!isPermalink) {
+ url = PermalinkService.MATRIX_TO_URL_BASE + url
+ }
+ val span = MatrixPermalinkSpan(url, callback)
+ spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
- val span = MatrixPermalinkSpan(url, callback)
- spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt
index 974f1cfcbe..0fd96798c8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt
@@ -76,7 +76,8 @@ sealed class MatrixItem(
data class RoomItem(
override val id: String,
override val displayName: String? = null,
- override val avatarUrl: String? = null
+ override val avatarUrl: String? = null,
+ val roomDisplayName: String? = null
) :
MatrixItem(id, displayName, avatarUrl) {
init {
@@ -102,7 +103,8 @@ sealed class MatrixItem(
data class RoomAliasItem(
override val id: String,
override val displayName: String? = null,
- override val avatarUrl: String? = null
+ override val avatarUrl: String? = null,
+ val roomDisplayName: String? = null
) :
MatrixItem(id, displayName, avatarUrl) {
init {
@@ -136,6 +138,8 @@ sealed class MatrixItem(
val displayName = when (this) {
// use the room display name for the notify everyone item
is EveryoneInRoomItem -> roomDisplayName
+ is RoomItem -> roomDisplayName ?: displayName
+ is RoomAliasItem -> roomDisplayName ?: displayName
else -> displayName
}
return (displayName?.takeIf { it.isNotBlank() } ?: id)
diff --git a/vector/src/main/java/im/vector/app/features/displayname/Extension.kt b/vector/src/main/java/im/vector/app/features/displayname/Extension.kt
index 71c1cbf27d..4069b41a0c 100644
--- a/vector/src/main/java/im/vector/app/features/displayname/Extension.kt
+++ b/vector/src/main/java/im/vector/app/features/displayname/Extension.kt
@@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.util.MatrixItem
fun MatrixItem.getBestName(): String {
// Note: this code is copied from [DisplayNameResolver] in the SDK
- return if (this is MatrixItem.RoomAliasItem) {
+ return if (this is MatrixItem.RoomAliasItem && displayName.isNullOrBlank()) {
// Best name is the id, and we keep the displayName of the room for the case we need the first letter
id
} else {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
index 034ae52a46..06444e9816 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
@@ -163,7 +163,6 @@ import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
import im.vector.app.features.home.room.threads.ThreadsManager
import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs
import im.vector.app.features.html.EventHtmlRenderer
-import im.vector.app.features.html.PillsPostProcessor
import im.vector.app.features.invite.VectorInviteView
import im.vector.app.features.location.LocationSharingMode
import im.vector.app.features.location.toLocationData
@@ -247,7 +246,6 @@ class TimelineFragment :
@Inject lateinit var matrixItemColorProvider: MatrixItemColorProvider
@Inject lateinit var imageContentRenderer: ImageContentRenderer
@Inject lateinit var roomDetailPendingActionStore: RoomDetailPendingActionStore
- @Inject lateinit var pillsPostProcessorFactory: PillsPostProcessor.Factory
@Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var audioMessagePlaybackTracker: AudioMessagePlaybackTracker
@Inject lateinit var shareIntentHandler: ShareIntentHandler
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 c46112f995..cc09ea0296 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
@@ -20,21 +20,30 @@ import android.content.Context
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.Spanned
+import android.util.Patterns
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 im.vector.app.features.html.PillImageSpan
+import org.matrix.android.sdk.api.MatrixPatterns
+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
+import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.util.MatrixItem
+import org.matrix.android.sdk.api.util.toMatrixItem
class EventTextRenderer @AssistedInject constructor(
@Assisted private val roomId: String?,
private val context: Context,
private val avatarRenderer: AvatarRenderer,
- private val activeSessionHolder: ActiveSessionHolder,
+ private val sessionHolder: ActiveSessionHolder,
) {
@AssistedFactory
@@ -46,7 +55,8 @@ class EventTextRenderer @AssistedInject constructor(
* @param text the text to be rendered
*/
fun render(text: CharSequence): CharSequence {
- return renderNotifyEveryone(text)
+ val formattedText = renderPermalinks(text)
+ return renderNotifyEveryone(formattedText)
}
private fun renderNotifyEveryone(text: CharSequence): CharSequence {
@@ -59,8 +69,18 @@ class EventTextRenderer @AssistedInject constructor(
}
}
+ private fun renderPermalinks(text: CharSequence): CharSequence {
+ return if (roomId != null) {
+ SpannableStringBuilder(text).apply {
+ addPermalinksSpans(this)
+ }
+ } else {
+ text
+ }
+ }
+
private fun addNotifyEveryoneSpans(text: Spannable, roomId: String) {
- val room: RoomSummary? = activeSessionHolder.getSafeActiveSession()?.roomService()?.getRoomSummary(roomId)
+ val room: RoomSummary? = sessionHolder.getSafeActiveSession()?.roomService()?.getRoomSummary(roomId)
val matrixItem = MatrixItem.EveryoneInRoomItem(
id = roomId,
avatarUrl = room?.avatarUrl,
@@ -76,6 +96,23 @@ 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)) {
+ when (val permalinkData = PermalinkParser.parse(url)) {
+ is PermalinkData.UserLink -> permalinkData.toMatrixItem()
+ is PermalinkData.RoomLink -> permalinkData.toMatrixItem()
+ else -> null
+ }
+ } else null
+
+ if (matrixItem != null) {
+ addPillSpan(text, createPillImageSpan(matrixItem), match.range.first, match.range.last + 1)
+ }
+ }
+ }
+
private fun createPillImageSpan(matrixItem: MatrixItem) =
PillImageSpan(GlideApp.with(context), avatarRenderer, context, matrixItem)
@@ -87,4 +124,46 @@ class EventTextRenderer @AssistedInject constructor(
) {
renderedText.setSpan(pillSpan, startSpan, endSpan, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
+
+ private fun PermalinkData.UserLink.toMatrixItem(): MatrixItem? =
+ roomId?.let { sessionHolder.getSafeActiveSession()?.roomService()?.getRoomMember(userId, it)?.toMatrixItem() }
+ ?: sessionHolder.getSafeActiveSession()?.getUserOrDefault(userId)?.toMatrixItem()
+
+ private fun PermalinkData.RoomLink.toMatrixItem(): MatrixItem =
+ if (eventId.isNullOrEmpty()) {
+ val room: RoomSummary? = sessionHolder.getSafeActiveSession()?.getRoomSummary(roomIdOrAlias)
+ when {
+ isRoomAlias -> MatrixItem.RoomAliasItem(roomIdOrAlias, room?.displayName, room?.avatarUrl)
+ room == null -> MatrixItem.RoomItem(roomIdOrAlias, context.getString(R.string.pill_message_unknown_room_or_space))
+ room.roomType == RoomType.SPACE -> MatrixItem.SpaceItem(roomIdOrAlias, room.displayName, room.avatarUrl)
+ else -> MatrixItem.RoomItem(roomIdOrAlias, room.displayName, room.avatarUrl)
+ }
+ } else {
+ if (roomIdOrAlias == roomId) {
+ val session = sessionHolder.getSafeActiveSession()
+ val event = session?.eventService()?.getEventFromCache(roomId, eventId!!)
+ val user = event?.senderId?.let { session.roomService().getRoomMember(it, roomId) }
+ val text = user?.let {
+ context.getString(R.string.pill_message_from_user, user.displayName)
+ } ?: context.getString(R.string.pill_message_from_unknown_user)
+ MatrixItem.RoomItem(roomIdOrAlias, text, user?.avatarUrl, user?.displayName)
+ } else {
+ val room: RoomSummary? = sessionHolder.getSafeActiveSession()?.getRoomSummary(roomIdOrAlias)
+ when {
+ isRoomAlias -> MatrixItem.RoomAliasItem(
+ roomIdOrAlias,
+ context.getString(R.string.pill_message_in_room, room?.displayName ?: roomIdOrAlias),
+ room?.avatarUrl,
+ room?.displayName
+ )
+ room != null -> MatrixItem.RoomItem(
+ roomIdOrAlias,
+ context.getString(R.string.pill_message_in_room, room.displayName),
+ room.avatarUrl,
+ room.displayName
+ )
+ else -> MatrixItem.RoomItem(roomIdOrAlias, context.getString(R.string.pill_message_in_unknown_room))
+ }
+ }
+ }
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/tools/EventRenderingTools.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/tools/EventRenderingTools.kt
index 3226b56c24..75babe9d64 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/tools/EventRenderingTools.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/tools/EventRenderingTools.kt
@@ -44,12 +44,11 @@ fun CharSequence.findPillsAndProcess(scope: CoroutineScope, processBlock: (PillI
}
fun CharSequence.linkify(callback: TimelineEventController.UrlClickCallback?): CharSequence {
- val text = this.toString()
// SpannableStringBuilder is used to avoid Epoxy throwing ImmutableModelException
val spannable = SpannableStringBuilder(this)
MatrixLinkify.addLinks(spannable, object : MatrixPermalinkSpan.Callback {
override fun onUrlClicked(url: String) {
- callback?.onUrlClicked(url, text)
+ callback?.onUrlClicked(url, this.toString())
}
})
VectorLinkify.addLinks(spannable, true)
diff --git a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt
index b285bef9ec..af1bcb866f 100644
--- a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt
+++ b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt
@@ -26,14 +26,17 @@ import android.graphics.drawable.Drawable
import android.text.style.ReplacementSpan
import android.widget.TextView
import androidx.annotation.UiThread
+import androidx.core.content.ContextCompat
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.google.android.material.chip.ChipDrawable
import im.vector.app.R
+import im.vector.app.core.extensions.isMatrixId
import im.vector.app.core.glide.GlideRequests
import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.themes.ThemeUtils
+import org.matrix.android.sdk.api.extensions.orTrue
import org.matrix.android.sdk.api.session.room.send.MatrixItemSpan
import org.matrix.android.sdk.api.util.MatrixItem
import java.lang.ref.WeakReference
@@ -111,10 +114,28 @@ class PillImageSpan(
private fun createChipDrawable(): ChipDrawable {
val textPadding = context.resources.getDimension(R.dimen.pill_text_padding)
- val icon = try {
- avatarRenderer.getCachedDrawable(glideRequests, matrixItem)
- } catch (exception: Exception) {
- avatarRenderer.getPlaceholderDrawable(matrixItem)
+ val icon = when {
+ matrixItem is MatrixItem.RoomAliasItem && matrixItem.avatarUrl.isNullOrEmpty() &&
+ matrixItem.displayName == context.getString(R.string.pill_message_in_room, matrixItem.id) -> {
+ ContextCompat.getDrawable(context, R.drawable.ic_permalink_round)
+ }
+ matrixItem is MatrixItem.RoomItem && matrixItem.avatarUrl.isNullOrEmpty() && (
+ matrixItem.displayName == context.getString(R.string.pill_message_in_unknown_room) ||
+ matrixItem.displayName == context.getString(R.string.pill_message_unknown_room_or_space) ||
+ matrixItem.displayName == context.getString(R.string.pill_message_from_unknown_user)
+ ) -> {
+ ContextCompat.getDrawable(context, R.drawable.ic_permalink_round)
+ }
+ matrixItem is MatrixItem.UserItem && matrixItem.avatarUrl.isNullOrEmpty() && matrixItem.displayName?.isMatrixId().orTrue() -> {
+ ContextCompat.getDrawable(context, R.drawable.ic_user_round)
+ }
+ else -> {
+ try {
+ avatarRenderer.getCachedDrawable(glideRequests, matrixItem)
+ } catch (exception: Exception) {
+ avatarRenderer.getPlaceholderDrawable(matrixItem)
+ }
+ }
}
return ChipDrawable.createFromResource(context, R.xml.pill_view).apply {
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 f6e10a6df9..6b23d68e80 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
@@ -27,7 +27,7 @@ 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.session.getRoomSummary
-import org.matrix.android.sdk.api.session.getUserOrDefault
+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.PermalinkParser
import org.matrix.android.sdk.api.session.room.model.RoomSummary
@@ -56,15 +56,15 @@ class PillsPostProcessor @AssistedInject constructor(
* ========================================================================================== */
override fun afterRender(renderedText: Spannable) {
- addPillSpans(renderedText, roomId)
+ addPillSpans(renderedText)
}
/* ==========================================================================================
* Helper methods
* ========================================================================================== */
- private fun addPillSpans(renderedText: Spannable, roomId: String?) {
- addLinkSpans(renderedText, roomId)
+ private fun addPillSpans(renderedText: Spannable) {
+ addLinkSpans(renderedText)
}
private fun addPillSpan(
@@ -76,11 +76,11 @@ class PillsPostProcessor @AssistedInject constructor(
renderedText.setSpan(pillSpan, startSpan, endSpan, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
- private fun addLinkSpans(renderedText: Spannable, roomId: String?) {
+ private fun addLinkSpans(renderedText: Spannable) {
// We let markdown handle links and then we add PillImageSpan if needed.
val linkSpans = renderedText.getSpans(0, renderedText.length, LinkSpan::class.java)
linkSpans.forEach { linkSpan ->
- val pillSpan = linkSpan.createPillSpan(roomId) ?: return@forEach
+ val pillSpan = linkSpan.createPillSpan() ?: return@forEach
val startSpan = renderedText.getSpanStart(linkSpan)
val endSpan = renderedText.getSpanEnd(linkSpan)
// GlideImagesPlugin causes duplicated pills if we have a nested spans in the pill span,
@@ -104,21 +104,18 @@ class PillsPostProcessor @AssistedInject constructor(
private fun createPillImageSpan(matrixItem: MatrixItem) =
PillImageSpan(GlideApp.with(context), avatarRenderer, context, matrixItem)
- private fun LinkSpan.createPillSpan(roomId: String?): PillImageSpan? {
+ private fun LinkSpan.createPillSpan(): PillImageSpan? {
val matrixItem = when (val permalinkData = PermalinkParser.parse(url)) {
- is PermalinkData.UserLink -> permalinkData.toMatrixItem(roomId)
+ is PermalinkData.UserLink -> permalinkData.toMatrixItem()
is PermalinkData.RoomLink -> permalinkData.toMatrixItem()
else -> null
} ?: return null
return createPillImageSpan(matrixItem)
}
- private fun PermalinkData.UserLink.toMatrixItem(roomId: String?): MatrixItem? =
- if (roomId == null) {
- sessionHolder.getSafeActiveSession()?.getUserOrDefault(userId)?.toMatrixItem()
- } else {
- sessionHolder.getSafeActiveSession()?.roomService()?.getRoomMember(userId, roomId)?.toMatrixItem()
- }
+ private fun PermalinkData.UserLink.toMatrixItem(): MatrixItem? =
+ roomId?.let { sessionHolder.getSafeActiveSession()?.roomService()?.getRoomMember(userId, it)?.toMatrixItem() }
+ ?: sessionHolder.getSafeActiveSession()?.getUser(userId)?.toMatrixItem()
private fun PermalinkData.RoomLink.toMatrixItem(): MatrixItem? =
if (eventId == null) {
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 18b9f03444..304bfa6d43 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
@@ -110,13 +110,8 @@ class PermalinkHandler @Inject constructor(
val rootThreadEventId = permalinkData.eventId?.let { eventId ->
val room = roomId?.let { session?.getRoom(it) }
-
- val rootThreadEventId = room?.getTimelineEvent(eventId)?.root?.getRootThreadEventId()
- rootThreadEventId ?: if (room?.getTimelineEvent(eventId)?.isRootThread() == true) {
- eventId
- } else {
- null
- }
+ val event = room?.getTimelineEvent(eventId)
+ event?.root?.getRootThreadEventId() ?: eventId.takeIf { event?.isRootThread() == true }
}
openRoom(
navigationInterceptor,
diff --git a/vector/src/main/res/drawable/ic_permalink_round.xml b/vector/src/main/res/drawable/ic_permalink_round.xml
new file mode 100644
index 0000000000..b63209017f
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_permalink_round.xml
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_user_round.xml b/vector/src/main/res/drawable/ic_user_round.xml
index 721f3aa81c..5e0f2b417f 100644
--- a/vector/src/main/res/drawable/ic_user_round.xml
+++ b/vector/src/main/res/drawable/ic_user_round.xml
@@ -4,15 +4,15 @@
android:viewportWidth="24"
android:viewportHeight="24">
+ android:pathData="M18.709,21.951L19.564,23.216L18.709,21.951ZM4.8,21.601L3.883,22.822H3.883L4.8,21.601ZM18.676,18.899L19.738,19.996L20.478,19.28L20.092,18.325L18.676,18.899ZM5.324,18.899L3.908,18.325L3.522,19.28L4.262,19.996L5.324,18.899ZM12,25.527C14.8,25.527 17.404,24.675 19.564,23.216L17.854,20.685C16.184,21.814 14.171,22.473 12,22.473V25.527ZM3.883,22.822C6.144,24.52 8.956,25.527 12,25.527V22.473C9.641,22.473 7.467,21.694 5.717,20.38L3.883,22.822ZM-1.527,12C-1.527,16.427 0.601,20.357 3.883,22.822L5.717,20.38C3.17,18.466 1.527,15.425 1.527,12H-1.527ZM12,-1.527C4.529,-1.527 -1.527,4.529 -1.527,12H1.527C1.527,6.216 6.216,1.527 12,1.527V-1.527ZM25.527,12C25.527,4.529 19.471,-1.527 12,-1.527V1.527C17.784,1.527 22.473,6.216 22.473,12H25.527ZM19.564,23.216C23.159,20.788 25.527,16.671 25.527,12H22.473C22.473,15.613 20.644,18.8 17.854,20.685L19.564,23.216ZM14.073,8.7C14.073,10.128 13.032,11.073 12,11.073V14.127C14.944,14.127 17.127,11.58 17.127,8.7H14.073ZM12,6.327C13.032,6.327 14.073,7.272 14.073,8.7H17.127C17.127,5.82 14.944,3.273 12,3.273V6.327ZM9.927,8.7C9.927,7.272 10.968,6.327 12,6.327V3.273C9.055,3.273 6.873,5.82 6.873,8.7H9.927ZM12,11.073C10.968,11.073 9.927,10.128 9.927,8.7H6.873C6.873,11.58 9.055,14.127 12,14.127V11.073ZM17.614,17.801C16.16,19.209 14.182,20.073 12,20.073V23.127C15.007,23.127 17.737,21.933 19.738,19.996L17.614,17.801ZM12,15.927C14.378,15.927 16.417,17.391 17.26,19.472L20.092,18.325C18.798,15.131 15.664,12.873 12,12.873V15.927ZM6.74,19.472C7.582,17.391 9.622,15.927 12,15.927V12.873C8.336,12.873 5.202,15.131 3.908,18.325L6.74,19.472ZM12,20.073C9.818,20.073 7.84,19.209 6.386,17.801L4.262,19.996C6.263,21.933 8.993,23.127 12,23.127V20.073Z"
+ android:fillColor="?vctr_content_secondary"/>