mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-04 01:19:33 +00:00
Stop live location share on location tick when past expiry
This commit is contained in:
+20
-8
@@ -52,9 +52,11 @@ class DefaultActiveLiveLocationShareManager(
|
|||||||
private val clock: SystemClock,
|
private val clock: SystemClock,
|
||||||
private val sessionObserver: SessionObserver,
|
private val sessionObserver: SessionObserver,
|
||||||
) : ActiveLiveLocationShareManager, LiveLocationReceiver {
|
) : ActiveLiveLocationShareManager, LiveLocationReceiver {
|
||||||
|
private data class Timeout(val expiresAt: Instant, val job: Job)
|
||||||
|
|
||||||
private val isSetup = AtomicBoolean(false)
|
private val isSetup = AtomicBoolean(false)
|
||||||
private val cachedRooms = ConcurrentHashMap<RoomId, JoinedRoom>()
|
private val cachedRooms = ConcurrentHashMap<RoomId, JoinedRoom>()
|
||||||
private val timeoutJobs = ConcurrentHashMap<RoomId, Job>()
|
private val timeouts = ConcurrentHashMap<RoomId, Timeout>()
|
||||||
private val syncedActiveShareIds = MutableStateFlow<Set<BeaconId>>(emptySet())
|
private val syncedActiveShareIds = MutableStateFlow<Set<BeaconId>>(emptySet())
|
||||||
private val localSharingRoomIds = MutableStateFlow<Set<RoomId>>(emptySet())
|
private val localSharingRoomIds = MutableStateFlow<Set<RoomId>>(emptySet())
|
||||||
override val sharingRoomIds: StateFlow<Set<RoomId>> = localSharingRoomIds
|
override val sharingRoomIds: StateFlow<Set<RoomId>> = localSharingRoomIds
|
||||||
@@ -139,9 +141,18 @@ class DefaultActiveLiveLocationShareManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun onLocationUpdate(location: Location) {
|
override suspend fun onLocationUpdate(location: Location) {
|
||||||
val activeSharesCount = localSharingRoomIds.value.size
|
val nowMillis = clock.epochMillis()
|
||||||
|
val (expired, active) = localSharingRoomIds.value.partition { roomId ->
|
||||||
|
val timeout = timeouts[roomId] ?: return@partition false
|
||||||
|
timeout.expiresAt.toEpochMilliseconds() <= nowMillis
|
||||||
|
}
|
||||||
|
expired.forEach { roomId ->
|
||||||
|
Timber.d("ActiveLiveLocationShareManager location tick detected expired share for room $roomId, stopping")
|
||||||
|
stopShare(roomId)
|
||||||
|
}
|
||||||
|
val activeSharesCount = active.size
|
||||||
Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)")
|
Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)")
|
||||||
localSharingRoomIds.value.forEach { roomId ->
|
active.forEach { roomId ->
|
||||||
Timber.d("ActiveLiveLocationShareManager sending location to room $roomId")
|
Timber.d("ActiveLiveLocationShareManager sending location to room $roomId")
|
||||||
sendLiveLocation(roomId, location)
|
sendLiveLocation(roomId, location)
|
||||||
.onFailure {
|
.onFailure {
|
||||||
@@ -192,20 +203,21 @@ class DefaultActiveLiveLocationShareManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun scheduleTimeout(roomId: RoomId, expiresAt: Instant) {
|
private fun scheduleTimeout(roomId: RoomId, expiresAt: Instant) {
|
||||||
timeoutJobs.remove(roomId)?.cancel()
|
timeouts.remove(roomId)?.job?.cancel()
|
||||||
val delayMillis = expiresAt.toEpochMilliseconds() - clock.epochMillis()
|
val delayMillis = expiresAt.toEpochMilliseconds() - clock.epochMillis()
|
||||||
timeoutJobs[roomId] = matrixClient.sessionCoroutineScope.launch {
|
val job = matrixClient.sessionCoroutineScope.launch {
|
||||||
delay(delayMillis)
|
delay(delayMillis)
|
||||||
stopShare(roomId)
|
stopShare(roomId)
|
||||||
.onFailure { error ->
|
.onFailure { error ->
|
||||||
Timber.e(error, "ActiveLiveLocationShareManager failed to stop timed out share for room $roomId")
|
Timber.e(error, "ActiveLiveLocationShareManager failed to stop timed out share for room $roomId")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
timeouts[roomId] = Timeout(expiresAt = expiresAt, job = job)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun stopLocalShare(roomId: RoomId) {
|
private suspend fun stopLocalShare(roomId: RoomId) {
|
||||||
Timber.d("ActiveLiveLocationShareManager stop local share in $roomId")
|
Timber.d("ActiveLiveLocationShareManager stop local share in $roomId")
|
||||||
timeoutJobs.remove(roomId)?.cancel()
|
timeouts.remove(roomId)?.job?.cancel()
|
||||||
val wasSharing = localSharingRoomIds.getAndUpdate { it - roomId }.isNotEmpty()
|
val wasSharing = localSharingRoomIds.getAndUpdate { it - roomId }.isNotEmpty()
|
||||||
cachedRooms.remove(roomId)?.close()
|
cachedRooms.remove(roomId)?.close()
|
||||||
liveLocationStore.removeLiveLocationExpiry(roomId)
|
liveLocationStore.removeLiveLocationExpiry(roomId)
|
||||||
@@ -220,11 +232,11 @@ class DefaultActiveLiveLocationShareManager(
|
|||||||
sessionObserver.removeListener(sessionListener)
|
sessionObserver.removeListener(sessionListener)
|
||||||
coordinator.unregister(matrixClient.sessionId)
|
coordinator.unregister(matrixClient.sessionId)
|
||||||
liveLocationStore.clear()
|
liveLocationStore.clear()
|
||||||
|
timeouts.values.forEach { it.job.cancel() }
|
||||||
|
timeouts.clear()
|
||||||
for (room in cachedRooms.values) {
|
for (room in cachedRooms.values) {
|
||||||
room.close()
|
room.close()
|
||||||
timeoutJobs[room.roomId]?.cancel()
|
|
||||||
}
|
}
|
||||||
timeoutJobs.clear()
|
|
||||||
cachedRooms.clear()
|
cachedRooms.clear()
|
||||||
localSharingRoomIds.value = emptySet()
|
localSharingRoomIds.value = emptySet()
|
||||||
syncedActiveShareIds.value = emptySet()
|
syncedActiveShareIds.value = emptySet()
|
||||||
|
|||||||
Reference in New Issue
Block a user