Use static map image in timeline.
This commit is contained in:
parent
4026ddb34f
commit
50279e3183
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.app.features.home.room.detail.timeline.factory
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
|
@ -127,7 +128,8 @@ class MessageItemFactory @Inject constructor(
|
|||
private val session: Session,
|
||||
private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker,
|
||||
private val locationPinProvider: LocationPinProvider,
|
||||
private val vectorPreferences: VectorPreferences) {
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val resources: Resources) {
|
||||
|
||||
// TODO inject this properly?
|
||||
private var roomId: String = ""
|
||||
|
@ -207,11 +209,16 @@ class MessageItemFactory @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
val width = resources.displayMetrics.widthPixels - dimensionConverter.dpToPx(60)
|
||||
val height = dimensionConverter.dpToPx(200)
|
||||
|
||||
return MessageLocationItem_()
|
||||
.attributes(attributes)
|
||||
.locationData(locationData)
|
||||
.userId(informationData.senderId)
|
||||
.locationPinProvider(locationPinProvider)
|
||||
.mapWidth(width)
|
||||
.mapHeight(height)
|
||||
.highlighted(highlight)
|
||||
.leftGuideline(avatarSizeProvider.leftGuideline)
|
||||
.callback(mapCallback)
|
||||
|
|
|
@ -17,15 +17,17 @@
|
|||
package im.vector.app.features.home.room.detail.timeline.item
|
||||
|
||||
import android.widget.FrameLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import android.widget.ImageView
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
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.MapState
|
||||
import im.vector.app.features.location.MapTilerMapView
|
||||
import im.vector.app.features.location.getStaticMapUrl
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_base)
|
||||
abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>() {
|
||||
|
@ -46,6 +48,12 @@ abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>(
|
|||
@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.mapViewContainer, null)
|
||||
|
@ -53,39 +61,28 @@ abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>(
|
|||
val location = locationData ?: return
|
||||
val locationOwnerId = userId ?: return
|
||||
|
||||
holder.clickableMapArea.onClick {
|
||||
holder.mapViewContainer.onClick {
|
||||
callback?.onMapClicked()
|
||||
}
|
||||
|
||||
holder.mapView.initialize()
|
||||
holder.mapView.render(
|
||||
MapState(
|
||||
zoomOnlyOnce = false,
|
||||
pinLocationData = location,
|
||||
pinId = locationOwnerId,
|
||||
pinDrawable = null
|
||||
)
|
||||
)
|
||||
GlideApp.with(holder.staticMapImageView)
|
||||
.load(getStaticMapUrl(location.latitude, location.longitude, INITIAL_MAP_ZOOM_IN_TIMELINE, mapWidth, mapHeight))
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(holder.staticMapImageView)
|
||||
|
||||
locationPinProvider?.create(locationOwnerId) { pinDrawable ->
|
||||
if (holder.view.isAttachedToWindow) {
|
||||
holder.mapView.render(
|
||||
MapState(
|
||||
zoomOnlyOnce = false,
|
||||
pinLocationData = location,
|
||||
pinId = locationOwnerId,
|
||||
pinDrawable = pinDrawable
|
||||
)
|
||||
)
|
||||
}
|
||||
GlideApp.with(holder.staticMapPinImageView)
|
||||
.load(pinDrawable)
|
||||
.into(holder.staticMapPinImageView)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getViewType() = STUB_ID
|
||||
|
||||
class Holder : AbsMessageItem.Holder(STUB_ID) {
|
||||
val mapViewContainer by bind<ConstraintLayout>(R.id.mapViewContainer)
|
||||
val mapView by bind<MapTilerMapView>(R.id.mapView)
|
||||
val clickableMapArea by bind<FrameLayout>(R.id.clickableMapArea)
|
||||
val mapViewContainer by bind<FrameLayout>(R.id.mapViewContainer)
|
||||
val staticMapImageView by bind<ImageView>(R.id.staticMapImageView)
|
||||
val staticMapPinImageView by bind<ImageView>(R.id.staticMapPinImageView)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -16,6 +16,33 @@
|
|||
|
||||
package im.vector.app.features.location
|
||||
|
||||
const val INITIAL_MAP_ZOOM = 15.0
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ import javax.inject.Inject
|
|||
/**
|
||||
* We should consider using SupportMapFragment for a out of the box lifecycle handling
|
||||
*/
|
||||
class LocationSharingFragment @Inject constructor(
|
||||
) : VectorBaseFragment<FragmentLocationSharingBinding>() {
|
||||
class LocationSharingFragment @Inject constructor() : VectorBaseFragment<FragmentLocationSharingBinding>() {
|
||||
|
||||
private val viewModel: LocationSharingViewModel by fragmentViewModel()
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ import com.mapbox.mapboxsdk.maps.Style
|
|||
import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
|
||||
import com.mapbox.mapboxsdk.style.layers.Property
|
||||
import im.vector.app.BuildConfig
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
|
@ -58,7 +57,7 @@ class MapTilerMapView @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
getMapAsync { map ->
|
||||
map.setStyle(styleUrl) { style ->
|
||||
map.setStyle(MAP_STYLE_URL) { style ->
|
||||
mapRefs = MapRefs(
|
||||
map,
|
||||
SymbolManager(this, map, style),
|
||||
|
@ -102,11 +101,7 @@ class MapTilerMapView @JvmOverloads constructor(
|
|||
Timber.d("## Location: zoomToLocation")
|
||||
mapRefs?.map?.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(latitude, longitude))
|
||||
.zoom(INITIAL_MAP_ZOOM)
|
||||
.zoom(INITIAL_MAP_ZOOM_IN_PREVIEW)
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val styleUrl = "https://api.maptiler.com/maps/streets/style.json?key=${BuildConfig.mapTilerKey}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,30 +6,25 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="8dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<FrameLayout
|
||||
android:id="@+id/mapViewContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<im.vector.app.features.location.MapTilerMapView
|
||||
android:id="@+id/mapView"
|
||||
android:layout_width="0dp"
|
||||
<ImageView
|
||||
android:id="@+id/staticMapImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:mapbox_renderTextureMode="true" />
|
||||
android:contentDescription="@string/a11y_static_map_image" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/clickableMapArea"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/mapView"
|
||||
app:layout_constraintEnd_toEndOf="@id/mapView"
|
||||
app:layout_constraintStart_toStartOf="@id/mapView"
|
||||
app:layout_constraintTop_toTopOf="@id/mapView" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<ImageView
|
||||
android:id="@+id/staticMapPinImageView"
|
||||
android:layout_width="51dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="28dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/bg_map_user_pin" />
|
||||
</FrameLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
|
|
@ -3711,6 +3711,7 @@
|
|||
<string name="location_activity_title_static_sharing">Share location</string>
|
||||
<string name="location_activity_title_preview">Location</string>
|
||||
<string name="a11y_location_share_icon">Share location</string>
|
||||
<string name="a11y_static_map_image">Map</string>
|
||||
<string name="location_share">Share location</string>
|
||||
<string name="template_location_not_available_dialog_title">${app_name} could not access your location</string>
|
||||
<string name="template_location_not_available_dialog_content">${app_name} could not access your location. Please try again later.</string>
|
||||
|
|
Loading…
Reference in New Issue