Merge pull request #6539 from vector-im/bugfix/mna/lls-status-bar-disappearing

[Location Share] - Wrong room live location status bar visibility in timeline (PSG-625)
This commit is contained in:
Maxime NATUREL 2022-07-20 09:55:06 +02:00 committed by GitHub
commit 448b6e1c74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 22 deletions

1
changelog.d/6537.bugfix Normal file
View file

@ -0,0 +1 @@
[Location Share] - Wrong room live location status bar visibility in timeline

View file

@ -84,6 +84,4 @@ sealed class RoomDetailViewEvents : VectorViewEvents {
data class StartChatEffect(val type: ChatEffect) : RoomDetailViewEvents()
object StopChatEffects : RoomDetailViewEvents()
object RoomReplacementStarted : RoomDetailViewEvents()
data class ChangeLocationIndicator(val isVisible: Boolean) : RoomDetailViewEvents()
}

View file

@ -75,7 +75,8 @@ data class RoomDetailViewState(
val switchToParentSpace: Boolean = false,
val rootThreadEventId: String? = null,
val threadNotificationBadgeState: ThreadNotificationBadgeState = ThreadNotificationBadgeState(),
val typingUsers: List<SenderInfo>? = null
val typingUsers: List<SenderInfo>? = null,
val isSharingLiveLocation: Boolean = false,
) : MavericksState {
constructor(args: TimelineArgs) : this(

View file

@ -498,7 +498,6 @@ class TimelineFragment @Inject constructor(
RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects()
is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
RoomDetailViewEvents.RoomReplacementStarted -> handleRoomReplacement()
is RoomDetailViewEvents.ChangeLocationIndicator -> handleChangeLocationIndicator(it)
}
}
@ -663,10 +662,6 @@ class TimelineFragment @Inject constructor(
)
}
private fun handleChangeLocationIndicator(event: RoomDetailViewEvents.ChangeLocationIndicator) {
views.locationLiveStatusIndicator.isVisible = event.isVisible
}
private fun displayErrorMessage(error: RoomDetailViewEvents.Failure) {
if (error.showInDialog) displayErrorDialog(error.throwable) else showErrorInSnackbar(error.throwable)
}
@ -1686,6 +1681,11 @@ class TimelineFragment @Inject constructor(
} else if (mainState.asyncInviter.complete) {
vectorBaseActivity.finish()
}
updateLiveLocationIndicator(mainState.isSharingLiveLocation)
}
private fun updateLiveLocationIndicator(isSharingLiveLocation: Boolean) {
views.locationLiveStatusIndicator.isVisible = isSharingLiveLocation
}
private fun FragmentTimelineBinding.hideComposerViews() {

View file

@ -1303,12 +1303,12 @@ class TimelineViewModel @AssistedInject constructor(
_viewEvents.post(RoomDetailViewEvents.OnNewTimelineEvents(eventIds))
}
override fun onLocationServiceRunning() {
_viewEvents.post(RoomDetailViewEvents.ChangeLocationIndicator(isVisible = true))
override fun onLocationServiceRunning(roomIds: Set<String>) {
setState { copy(isSharingLiveLocation = roomId in roomIds) }
}
override fun onLocationServiceStopped() {
_viewEvents.post(RoomDetailViewEvents.ChangeLocationIndicator(isVisible = false))
setState { copy(isSharingLiveLocation = false) }
// Bind again in case user decides to share live location without leaving the room
locationSharingServiceConnection.bind(this)
}

View file

@ -30,6 +30,8 @@ import im.vector.app.features.redaction.CheckIfEventIsRedactedUseCase
import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
@ -68,6 +70,9 @@ class LocationSharingAndroidService : VectorAndroidService(), LocationTracker.Ca
private val jobs = mutableListOf<Job>()
private var startInProgress = false
private val _roomIdsOfActiveLives = MutableSharedFlow<Set<String>>(replay = 1)
val roomIdsOfActiveLives = _roomIdsOfActiveLives.asSharedFlow()
override fun onCreate() {
super.onCreate()
Timber.i("onCreate")
@ -195,11 +200,13 @@ class LocationSharingAndroidService : VectorAndroidService(), LocationTracker.Ca
private fun addRoomArgs(beaconEventId: String, roomArgs: RoomArgs) {
Timber.i("adding roomArgs for beaconEventId: $beaconEventId")
roomArgsMap[beaconEventId] = roomArgs
launchWithActiveSession { _roomIdsOfActiveLives.emit(getRoomIdsOfActiveLives()) }
}
private fun removeRoomArgs(beaconEventId: String) {
Timber.i("removing roomArgs for beaconEventId: $beaconEventId")
roomArgsMap.remove(beaconEventId)
launchWithActiveSession { _roomIdsOfActiveLives.emit(getRoomIdsOfActiveLives()) }
}
private fun listenForLiveSummaryChanges(roomId: String, beaconEventId: String) {
@ -226,6 +233,10 @@ class LocationSharingAndroidService : VectorAndroidService(), LocationTracker.Ca
)
}
fun getRoomIdsOfActiveLives(): Set<String> {
return roomArgsMap.map { it.value.roomId }.toSet()
}
override fun onBind(intent: Intent?): IBinder {
return binder
}

View file

@ -21,17 +21,22 @@ import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LocationSharingServiceConnection @Inject constructor(
private val context: Context
) : ServiceConnection,
LocationSharingAndroidService.Callback {
private val context: Context,
private val activeSessionHolder: ActiveSessionHolder
) : ServiceConnection, LocationSharingAndroidService.Callback {
interface Callback {
fun onLocationServiceRunning()
fun onLocationServiceRunning(roomIds: Set<String>)
fun onLocationServiceStopped()
fun onLocationServiceError(error: Throwable)
}
@ -44,7 +49,7 @@ class LocationSharingServiceConnection @Inject constructor(
addCallback(callback)
if (isBound) {
callback.onLocationServiceRunning()
callback.onLocationServiceRunning(getRoomIdsOfActiveLives())
} else {
Intent(context, LocationSharingAndroidService::class.java).also { intent ->
context.bindService(intent, this, 0)
@ -56,12 +61,24 @@ class LocationSharingServiceConnection @Inject constructor(
removeCallback(callback)
}
private fun getRoomIdsOfActiveLives(): Set<String> {
return locationSharingAndroidService?.getRoomIdsOfActiveLives() ?: emptySet()
}
override fun onServiceConnected(className: ComponentName, binder: IBinder) {
locationSharingAndroidService = (binder as LocationSharingAndroidService.LocalBinder).getService().also {
it.callback = this
locationSharingAndroidService = (binder as LocationSharingAndroidService.LocalBinder).getService().also { service ->
service.callback = this
getActiveSessionCoroutineScope()?.let { scope ->
service.roomIdsOfActiveLives
.onEach(::onRoomIdsUpdate)
.launchIn(scope)
}
}
isBound = true
onCallbackActionNoArg(Callback::onLocationServiceRunning)
}
private fun getActiveSessionCoroutineScope(): CoroutineScope? {
return activeSessionHolder.getSafeActiveSession()?.coroutineScope
}
override fun onServiceDisconnected(className: ComponentName) {
@ -71,6 +88,10 @@ class LocationSharingServiceConnection @Inject constructor(
onCallbackActionNoArg(Callback::onLocationServiceStopped)
}
private fun onRoomIdsUpdate(roomIds: Set<String>) {
forwardRoomIdsToCallbacks(roomIds)
}
override fun onServiceError(error: Throwable) {
forwardErrorToCallbacks(error)
}
@ -87,6 +108,10 @@ class LocationSharingServiceConnection @Inject constructor(
callbacks.toList().forEach(action)
}
private fun forwardRoomIdsToCallbacks(roomIds: Set<String>) {
callbacks.toList().forEach { it.onLocationServiceRunning(roomIds) }
}
private fun forwardErrorToCallbacks(error: Throwable) {
callbacks.toList().forEach { it.onLocationServiceError(error) }
}

View file

@ -87,7 +87,7 @@ class LocationLiveMapViewModel @AssistedInject constructor(
}
}
override fun onLocationServiceRunning() {
override fun onLocationServiceRunning(roomIds: Set<String>) {
// NOOP
}