diff --git a/dependencies.gradle b/dependencies.gradle index 355f5de6619..cc1abb3cf67 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -20,7 +20,7 @@ def lifecycle = "2.5.1" def flowBinding = "1.2.0" def flipper = "0.190.0" def epoxy = "5.0.0" -def mavericks = "3.0.2" +def mavericks = "3.0.7" def glide = "4.15.1" def bigImageViewer = "1.8.1" def jjwt = "0.11.5" @@ -101,7 +101,7 @@ ext.libs = [ ], element : [ 'opusencoder' : "io.element.android:opusencoder:1.1.0", - 'wysiwyg' : "io.element.android:wysiwyg:2.2.2" + 'wysiwyg' : "io.element.android:wysiwyg:2.14.1" ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", diff --git a/gradle.properties b/gradle.properties index ea70ad5e518..682c94a9164 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,4 +42,4 @@ signing.element.nightly.keyPassword=Secret # Customise the Lint version to use a more recent version than the one bundled with AGP # https://googlesamples.github.io/android-custom-lint-rules/usage/newer-lint.md.html -android.experimental.lint.version=8.0.0-alpha10 +android.experimental.lint.version=8.3.0-alpha12 diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index 48163a43bf0..1b999b65c8b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -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.mentions.PillDisplayHandler import io.element.android.wysiwyg.EditorEditText -import io.element.android.wysiwyg.display.KeywordDisplayHandler -import io.element.android.wysiwyg.display.LinkDisplayHandler +import io.element.android.wysiwyg.display.MentionDisplayHandler import io.element.android.wysiwyg.display.TextDisplay import io.element.android.wysiwyg.utils.RustErrorCollector import io.element.android.wysiwyg.view.models.InlineFormat @@ -238,15 +237,12 @@ internal class RichTextComposerLayout @JvmOverloads constructor( views.composerEditTextOuterBorder.background = borderShapeDrawable setupRichTextMenu() - views.richTextComposerEditText.linkDisplayHandler = LinkDisplayHandler { text, url -> - pillDisplayHandler?.resolveLinkDisplay(text, url) ?: TextDisplay.Plain - } - views.richTextComposerEditText.keywordDisplayHandler = object : KeywordDisplayHandler { - override val keywords: List - get() = pillDisplayHandler?.keywords.orEmpty() + views.richTextComposerEditText.mentionDisplayHandler = object : MentionDisplayHandler { + override fun resolveMentionDisplay(text: String, url: String): TextDisplay = + pillDisplayHandler?.resolveMentionDisplay(text, url) ?: TextDisplay.Plain - override fun resolveKeywordDisplay(text: String): TextDisplay = - pillDisplayHandler?.resolveKeywordDisplay(text) ?: TextDisplay.Plain + override fun resolveAtRoomMentionDisplay(): TextDisplay = + pillDisplayHandler?.resolveAtRoomMentionDisplay() ?: TextDisplay.Plain } updateTextFieldBorder(isFullScreen) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt index c2b71ea15ba..e5e6aa347da 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt @@ -17,8 +17,7 @@ package im.vector.app.features.home.room.detail.composer.mentions import android.text.style.ReplacementSpan -import io.element.android.wysiwyg.display.KeywordDisplayHandler -import io.element.android.wysiwyg.display.LinkDisplayHandler +import io.element.android.wysiwyg.display.MentionDisplayHandler import io.element.android.wysiwyg.display.TextDisplay import org.matrix.android.sdk.api.session.permalinks.PermalinkData 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 /** - * A rich text editor [LinkDisplayHandler] and [KeywordDisplayHandler] - * that helps with replacing user and room links with pills. + * A rich text editor [MentionDisplayHandler] that helps with replacing user and room links with pills. */ internal class PillDisplayHandler( private val roomId: String, private val getRoom: (roomId: String) -> RoomSummary?, private val getMember: (userId: String) -> RoomMemberSummary?, private val replacementSpanFactory: (matrixItem: MatrixItem) -> ReplacementSpan, -) : LinkDisplayHandler, KeywordDisplayHandler { - override fun resolveLinkDisplay(text: String, url: String): TextDisplay { +) : MentionDisplayHandler { + override fun resolveMentionDisplay(text: String, url: String): TextDisplay { val matrixItem = when (val permalink = PermalinkParser.parse(url)) { is PermalinkData.UserLink -> { val userId = permalink.userId @@ -65,16 +63,9 @@ internal class PillDisplayHandler( return TextDisplay.Custom(customSpan = replacement) } - override val keywords: List - get() = listOf(MatrixItem.NOTIFY_EVERYONE) - - override fun resolveKeywordDisplay(text: String): TextDisplay = - when (text) { - MatrixItem.NOTIFY_EVERYONE -> { - val matrixItem = getRoom(roomId)?.toEveryoneInRoomMatrixItem() - ?: MatrixItem.EveryoneInRoomItem(roomId) - TextDisplay.Custom(replacementSpanFactory.invoke(matrixItem)) - } - else -> TextDisplay.Plain - } + override fun resolveAtRoomMentionDisplay(): TextDisplay { + val matrixItem = getRoom(roomId)?.toEveryoneInRoomMatrixItem() + ?: MatrixItem.EveryoneInRoomItem(roomId) + return TextDisplay.Custom(replacementSpanFactory.invoke(matrixItem)) + } } diff --git a/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt b/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt index bf2075d3a8e..bcfd651ce25 100644 --- a/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt +++ b/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt @@ -41,7 +41,7 @@ import im.vector.app.features.pin.lockscreen.ui.fallbackprompt.FallbackBiometric import im.vector.app.features.pin.lockscreen.utils.DevicePromptCheck import im.vector.app.features.pin.lockscreen.utils.hasFlag import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.BufferOverflow @@ -155,11 +155,11 @@ class BiometricHelper @AssistedInject constructor( return authenticate(activity) } - @OptIn(ExperimentalCoroutinesApi::class) + @OptIn(DelicateCoroutinesApi::class) private fun authenticateInternal( - activity: FragmentActivity, - checkSystemKeyExists: Boolean, - cryptoObject: BiometricPrompt.CryptoObject, + activity: FragmentActivity, + checkSystemKeyExists: Boolean, + cryptoObject: BiometricPrompt.CryptoObject, ): Flow { if (checkSystemKeyExists && !isSystemAuthEnabledAndValid) return flowOf(false) @@ -195,9 +195,9 @@ class BiometricHelper @AssistedInject constructor( @VisibleForTesting(otherwise = PRIVATE) internal fun authenticateWithPromptInternal( - activity: FragmentActivity, - cryptoObject: BiometricPrompt.CryptoObject, - channel: Channel, + activity: FragmentActivity, + cryptoObject: BiometricPrompt.CryptoObject, + channel: Channel, ): BiometricPrompt { val executor = ContextCompat.getMainExecutor(context) val callback = createSuspendingAuthCallback(channel, executor.asCoroutineDispatcher()) @@ -314,9 +314,9 @@ class BiometricHelper @AssistedInject constructor( fallbackFragment.onDismiss = { cancelPrompt() } fallbackFragment.authenticationFlow = authenticationFLow - activity.supportFragmentManager.beginTransaction() + val transaction = activity.supportFragmentManager.beginTransaction() .runOnCommit { scope.launch { showPrompt() } } - .apply { fallbackFragment.show(this, FALLBACK_BIOMETRIC_FRAGMENT_TAG) } + fallbackFragment.show(transaction, FALLBACK_BIOMETRIC_FRAGMENT_TAG) } else { scope.launch { showPrompt() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt index f74d88790c1..42d9f015953 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt @@ -97,6 +97,7 @@ class SessionsListHeaderView @JvmOverloads constructor( } } + @Suppress("RestrictedApi") private fun setMenu(typedArray: TypedArray) { val menuResId = typedArray.getResourceId(R.styleable.SessionsListHeaderView_sessionsListHeaderMenu, -1) if (menuResId == -1) { diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt index 57c7aee4208..be5a6a93ee7 100644 --- a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt +++ b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt @@ -80,7 +80,7 @@ internal class PillDisplayHandlerTest { fun `when resolve non-matrix link, then it returns plain text`() { val subject = createSubject() - val result = subject.resolveLinkDisplay("text", NON_MATRIX_URL) + val result = subject.resolveMentionDisplay("text", NON_MATRIX_URL) assertEquals(TextDisplay.Plain, result) } @@ -89,7 +89,7 @@ internal class PillDisplayHandlerTest { fun `when resolve unknown user link, then it returns generic custom pill`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("text", UNKNOWN_MATRIX_USER_URL) + val matrixItem = subject.resolveMentionDisplay("text", UNKNOWN_MATRIX_USER_URL) .getMatrixItem() 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`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_USER_URL) + val matrixItem = subject.resolveMentionDisplay("text", KNOWN_MATRIX_USER_URL) .getMatrixItem() 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`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("text", UNKNOWN_MATRIX_ROOM_URL) + val matrixItem = subject.resolveMentionDisplay("text", UNKNOWN_MATRIX_ROOM_URL) .getMatrixItem() 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`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_ROOM_URL) + val matrixItem = subject.resolveMentionDisplay("text", KNOWN_MATRIX_ROOM_URL) .getMatrixItem() 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`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("@room", KNOWN_MATRIX_ROOM_URL) + val matrixItem = subject.resolveMentionDisplay("@room", KNOWN_MATRIX_ROOM_URL) .getMatrixItem() 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`() { val subject = createSubject() - val matrixItem = subject.resolveKeywordDisplay("@room") + val matrixItem = subject.resolveAtRoomMentionDisplay() .getMatrixItem() 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() every { mockGetRoom(ROOM_ID) } returns null - val matrixItem = subject.resolveKeywordDisplay("@room") + val matrixItem = subject.resolveAtRoomMentionDisplay() .getMatrixItem() 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 fun `when resolve known user for custom domain link, then it returns named custom pill`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("text", CUSTOM_DOMAIN_MATRIX_USER_URL) + val matrixItem = subject.resolveMentionDisplay("text", CUSTOM_DOMAIN_MATRIX_USER_URL) .getMatrixItem() 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`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("text", CUSTOM_DOMAIN_MATRIX_ROOM_URL) + val matrixItem = subject.resolveMentionDisplay("text", CUSTOM_DOMAIN_MATRIX_ROOM_URL) .getMatrixItem() 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`() { val subject = createSubject() - val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_ROOM_ALIAS_URL) + val matrixItem = subject.resolveMentionDisplay("text", KNOWN_MATRIX_ROOM_ALIAS_URL) .getMatrixItem() 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 assertNotNull("The URL did not resolve to a custom link display method", customSpan)