From 8b2121ae991dfb5dbe1fb831edcb94af1232e9da Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Jun 2023 18:00:40 +0200 Subject: [PATCH 01/13] Restore sonar task on PR, we want to have sonarcloud comment on PR to track code quality (#619) --- .github/workflows/tests.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aea05b5a22..3e9dbab5c6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -81,8 +81,12 @@ jobs: **/out/failures/ **/build/reports/tests/*UnitTest/ - - name: 🔊 Publish results to Sonar (disabled) - run: echo "This is now done only once a day, see nightlyReports.yml" + - name: 🔊 Publish results to Sonar + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }} + if: ${{ always() && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }} + run: ./gradlew sonar $CI_GRADLE_ARG_PROPERTIES # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov From 2452d8aa910e4b624f1949b28ffa1c1ae5970a55 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Jun 2023 18:08:20 +0200 Subject: [PATCH 02/13] Fix the 6 issues reported by Sonar. --- .../features/createroom/impl/CreateRoomDataStore.kt | 3 ++- .../ConfirmAccountProviderView.kt | 3 +-- .../login/impl/src/main/res/values/localazy.xml | 1 + .../android/libraries/androidutils/file/File.kt | 13 +++++++++++++ .../mediaupload/AndroidMediaPreProcessor.kt | 3 ++- .../libraries/mediaupload/VideoCompressor.kt | 5 +++-- .../notifications/NotificationEventPersistence.kt | 3 ++- 7 files changed, 24 insertions(+), 7 deletions(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt index 46de8fff91..f79284d082 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt @@ -20,6 +20,7 @@ import android.net.Uri import io.element.android.features.createroom.impl.configureroom.RoomPrivacy import io.element.android.features.createroom.impl.di.CreateRoomScope import io.element.android.features.createroom.impl.userlist.UserListDataStore +import io.element.android.libraries.androidutils.file.safeDelete import io.element.android.libraries.di.SingleIn import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.Flow @@ -36,7 +37,7 @@ class CreateRoomDataStore @Inject constructor( private val createRoomConfigFlow: MutableStateFlow = MutableStateFlow(CreateRoomConfig()) private var cachedAvatarUri: Uri? = null set(value) { - field?.path?.let { File(it) }?.delete() + field?.path?.let { File(it) }?.safeDelete() field = value } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt index c9053d67c9..e6e1ce8e83 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt @@ -80,8 +80,7 @@ fun ConfirmAccountProviderView( id = if (state.isAccountCreation) { R.string.screen_account_provider_signup_subtitle } else { - // Use same value for now. - R.string.screen_account_provider_signup_subtitle + R.string.screen_account_provider_signin_subtitle }, ) ) diff --git a/features/login/impl/src/main/res/values/localazy.xml b/features/login/impl/src/main/res/values/localazy.xml index bb27ca51e1..55324613ed 100644 --- a/features/login/impl/src/main/res/values/localazy.xml +++ b/features/login/impl/src/main/res/values/localazy.xml @@ -6,6 +6,7 @@ "Enter a search term or a domain address." "Search for a company, community, or private server." "Find an account provider" + "This is where you conversations will live — just like you would use an email provider to keep your emails." "You’re about to sign in to %s" "This is where you conversations will live — just like you would use an email provider to keep your emails." "You’re about to create an account on %s" diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt index 581d45a2b0..269407d3b5 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt @@ -35,6 +35,19 @@ fun File.safeDelete() { ) } +fun File.safeRenameTo(dest: File) { + tryOrNull( + onError = { + Timber.e(it, "Error, unable to rename file $path to ${dest.path}") + }, + operation = { + if (renameTo(dest).not()) { + Timber.w("Warning, unable to rename file $path to ${dest.path}") + } + } + ) +} + fun Context.createTmpFile(baseDir: File = cacheDir, extension: String? = null): File { val suffix = extension?.let { ".$extension" } return File.createTempFile(UUID.randomUUID().toString(), suffix, baseDir).apply { mkdirs() } diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/AndroidMediaPreProcessor.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/AndroidMediaPreProcessor.kt index 0f8ebab21a..c53efeeafc 100644 --- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/AndroidMediaPreProcessor.kt +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/AndroidMediaPreProcessor.kt @@ -24,6 +24,7 @@ import androidx.exifinterface.media.ExifInterface import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.androidutils.file.createTmpFile import io.element.android.libraries.androidutils.file.getFileName +import io.element.android.libraries.androidutils.file.safeRenameTo import io.element.android.libraries.androidutils.media.runAndRelease import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.data.tryOrNull @@ -133,7 +134,7 @@ class AndroidMediaPreProcessor @Inject constructor( private fun MediaUploadInfo.postProcess(uri: Uri): MediaUploadInfo { val name = context.getFileName(uri) ?: return this val renamedFile = File(context.cacheDir, name).also { - file.renameTo(it) + file.safeRenameTo(it) } return when (this) { is MediaUploadInfo.AnyFile -> copy(file = renamedFile) diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/VideoCompressor.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/VideoCompressor.kt index 490e286353..e7e294cd7c 100644 --- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/VideoCompressor.kt +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/VideoCompressor.kt @@ -21,6 +21,7 @@ import android.net.Uri import com.otaliastudios.transcoder.Transcoder import com.otaliastudios.transcoder.TranscoderListener import io.element.android.libraries.androidutils.file.createTmpFile +import io.element.android.libraries.androidutils.file.safeDelete import io.element.android.libraries.di.ApplicationContext import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow @@ -46,12 +47,12 @@ class VideoCompressor @Inject constructor( } override fun onTranscodeCanceled() { - tmpFile.delete() + tmpFile.safeDelete() close() } override fun onTranscodeFailed(exception: Throwable) { - tmpFile.delete() + tmpFile.safeDelete() close(exception) } }) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt index d6135f28b0..613a8d2bb7 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.push.impl.notifications import android.content.Context import io.element.android.libraries.androidutils.file.EncryptedFileFactory +import io.element.android.libraries.androidutils.file.safeDelete import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.di.ApplicationContext @@ -70,7 +71,7 @@ class NotificationEventPersistence @Inject constructor( fun persistEvents(queuedEvents: NotificationEventQueue) { Timber.tag(loggerTag.value).d("Serializing ${queuedEvents.rawEvents().size} NotifiableEvent(s)") // Always delete file before writing, or encryptedFile.openFileOutput() will throw - file.delete() + file.safeDelete() if (queuedEvents.isEmpty()) return try { encryptedFile.openFileOutput().use { fos -> From 9f01d6f66aeec1796680714a2a396b408a89c4c6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 19 Jun 2023 11:16:55 +0200 Subject: [PATCH 03/13] Display a banner instead of the composer when user cannot post message to a room (#602) --- .../messages/impl/MessagesPresenter.kt | 13 +++++ .../features/messages/impl/MessagesState.kt | 1 + .../messages/impl/MessagesStateProvider.kt | 2 + .../features/messages/impl/MessagesView.kt | 43 ++++++++++++-- .../impl/src/main/res/values/localazy.xml | 5 +- .../messages/MessagesPresenterTest.kt | 29 +++++++++- .../libraries/matrix/api/room/MatrixRoom.kt | 2 + .../matrix/api/room/MessageEventType.kt | 36 ++++++++++++ .../matrix/impl/room/MessageEventType.kt | 58 +++++++++++++++++++ .../matrix/impl/room/RustMatrixRoom.kt | 10 +++- .../matrix/test/room/FakeMatrixRoom.kt | 10 ++++ 11 files changed, 199 insertions(+), 10 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 089f0e79cb..d78025dea0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -19,6 +19,7 @@ package io.element.android.features.messages.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState +import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -55,6 +56,7 @@ import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.handleSnackbarMessage import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.textcomposer.MessageComposerMode @@ -86,6 +88,7 @@ class MessagesPresenter @Inject constructor( val retryState = retrySendMenuPresenter.present() val syncUpdateFlow = room.syncUpdateFlow().collectAsState(0L) + val userHasPermissionToSendMessage by getCanSendEvent(MessageEventType.ROOM_MESSAGE) val roomName: MutableState = rememberSaveable { mutableStateOf(null) } @@ -125,6 +128,7 @@ class MessagesPresenter @Inject constructor( roomId = room.roomId, roomName = roomName.value, roomAvatar = roomAvatar.value, + userHasPermissionToSendMessage = userHasPermissionToSendMessage, composerState = composerState, timelineState = timelineState, actionListState = actionListState, @@ -218,4 +222,13 @@ class MessagesPresenter @Inject constructor( MessageComposerEvents.SetMode(composerMode) ) } + + @Composable + private fun getCanSendEvent(type: MessageEventType): State { + val canSendEvent = remember(type) { mutableStateOf(false) } + LaunchedEffect(type) { + canSendEvent.value = room.canSendEvent(type).getOrElse { false } + } + return canSendEvent + } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 6e29eefe08..38c9101c9e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -31,6 +31,7 @@ data class MessagesState( val roomId: RoomId, val roomName: String?, val roomAvatar: AvatarData?, + val userHasPermissionToSendMessage: Boolean, val composerState: MessageComposerState, val timelineState: TimelineState, val actionListState: ActionListState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 4ed43315cb..7691788e58 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -35,6 +35,7 @@ open class MessagesStateProvider : PreviewParameterProvider { aMessagesState(), aMessagesState().copy(hasNetworkConnection = false), aMessagesState().copy(composerState = aMessageComposerState().copy(showAttachmentSourcePicker = true)), + aMessagesState().copy(userHasPermissionToSendMessage = false), ) } @@ -42,6 +43,7 @@ fun aMessagesState() = MessagesState( roomId = RoomId("!id:domain"), roomName = "Room name", roomAvatar = AvatarData("!id:domain", "Room name"), + userHasPermissionToSendMessage = true, composerState = aMessageComposerState().copy( text = StableCharSequence("Hello"), isFullScreen = false, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 0687d46787..93b74806d6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -16,7 +16,9 @@ package io.element.android.features.messages.impl +import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Row @@ -34,6 +36,7 @@ import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SnackbarHost import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -41,7 +44,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter @@ -231,12 +236,16 @@ fun MessagesViewContent( onTimestampClicked = onTimestampClicked, ) } - MessageComposerView( - state = state.composerState, - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight(Alignment.Bottom) - ) + if (state.userHasPermissionToSendMessage) { + MessageComposerView( + state = state.composerState, + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(Alignment.Bottom) + ) + } else { + CantSendMessageBanner() + } } } @@ -281,6 +290,28 @@ fun MessagesViewTopBar( ) } +@Composable +fun CantSendMessageBanner( + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.secondary) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Text( + text = stringResource(id = R.string.screen_room_no_permission_to_post), + color = MaterialTheme.colorScheme.onSecondary, + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + fontStyle = FontStyle.Italic, + ) + } +} + @Preview @Composable internal fun MessagesViewLightPreview(@PreviewParameter(MessagesStateProvider::class) state: MessagesState) = diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index 16672f15ec..557b6ccd90 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -10,8 +10,11 @@ "Attachment" "Photo & Video Library" "Could not retrieve user details" + "Would you like to invite them back?" + "You are alone in this chat" + "You do not have permission to post to this room" "Send again" "Your message failed to send" "Failed processing media to upload, please try again." "Remove" - \ No newline at end of file + diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index 1e03f60c88..4a71ec5546 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -46,6 +46,7 @@ import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -166,7 +167,7 @@ class MessagesPresenterTest { content = TimelineItemImageContent( body = "image.jpg", mediaSource = MediaSource(AN_AVATAR_URL), - thumbnailSource = null, + thumbnailSource = null, mimeType = MimeTypes.Jpeg, blurhash = null, width = 20, @@ -318,6 +319,32 @@ class MessagesPresenterTest { } } + @Test + fun `present - permission to post`() = runTest { + val matrixRoom = FakeMatrixRoom() + matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(true)) + val presenter = createMessagePresenter(matrixRoom = matrixRoom) + moleculeFlow(RecompositionClock.Immediate) { + presenter.present() + }.test { + skipItems(1) + assertThat(awaitItem().userHasPermissionToSendMessage).isTrue() + } + } + + @Test + fun `present - no permission to post`() = runTest { + val matrixRoom = FakeMatrixRoom() + matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(false)) + val presenter = createMessagePresenter(matrixRoom = matrixRoom) + moleculeFlow(RecompositionClock.Immediate) { + presenter.present() + }.test { + skipItems(1) + assertThat(awaitItem().userHasPermissionToSendMessage).isFalse() + } + } + private fun TestScope.createMessagePresenter( coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), matrixRoom: MatrixRoom = FakeMatrixRoom() diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 0ddd75966b..c31db970e0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -99,6 +99,8 @@ interface MatrixRoom : Closeable { suspend fun canSendStateEvent(type: StateEventType): Result + suspend fun canSendEvent(type: MessageEventType): Result + suspend fun updateAvatar(mimeType: String, data: ByteArray): Result suspend fun removeAvatar(): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt new file mode 100644 index 0000000000..109e50e602 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.room + +enum class MessageEventType { + CALL_ANSWER, + CALL_INVITE, + CALL_HANGUP, + CALL_CANDIDATES, + KEY_VERIFICATION_READY, + KEY_VERIFICATION_START, + KEY_VERIFICATION_CANCEL, + KEY_VERIFICATION_ACCEPT, + KEY_VERIFICATION_KEY, + KEY_VERIFICATION_MAC, + KEY_VERIFICATION_DONE, + REACTION_SENT, + ROOM_ENCRYPTED, + ROOM_MESSAGE, + ROOM_REDACTION, + STICKER +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt new file mode 100644 index 0000000000..a117c1d313 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.room + +import io.element.android.libraries.matrix.api.room.MessageEventType +import org.matrix.rustcomponents.sdk.MessageLikeEventType + +fun MessageEventType.map(): MessageLikeEventType = when (this) { + MessageEventType.CALL_ANSWER -> MessageLikeEventType.CALL_ANSWER + MessageEventType.CALL_INVITE -> MessageLikeEventType.CALL_INVITE + MessageEventType.CALL_HANGUP -> MessageLikeEventType.CALL_HANGUP + MessageEventType.CALL_CANDIDATES -> MessageLikeEventType.CALL_CANDIDATES + MessageEventType.KEY_VERIFICATION_READY -> MessageLikeEventType.KEY_VERIFICATION_READY + MessageEventType.KEY_VERIFICATION_START -> MessageLikeEventType.KEY_VERIFICATION_START + MessageEventType.KEY_VERIFICATION_CANCEL -> MessageLikeEventType.KEY_VERIFICATION_CANCEL + MessageEventType.KEY_VERIFICATION_ACCEPT -> MessageLikeEventType.KEY_VERIFICATION_ACCEPT + MessageEventType.KEY_VERIFICATION_KEY -> MessageLikeEventType.KEY_VERIFICATION_KEY + MessageEventType.KEY_VERIFICATION_MAC -> MessageLikeEventType.KEY_VERIFICATION_MAC + MessageEventType.KEY_VERIFICATION_DONE -> MessageLikeEventType.KEY_VERIFICATION_DONE + MessageEventType.REACTION_SENT -> MessageLikeEventType.REACTION_SENT + MessageEventType.ROOM_ENCRYPTED -> MessageLikeEventType.ROOM_ENCRYPTED + MessageEventType.ROOM_MESSAGE -> MessageLikeEventType.ROOM_MESSAGE + MessageEventType.ROOM_REDACTION -> MessageLikeEventType.ROOM_REDACTION + MessageEventType.STICKER -> MessageLikeEventType.STICKER +} + +fun MessageLikeEventType.map(): MessageEventType = when (this) { + MessageLikeEventType.CALL_ANSWER -> MessageEventType.CALL_ANSWER + MessageLikeEventType.CALL_INVITE -> MessageEventType.CALL_INVITE + MessageLikeEventType.CALL_HANGUP -> MessageEventType.CALL_HANGUP + MessageLikeEventType.CALL_CANDIDATES -> MessageEventType.CALL_CANDIDATES + MessageLikeEventType.KEY_VERIFICATION_READY -> MessageEventType.KEY_VERIFICATION_READY + MessageLikeEventType.KEY_VERIFICATION_START -> MessageEventType.KEY_VERIFICATION_START + MessageLikeEventType.KEY_VERIFICATION_CANCEL -> MessageEventType.KEY_VERIFICATION_CANCEL + MessageLikeEventType.KEY_VERIFICATION_ACCEPT -> MessageEventType.KEY_VERIFICATION_ACCEPT + MessageLikeEventType.KEY_VERIFICATION_KEY -> MessageEventType.KEY_VERIFICATION_KEY + MessageLikeEventType.KEY_VERIFICATION_MAC -> MessageEventType.KEY_VERIFICATION_MAC + MessageLikeEventType.KEY_VERIFICATION_DONE -> MessageEventType.KEY_VERIFICATION_DONE + MessageLikeEventType.REACTION_SENT -> MessageEventType.REACTION_SENT + MessageLikeEventType.ROOM_ENCRYPTED -> MessageEventType.ROOM_ENCRYPTED + MessageLikeEventType.ROOM_MESSAGE -> MessageEventType.ROOM_MESSAGE + MessageLikeEventType.ROOM_REDACTION -> MessageEventType.ROOM_REDACTION + MessageLikeEventType.STICKER -> MessageEventType.STICKER +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 8452ef193b..a0cfd24c05 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.timeline.MatrixTimeline @@ -34,7 +35,6 @@ import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -235,6 +235,12 @@ class RustMatrixRoom( } } + override suspend fun canSendEvent(type: MessageEventType): Result = withContext(coroutineDispatchers.io) { + runCatching { + innerRoom.member(sessionId.value).use { it.canSendMessage(type.map()) } + } + } + override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo): Result = withContext(coroutineDispatchers.io) { runCatching { innerRoom.sendImage(file.path, thumbnailFile.path, imageInfo.map()) @@ -272,7 +278,7 @@ class RustMatrixRoom( } } - override suspend fun cancelSend(transactionId: String): Result = + override suspend fun cancelSend(transactionId: String): Result = withContext(coroutineDispatchers.io) { runCatching { innerRoom.cancelSend(transactionId) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index b6d2f102af..912f0c629d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -26,6 +26,7 @@ import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -64,6 +65,7 @@ class FakeMatrixRoom( private var inviteUserResult = Result.success(Unit) private var canInviteResult = Result.success(true) private val canSendStateResults = mutableMapOf>() + private val canSendEventResults = mutableMapOf>() private var sendMediaResult = Result.success(Unit) private var setNameResult = Result.success(Unit) private var setTopicResult = Result.success(Unit) @@ -198,6 +200,10 @@ class FakeMatrixRoom( return canSendStateResults[type] ?: Result.failure(IllegalStateException("No fake answer")) } + override suspend fun canSendEvent(type: MessageEventType): Result { + return canSendEventResults[type] ?: Result.failure(IllegalStateException("No fake answer")) + } + override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo): Result = fakeSendMedia() override suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo): Result = fakeSendMedia() @@ -274,6 +280,10 @@ class FakeMatrixRoom( canSendStateResults[type] = result } + fun givenCanSendEventResult(type: MessageEventType, result: Result) { + canSendEventResults[type] = result + } + fun givenIgnoreResult(result: Result) { ignoreResult = result } From de9698b87475d731e86db02f61709eb1c2eead69 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 19 Jun 2023 10:00:45 +0000 Subject: [PATCH 04/13] Update screenshots --- ...tGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png | 3 +++ ...Group_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..77ae334920 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f145f138983fce06084866f28e14e6babe6b242ea40f89a7544a8c2580020249 +size 49121 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..84d4bfb339 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb2aa0a032dcd1597fd2e7971f47a9025f41f4fb3bf29fac709dd6d33a0a2cf8 +size 48551 From da110bd2c4e9e843d7467993646248a6144d3aa4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Jun 2023 10:50:49 +0200 Subject: [PATCH 05/13] Extract `getCanSendEvent` to the `matrixui` module, rename to `canSendEventAsState` and use produceState. --- .../messages/impl/MessagesPresenter.kt | 13 ++------ .../matrix/ui/room/MatrixRoomState.kt | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index d78025dea0..50a66f3a8e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -19,7 +19,6 @@ package io.element.android.features.messages.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState -import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -59,6 +58,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType +import io.element.android.libraries.matrix.ui.room.canSendEventAsState import io.element.android.libraries.textcomposer.MessageComposerMode import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -88,7 +88,7 @@ class MessagesPresenter @Inject constructor( val retryState = retrySendMenuPresenter.present() val syncUpdateFlow = room.syncUpdateFlow().collectAsState(0L) - val userHasPermissionToSendMessage by getCanSendEvent(MessageEventType.ROOM_MESSAGE) + val userHasPermissionToSendMessage by room.canSendEventAsState(type = MessageEventType.ROOM_MESSAGE) val roomName: MutableState = rememberSaveable { mutableStateOf(null) } @@ -222,13 +222,4 @@ class MessagesPresenter @Inject constructor( MessageComposerEvents.SetMode(composerMode) ) } - - @Composable - private fun getCanSendEvent(type: MessageEventType): State { - val canSendEvent = remember(type) { mutableStateOf(false) } - LaunchedEffect(type) { - canSendEvent.value = room.canSendEvent(type).getOrElse { false } - } - return canSendEvent - } } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt new file mode 100644 index 0000000000..19d7001342 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.ui.room + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.produceState +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MessageEventType + +@Composable +fun MatrixRoom.canSendEventAsState(type: MessageEventType): State { + return produceState(initialValue = false, key1 = type) { + value = canSendEvent(type).getOrElse { false } + } +} + From 6a39b8d242a19d2a8beb2739ae65617558a78a67 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 21 Jun 2023 11:12:47 +0200 Subject: [PATCH 06/13] Use github action that caches LFS files when checking out the repo (#647) Uses https://github.com/nschloe/action-cached-lfs-checkout where we're using git-lfs. This is a wrapper around `actions/checkout@v3` which uses `actions/cache@v3` to cache the files on LFS to avoid downloading them every time and spare LFS bandwidth. --- .github/workflows/nightlyReports.yml | 4 +--- .github/workflows/recordScreenshots.yml | 3 +-- .github/workflows/tests.yml | 3 +-- .github/workflows/validate-lfs.yml | 4 +--- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index fad1e4a426..240a9f7cd7 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -18,9 +18,7 @@ jobs: if: ${{ github.repository == 'vector-im/element-x-android' }} steps: - name: ⏬ Checkout with LFS - uses: actions/checkout@v3 - with: - lfs: 'true' + uses: nschloe/action-cached-lfs-checkout@v1.2.1 - name: Use JDK 17 uses: actions/setup-java@v3 diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 1790bb2a8d..8803ef156d 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -14,10 +14,9 @@ jobs: steps: - name: ⏬ Checkout with LFS - uses: actions/checkout@v3 + uses: nschloe/action-cached-lfs-checkout@v1.2.1 with: persist-credentials: false - lfs: 'true' - name: ☕️ Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3e9dbab5c6..a65c78c7a2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,12 +22,11 @@ jobs: cancel-in-progress: true steps: - name: ⏬ Checkout with LFS - uses: actions/checkout@v3 + uses: nschloe/action-cached-lfs-checkout@v1.2.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - lfs: 'true' - name: ☕️ Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/validate-lfs.yml b/.github/workflows/validate-lfs.yml index 417b95ce2c..25fe50359c 100644 --- a/.github/workflows/validate-lfs.yml +++ b/.github/workflows/validate-lfs.yml @@ -7,9 +7,7 @@ jobs: runs-on: ubuntu-latest name: Validate steps: - - uses: actions/checkout@v3 - with: - lfs: 'true' + - uses: nschloe/action-cached-lfs-checkout@v1.2.1 - run: | ./tools/git/validate_lfs.sh From 8e617b427d93b7cdebfa071bdc50a75617d8ed5e Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 21 Jun 2023 17:43:08 +0200 Subject: [PATCH 07/13] CanSendEvent default to true and branch refresh mechanism... --- .../android/features/messages/impl/MessagesPresenter.kt | 2 +- .../android/libraries/matrix/ui/room/MatrixRoomState.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 50a66f3a8e..7daf99283d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -88,7 +88,7 @@ class MessagesPresenter @Inject constructor( val retryState = retrySendMenuPresenter.present() val syncUpdateFlow = room.syncUpdateFlow().collectAsState(0L) - val userHasPermissionToSendMessage by room.canSendEventAsState(type = MessageEventType.ROOM_MESSAGE) + val userHasPermissionToSendMessage by room.canSendEventAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value) val roomName: MutableState = rememberSaveable { mutableStateOf(null) } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt index 19d7001342..4533f1f5ef 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt @@ -23,9 +23,9 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MessageEventType @Composable -fun MatrixRoom.canSendEventAsState(type: MessageEventType): State { - return produceState(initialValue = false, key1 = type) { - value = canSendEvent(type).getOrElse { false } +fun MatrixRoom.canSendEventAsState(type: MessageEventType, updateKey: Long): State { + return produceState(initialValue = true, key1 = updateKey) { + value = canSendEvent(type).getOrElse { true } } } From 0c41b1a827654b0bbb89e3a3abf947e4dd34e1d4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 16:44:09 +0000 Subject: [PATCH 08/13] Update dependency org.matrix.rustcomponents:sdk-android to v0.1.22 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e40f30b56b..4a3e80addc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -142,7 +142,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.21" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.22" sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "com.squareup.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" } From b7c488131600cb014d02e5129173e448650982ec Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 00:42:24 +0000 Subject: [PATCH 09/13] Update dependency androidx.compose:compose-bom to v2023.06.01 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e40f30b56b..c2e4e26114 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ media3 = "1.0.2" browser = "1.5.0" # Compose -compose_bom = "2023.06.00" +compose_bom = "2023.06.01" composecompiler = "1.4.7" # Coroutines From b8957143335bad82aa0b4ef541b4801faa234e08 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 08:29:52 +0200 Subject: [PATCH 10/13] Update plugin ktlint to v11.4.1 (#653) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e40f30b56b..1179341d86 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -190,7 +190,7 @@ kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } anvil = { id = "com.squareup.anvil", version.ref = "anvil" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } -ktlint = "org.jlleitschuh.gradle.ktlint:11.4.0" +ktlint = "org.jlleitschuh.gradle.ktlint:11.4.1" dependencygraph = { id = "com.savvasdalkitsis.module-dependency-graph", version.ref = "dependencygraph" } dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "dependencycheck" } dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyanalysis" } From 9ef53c56ba1e9ec061b108e7b55393652ccbed00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 08:30:04 +0200 Subject: [PATCH 11/13] Update dependency app.cash.turbine:turbine to v1 (#646) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1179341d86..3ca790765a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -124,7 +124,7 @@ test_mockk = "io.mockk:mockk:1.13.5" test_barista = "com.adevinta.android:barista:4.3.0" test_hamcrest = "org.hamcrest:hamcrest:2.2" test_orchestrator = "androidx.test:orchestrator:1.4.2" -test_turbine = "app.cash.turbine:turbine:0.13.0" +test_turbine = "app.cash.turbine:turbine:1.0.0" test_truth = "com.google.truth:truth:1.1.5" test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.12" test_robolectric = "org.robolectric:robolectric:4.10.3" From da2ab0ae1f85313f9ccc4fd5bdde4cbbb60365d2 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 22 Jun 2023 07:21:19 +0000 Subject: [PATCH 12/13] Update screenshots --- ...ets_ModalBottomSheetDarkPreview_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...ts_ModalBottomSheetLightPreview_0_null,NEXUS_5,1.0,en].png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetDarkPreview_0_null,NEXUS_5,1.0,en].png index fca921c50b..0a268ba362 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetDarkPreview_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetDarkPreview_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1c1eedbab868e0c2501220293608572850e052f685f7076ec939b3f1a9abf27 -size 4464 +oid sha256:4aee0816507bc71c8649aae95e57c3b75fb5e7fbd3888531817f659e1153f5be +size 7971 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetLightPreview_0_null,NEXUS_5,1.0,en].png index 665c8811ac..09a7bd0089 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetLightPreview_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_BottomSheets_ModalBottomSheetLightPreview_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb0d3bfcfd75cbd75fd9270ff1dc27090e5dbac79ca8db8a46d91a4c12bc966b -size 4457 +oid sha256:dac298843eacb59d4666d50712e5cdbe82620a25c5c01d23b77f4dcba9df9c43 +size 7979 From 2115db7af558c8bd787d1d28bdff6dc044b4ec6a Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 22 Jun 2023 09:50:17 +0200 Subject: [PATCH 13/13] Rust sdk update: make the app compile --- .../configureroom/ConfigureRoomPresenter.kt | 2 +- .../libraries/matrix/api/MatrixClient.kt | 3 +- .../matrix/api/core/ProgressCallback.kt | 21 +++++++++++++ .../libraries/matrix/api/room/MatrixRoom.kt | 9 +++--- .../libraries/matrix/impl/RustMatrixClient.kt | 6 ++-- .../impl/core/ProgressWatcherWrapper.kt | 31 +++++++++++++++++++ .../impl/notification/TimelineEventMapper.kt | 3 +- .../matrix/impl/room/RustMatrixRoom.kt | 22 ++++++++----- .../timeline/item/event/EventMessageMapper.kt | 2 ++ .../libraries/matrix/test/FakeMatrixClient.kt | 7 ++++- .../matrix/test/room/FakeMatrixRoom.kt | 14 ++++++--- .../libraries/mediaupload/api/MediaSender.kt | 9 ++++-- 12 files changed, 103 insertions(+), 26 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/ProgressCallback.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapper.kt diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index ca714b1e59..f2a03ca2c0 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -131,6 +131,6 @@ class ConfigureRoomPresenter @Inject constructor( private suspend fun uploadAvatar(avatarUri: Uri): String { val preprocessed = mediaPreProcessor.process(avatarUri, MimeTypes.Jpeg, compressIfPossible = false).getOrThrow() val byteArray = preprocessed.file.readBytes() - return matrixClient.uploadMedia(MimeTypes.Jpeg, byteArray).getOrThrow() + return matrixClient.uploadMedia(MimeTypes.Jpeg, byteArray, null).getOrThrow() } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index f0dec42855..4a018e18da 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.api +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId @@ -52,7 +53,7 @@ interface MatrixClient : Closeable { suspend fun logout() suspend fun loadUserDisplayName(): Result suspend fun loadUserAvatarURLString(): Result - suspend fun uploadMedia(mimeType: String, data: ByteArray): Result + suspend fun uploadMedia(mimeType: String, data: ByteArray, progressCallback: ProgressCallback?): Result fun onSlidingSyncUpdate() fun roomMembershipObserver(): RoomMembershipObserver } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/ProgressCallback.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/ProgressCallback.kt new file mode 100644 index 0000000000..2b41907eec --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/ProgressCallback.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.core + +interface ProgressCallback { + fun onProgress(current: Long, total: Long) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index c31db970e0..664ad9dbcb 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.api.room import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId @@ -73,13 +74,13 @@ interface MatrixRoom : Closeable { suspend fun redactEvent(eventId: EventId, reason: String? = null): Result - suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo): Result + suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo, progressCallback: ProgressCallback?): Result - suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo): Result + suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo, progressCallback: ProgressCallback?): Result - suspend fun sendAudio(file: File, audioInfo: AudioInfo): Result + suspend fun sendAudio(file: File, audioInfo: AudioInfo, progressCallback: ProgressCallback?): Result - suspend fun sendFile(file: File, fileInfo: FileInfo): Result + suspend fun sendFile(file: File, fileInfo: FileInfo, progressCallback: ProgressCallback?): Result suspend fun sendReaction(emoji: String, eventId: EventId): Result diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index d8cd8c480f..29009f9637 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -20,6 +20,7 @@ package io.element.android.libraries.matrix.impl import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters @@ -35,6 +36,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventType import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService +import io.element.android.libraries.matrix.impl.core.toProgressWatcher import io.element.android.libraries.matrix.impl.media.RustMediaLoader import io.element.android.libraries.matrix.impl.notification.RustNotificationService import io.element.android.libraries.matrix.impl.pushers.RustPushersService @@ -351,9 +353,9 @@ class RustMatrixClient constructor( } @OptIn(ExperimentalUnsignedTypes::class) - override suspend fun uploadMedia(mimeType: String, data: ByteArray): Result = withContext(dispatchers.io) { + override suspend fun uploadMedia(mimeType: String, data: ByteArray, progressCallback: ProgressCallback?): Result = withContext(dispatchers.io) { runCatching { - client.uploadMedia(mimeType, data.toUByteArray().toList()) + client.uploadMedia(mimeType, data.toUByteArray().toList(), progressCallback?.toProgressWatcher()) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapper.kt new file mode 100644 index 0000000000..f904e13bd6 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapper.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.core + +import io.element.android.libraries.matrix.api.core.ProgressCallback +import org.matrix.rustcomponents.sdk.ProgressWatcher +import org.matrix.rustcomponents.sdk.TransmissionProgress + +internal class ProgressWatcherWrapper(private val progressCallback: ProgressCallback) : ProgressWatcher { + override fun transmissionProgress(progress: TransmissionProgress) { + progressCallback.onProgress(progress.current.toLong(), progress.total.toLong()) + } +} + +internal fun ProgressCallback.toProgressWatcher(): ProgressWatcher { + return ProgressWatcherWrapper(this) +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventMapper.kt index adb9dcce72..9b70582308 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventMapper.kt @@ -16,8 +16,6 @@ package io.element.android.libraries.matrix.impl.notification -import io.element.android.libraries.matrix.api.core.EventId -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.notification.NotificationEvent import org.matrix.rustcomponents.sdk.MessageLikeEventContent import org.matrix.rustcomponents.sdk.MessageType @@ -105,5 +103,6 @@ private fun MessageType.toContent(): String { is MessageType.Notice -> content.body is MessageType.Text -> content.body is MessageType.Video -> content.use { it.body } + is MessageType.Location -> content.body } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index a0cfd24c05..8db9619c34 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.impl.room import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId @@ -31,6 +32,7 @@ import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.timeline.MatrixTimeline +import io.element.android.libraries.matrix.impl.core.toProgressWatcher import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline import io.element.android.services.toolbox.api.systemclock.SystemClock @@ -241,27 +243,31 @@ class RustMatrixRoom( } } - override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo): Result = withContext(coroutineDispatchers.io) { + override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo, progressCallback: ProgressCallback?): Result = withContext( + coroutineDispatchers.io + ) { runCatching { - innerRoom.sendImage(file.path, thumbnailFile.path, imageInfo.map()) + innerRoom.sendImage(file.path, thumbnailFile.path, imageInfo.map(), progressCallback?.toProgressWatcher()) } } - override suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo): Result = withContext(coroutineDispatchers.io) { + override suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo, progressCallback: ProgressCallback?): Result = withContext( + coroutineDispatchers.io + ) { runCatching { - innerRoom.sendVideo(file.path, thumbnailFile.path, videoInfo.map()) + innerRoom.sendVideo(file.path, thumbnailFile.path, videoInfo.map(), progressCallback?.toProgressWatcher()) } } - override suspend fun sendAudio(file: File, audioInfo: AudioInfo): Result = withContext(coroutineDispatchers.io) { + override suspend fun sendAudio(file: File, audioInfo: AudioInfo, progressCallback: ProgressCallback?): Result = withContext(coroutineDispatchers.io) { runCatching { - innerRoom.sendAudio(file.path, audioInfo.map()) + innerRoom.sendAudio(file.path, audioInfo.map(), progressCallback?.toProgressWatcher()) } } - override suspend fun sendFile(file: File, fileInfo: FileInfo): Result = withContext(coroutineDispatchers.io) { + override suspend fun sendFile(file: File, fileInfo: FileInfo, progressCallback: ProgressCallback?): Result = withContext(coroutineDispatchers.io) { runCatching { - innerRoom.sendFile(file.path, fileInfo.map()) + innerRoom.sendFile(file.path, fileInfo.map(), progressCallback?.toProgressWatcher()) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt index 7fdbe06e8a..d45124bf40 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt @@ -65,9 +65,11 @@ class EventMessageMapper { is MessageType.Video -> { VideoMessageType(type.content.body, type.content.source.map(), type.content.info?.map()) } + is MessageType.Location, null -> { UnknownMessageType } + } } val inReplyToId = it.inReplyTo()?.eventId?.let(::EventId) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 85c3555844..8b38a74457 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.test import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId @@ -116,7 +117,11 @@ class FakeMatrixClient( return userAvatarURLString } - override suspend fun uploadMedia(mimeType: String, data: ByteArray): Result { + override suspend fun uploadMedia( + mimeType: String, + data: ByteArray, + progressCallback: ProgressCallback? + ): Result { return uploadMediaResult } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 912f0c629d..01f1d17f7c 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.test.room import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId @@ -204,13 +205,18 @@ class FakeMatrixRoom( return canSendEventResults[type] ?: Result.failure(IllegalStateException("No fake answer")) } - override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo): Result = fakeSendMedia() + override suspend fun sendImage( + file: File, + thumbnailFile: File, + imageInfo: ImageInfo, + progressCallback: ProgressCallback? + ): Result = fakeSendMedia() - override suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo): Result = fakeSendMedia() + override suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo, progressCallback: ProgressCallback?): Result = fakeSendMedia() - override suspend fun sendAudio(file: File, audioInfo: AudioInfo): Result = fakeSendMedia() + override suspend fun sendAudio(file: File, audioInfo: AudioInfo, progressCallback: ProgressCallback?): Result = fakeSendMedia() - override suspend fun sendFile(file: File, fileInfo: FileInfo): Result = fakeSendMedia() + override suspend fun sendFile(file: File, fileInfo: FileInfo, progressCallback: ProgressCallback?): Result = fakeSendMedia() private suspend fun fakeSendMedia(): Result = simulateLongTask { sendMediaResult.onSuccess { diff --git a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt index 5de8239e38..9f27824858 100644 --- a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt +++ b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt @@ -47,7 +47,8 @@ class MediaSender @Inject constructor( sendImage( file = info.file, thumbnailFile = info.thumbnailFile, - imageInfo = info.info + imageInfo = info.info, + progressCallback = null ) } @@ -55,14 +56,16 @@ class MediaSender @Inject constructor( sendVideo( file = info.file, thumbnailFile = info.thumbnailFile, - videoInfo = info.info + videoInfo = info.info, + progressCallback = null ) } is MediaUploadInfo.AnyFile -> { sendFile( file = info.file, - fileInfo = info.info + fileInfo = info.info, + progressCallback = null ) } else -> Result.failure(IllegalStateException("Unexpected MediaUploadInfo format: $info"))