diff --git a/library/ui-styles/src/main/res/values-ldrtl/bools.xml b/library/ui-styles/src/main/res/values-ldrtl/bools.xml new file mode 100644 index 0000000000..27b280985f --- /dev/null +++ b/library/ui-styles/src/main/res/values-ldrtl/bools.xml @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/library/ui-styles/src/main/res/values/bools.xml b/library/ui-styles/src/main/res/values/bools.xml index 93d5f925af..9966999f28 100644 --- a/library/ui-styles/src/main/res/values/bools.xml +++ b/library/ui-styles/src/main/res/values/bools.xml @@ -4,4 +4,6 @@ false + false + \ No newline at end of file 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 8805c07109..5295cbaec3 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 @@ -36,9 +36,6 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.home.room.detail.timeline.item.BindingOptions import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess -import im.vector.app.features.location.INITIAL_MAP_ZOOM_IN_TIMELINE -import im.vector.app.features.location.LocationData -import im.vector.app.features.location.getStaticMapUrl import im.vector.app.features.media.ImageContentRenderer import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import org.matrix.android.sdk.api.util.MatrixItem @@ -74,7 +71,7 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel() { @@ -74,9 +77,11 @@ 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 locationData = state.timelineEvent()?.root?.getClearContent()?.toModel(catchError = true)?.let { - LocationData.create(it.getUri()) - } + val locationUrl = state.timelineEvent()?.root?.getClearContent() + ?.toModel(catchError = true) + ?.let { LocationData.create(it.getUri()) } + ?.let { urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, 1200, 800) } + bottomSheetMessagePreviewItem { id("preview") avatarRenderer(host.avatarRenderer) @@ -89,7 +94,7 @@ class MessageActionsEpoxyController @Inject constructor( body(body.toEpoxyCharSequence()) bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root)?.toEpoxyCharSequence()) time(formattedDate) - locationData(locationData) + locationUrl(locationUrl) locationPinProvider(host.locationPinProvider) } 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 b0bdef5636..8355aeed90 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 @@ -72,7 +72,9 @@ import im.vector.app.features.html.EventHtmlRenderer import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.html.SpanUtils import im.vector.app.features.html.VectorHtmlCompressor +import im.vector.app.features.location.INITIAL_MAP_ZOOM_IN_TIMELINE import im.vector.app.features.location.LocationData +import im.vector.app.features.location.UrlMapProvider import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.VideoContentRenderer import im.vector.app.features.settings.VectorPreferences @@ -129,7 +131,9 @@ class MessageItemFactory @Inject constructor( private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker, private val locationPinProvider: LocationPinProvider, private val vectorPreferences: VectorPreferences, - private val resources: Resources) { + private val urlMapProvider: UrlMapProvider, + private val resources: Resources +) { // TODO inject this properly? private var roomId: String = "" @@ -212,13 +216,15 @@ class MessageItemFactory @Inject constructor( val width = resources.displayMetrics.widthPixels - dimensionConverter.dpToPx(60) val height = dimensionConverter.dpToPx(200) + val locationUrl = locationData?.let { + urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, width, height) + } + return MessageLocationItem_() .attributes(attributes) - .locationData(locationData) + .locationUrl(locationUrl) .userId(informationData.senderId) .locationPinProvider(locationPinProvider) - .mapWidth(width) - .mapHeight(height) .highlighted(highlight) .leftGuideline(avatarSizeProvider.leftGuideline) .callback(mapCallback) 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 619d799ec5..1e8ce4fb4d 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 @@ -24,9 +24,6 @@ import im.vector.app.R import im.vector.app.core.epoxy.onClick import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider -import im.vector.app.features.location.INITIAL_MAP_ZOOM_IN_TIMELINE -import im.vector.app.features.location.LocationData -import im.vector.app.features.location.getStaticMapUrl @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageLocationItem : AbsMessageItem() { @@ -39,7 +36,7 @@ abstract class MessageLocationItem : AbsMessageItem( var callback: Callback? = null @EpoxyAttribute - var locationData: LocationData? = null + var locationUrl: String? = null @EpoxyAttribute var userId: String? = null @@ -47,17 +44,11 @@ abstract class MessageLocationItem : AbsMessageItem( @EpoxyAttribute var locationPinProvider: LocationPinProvider? = null - @EpoxyAttribute - var mapWidth: Int = 1200 - - @EpoxyAttribute - var mapHeight: Int = 800 - override fun bind(holder: Holder) { super.bind(holder) renderSendState(holder.view, null) - val location = locationData ?: return + val location = locationUrl ?: return val locationOwnerId = userId ?: return holder.view.onClick { @@ -65,7 +56,7 @@ abstract class MessageLocationItem : AbsMessageItem( } GlideApp.with(holder.staticMapImageView) - .load(getStaticMapUrl(location.latitude, location.longitude, INITIAL_MAP_ZOOM_IN_TIMELINE, mapWidth, mapHeight)) + .load(location) .apply(RequestOptions.centerCropTransform()) .into(holder.staticMapImageView) 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 eb5f1ac3b7..29ca6b81a9 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 @@ -16,34 +16,10 @@ package im.vector.app.features.location -import im.vector.app.BuildConfig - -const val MAP_STYLE_URL = "https://api.maptiler.com/maps/streets/style.json?key=${BuildConfig.mapTilerKey}" -private const val STATIC_MAP_IMAGE_URL = "https://api.maptiler.com/maps/basic/static/" +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 INITIAL_MAP_ZOOM_IN_PREVIEW = 15.0 const val INITIAL_MAP_ZOOM_IN_TIMELINE = 17.0 const val MIN_TIME_TO_UPDATE_LOCATION_MILLIS = 5 * 1_000L // every 5 seconds const val MIN_DISTANCE_TO_UPDATE_LOCATION_METERS = 10f - -fun getStaticMapUrl(latitude: Double, - longitude: Double, - zoom: Double, - width: Int, - height: Int): String { - return buildString { - append(STATIC_MAP_IMAGE_URL) - append(longitude) - append(",") - append(latitude) - append(",") - append(zoom) - append("/") - append(width) - append("x") - append(height) - append(".png?key=") - append(BuildConfig.mapTilerKey) - append("&attribution=bottomleft") - } -} 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 01417fdca0..c4f2f148bf 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 @@ -36,6 +36,7 @@ import javax.inject.Inject * TODO Move locationPinProvider to a ViewModel */ class LocationPreviewFragment @Inject constructor( + private val urlMapProvider: UrlMapProvider, private val locationPinProvider: LocationPinProvider ) : VectorBaseFragment() { @@ -53,7 +54,7 @@ class LocationPreviewFragment @Inject constructor( mapView = WeakReference(views.mapView) views.mapView.onCreate(savedInstanceState) - views.mapView.initialize() + views.mapView.initialize(urlMapProvider.mapUrl) loadPinDrawable() } 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 900d70e825..f6bad2826b 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 @@ -35,7 +35,9 @@ import javax.inject.Inject /** * We should consider using SupportMapFragment for a out of the box lifecycle handling */ -class LocationSharingFragment @Inject constructor() : VectorBaseFragment() { +class LocationSharingFragment @Inject constructor( + private val urlMapProvider: UrlMapProvider +) : VectorBaseFragment() { private val viewModel: LocationSharingViewModel by fragmentViewModel() @@ -51,7 +53,7 @@ class LocationSharingFragment @Inject constructor() : VectorBaseFragment - map.setStyle(MAP_STYLE_URL) { style -> + map.setStyle(url) { style -> mapRefs = MapRefs( map, SymbolManager(this, map, style), diff --git a/vector/src/main/java/im/vector/app/features/location/UrlMapProvider.kt b/vector/src/main/java/im/vector/app/features/location/UrlMapProvider.kt new file mode 100644 index 0000000000..76d44f5ece --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/UrlMapProvider.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.location + +import android.content.res.Resources +import im.vector.app.BuildConfig +import im.vector.app.R +import javax.inject.Inject + +class UrlMapProvider @Inject constructor( + private val resources: Resources +) { + private val keyParam = "?key=${BuildConfig.mapTilerKey}" + + // This is static so no need for a fun + val mapUrl = buildString { + append(MAP_BASE_URL) + append(keyParam) + } + + fun buildStaticMapUrl(locationData: LocationData, + zoom: Double, + width: Int, + height: Int): String { + return buildString { + append(STATIC_MAP_BASE_URL) + append(locationData.longitude) + append(",") + append(locationData.latitude) + append(",") + append(zoom) + append("/") + append(width) + append("x") + append(height) + append(".png") + append(keyParam) + if (!resources.getBoolean(R.bool.is_rtl)) { + // On LTR languages we want the legal mentions to be displayed on the bottom left of the image + append("&attribution=bottomleft") + } + } + } +}