diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt index c090487c58..2451b50e9b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt @@ -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 + } } diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index 5295cbaec3..14ba34cc52 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -76,6 +76,9 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel + locationPinProvider?.create(locationOwnerId) { pinDrawable -> GlideApp.with(holder.staticMapPinImageView) .load(pinDrawable) .into(holder.staticMapPinImageView) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index b58a1d627e..d219f45815 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -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 ) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index 086a093068..a0e70c8f70 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -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(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 diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 352b87a4d8..c501f5ea24 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -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) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt index e92376c44d..0cf30c8c01 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt @@ -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 diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt index 6f0b6abb72..607458678e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt @@ -41,14 +41,13 @@ abstract class MessageLocationItem : AbsMessageItem( 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) diff --git a/vector/src/main/java/im/vector/app/features/location/Config.kt b/vector/src/main/java/im/vector/app/features/location/Config.kt index 29ca6b81a9..82f3b0ae43 100644 --- a/vector/src/main/java/im/vector/app/features/location/Config.kt +++ b/vector/src/main/java/im/vector/app/features/location/Config.kt @@ -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 diff --git a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt index c4f2f148bf..92eaf2d112 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt @@ -121,7 +121,7 @@ class LocationPreviewFragment @Inject constructor( MapState( zoomOnlyOnce = true, pinLocationData = location, - pinId = args.locationOwnerId, + pinId = args.locationOwnerId ?: USER_PIN_NAME, pinDrawable = pinDrawable ) ) diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt index 67b36b8442..10c271727b 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt @@ -30,7 +30,7 @@ data class LocationSharingArgs( val roomId: String, val mode: LocationSharingMode, val initialLocationData: LocationData?, - val locationOwnerId: String + val locationOwnerId: String? ) : Parcelable @AndroidEntryPoint 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 f6bad2826b..7099bec9f0 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 @@ -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" - } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt index f3b937855a..960e6b5fb9 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt @@ -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 ) diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 8f0b1723a0..7062f6a97e 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -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) diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index d6ca83a8a3..275a1f214e 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -161,5 +161,5 @@ interface Navigator { roomId: String, mode: LocationSharingMode, initialLocationData: LocationData?, - locationOwnerId: String) + locationOwnerId: String?) } diff --git a/vector/src/main/res/drawable/ic_location_pin.xml b/vector/src/main/res/drawable/ic_location_pin.xml new file mode 100644 index 0000000000..8227ea4e05 --- /dev/null +++ b/vector/src/main/res/drawable/ic_location_pin.xml @@ -0,0 +1,13 @@ + + + + diff --git a/vector/src/test/java/im/vector/app/features/location/LocationDataTest.kt b/vector/src/test/java/im/vector/app/features/location/LocationDataTest.kt index fcfff0096f..088ce1a9ac 100644 --- a/vector/src/test/java/im/vector/app/features/location/LocationDataTest.kt +++ b/vector/src/test/java/im/vector/app/features/location/LocationDataTest.kt @@ -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) + } }