diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml
index 6737f4faf1..08fe557f7c 100644
--- a/library/ui-styles/src/main/res/values/dimens.xml
+++ b/library/ui-styles/src/main/res/values/dimens.xml
@@ -64,4 +64,7 @@
10dp
+ 16dp
+ 12dp
+ 8dp
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt
index fb86033065..dc28c2dba9 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt
@@ -67,10 +67,12 @@ class LocationSharingFragment @Inject constructor(
lifecycleScope.launchWhenCreated {
views.mapView.initialize(
url = urlMapProvider.getMapUrl(),
+ showLocateBtn = true,
locationTargetChangeListener = this@LocationSharingFragment
)
}
+ initLocateBtn()
initOptionsPicker()
viewModel.observeViewEvents {
@@ -141,12 +143,18 @@ class LocationSharingFragment @Inject constructor(
.show()
}
+ private fun initLocateBtn() {
+ views.mapView.locateBtn.setOnClickListener {
+ // TODO retrieve user location and zoom to this location
+ }
+ }
+
private fun initOptionsPicker() {
// TODO
// reset map to user location when clicking on reset icon
+ // changes in the event sent when this is a pinned location
+ // changes in the parsing of events when receiving pinned location: since we may present a different UI
// unit tests
- // need changes in the event sent when this is a pin drop location?
- // need changes in the parsing of events when receiving pin drop location?: should it be shown with user avatar or with pin?
// set no option at start
views.shareLocationOptionsPicker.render()
views.shareLocationOptionsPicker.optionPinned.debouncedClicks {
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
index b721adb93f..5ad762adff 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
@@ -37,6 +37,9 @@ import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.util.toMatrixItem
+/**
+ * Sampling period to compare target location and user location.
+ */
private const val TARGET_LOCATION_CHANGE_SAMPLING_PERIOD_IN_MS = 100L
class LocationSharingViewModel @AssistedInject constructor(
@@ -122,7 +125,7 @@ class LocationSharingViewModel @AssistedInject constructor(
}
private fun handlePinnedLocationSharingAction(action: LocationSharingAction.PinnedLocationSharingAction) {
- // TODO check if we can use the same api than for user location?
+ // TODO confirm how to differentiate the user location and pinned location events?
shareLocation(action.locationData)
}
diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt
index 903b88423a..1c6a20aadf 100644
--- a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt
+++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt
@@ -18,7 +18,12 @@ package im.vector.app.features.location
import android.content.Context
import android.util.AttributeSet
+import android.view.Gravity
+import android.widget.ImageView
import androidx.core.content.ContextCompat
+import androidx.core.view.marginBottom
+import androidx.core.view.marginTop
+import androidx.core.view.updateLayoutParams
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.maps.MapView
@@ -47,16 +52,24 @@ class MapTilerMapView @JvmOverloads constructor(
private val userLocationDrawable by lazy {
ContextCompat.getDrawable(context, R.drawable.ic_location_user)
}
+ val locateBtn by lazy { createLocateBtn() }
private var mapRefs: MapRefs? = null
private var initZoomDone = false
/**
* For location fragments
*/
- fun initialize(url: String, locationTargetChangeListener: LocationTargetChangeListener? = null) {
+ fun initialize(
+ url: String,
+ showLocateBtn: Boolean = false, // TODO transform into xml attribute
+ locationTargetChangeListener: LocationTargetChangeListener? = null
+ ) {
Timber.d("## Location: initialize")
getMapAsync { map ->
initMapStyle(map, url)
+ if (showLocateBtn) {
+ showLocateBtn(map)
+ }
notifyLocationOfMapCenter(locationTargetChangeListener)
listenCameraMove(map, locationTargetChangeListener)
}
@@ -86,6 +99,30 @@ class MapTilerMapView @JvmOverloads constructor(
}
}
+ private fun createLocateBtn(): ImageView =
+ ImageView(context).apply {
+ setImageDrawable(ContextCompat.getDrawable(context, R.drawable.btn_locate))
+ contentDescription = context.getString(R.string.a11y_location_share_locate_btn)
+ layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
+ updateLayoutParams {
+ val marginHorizontal = context.resources.getDimensionPixelOffset(R.dimen.location_sharing_locate_btn_margin_horizontal)
+ val marginVertical = context.resources.getDimensionPixelOffset(R.dimen.location_sharing_locate_btn_margin_vertical)
+ setMargins(marginHorizontal, marginVertical, marginHorizontal, marginVertical)
+ }
+ updateLayoutParams {
+ gravity = Gravity.TOP or Gravity.END
+ }
+ }
+
+ private fun showLocateBtn(map: MapboxMap) {
+ addView(locateBtn)
+ locateBtn.post {
+ val marginTop = locateBtn.height + locateBtn.marginTop + locateBtn.marginBottom
+ val marginRight = context.resources.getDimensionPixelOffset(R.dimen.location_sharing_compass_btn_margin_horizontal)
+ map.uiSettings.setCompassMargins(0, marginTop, marginRight, 0)
+ }
+ }
+
fun render(state: MapState) {
val safeMapRefs = mapRefs ?: return Unit.also {
pendingState = state
@@ -93,7 +130,6 @@ class MapTilerMapView @JvmOverloads constructor(
safeMapRefs.map.uiSettings.setLogoMargins(0, 0, 0, state.logoMarginBottom)
- // TODO add reset to user location button
// TODO check conflict of rendering with preview location in timeline
val pinDrawable = state.pinDrawable ?: userLocationDrawable
pinDrawable?.let { drawable ->
@@ -110,7 +146,7 @@ class MapTilerMapView @JvmOverloads constructor(
}
safeMapRefs.symbolManager.deleteAll()
- if(pinDrawable != null && state.showPin) {
+ if (pinDrawable != null && state.showPin) {
safeMapRefs.symbolManager.create(
SymbolOptions()
.withLatLng(LatLng(locationData.latitude, locationData.longitude))
diff --git a/vector/src/main/res/drawable/btn_locate.xml b/vector/src/main/res/drawable/btn_locate.xml
new file mode 100644
index 0000000000..583b3a97ea
--- /dev/null
+++ b/vector/src/main/res/drawable/btn_locate.xml
@@ -0,0 +1,17 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_locate.xml b/vector/src/main/res/drawable/ic_locate.xml
new file mode 100644
index 0000000000..784665fcdd
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_locate.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 62f6c37428..bbb2bc7740 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -2930,6 +2930,7 @@
Share location
Pin of selected location on map
+ Zoom to current location
Share my current location
Share my current location
Share live location