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() data class StartChatEffect(val type: ChatEffect) : RoomDetailViewEvents()
object StopChatEffects : RoomDetailViewEvents() object StopChatEffects : RoomDetailViewEvents()
object RoomReplacementStarted : 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 switchToParentSpace: Boolean = false,
val rootThreadEventId: String? = null, val rootThreadEventId: String? = null,
val threadNotificationBadgeState: ThreadNotificationBadgeState = ThreadNotificationBadgeState(), val threadNotificationBadgeState: ThreadNotificationBadgeState = ThreadNotificationBadgeState(),
val typingUsers: List<SenderInfo>? = null val typingUsers: List<SenderInfo>? = null,
val isSharingLiveLocation: Boolean = false,
) : MavericksState { ) : MavericksState {
constructor(args: TimelineArgs) : this( constructor(args: TimelineArgs) : this(

View File

@ -498,7 +498,6 @@ class TimelineFragment @Inject constructor(
RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects() RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects()
is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it) is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
RoomDetailViewEvents.RoomReplacementStarted -> handleRoomReplacement() 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) { private fun displayErrorMessage(error: RoomDetailViewEvents.Failure) {
if (error.showInDialog) displayErrorDialog(error.throwable) else showErrorInSnackbar(error.throwable) if (error.showInDialog) displayErrorDialog(error.throwable) else showErrorInSnackbar(error.throwable)
} }
@ -1686,6 +1681,11 @@ class TimelineFragment @Inject constructor(
} else if (mainState.asyncInviter.complete) { } else if (mainState.asyncInviter.complete) {
vectorBaseActivity.finish() vectorBaseActivity.finish()
} }
updateLiveLocationIndicator(mainState.isSharingLiveLocation)
}
private fun updateLiveLocationIndicator(isSharingLiveLocation: Boolean) {
views.locationLiveStatusIndicator.isVisible = isSharingLiveLocation
} }
private fun FragmentTimelineBinding.hideComposerViews() { private fun FragmentTimelineBinding.hideComposerViews() {
@ -1706,7 +1706,7 @@ class TimelineFragment @Inject constructor(
private fun renderToolbar(roomSummary: RoomSummary?) { private fun renderToolbar(roomSummary: RoomSummary?) {
when { when {
isLocalRoom() -> { isLocalRoom() -> {
views.includeRoomToolbar.roomToolbarContentView.isVisible = false views.includeRoomToolbar.roomToolbarContentView.isVisible = false
views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false
setupToolbar(views.roomToolbar) setupToolbar(views.roomToolbar)
@ -1724,7 +1724,7 @@ class TimelineFragment @Inject constructor(
} }
views.includeThreadToolbar.roomToolbarThreadTitleTextView.text = resources.getText(R.string.thread_timeline_title) views.includeThreadToolbar.roomToolbarThreadTitleTextView.text = resources.getText(R.string.thread_timeline_title)
} }
else -> { else -> {
views.includeRoomToolbar.roomToolbarContentView.isVisible = true views.includeRoomToolbar.roomToolbarContentView.isVisible = true
views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false
if (roomSummary == null) { if (roomSummary == null) {

View File

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

View File

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

View File

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