Feature : share live location (#6741)

* First live location sharing sending implementation

* Simplify logic around canStop sharing

* Add some debug logs around LiveLocationSharingService

* Add LiveLocationException

* Expose beaconId to identify the current share

* Throttle live location instead of debouncing

* Keep sync alive when sharing live location

* Improve LiveLocation sharing

* Show LiveLocationDisclaimer

* Read minDistanceUpdate in LiveLocationSharingService

* Set minDistanceUpdate in AdvancedSettings

* Display banner in room when sharing live location

* Fix tests around LiveLocationSharing

* Ensure shares are properly restarted/stopped when app is re-launched

* Ensure LLS data is cleared when session is removed

* Update and fix LLS tests

* Handle Start LLS in ui

* Add check LLS permissions

* Remove hardcoded strings

* Fix quality and format

* Create DeviceLocationProvider so we can share location data between sources (presenter/live location service)

* Update screenshots

* Fix warning

* Do not try to stop if it was not sharing

* Revert "Create DeviceLocationProvider so we can share location data between sources (presenter/live location service)"

This reverts commit ba12bd968e82941cc231bdbb449310b24c97c5b8.

* Tweak location provider config values

* Address PR review remarks

* Fix ktlint

* Update screenshots

* Fix some tests after merging develop

* Adjust TimelineItemLocationView ui to match figma

* Update screenshots

* Documentation and cleanup

* Remove temporary resource

---------

Co-authored-by: ElementBot <android@element.io>
Co-authored-by: Benoit Marty <benoit@matrix.org>
Co-authored-by: Benoit Marty <benoitm@matrix.org>
This commit is contained in:
ganfra 2026-05-11 10:19:28 +02:00 committed by GitHub
parent 0c657c258a
commit e49e183178
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
145 changed files with 2913 additions and 278 deletions

View file

@ -34,6 +34,8 @@ interface AppForegroundStateService {
*/
val isSyncingNotificationEvent: StateFlow<Boolean>
val isSharingLiveLocation: StateFlow<Boolean>
/**
* Start observing the foreground state.
*/
@ -53,4 +55,6 @@ interface AppForegroundStateService {
* Update the active state for the syncing notification event flow.
*/
fun updateIsSyncingNotificationEvent(isSyncingNotificationEvent: Boolean)
fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean)
}

View file

@ -20,6 +20,8 @@ class DefaultAppForegroundStateService : AppForegroundStateService {
override val isSyncingNotificationEvent = MutableStateFlow(false)
override val hasRingingCall = MutableStateFlow(false)
override val isSharingLiveLocation = MutableStateFlow<Boolean>(false)
private val appLifecycle: Lifecycle by lazy { ProcessLifecycleOwner.get().lifecycle }
override fun startObservingForeground() {
@ -38,6 +40,10 @@ class DefaultAppForegroundStateService : AppForegroundStateService {
this.isSyncingNotificationEvent.value = isSyncingNotificationEvent
}
override fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) {
this.isSharingLiveLocation.value = isSharingLiveLocation
}
private val lifecycleObserver = LifecycleEventObserver { _, _ -> isInForeground.value = getCurrentState() }
private fun getCurrentState(): Boolean = appLifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)

View file

@ -16,12 +16,15 @@ class FakeAppForegroundStateService(
initialIsInCallValue: Boolean = false,
initialIsSyncingNotificationEventValue: Boolean = false,
initialHasRingingCall: Boolean = false,
initialIsSharingLiveLocation: Boolean = false,
) : AppForegroundStateService {
override val isInForeground = MutableStateFlow(initialForegroundValue)
override val isInCall = MutableStateFlow(initialIsInCallValue)
override val isSyncingNotificationEvent = MutableStateFlow(initialIsSyncingNotificationEventValue)
override val hasRingingCall = MutableStateFlow(initialHasRingingCall)
override val isSharingLiveLocation = MutableStateFlow<Boolean>(initialIsSharingLiveLocation)
override fun startObservingForeground() {
// No-op
}
@ -41,4 +44,8 @@ class FakeAppForegroundStateService(
override fun updateHasRingingCall(hasRingingCall: Boolean) {
this.hasRingingCall.value = hasRingingCall
}
override fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) {
this.isSharingLiveLocation.value = isSharingLiveLocation
}
}