Stop sharing live location if live is redacted
This commit is contained in:
parent
63626b79de
commit
8fb402ab10
@ -24,6 +24,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.services.VectorAndroidService
|
import im.vector.app.core.services.VectorAndroidService
|
||||||
|
import im.vector.app.features.location.live.CheckIfLiveLocationShareIsRedactedUseCase
|
||||||
import im.vector.app.features.location.live.GetLiveLocationShareSummaryUseCase
|
import im.vector.app.features.location.live.GetLiveLocationShareSummaryUseCase
|
||||||
import im.vector.app.features.notifications.NotificationUtils
|
import im.vector.app.features.notifications.NotificationUtils
|
||||||
import im.vector.app.features.session.coroutineScope
|
import im.vector.app.features.session.coroutineScope
|
||||||
@ -55,6 +56,7 @@ class LocationSharingAndroidService : VectorAndroidService(), LocationTracker.Ca
|
|||||||
@Inject lateinit var locationTracker: LocationTracker
|
@Inject lateinit var locationTracker: LocationTracker
|
||||||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||||
@Inject lateinit var getLiveLocationShareSummaryUseCase: GetLiveLocationShareSummaryUseCase
|
@Inject lateinit var getLiveLocationShareSummaryUseCase: GetLiveLocationShareSummaryUseCase
|
||||||
|
@Inject lateinit var checkIfLiveLocationShareIsRedactedUseCase: CheckIfLiveLocationShareIsRedactedUseCase
|
||||||
|
|
||||||
private val binder = LocalBinder()
|
private val binder = LocalBinder()
|
||||||
|
|
||||||
@ -203,14 +205,18 @@ class LocationSharingAndroidService : VectorAndroidService(), LocationTracker.Ca
|
|||||||
private fun listenForLiveSummaryChanges(roomId: String, beaconEventId: String) {
|
private fun listenForLiveSummaryChanges(roomId: String, beaconEventId: String) {
|
||||||
launchWithActiveSession { session ->
|
launchWithActiveSession { session ->
|
||||||
val job = getLiveLocationShareSummaryUseCase.execute(roomId, beaconEventId)
|
val job = getLiveLocationShareSummaryUseCase.execute(roomId, beaconEventId)
|
||||||
.distinctUntilChangedBy { it.isActive }
|
.distinctUntilChangedBy { it?.isActive }
|
||||||
.filter { it.isActive == false }
|
.filter { it?.isActive == false || (it == null && isLiveRedacted(roomId, beaconEventId)) }
|
||||||
.onEach { stopSharingLocation(beaconEventId) }
|
.onEach { stopSharingLocation(beaconEventId) }
|
||||||
.launchIn(session.coroutineScope)
|
.launchIn(session.coroutineScope)
|
||||||
jobs.add(job)
|
jobs.add(job)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun isLiveRedacted(roomId: String, beaconEventId: String): Boolean {
|
||||||
|
return checkIfLiveLocationShareIsRedactedUseCase.execute(roomId = roomId, eventId = beaconEventId)
|
||||||
|
}
|
||||||
|
|
||||||
private fun launchWithActiveSession(block: suspend CoroutineScope.(Session) -> Unit) =
|
private fun launchWithActiveSession(block: suspend CoroutineScope.(Session) -> Unit) =
|
||||||
activeSessionHolder
|
activeSessionHolder
|
||||||
.getSafeActiveSession()
|
.getSafeActiveSession()
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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 im.vector.app.features.location.live
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CheckIfLiveLocationShareIsRedactedUseCase @Inject constructor(
|
||||||
|
private val session: Session,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun execute(roomId: String, eventId: String): Boolean {
|
||||||
|
Timber.d("checking if event is redacted for roomId=$roomId and eventId=$eventId")
|
||||||
|
return try {
|
||||||
|
session.eventService()
|
||||||
|
.getEvent(roomId, eventId)
|
||||||
|
.isRedacted()
|
||||||
|
.also { Timber.d("event isRedacted=$it") }
|
||||||
|
} catch (error: Exception) {
|
||||||
|
Timber.e(error, "error when getting event, it may not exist yet")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,7 @@ package im.vector.app.features.location.live
|
|||||||
import androidx.lifecycle.asFlow
|
import androidx.lifecycle.asFlow
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
@ -31,13 +31,13 @@ class GetLiveLocationShareSummaryUseCase @Inject constructor(
|
|||||||
private val session: Session,
|
private val session: Session,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun execute(roomId: String, eventId: String): Flow<LiveLocationShareAggregatedSummary> = withContext(session.coroutineDispatchers.main) {
|
suspend fun execute(roomId: String, eventId: String): Flow<LiveLocationShareAggregatedSummary?> = withContext(session.coroutineDispatchers.main) {
|
||||||
Timber.d("getting flow for roomId=$roomId and eventId=$eventId")
|
Timber.d("getting flow for roomId=$roomId and eventId=$eventId")
|
||||||
session.getRoom(roomId)
|
session.getRoom(roomId)
|
||||||
?.locationSharingService()
|
?.locationSharingService()
|
||||||
?.getLiveLocationShareSummary(eventId)
|
?.getLiveLocationShareSummary(eventId)
|
||||||
?.asFlow()
|
?.asFlow()
|
||||||
?.mapNotNull { it.getOrNull() }
|
?.map { it.getOrNull() }
|
||||||
?: emptyFlow()
|
?: emptyFlow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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 im.vector.app.features.location.live
|
||||||
|
|
||||||
|
import im.vector.app.test.fakes.FakeSession
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.UnsignedData
|
||||||
|
|
||||||
|
private const val A_ROOM_ID = "room_id"
|
||||||
|
private const val AN_EVENT_ID = "event_id"
|
||||||
|
|
||||||
|
class CheckIfLiveLocationShareIsRedactedUseCaseTest {
|
||||||
|
|
||||||
|
private val fakeSession = FakeSession()
|
||||||
|
|
||||||
|
private val checkIfLiveLocationShareIsRedactedUseCase = CheckIfLiveLocationShareIsRedactedUseCase(
|
||||||
|
session = fakeSession
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a room id and event id for redacted event when calling use case then true is returned`() = runTest {
|
||||||
|
val event = Event(
|
||||||
|
unsignedData = UnsignedData(age = 123, redactedEvent = Event())
|
||||||
|
)
|
||||||
|
fakeSession.eventService()
|
||||||
|
.givenGetEventReturns(event)
|
||||||
|
|
||||||
|
val result = checkIfLiveLocationShareIsRedactedUseCase.execute(A_ROOM_ID, AN_EVENT_ID)
|
||||||
|
|
||||||
|
result shouldBeEqualTo true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a room id and event id for non redacted event when calling use case then false is returned`() = runTest {
|
||||||
|
val event = Event()
|
||||||
|
fakeSession.eventService()
|
||||||
|
.givenGetEventReturns(event)
|
||||||
|
|
||||||
|
val result = checkIfLiveLocationShareIsRedactedUseCase.execute(A_ROOM_ID, AN_EVENT_ID)
|
||||||
|
|
||||||
|
result shouldBeEqualTo false
|
||||||
|
}
|
||||||
|
}
|
@ -53,7 +53,7 @@ class GetLiveLocationShareSummaryUseCaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given a room id and event id when calling use case then live data on summary is returned`() = runTest {
|
fun `given a room id and event id when calling use case then flow on summary is returned`() = runTest {
|
||||||
val summary = LiveLocationShareAggregatedSummary(
|
val summary = LiveLocationShareAggregatedSummary(
|
||||||
userId = "userId",
|
userId = "userId",
|
||||||
isActive = true,
|
isActive = true,
|
||||||
@ -70,4 +70,17 @@ class GetLiveLocationShareSummaryUseCaseTest {
|
|||||||
|
|
||||||
result shouldBeEqualTo summary
|
result shouldBeEqualTo summary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a room id, event id and a null summary when calling use case then null is emitted in the flow`() = runTest {
|
||||||
|
fakeSession.roomService()
|
||||||
|
.getRoom(A_ROOM_ID)
|
||||||
|
.locationSharingService()
|
||||||
|
.givenLiveLocationShareSummaryReturns(AN_EVENT_ID, null)
|
||||||
|
.givenAsFlowReturns(Optional(null))
|
||||||
|
|
||||||
|
val result = getLiveLocationShareSummaryUseCase.execute(A_ROOM_ID, AN_EVENT_ID).first()
|
||||||
|
|
||||||
|
result shouldBeEqualTo null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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 im.vector.app.test.fakes
|
||||||
|
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.api.session.events.EventService
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
|
||||||
|
class FakeEventService : EventService by mockk() {
|
||||||
|
|
||||||
|
fun givenGetEventReturns(event: Event) {
|
||||||
|
coEvery { getEvent(any(), any()) } returns event
|
||||||
|
}
|
||||||
|
}
|
@ -41,7 +41,7 @@ class FakeLocationSharingService : LocationSharingService by mockk() {
|
|||||||
|
|
||||||
fun givenLiveLocationShareSummaryReturns(
|
fun givenLiveLocationShareSummaryReturns(
|
||||||
eventId: String,
|
eventId: String,
|
||||||
summary: LiveLocationShareAggregatedSummary
|
summary: LiveLocationShareAggregatedSummary?
|
||||||
): LiveData<Optional<LiveLocationShareAggregatedSummary>> {
|
): LiveData<Optional<LiveLocationShareAggregatedSummary>> {
|
||||||
return MutableLiveData(Optional(summary)).also {
|
return MutableLiveData(Optional(summary)).also {
|
||||||
every { getLiveLocationShareSummary(eventId) } returns it
|
every { getLiveLocationShareSummary(eventId) } returns it
|
||||||
|
@ -35,6 +35,7 @@ class FakeSession(
|
|||||||
val fakeHomeServerCapabilitiesService: FakeHomeServerCapabilitiesService = FakeHomeServerCapabilitiesService(),
|
val fakeHomeServerCapabilitiesService: FakeHomeServerCapabilitiesService = FakeHomeServerCapabilitiesService(),
|
||||||
val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService(),
|
val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService(),
|
||||||
private val fakeRoomService: FakeRoomService = FakeRoomService(),
|
private val fakeRoomService: FakeRoomService = FakeRoomService(),
|
||||||
|
private val fakeEventService: FakeEventService = FakeEventService(),
|
||||||
) : Session by mockk(relaxed = true) {
|
) : Session by mockk(relaxed = true) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -50,6 +51,7 @@ class FakeSession(
|
|||||||
override fun homeServerCapabilitiesService(): HomeServerCapabilitiesService = fakeHomeServerCapabilitiesService
|
override fun homeServerCapabilitiesService(): HomeServerCapabilitiesService = fakeHomeServerCapabilitiesService
|
||||||
override fun sharedSecretStorageService() = fakeSharedSecretStorageService
|
override fun sharedSecretStorageService() = fakeSharedSecretStorageService
|
||||||
override fun roomService() = fakeRoomService
|
override fun roomService() = fakeRoomService
|
||||||
|
override fun eventService() = fakeEventService
|
||||||
|
|
||||||
fun givenVectorStore(vectorSessionStore: VectorSessionStore) {
|
fun givenVectorStore(vectorSessionStore: VectorSessionStore) {
|
||||||
coEvery {
|
coEvery {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user