Merge branch 'vector-im:develop' into develop

This commit is contained in:
Ivars Julien
2023-05-15 10:26:45 +02:00
committed by GitHub
42 changed files with 118 additions and 197 deletions

View File

@@ -0,0 +1,5 @@
appId: ${APP_ID}
---
- extendedWaitUntil:
visible: ${ROOM_NAME}
timeout: 10_000

View File

@@ -1,5 +1,6 @@
appId: ${APP_ID}
---
- runFlow: ../assertions/assertRoomListSynced.yaml
- tapOn: "search"
- inputText: ${ROOM_NAME.substring(0, 3)}
- takeScreenshot: build/maestro/400-SearchRoom

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.appnav
import app.cash.molecule.RecompositionClock
@@ -30,7 +28,6 @@ import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.features.rageshake.test.rageshake.FakeRageShake
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.appnav.loggedin
import app.cash.molecule.RecompositionClock
@@ -29,7 +27,6 @@ import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter
import io.element.android.libraries.push.api.PushService
import io.element.android.libraries.push.providers.api.Distributor
import io.element.android.libraries.push.providers.api.PushProvider
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -65,11 +65,12 @@ class CreateRoomRootPresenter @Inject constructor(
fun startDm(matrixUser: MatrixUser) {
startDmAction.value = Async.Uninitialized
val existingDM = matrixClient.findDM(matrixUser.userId)
if (existingDM == null) {
localCoroutineScope.createDM(matrixUser, startDmAction)
} else {
startDmAction.value = Async.Success(existingDM.roomId)
matrixClient.findDM(matrixUser.userId).use { existingDM ->
if (existingDM == null) {
localCoroutineScope.createDM(matrixUser, startDmAction)
} else {
startDmAction.value = Async.Success(existingDM.roomId)
}
}
}

View File

@@ -25,11 +25,9 @@ import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.FakeMatrixClient
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
internal class AllMatrixUsersDataSourceTest {
@Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.createroom.impl.addpeople
import app.cash.molecule.RecompositionClock
@@ -26,7 +24,6 @@ import io.element.android.features.createroom.impl.CreateRoomDataStore
import io.element.android.features.userlist.api.UserListDataStore
import io.element.android.features.userlist.test.FakeUserListDataSource
import io.element.android.features.userlist.test.FakeUserListPresenterFactory
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.createroom.impl.configureroom
import android.net.Uri
@@ -36,7 +34,6 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.ui.components.aMatrixUser
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.createroom.impl.root
import app.cash.molecule.RecompositionClock
@@ -35,7 +33,6 @@ import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test

View File

@@ -131,14 +131,18 @@ class InviteListPresenter @Inject constructor(
private fun CoroutineScope.acceptInvite(roomId: RoomId, acceptedAction: MutableState<Async<RoomId>>) = launch {
suspend {
client.getRoom(roomId)?.acceptInvitation()?.getOrThrow()
client.getRoom(roomId)?.use {
it.acceptInvitation().getOrThrow()
}
roomId
}.execute(acceptedAction)
}
private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState<Async<Unit>>) = launch {
suspend {
client.getRoom(roomId)?.rejectInvitation()?.getOrThrow() ?: Unit
client.getRoom(roomId)?.use {
it.rejectInvitation().getOrThrow()
} ?: Unit
}.execute(declinedAction)
}

View File

@@ -38,11 +38,9 @@ import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class InviteListPresenterTests {
@Test
@@ -509,5 +507,4 @@ class InviteListPresenterTests {
unreadNotificationCount = 0,
)
)
}

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.login.impl.changeserver
import app.cash.molecule.RecompositionClock
@@ -28,11 +26,9 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL_2
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class ChangeServerPresenterTest {
@Test
fun `present - should start with default homeserver`() = runTest {

View File

@@ -14,25 +14,18 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.login.impl.root
import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.login.impl.root.LoggedInState
import io.element.android.features.login.impl.root.LoginFormState
import io.element.android.features.login.impl.root.LoginRootEvents
import io.element.android.features.login.impl.root.LoginRootPresenter
import io.element.android.libraries.matrix.test.A_HOMESERVER
import io.element.android.libraries.matrix.test.A_PASSWORD
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.logout.impl
import app.cash.molecule.RecompositionClock
@@ -28,7 +26,6 @@ import io.element.android.libraries.architecture.Async
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.messages
import app.cash.molecule.RecompositionClock
@@ -40,7 +38,6 @@ import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.mediapickers.test.FakePickerProvider
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
import io.element.android.libraries.textcomposer.MessageComposerMode
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.messages.actionlist
import app.cash.molecule.RecompositionClock
@@ -23,9 +21,9 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.messages.impl.actionlist.ActionListEvents
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.actionlist.ActionListPresenter
import io.element.android.features.messages.impl.actionlist.ActionListState
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
@@ -37,7 +35,6 @@ import io.element.android.libraries.matrix.test.A_MESSAGE
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_NAME
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.messages.fixtures
import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory
@@ -34,7 +32,6 @@ import io.element.android.features.messages.impl.timeline.factories.virtual.Time
import io.element.android.features.messages.impl.timeline.factories.virtual.TimelineItemVirtualFactory
import io.element.android.libraries.dateformatter.test.FakeDaySeparatorFormatter
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
internal fun aTimelineItemsFactory() = TimelineItemsFactory(
dispatchers = testCoroutineDispatchers(),

View File

@@ -52,14 +52,10 @@ import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
import io.element.android.libraries.textcomposer.MessageComposerMode
import io.mockk.mockk
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.android.awaitFrame
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.Test
import java.io.File
@@ -302,30 +298,32 @@ class MessageComposerPresenterTest {
val room = FakeMatrixRoom()
val presenter = createPresenter(this, room = room)
pickerProvider.givenMimeType(MimeTypes.Images)
mediaPreProcessor.givenResult(Result.success(
MediaUploadInfo.Image(
file = File("/some/path"),
info = ImageInfo(
width = null,
height = null,
mimetype = null,
size = null,
thumbnailInfo = null,
thumbnailUrl = null,
blurhash = null,
),
thumbnailInfo = ThumbnailProcessingInfo(
mediaPreProcessor.givenResult(
Result.success(
MediaUploadInfo.Image(
file = File("/some/path"),
info = ThumbnailInfo(
info = ImageInfo(
width = null,
height = null,
mimetype = null,
size = null,
thumbnailInfo = null,
thumbnailUrl = null,
blurhash = null,
),
blurhash = "",
thumbnailInfo = ThumbnailProcessingInfo(
file = File("/some/path"),
info = ThumbnailInfo(
width = null,
height = null,
mimetype = null,
size = null,
),
blurhash = "",
)
)
)
))
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@@ -342,31 +340,33 @@ class MessageComposerPresenterTest {
val room = FakeMatrixRoom()
val presenter = createPresenter(this, room = room)
pickerProvider.givenMimeType(MimeTypes.Videos)
mediaPreProcessor.givenResult(Result.success(
MediaUploadInfo.Video(
file = File("/some/path"),
info = VideoInfo(
width = null,
height = null,
mimetype = null,
duration = null,
size = null,
thumbnailInfo = null,
thumbnailUrl = null,
blurhash = null,
),
thumbnailInfo = ThumbnailProcessingInfo(
mediaPreProcessor.givenResult(
Result.success(
MediaUploadInfo.Video(
file = File("/some/path"),
info = ThumbnailInfo(
info = VideoInfo(
width = null,
height = null,
mimetype = null,
duration = null,
size = null,
thumbnailInfo = null,
thumbnailUrl = null,
blurhash = null,
),
blurhash = "",
thumbnailInfo = ThumbnailProcessingInfo(
file = File("/some/path"),
info = ThumbnailInfo(
width = null,
height = null,
mimetype = null,
size = null,
),
blurhash = "",
)
)
)
))
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
@@ -394,7 +394,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Pick media from gallery & cancel does nothing`() = runTest {
val presenter = createPresenter(this)
with(pickerProvider){
with(pickerProvider) {
givenResult(null) // Simulate a user canceling the flow
givenMimeType(MimeTypes.Images)
}

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.messages.timeline
import app.cash.molecule.RecompositionClock
@@ -27,8 +25,6 @@ import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.TimelinePresenter
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.preferences.impl.developer
import app.cash.molecule.RecompositionClock
@@ -24,7 +22,6 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.preferences.impl.root
import app.cash.molecule.RecompositionClock
@@ -29,7 +27,6 @@ import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataSto
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.matrix.test.FakeMatrixClient
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.rageshake.impl.bugreport
import app.cash.molecule.RecompositionClock
@@ -28,7 +26,6 @@ import io.element.android.features.rageshake.test.screenshot.A_SCREENSHOT_URI
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.matrix.test.A_FAILURE_REASON
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.rageshake.impl.crash.ui
import app.cash.molecule.RecompositionClock
@@ -26,7 +24,6 @@ import io.element.android.features.rageshake.api.crash.CrashDetectionEvents
import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter
import io.element.android.features.rageshake.test.crash.A_CRASH_DATA
import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.rageshake.impl.detection
import android.graphics.Bitmap
@@ -31,10 +29,10 @@ import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataSto
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Test
import kotlin.time.Duration.Companion.seconds
class RageshakeDetectionPresenterTest {
@Test
@@ -101,7 +99,7 @@ class RageshakeDetectionPresenterTest {
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
}.test {
}.test(timeout = 30.seconds) {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.isStarted).isFalse()
@@ -155,7 +153,7 @@ class RageshakeDetectionPresenterTest {
}
@Test
fun `present - screenshot then disable`() = runTest {
fun `present - screenshot then disable`() = runTest(timeout = 1.seconds) {
val screenshotHolder = FakeScreenshotHolder(screenshotUri = null)
val rageshake = FakeRageShake(isAvailableValue = true)
val rageshakeDataStore = FakeRageshakeDataStore(isEnabled = true)

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.rageshake.impl.preferences
import app.cash.molecule.RecompositionClock
@@ -26,7 +24,6 @@ import io.element.android.features.rageshake.api.preferences.RageshakePreference
import io.element.android.features.rageshake.test.rageshake.A_SENSITIVITY
import io.element.android.features.rageshake.test.rageshake.FakeRageShake
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -27,11 +27,9 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
internal class DefaultInviteStateDataSourceTest {
@Test
@@ -133,5 +131,4 @@ internal class DefaultInviteStateDataSourceTest {
Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
}
}
}

View File

@@ -38,12 +38,11 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) class RoomListPresenterTests {
class RoomListPresenterTests {
@Test
fun `present - should start with no user and then load user with success`() = runTest {

View File

@@ -16,7 +16,6 @@
package io.element.android.features.userlist.impl
import androidx.compose.foundation.lazy.LazyListState
import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
@@ -30,14 +29,10 @@ import io.element.android.features.userlist.test.FakeUserListDataSource
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.mockk.coJustRun
import io.mockk.mockkConstructor
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class DefaultUserListPresenterTests {
private val userListDataSource = FakeUserListDataSource()
@@ -136,9 +131,6 @@ class DefaultUserListPresenterTests {
@Test
fun `present - select a user`() = runTest {
mockkConstructor(LazyListState::class)
coJustRun { anyConstructed<LazyListState>().scrollToItem(index = any()) }
val presenter = DefaultUserListPresenter(
UserListPresenterArgs(selectionMode = SelectionMode.Single),
userListDataSource,
@@ -158,16 +150,15 @@ class DefaultUserListPresenterTests {
assertThat(awaitItem().selectedUsers).containsExactly(userA)
initialState.eventSink(UserListEvents.AddToSelection(userB))
// the last added user should be presented first
assertThat(awaitItem().selectedUsers).containsExactly(userB, userA)
assertThat(awaitItem().selectedUsers).containsExactly(userA, userB)
initialState.eventSink(UserListEvents.AddToSelection(userABis))
initialState.eventSink(UserListEvents.AddToSelection(userC))
// duplicated users should be ignored
assertThat(awaitItem().selectedUsers).containsExactly(userC, userB, userA)
assertThat(awaitItem().selectedUsers).containsExactly(userA, userB, userC)
initialState.eventSink(UserListEvents.RemoveFromSelection(userB))
assertThat(awaitItem().selectedUsers).containsExactly(userC, userA)
assertThat(awaitItem().selectedUsers).containsExactly(userA, userC)
initialState.eventSink(UserListEvents.RemoveFromSelection(userA))
assertThat(awaitItem().selectedUsers).containsExactly(userC)
initialState.eventSink(UserListEvents.RemoveFromSelection(userC))

View File

@@ -23,7 +23,7 @@ compose_bom = "2023.04.01"
composecompiler = "1.4.7"
# Coroutines
coroutines = "1.6.4"
coroutines = "1.7.0"
# Accompanist
accompanist = "0.30.1"

View File

@@ -14,6 +14,8 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.libraries.matrix.impl
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
@@ -300,7 +302,6 @@ class RustMatrixClient constructor(
}
}
@ExperimentalCoroutinesApi
override fun close() {
slidingSyncUpdateJob?.cancel()
stopSync()

View File

@@ -24,17 +24,18 @@ import org.matrix.rustcomponents.sdk.RoomMember as RustRoomMember
object RoomMemberMapper {
fun map(roomMember: RustRoomMember): RoomMember =
fun map(roomMember: RustRoomMember): RoomMember = roomMember.use {
RoomMember(
UserId(roomMember.userId()),
roomMember.displayName(),
roomMember.avatarUrl(),
mapMembership(roomMember.membership()),
roomMember.isNameAmbiguous(),
roomMember.powerLevel(),
roomMember.normalizedPowerLevel(),
roomMember.isIgnored(),
UserId(it.userId()),
it.displayName(),
it.avatarUrl(),
mapMembership(it.membership()),
it.isNameAmbiguous(),
it.powerLevel(),
it.normalizedPowerLevel(),
it.isIgnored(),
)
}
fun mapMembership(membershipState: RustMembershipState): RoomMembershipState =
when (membershipState) {

View File

@@ -161,9 +161,10 @@ class RustMatrixRoom(
override suspend fun sendMessage(message: String): Result<Unit> = withContext(coroutineDispatchers.io) {
val transactionId = genTransactionId()
val content = messageEventContentFromMarkdown(message)
runCatching {
innerRoom.send(content, transactionId)
messageEventContentFromMarkdown(message).use { content ->
runCatching {
innerRoom.send(content, transactionId)
}
}
}

View File

@@ -27,12 +27,12 @@ class MatrixTimelineItemMapper(
) {
fun map(timelineItem: TimelineItem): MatrixTimelineItem = timelineItem.use {
val asEvent = timelineItem.asEvent()
val asEvent = it.asEvent()
if (asEvent != null) {
val eventTimelineItem = eventTimelineItemMapper.map(asEvent)
return MatrixTimelineItem.Event(eventTimelineItem)
}
val asVirtual = timelineItem.asVirtual()
val asVirtual = it.asVirtual()
if (asVirtual != null) {
val virtualTimelineItem = virtualTimelineItemMapper.map(asVirtual)
return MatrixTimelineItem.Virtual(virtualTimelineItem)

View File

@@ -39,7 +39,7 @@ import org.matrix.rustcomponents.sdk.MessageFormat as RustMessageFormat
class EventMessageMapper {
fun map(message: Message): MessageContent = message.use {
val type = message.msgtype().use { type ->
val type = it.msgtype().use { type ->
when (type) {
is MessageType.Audio -> {
AudioMessageType(type.content.body, type.content.source.useUrl(), type.content.info?.map())
@@ -68,9 +68,9 @@ class EventMessageMapper {
}
}
MessageContent(
body = message.body(),
inReplyTo = message.inReplyTo()?.eventId?.let(::EventId),
isEdited = message.isEdited(),
body = it.body(),
inReplyTo = it.inReplyTo()?.eventId?.let(::EventId),
isEdited = it.isEdited(),
type = type
)
}

View File

@@ -31,18 +31,18 @@ class EventTimelineItemMapper(private val contentMapper: TimelineEventContentMap
fun map(eventTimelineItem: RustEventTimelineItem): EventTimelineItem = eventTimelineItem.use {
EventTimelineItem(
uniqueIdentifier = eventTimelineItem.uniqueIdentifier(),
eventId = eventTimelineItem.eventId()?.let { EventId(it) },
isEditable = eventTimelineItem.isEditable(),
isLocal = eventTimelineItem.isLocal(),
isOwn = eventTimelineItem.isOwn(),
isRemote = eventTimelineItem.isRemote(),
localSendState = eventTimelineItem.localSendState()?.map(),
reactions = eventTimelineItem.reactions().map(),
sender = UserId(eventTimelineItem.sender()),
senderProfile = eventTimelineItem.senderProfile().map(),
timestamp = eventTimelineItem.timestamp().toLong(),
content = contentMapper.map(eventTimelineItem.content())
uniqueIdentifier = it.uniqueIdentifier(),
eventId = it.eventId()?.let { EventId(it) },
isEditable = it.isEditable(),
isLocal = it.isLocal(),
isOwn = it.isOwn(),
isRemote = it.isRemote(),
localSendState = it.localSendState()?.map(),
reactions = it.reactions().map(),
sender = UserId(it.sender()),
senderProfile = it.senderProfile().map(),
timestamp = it.timestamp().toLong(),
content = contentMapper.map(it.content())
)
}
}

View File

@@ -17,6 +17,7 @@
package io.element.android.libraries.matrix.impl.timeline.item.event
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
@@ -26,7 +27,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.RedactedConte
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
import io.element.android.libraries.matrix.impl.media.map
@@ -39,7 +39,7 @@ import org.matrix.rustcomponents.sdk.OtherState as RustOtherState
class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMapper = EventMessageMapper()) {
fun map(content: TimelineItemContent): EventContent = content.use {
when (val kind = content.kind()) {
when (val kind = it.kind()) {
is TimelineItemContentKind.FailedToParseMessageLike -> {
FailedToParseMessageLikeContent(
eventType = kind.eventType,
@@ -54,7 +54,7 @@ class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMap
)
}
TimelineItemContentKind.Message -> {
val message = content.asMessage()
val message = it.asMessage()
if (message == null) {
UnknownContent
} else {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalPermissionsApi::class)
@file:OptIn(ExperimentalPermissionsApi::class)
package io.element.android.libraries.permissions.impl
@@ -25,7 +25,6 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionStatus
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.permissions.api.PermissionsEvents
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,15 +14,12 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.libraries.permissions.noop
import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -14,13 +14,10 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.libraries.pushstore.impl.clientsecret
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.SessionId
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Test

View File

@@ -20,12 +20,10 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver
import io.element.android.libraries.matrix.session.SessionData
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class DatabaseSessionStoreTests {
private lateinit var database: SessionDatabase

View File

@@ -33,17 +33,16 @@ import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import java.util.Locale
import java.util.concurrent.Executors
class RoomListScreen(
context: Context,
private val matrixClient: MatrixClient,
private val coroutineDispatchers: CoroutineDispatchers = Singleton.coroutineDispatchers,
) {
private val clock = Clock.System
private val locale = Locale.getDefault()
@@ -58,28 +57,24 @@ class RoomListScreen(
sessionVerificationService = sessionVerificationService,
networkMonitor = NetworkMonitorImpl(context),
snackbarDispatcher = SnackbarDispatcher(),
inviteStateDataSource = DefaultInviteStateDataSource(
matrixClient,
DefaultSeenInvitesStore(context),
CoroutineDispatchers(
io = Dispatchers.IO,
computation = Dispatchers.Default,
main = Dispatchers.Main,
diffUpdateDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
)
)
inviteStateDataSource = DefaultInviteStateDataSource(matrixClient, DefaultSeenInvitesStore(context), coroutineDispatchers)
)
@Composable
fun Content(modifier: Modifier = Modifier) {
fun onRoomClicked(roomId: RoomId) {
val room = matrixClient.getRoom(roomId)!!
val timeline = room.timeline()
Singleton.appScope.launch {
timeline.apply {
initialize()
paginateBackwards(20, 50)
dispose()
withContext(coroutineDispatchers.io) {
matrixClient.getRoom(roomId)!!.use { room ->
val timeline = room.timeline()
timeline.apply {
// TODO This doesn't work reliably as initialize is asynchronous, and the timeline can't be used until it's finished
initialize()
paginateBackwards(20, 50)
dispose()
}
}
}
}
}

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.services.appnavstate.impl
import com.google.common.truth.Truth.assertThat
@@ -28,11 +26,11 @@ import io.element.android.services.appnavstate.test.A_ROOM_OWNER
import io.element.android.services.appnavstate.test.A_SESSION_OWNER
import io.element.android.services.appnavstate.test.A_SPACE_OWNER
import io.element.android.services.appnavstate.test.A_THREAD_OWNER
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertThrows
import org.junit.Test
class DefaultAppNavigationStateServiceTest {
@Test