diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt index 4620bfb2cd..1ddaa87d34 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.session.room.location import androidx.lifecycle.LiveData import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.api.util.Cancelable +import org.matrix.android.sdk.api.util.Optional /** * Manage all location sharing related features. @@ -62,8 +63,8 @@ interface LocationSharingService { fun getRunningLiveLocationShareSummaries(): LiveData> /** - * Returns a LiveData on the list of live location shares with the given eventIds. - * @param eventIds the list of event ids + * Returns a LiveData on the live location share summary with the given eventId. + * @param beaconInfoEventId event id of the initial beacon info state event */ - fun getLiveLocationShareSummaries(eventIds: List): LiveData> + fun getLiveLocationShareSummary(beaconInfoEventId: String): LiveData> } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt index 2dca96c492..d69f251f6f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt @@ -100,14 +100,3 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findRunningLiveI .isNotEmpty(LiveLocationShareAggregatedSummaryEntityFields.USER_ID) .isNotNull(LiveLocationShareAggregatedSummaryEntityFields.LAST_LOCATION_CONTENT) } - -internal fun LiveLocationShareAggregatedSummaryEntity.Companion.findLiveInRoom( - realm: Realm, - roomId: String, - eventIds: List, -): RealmQuery { - return LiveLocationShareAggregatedSummaryEntity - .whereRoomId(realm, roomId = roomId) - .isNotEmpty(LiveLocationShareAggregatedSummaryEntityFields.USER_ID) - .`in`(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, eventIds.toTypedArray()) -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt index bf2d9398ba..8e67142c52 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.session.room.location import androidx.lifecycle.LiveData +import androidx.lifecycle.Transformations import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -25,10 +26,12 @@ import org.matrix.android.sdk.api.session.room.location.LocationSharingService import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.api.util.Cancelable +import org.matrix.android.sdk.api.util.Optional +import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity -import org.matrix.android.sdk.internal.database.query.findLiveInRoom import org.matrix.android.sdk.internal.database.query.findRunningLiveInRoom +import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase internal class DefaultLocationSharingService @AssistedInject constructor( @@ -90,10 +93,14 @@ internal class DefaultLocationSharingService @AssistedInject constructor( ) } - override fun getLiveLocationShareSummaries(eventIds: List): LiveData> { - return monarchy.findAllMappedWithChanges( - { LiveLocationShareAggregatedSummaryEntity.findLiveInRoom(it, roomId = roomId, eventIds = eventIds) }, - liveLocationShareAggregatedSummaryMapper - ) + override fun getLiveLocationShareSummary(beaconInfoEventId: String): LiveData> { + return Transformations.map( + monarchy.findAllMappedWithChanges( + { LiveLocationShareAggregatedSummaryEntity.where(it, roomId = roomId, eventId = beaconInfoEventId) }, + liveLocationShareAggregatedSummaryMapper + ) + ) { + it.firstOrNull().toOptional() + } } } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt index e06e3af7fb..4b556402d5 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt @@ -16,24 +16,32 @@ package org.matrix.android.sdk.internal.session.room.location +import androidx.arch.core.util.Function +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Transformations import io.mockk.coEvery import io.mockk.coVerify +import io.mockk.every import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.slot import io.mockk.unmockkAll import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBeEqualTo import org.junit.After +import org.junit.Before import org.junit.Test import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.api.util.Cancelable +import org.matrix.android.sdk.api.util.Optional +import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields import org.matrix.android.sdk.test.fakes.FakeMonarchy import org.matrix.android.sdk.test.fakes.givenEqualTo -import org.matrix.android.sdk.test.fakes.givenIn import org.matrix.android.sdk.test.fakes.givenIsNotEmpty import org.matrix.android.sdk.test.fakes.givenIsNotNull @@ -47,7 +55,6 @@ private const val A_TIMEOUT = 15_000L @ExperimentalCoroutinesApi internal class DefaultLocationSharingServiceTest { - private val fakeRoomId = A_ROOM_ID private val fakeMonarchy = FakeMonarchy() private val sendStaticLocationTask = mockk() private val sendLiveLocationTask = mockk() @@ -56,7 +63,7 @@ internal class DefaultLocationSharingServiceTest { private val fakeLiveLocationShareAggregatedSummaryMapper = mockk() private val defaultLocationSharingService = DefaultLocationSharingService( - roomId = fakeRoomId, + roomId = A_ROOM_ID, monarchy = fakeMonarchy.instance, sendStaticLocationTask = sendStaticLocationTask, sendLiveLocationTask = sendLiveLocationTask, @@ -65,6 +72,11 @@ internal class DefaultLocationSharingServiceTest { liveLocationShareAggregatedSummaryMapper = fakeLiveLocationShareAggregatedSummaryMapper ) + @Before + fun setUp() { + mockkStatic("androidx.lifecycle.Transformations") + } + @After fun tearDown() { unmockkAll() @@ -155,7 +167,7 @@ internal class DefaultLocationSharingServiceTest { ) fakeMonarchy.givenWhere() - .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, fakeRoomId) + .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, A_ROOM_ID) .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, true) .givenIsNotEmpty(LiveLocationShareAggregatedSummaryEntityFields.USER_ID) .givenIsNotNull(LiveLocationShareAggregatedSummaryEntityFields.LAST_LOCATION_CONTENT) @@ -171,8 +183,7 @@ internal class DefaultLocationSharingServiceTest { } @Test - fun `given a list of event ids livedata on live summaries is correctly computed`() { - val eventIds = listOf("event_id_1", "event_id_2", "event_id_3") + fun `given an event id when getting livedata on corresponding live summary then it is correctly computed`() { val entity = LiveLocationShareAggregatedSummaryEntity() val summary = LiveLocationShareAggregatedSummary( userId = "", @@ -182,17 +193,26 @@ internal class DefaultLocationSharingServiceTest { ) fakeMonarchy.givenWhere() - .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, fakeRoomId) - .givenIsNotEmpty(LiveLocationShareAggregatedSummaryEntityFields.USER_ID) - .givenIn(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, eventIds) - fakeMonarchy.givenFindAllMappedWithChangesReturns( + .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, A_ROOM_ID) + .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, AN_EVENT_ID) + val liveData = fakeMonarchy.givenFindAllMappedWithChangesReturns( realmEntities = listOf(entity), mappedResult = listOf(summary), fakeLiveLocationShareAggregatedSummaryMapper ) + val mapper = slot, Optional>>() + every { + Transformations.map( + liveData, + capture(mapper) + ) + } answers { + val value = secondArg, Optional>>().apply(listOf(summary)) + MutableLiveData(value) + } - val result = defaultLocationSharingService.getLiveLocationShareSummaries(eventIds).value + val result = defaultLocationSharingService.getLiveLocationShareSummary(AN_EVENT_ID).value - result shouldBeEqualTo listOf(summary) + result shouldBeEqualTo summary.toOptional() } } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt index 9b4ca332d5..d77084fe3b 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeMonarchy.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.test.fakes +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.zhuinden.monarchy.Monarchy import io.mockk.MockKVerificationScope @@ -60,10 +61,11 @@ internal class FakeMonarchy { realmEntities: List, mappedResult: List, mapper: Monarchy.Mapper - ) { + ): LiveData> { every { mapper.map(any()) } returns mockk() val monarchyQuery = slot>() val monarchyMapper = slot>() + val result = MutableLiveData(mappedResult) every { instance.findAllMappedWithChanges(capture(monarchyQuery), capture(monarchyMapper)) } answers { @@ -71,7 +73,8 @@ internal class FakeMonarchy { realmEntities.forEach { monarchyMapper.captured.map(it) } - MutableLiveData(mappedResult) + result } + return result } } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeRealm.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeRealm.kt index c3264a32f1..0ebff87278 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeRealm.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeRealm.kt @@ -97,11 +97,3 @@ inline fun RealmQuery.givenIsNotNull( every { isNotNull(fieldName) } returns this return this } - -inline fun RealmQuery.givenIn( - fieldName: String, - values: List -): RealmQuery { - every { `in`(fieldName, values.toTypedArray()) } returns this - return this -} diff --git a/vector/src/main/java/im/vector/app/features/location/live/GetLiveLocationShareSummariesUseCase.kt b/vector/src/main/java/im/vector/app/features/location/live/GetLiveLocationShareSummaryUseCase.kt similarity index 79% rename from vector/src/main/java/im/vector/app/features/location/live/GetLiveLocationShareSummariesUseCase.kt rename to vector/src/main/java/im/vector/app/features/location/live/GetLiveLocationShareSummaryUseCase.kt index 0753f093e2..0687189925 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/GetLiveLocationShareSummariesUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/GetLiveLocationShareSummaryUseCase.kt @@ -19,20 +19,22 @@ package im.vector.app.features.location.live import androidx.lifecycle.asFlow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.mapNotNull import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import javax.inject.Inject -class GetLiveLocationShareSummariesUseCase @Inject constructor( +class GetLiveLocationShareSummaryUseCase @Inject constructor( private val session: Session, ) { - fun execute(roomId: String, eventIds: List): Flow> { + fun execute(roomId: String, eventId: String): Flow { return session.getRoom(roomId) ?.locationSharingService() - ?.getLiveLocationShareSummaries(eventIds) + ?.getLiveLocationShareSummary(eventId) ?.asFlow() + ?.mapNotNull { it.getOrNull() } ?: emptyFlow() } } diff --git a/vector/src/test/java/im/vector/app/features/location/live/GetLiveLocationShareSummariesUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/location/live/GetLiveLocationShareSummaryUseCaseTest.kt similarity index 58% rename from vector/src/test/java/im/vector/app/features/location/live/GetLiveLocationShareSummariesUseCaseTest.kt rename to vector/src/test/java/im/vector/app/features/location/live/GetLiveLocationShareSummaryUseCaseTest.kt index e0ee2c8039..67e11e682d 100644 --- a/vector/src/test/java/im/vector/app/features/location/live/GetLiveLocationShareSummariesUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/features/location/live/GetLiveLocationShareSummaryUseCaseTest.kt @@ -30,14 +30,16 @@ import org.junit.Before import org.junit.Test import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent +import org.matrix.android.sdk.api.util.Optional private const val A_ROOM_ID = "room_id" +private const val AN_EVENT_ID = "event_id" -class GetLiveLocationShareSummariesUseCaseTest { +class GetLiveLocationShareSummaryUseCaseTest { private val fakeSession = FakeSession() - private val getLiveLocationShareSummariesUseCase = GetLiveLocationShareSummariesUseCase( + private val getLiveLocationShareSummaryUseCase = GetLiveLocationShareSummaryUseCase( session = fakeSession ) @@ -52,35 +54,21 @@ class GetLiveLocationShareSummariesUseCaseTest { } @Test - fun `given a room id when calling use case then the current live is stopped with success`() = runTest { - val eventIds = listOf("event_id_1", "event_id_2", "event_id_3") - val summary1 = LiveLocationShareAggregatedSummary( - userId = "userId1", + fun `given a room id and event id when calling use case then live data on summary is returned`() = runTest { + val summary = LiveLocationShareAggregatedSummary( + userId = "userId", isActive = true, endOfLiveTimestampMillis = 123, lastLocationDataContent = MessageBeaconLocationDataContent() ) - val summary2 = LiveLocationShareAggregatedSummary( - userId = "userId2", - isActive = true, - endOfLiveTimestampMillis = 1234, - lastLocationDataContent = MessageBeaconLocationDataContent() - ) - val summary3 = LiveLocationShareAggregatedSummary( - userId = "userId3", - isActive = true, - endOfLiveTimestampMillis = 1234, - lastLocationDataContent = MessageBeaconLocationDataContent() - ) - val summaries = listOf(summary1, summary2, summary3) val liveData = fakeSession.roomService() .getRoom(A_ROOM_ID) .locationSharingService() - .givenLiveLocationShareSummaries(eventIds, summaries) - every { liveData.asFlow() } returns flowOf(summaries) + .givenLiveLocationShareSummaryReturns(AN_EVENT_ID, summary) + every { liveData.asFlow() } returns flowOf(Optional(summary)) - val result = getLiveLocationShareSummariesUseCase.execute(A_ROOM_ID, eventIds).first() + val result = getLiveLocationShareSummaryUseCase.execute(A_ROOM_ID, AN_EVENT_ID).first() - result shouldBeEqualTo listOf(summary1, summary2, summary3) + result shouldBeEqualTo summary } } diff --git a/vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt index b747b72cb1..9eeaa31bbf 100644 --- a/vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/features/location/live/map/GetListOfUserLiveLocationUseCaseTest.kt @@ -17,7 +17,6 @@ package im.vector.app.features.location.live.map import androidx.lifecycle.asFlow -import com.airbnb.mvrx.test.MvRxTestRule import im.vector.app.features.location.LocationData import im.vector.app.test.fakes.FakeSession import io.mockk.coEvery @@ -25,15 +24,12 @@ import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.unmockkAll -import io.mockk.unmockkStatic import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest -import org.amshove.kluent.internal.assertEquals import org.amshove.kluent.shouldBeEqualTo import org.junit.After import org.junit.Before -import org.junit.Rule import org.junit.Test import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent @@ -85,7 +81,7 @@ class GetListOfUserLiveLocationUseCaseTest { val liveData = fakeSession.roomService() .getRoom(A_ROOM_ID) .locationSharingService() - .givenRunningLiveLocationShareSummaries(summaries) + .givenRunningLiveLocationShareSummariesReturns(summaries) every { liveData.asFlow() } returns flowOf(summaries) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt index 8ad7004c58..cebd45b2bb 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeLocationSharingService.kt @@ -24,10 +24,11 @@ import io.mockk.mockk import org.matrix.android.sdk.api.session.room.location.LocationSharingService import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary +import org.matrix.android.sdk.api.util.Optional class FakeLocationSharingService : LocationSharingService by mockk() { - fun givenRunningLiveLocationShareSummaries( + fun givenRunningLiveLocationShareSummariesReturns( summaries: List ): LiveData> { return MutableLiveData(summaries).also { @@ -35,12 +36,12 @@ class FakeLocationSharingService : LocationSharingService by mockk() { } } - fun givenLiveLocationShareSummaries( - eventIds: List, - summaries: List - ): LiveData> { - return MutableLiveData(summaries).also { - every { getLiveLocationShareSummaries(eventIds) } returns it + fun givenLiveLocationShareSummaryReturns( + eventId: String, + summary: LiveLocationShareAggregatedSummary + ): LiveData> { + return MutableLiveData(Optional(summary)).also { + every { getLiveLocationShareSummary(eventId) } returns it } }