mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 10:25:35 +03:00
Support generic location pin.
This commit is contained in:
parent
6213cc73c0
commit
37d35c9a7f
16 changed files with 68 additions and 17 deletions
|
@ -64,4 +64,12 @@ data class MessageLocationContent(
|
|||
) : MessageContent {
|
||||
|
||||
fun getBestGeoUri() = locationInfo?.geoUri ?: geoUri
|
||||
|
||||
/**
|
||||
* @return true if location asset is different than LocationAssetType.SELF
|
||||
*/
|
||||
fun isGenericLocation(): Boolean {
|
||||
// Should behave like m.self if locationAsset is null
|
||||
return locationAsset != null && locationAsset.type != LocationAssetType.SELF
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,9 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
|
|||
@EpoxyAttribute
|
||||
var locationPinProvider: LocationPinProvider? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var locationOwnerId: String? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var movementMethod: MovementMethod? = null
|
||||
|
||||
|
@ -109,7 +112,7 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
|
|||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(holder.staticMapImageView)
|
||||
|
||||
locationPinProvider?.create(matrixItem.id) { pinDrawable ->
|
||||
locationPinProvider?.create(locationOwnerId) { pinDrawable ->
|
||||
GlideApp.with(holder.staticMapPinImageView)
|
||||
.load(pinDrawable)
|
||||
.into(holder.staticMapPinImageView)
|
||||
|
|
|
@ -613,13 +613,14 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun handleShowLocationPreview(locationContent: MessageLocationContent, senderId: String) {
|
||||
val isGenericLocation = locationContent.isGenericLocation()
|
||||
navigator
|
||||
.openLocationSharing(
|
||||
context = requireContext(),
|
||||
roomId = roomDetailArgs.roomId,
|
||||
mode = LocationSharingMode.PREVIEW,
|
||||
initialLocationData = locationContent.toLocationData(),
|
||||
locationOwnerId = senderId
|
||||
locationOwnerId = if (isGenericLocation) null else senderId
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -77,10 +77,12 @@ class MessageActionsEpoxyController @Inject constructor(
|
|||
val formattedDate = dateFormatter.format(date, DateFormatKind.MESSAGE_DETAIL)
|
||||
val body = state.messageBody.linkify(host.listener)
|
||||
val bindingOptions = spanUtils.getBindingOptions(body)
|
||||
val locationUrl = state.timelineEvent()?.root?.getClearContent()
|
||||
|
||||
val locationContent = state.timelineEvent()?.root?.getClearContent()
|
||||
?.toModel<MessageLocationContent>(catchError = true)
|
||||
?.toLocationData()
|
||||
val locationUrl = locationContent?.toLocationData()
|
||||
?.let { urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, 1200, 800) }
|
||||
val locationOwnerId = if (locationContent?.isGenericLocation().orFalse()) null else state.informationData.matrixItem.id
|
||||
|
||||
bottomSheetMessagePreviewItem {
|
||||
id("preview")
|
||||
|
@ -96,6 +98,7 @@ class MessageActionsEpoxyController @Inject constructor(
|
|||
time(formattedDate)
|
||||
locationUrl(locationUrl)
|
||||
locationPinProvider(host.locationPinProvider)
|
||||
locationOwnerId(locationOwnerId)
|
||||
}
|
||||
|
||||
// Send state
|
||||
|
|
|
@ -207,10 +207,12 @@ class MessageItemFactory @Inject constructor(
|
|||
urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, width, height)
|
||||
}
|
||||
|
||||
val userId = if (locationContent.isGenericLocation()) null else informationData.senderId
|
||||
|
||||
return MessageLocationItem_()
|
||||
.attributes(attributes)
|
||||
.locationUrl(locationUrl)
|
||||
.userId(informationData.senderId)
|
||||
.userId(userId)
|
||||
.locationPinProvider(locationPinProvider)
|
||||
.highlighted(highlight)
|
||||
.leftGuideline(avatarSizeProvider.leftGuideline)
|
||||
|
|
|
@ -45,7 +45,17 @@ class LocationPinProvider @Inject constructor(
|
|||
GlideApp.with(context)
|
||||
}
|
||||
|
||||
fun create(userId: String, callback: (Drawable) -> Unit) {
|
||||
/**
|
||||
* Creates a pin drawable. If userId is null then a generic pin drawable will be created.
|
||||
* @param userId userId that will be used to retrieve user avatar
|
||||
* @param callback Pin drawable will be sent through the callback
|
||||
*/
|
||||
fun create(userId: String?, callback: (Drawable) -> Unit) {
|
||||
if (userId == null) {
|
||||
callback(ContextCompat.getDrawable(context, R.drawable.ic_location_pin)!!)
|
||||
return
|
||||
}
|
||||
|
||||
if (cache.contains(userId)) {
|
||||
callback(cache[userId]!!)
|
||||
return
|
||||
|
|
|
@ -41,14 +41,13 @@ abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>(
|
|||
renderSendState(holder.view, null)
|
||||
|
||||
val location = locationUrl ?: return
|
||||
val locationOwnerId = userId ?: return
|
||||
|
||||
GlideApp.with(holder.staticMapImageView)
|
||||
.load(location)
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(holder.staticMapImageView)
|
||||
|
||||
locationPinProvider?.create(locationOwnerId) { pinDrawable ->
|
||||
locationPinProvider?.create(userId) { pinDrawable ->
|
||||
GlideApp.with(holder.staticMapPinImageView)
|
||||
.load(pinDrawable)
|
||||
.into(holder.staticMapPinImageView)
|
||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.location
|
|||
|
||||
const val MAP_BASE_URL = "https://api.maptiler.com/maps/streets/style.json"
|
||||
const val STATIC_MAP_BASE_URL = "https://api.maptiler.com/maps/basic/static/"
|
||||
const val USER_PIN_NAME = "USER_PIN_NAME"
|
||||
|
||||
const val INITIAL_MAP_ZOOM_IN_PREVIEW = 15.0
|
||||
const val INITIAL_MAP_ZOOM_IN_TIMELINE = 17.0
|
||||
|
|
|
@ -121,7 +121,7 @@ class LocationPreviewFragment @Inject constructor(
|
|||
MapState(
|
||||
zoomOnlyOnce = true,
|
||||
pinLocationData = location,
|
||||
pinId = args.locationOwnerId,
|
||||
pinId = args.locationOwnerId ?: USER_PIN_NAME,
|
||||
pinDrawable = pinDrawable
|
||||
)
|
||||
)
|
||||
|
|
|
@ -30,7 +30,7 @@ data class LocationSharingArgs(
|
|||
val roomId: String,
|
||||
val mode: LocationSharingMode,
|
||||
val initialLocationData: LocationData?,
|
||||
val locationOwnerId: String
|
||||
val locationOwnerId: String?
|
||||
) : Parcelable
|
||||
|
||||
@AndroidEntryPoint
|
||||
|
|
|
@ -118,8 +118,4 @@ class LocationSharingFragment @Inject constructor(
|
|||
views.mapView.render(state.toMapState())
|
||||
views.shareLocationGpsLoading.isGone = state.lastKnownLocation != null
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val USER_PIN_NAME = "USER_PIN_NAME"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,6 @@ data class LocationSharingViewState(
|
|||
fun LocationSharingViewState.toMapState() = MapState(
|
||||
zoomOnlyOnce = true,
|
||||
pinLocationData = lastKnownLocation,
|
||||
pinId = LocationSharingFragment.USER_PIN_NAME,
|
||||
pinId = USER_PIN_NAME,
|
||||
pinDrawable = pinDrawable
|
||||
)
|
||||
|
|
|
@ -545,7 +545,7 @@ class DefaultNavigator @Inject constructor(
|
|||
roomId: String,
|
||||
mode: LocationSharingMode,
|
||||
initialLocationData: LocationData?,
|
||||
locationOwnerId: String) {
|
||||
locationOwnerId: String?) {
|
||||
val intent = LocationSharingActivity.getIntent(
|
||||
context,
|
||||
LocationSharingArgs(roomId = roomId, mode = mode, initialLocationData = initialLocationData, locationOwnerId = locationOwnerId)
|
||||
|
|
|
@ -161,5 +161,5 @@ interface Navigator {
|
|||
roomId: String,
|
||||
mode: LocationSharingMode,
|
||||
initialLocationData: LocationData?,
|
||||
locationOwnerId: String)
|
||||
locationOwnerId: String?)
|
||||
}
|
||||
|
|
13
vector/src/main/res/drawable/ic_location_pin.xml
Normal file
13
vector/src/main/res/drawable/ic_location_pin.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="51dp"
|
||||
android:height="54dp"
|
||||
android:viewportWidth="51"
|
||||
android:viewportHeight="54">
|
||||
<path
|
||||
android:pathData="M27.2956,44.2191C37.5577,42.7292 45.4403,33.8952 45.4403,23.2202C45.4403,11.5006 35.9397,2 24.2202,2C12.5006,2 3,11.5006 3,23.2202C3,33.8953 10.8827,42.7293 21.1449,44.2191L24.2202,47.1784L27.2956,44.2191Z"
|
||||
android:fillColor="#0DBD8B"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M23.8041,15.073C20.5837,15.073 17.979,17.7486 17.979,21.0567C17.979,24.6213 21.6572,29.5365 23.1717,31.4085C23.5046,31.8188 24.112,31.8188 24.4449,31.4085C25.9511,29.5365 29.6293,24.6213 29.6293,21.0567C29.6293,17.7486 27.0246,15.073 23.8041,15.073ZM23.8041,23.1937C22.6558,23.1937 21.7237,22.2364 21.7237,21.0567C21.7237,19.8771 22.6558,18.9197 23.8041,18.9197C24.9525,18.9197 25.8846,19.8771 25.8846,21.0567C25.8846,22.2364 24.9525,23.1937 23.8041,23.1937Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
|
@ -19,6 +19,9 @@ package im.vector.app.features.location
|
|||
import org.amshove.kluent.shouldBeEqualTo
|
||||
import org.amshove.kluent.shouldBeNull
|
||||
import org.junit.Test
|
||||
import org.matrix.android.sdk.api.session.room.model.message.LocationAsset
|
||||
import org.matrix.android.sdk.api.session.room.model.message.LocationAssetType
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent
|
||||
|
||||
class LocationDataTest {
|
||||
@Test
|
||||
|
@ -57,4 +60,16 @@ class LocationDataTest {
|
|||
parseGeo("ge o:12.34,56.78;13.56").shouldBeNull()
|
||||
parseGeo("geo :12.34,56.78;13.56").shouldBeNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun genericLocationTest() {
|
||||
val contentWithNullAsset = MessageLocationContent(body = "", geoUri = "", locationAsset = null)
|
||||
contentWithNullAsset.isGenericLocation() shouldBeEqualTo(false)
|
||||
|
||||
val contentWithNullAssetType = MessageLocationContent(body = "", geoUri = "", locationAsset = LocationAsset(type = null))
|
||||
contentWithNullAssetType.isGenericLocation() shouldBeEqualTo(true)
|
||||
|
||||
val contentWithSelfAssetType = MessageLocationContent(body = "", geoUri = "", locationAsset = LocationAsset(type = LocationAssetType.SELF))
|
||||
contentWithSelfAssetType.isGenericLocation() shouldBeEqualTo(false)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue