Update to new mentions API

This commit is contained in:
jonnyandrew 2023-08-18 10:52:03 +01:00 committed by Benoit Marty
parent 95070d3664
commit 6112082d07
3 changed files with 27 additions and 47 deletions

View File

@ -51,8 +51,7 @@ import im.vector.app.databinding.ViewRichTextMenuButtonBinding
import im.vector.app.features.home.room.detail.composer.images.UriContentListener import im.vector.app.features.home.room.detail.composer.images.UriContentListener
import im.vector.app.features.home.room.detail.composer.mentions.PillDisplayHandler import im.vector.app.features.home.room.detail.composer.mentions.PillDisplayHandler
import io.element.android.wysiwyg.EditorEditText import io.element.android.wysiwyg.EditorEditText
import io.element.android.wysiwyg.display.KeywordDisplayHandler import io.element.android.wysiwyg.display.MentionDisplayHandler
import io.element.android.wysiwyg.display.LinkDisplayHandler
import io.element.android.wysiwyg.display.TextDisplay import io.element.android.wysiwyg.display.TextDisplay
import io.element.android.wysiwyg.utils.RustErrorCollector import io.element.android.wysiwyg.utils.RustErrorCollector
import io.element.android.wysiwyg.view.models.InlineFormat import io.element.android.wysiwyg.view.models.InlineFormat
@ -238,15 +237,12 @@ internal class RichTextComposerLayout @JvmOverloads constructor(
views.composerEditTextOuterBorder.background = borderShapeDrawable views.composerEditTextOuterBorder.background = borderShapeDrawable
setupRichTextMenu() setupRichTextMenu()
views.richTextComposerEditText.linkDisplayHandler = LinkDisplayHandler { text, url -> views.richTextComposerEditText.mentionDisplayHandler = object : MentionDisplayHandler {
pillDisplayHandler?.resolveLinkDisplay(text, url) ?: TextDisplay.Plain override fun resolveMentionDisplay(text: String, url: String): TextDisplay =
} pillDisplayHandler?.resolveMentionDisplay(text, url) ?: TextDisplay.Plain
views.richTextComposerEditText.keywordDisplayHandler = object : KeywordDisplayHandler {
override val keywords: List<String>
get() = pillDisplayHandler?.keywords.orEmpty()
override fun resolveKeywordDisplay(text: String): TextDisplay = override fun resolveAtRoomMentionDisplay(): TextDisplay =
pillDisplayHandler?.resolveKeywordDisplay(text) ?: TextDisplay.Plain pillDisplayHandler?.resolveAtRoomMentionDisplay() ?: TextDisplay.Plain
} }
updateTextFieldBorder(isFullScreen) updateTextFieldBorder(isFullScreen)

View File

@ -17,8 +17,7 @@
package im.vector.app.features.home.room.detail.composer.mentions package im.vector.app.features.home.room.detail.composer.mentions
import android.text.style.ReplacementSpan import android.text.style.ReplacementSpan
import io.element.android.wysiwyg.display.KeywordDisplayHandler import io.element.android.wysiwyg.display.MentionDisplayHandler
import io.element.android.wysiwyg.display.LinkDisplayHandler
import io.element.android.wysiwyg.display.TextDisplay import io.element.android.wysiwyg.display.TextDisplay
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
@ -30,16 +29,15 @@ import org.matrix.android.sdk.api.util.toMatrixItem
import org.matrix.android.sdk.api.util.toRoomAliasMatrixItem import org.matrix.android.sdk.api.util.toRoomAliasMatrixItem
/** /**
* A rich text editor [LinkDisplayHandler] and [KeywordDisplayHandler] * A rich text editor [MentionDisplayHandler] that helps with replacing user and room links with pills.
* that helps with replacing user and room links with pills.
*/ */
internal class PillDisplayHandler( internal class PillDisplayHandler(
private val roomId: String, private val roomId: String,
private val getRoom: (roomId: String) -> RoomSummary?, private val getRoom: (roomId: String) -> RoomSummary?,
private val getMember: (userId: String) -> RoomMemberSummary?, private val getMember: (userId: String) -> RoomMemberSummary?,
private val replacementSpanFactory: (matrixItem: MatrixItem) -> ReplacementSpan, private val replacementSpanFactory: (matrixItem: MatrixItem) -> ReplacementSpan,
) : LinkDisplayHandler, KeywordDisplayHandler { ) : MentionDisplayHandler {
override fun resolveLinkDisplay(text: String, url: String): TextDisplay { override fun resolveMentionDisplay(text: String, url: String): TextDisplay {
val matrixItem = when (val permalink = PermalinkParser.parse(url)) { val matrixItem = when (val permalink = PermalinkParser.parse(url)) {
is PermalinkData.UserLink -> { is PermalinkData.UserLink -> {
val userId = permalink.userId val userId = permalink.userId
@ -65,16 +63,9 @@ internal class PillDisplayHandler(
return TextDisplay.Custom(customSpan = replacement) return TextDisplay.Custom(customSpan = replacement)
} }
override val keywords: List<String> override fun resolveAtRoomMentionDisplay(): TextDisplay {
get() = listOf(MatrixItem.NOTIFY_EVERYONE) val matrixItem = getRoom(roomId)?.toEveryoneInRoomMatrixItem()
?: MatrixItem.EveryoneInRoomItem(roomId)
override fun resolveKeywordDisplay(text: String): TextDisplay = return TextDisplay.Custom(replacementSpanFactory.invoke(matrixItem))
when (text) { }
MatrixItem.NOTIFY_EVERYONE -> {
val matrixItem = getRoom(roomId)?.toEveryoneInRoomMatrixItem()
?: MatrixItem.EveryoneInRoomItem(roomId)
TextDisplay.Custom(replacementSpanFactory.invoke(matrixItem))
}
else -> TextDisplay.Plain
}
} }

View File

@ -80,7 +80,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve non-matrix link, then it returns plain text`() { fun `when resolve non-matrix link, then it returns plain text`() {
val subject = createSubject() val subject = createSubject()
val result = subject.resolveLinkDisplay("text", NON_MATRIX_URL) val result = subject.resolveMentionDisplay("text", NON_MATRIX_URL)
assertEquals(TextDisplay.Plain, result) assertEquals(TextDisplay.Plain, result)
} }
@ -89,7 +89,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve unknown user link, then it returns generic custom pill`() { fun `when resolve unknown user link, then it returns generic custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("text", UNKNOWN_MATRIX_USER_URL) val matrixItem = subject.resolveMentionDisplay("text", UNKNOWN_MATRIX_USER_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.UserItem(UNKNOWN_MATRIX_USER_ID, UNKNOWN_MATRIX_USER_ID, null), matrixItem) assertEquals(MatrixItem.UserItem(UNKNOWN_MATRIX_USER_ID, UNKNOWN_MATRIX_USER_ID, null), matrixItem)
@ -99,7 +99,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve known user link, then it returns named custom pill`() { fun `when resolve known user link, then it returns named custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_USER_URL) val matrixItem = subject.resolveMentionDisplay("text", KNOWN_MATRIX_USER_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.UserItem(KNOWN_MATRIX_USER_ID, KNOWN_MATRIX_USER_NAME, KNOWN_MATRIX_USER_AVATAR), matrixItem) assertEquals(MatrixItem.UserItem(KNOWN_MATRIX_USER_ID, KNOWN_MATRIX_USER_NAME, KNOWN_MATRIX_USER_AVATAR), matrixItem)
@ -109,7 +109,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve unknown room link, then it returns generic custom pill`() { fun `when resolve unknown room link, then it returns generic custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("text", UNKNOWN_MATRIX_ROOM_URL) val matrixItem = subject.resolveMentionDisplay("text", UNKNOWN_MATRIX_ROOM_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.RoomItem(UNKNOWN_MATRIX_ROOM_ID, UNKNOWN_MATRIX_ROOM_ID, null), matrixItem) assertEquals(MatrixItem.RoomItem(UNKNOWN_MATRIX_ROOM_ID, UNKNOWN_MATRIX_ROOM_ID, null), matrixItem)
@ -119,7 +119,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve known room link, then it returns named custom pill`() { fun `when resolve known room link, then it returns named custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_ROOM_URL) val matrixItem = subject.resolveMentionDisplay("text", KNOWN_MATRIX_ROOM_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.RoomItem(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem) assertEquals(MatrixItem.RoomItem(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem)
@ -129,7 +129,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve @room link, then it returns room notification custom pill`() { fun `when resolve @room link, then it returns room notification custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("@room", KNOWN_MATRIX_ROOM_URL) val matrixItem = subject.resolveMentionDisplay("@room", KNOWN_MATRIX_ROOM_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.EveryoneInRoomItem(KNOWN_MATRIX_ROOM_ID, NOTIFY_EVERYONE, KNOWN_MATRIX_ROOM_AVATAR, KNOWN_MATRIX_ROOM_NAME), matrixItem) assertEquals(MatrixItem.EveryoneInRoomItem(KNOWN_MATRIX_ROOM_ID, NOTIFY_EVERYONE, KNOWN_MATRIX_ROOM_AVATAR, KNOWN_MATRIX_ROOM_NAME), matrixItem)
@ -139,7 +139,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve @room keyword, then it returns room notification custom pill`() { fun `when resolve @room keyword, then it returns room notification custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveKeywordDisplay("@room") val matrixItem = subject.resolveAtRoomMentionDisplay()
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.EveryoneInRoomItem(ROOM_ID, NOTIFY_EVERYONE, KNOWN_MATRIX_ROOM_AVATAR, KNOWN_MATRIX_ROOM_NAME), matrixItem) assertEquals(MatrixItem.EveryoneInRoomItem(ROOM_ID, NOTIFY_EVERYONE, KNOWN_MATRIX_ROOM_AVATAR, KNOWN_MATRIX_ROOM_NAME), matrixItem)
@ -150,24 +150,17 @@ internal class PillDisplayHandlerTest {
val subject = createSubject() val subject = createSubject()
every { mockGetRoom(ROOM_ID) } returns null every { mockGetRoom(ROOM_ID) } returns null
val matrixItem = subject.resolveKeywordDisplay("@room") val matrixItem = subject.resolveAtRoomMentionDisplay()
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.EveryoneInRoomItem(ROOM_ID, NOTIFY_EVERYONE, null, null), matrixItem) assertEquals(MatrixItem.EveryoneInRoomItem(ROOM_ID, NOTIFY_EVERYONE, null, null), matrixItem)
} }
@Test
fun `when get keywords, then it returns @room`() {
val subject = createSubject()
assertEquals(listOf("@room"), subject.keywords)
}
@Test @Test
fun `when resolve known user for custom domain link, then it returns named custom pill`() { fun `when resolve known user for custom domain link, then it returns named custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("text", CUSTOM_DOMAIN_MATRIX_USER_URL) val matrixItem = subject.resolveMentionDisplay("text", CUSTOM_DOMAIN_MATRIX_USER_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.UserItem(KNOWN_MATRIX_USER_ID, KNOWN_MATRIX_USER_NAME, KNOWN_MATRIX_USER_AVATAR), matrixItem) assertEquals(MatrixItem.UserItem(KNOWN_MATRIX_USER_ID, KNOWN_MATRIX_USER_NAME, KNOWN_MATRIX_USER_AVATAR), matrixItem)
@ -177,7 +170,7 @@ internal class PillDisplayHandlerTest {
fun `when resolve known room for custom domain link, then it returns named custom pill`() { fun `when resolve known room for custom domain link, then it returns named custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("text", CUSTOM_DOMAIN_MATRIX_ROOM_URL) val matrixItem = subject.resolveMentionDisplay("text", CUSTOM_DOMAIN_MATRIX_ROOM_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.RoomItem(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem) assertEquals(MatrixItem.RoomItem(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem)
@ -187,13 +180,13 @@ internal class PillDisplayHandlerTest {
fun `when resolve known room with alias link, then it returns named custom pill`() { fun `when resolve known room with alias link, then it returns named custom pill`() {
val subject = createSubject() val subject = createSubject()
val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_ROOM_ALIAS_URL) val matrixItem = subject.resolveMentionDisplay("text", KNOWN_MATRIX_ROOM_ALIAS_URL)
.getMatrixItem() .getMatrixItem()
assertEquals(MatrixItem.RoomAliasItem(KNOWN_MATRIX_ROOM_ALIAS, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem) assertEquals(MatrixItem.RoomAliasItem(KNOWN_MATRIX_ROOM_ALIAS, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem)
} }
private fun TextDisplay.getMatrixItem(): MatrixItem? { private fun TextDisplay.getMatrixItem(): MatrixItem {
val customSpan = this as? TextDisplay.Custom val customSpan = this as? TextDisplay.Custom
assertNotNull("The URL did not resolve to a custom link display method", customSpan) assertNotNull("The URL did not resolve to a custom link display method", customSpan)