Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/7852.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Refactored location sharing timeline items to use the mapserver configured by the wellknown file
2 changes: 0 additions & 2 deletions library/ui-strings/src/main/res/values/donottranslate.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@
<!-- onboarding english only word play -->
<string name="cut_the_slack_from_teams" translatable="false">Cut the slack from teams.</string>

<!-- WIP -->
<string name="location_map_view_copyright" translatable="false">© MapTiler © OpenStreetMap contributors</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import android.widget.TextView
import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.bumptech.glide.request.RequestOptions
import com.mapbox.mapboxsdk.maps.MapView
import im.vector.app.R
import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
Expand All @@ -36,6 +36,7 @@ import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.action.LocationUiData
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.zoomToLocation
import im.vector.app.features.media.ImageContentRenderer
import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
import org.matrix.android.sdk.api.util.MatrixItem
Expand Down Expand Up @@ -98,10 +99,13 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
holder.body.isVisible = locationUiData == null
holder.mapViewContainer.isVisible = locationUiData != null
locationUiData?.let { safeLocationUiData ->
GlideApp.with(holder.staticMapImageView)
.load(safeLocationUiData.locationUrl)
.apply(RequestOptions.centerCropTransform())
.into(holder.staticMapImageView)
holder.staticMapView.getMapAsync { mapbox ->
mapbox.setStyle(safeLocationUiData.locationUrl)
safeLocationUiData.locationData?.let {
mapbox.zoomToLocation(it, animate = false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I think the zoom level may not be correct. What we want in the timeline is INITIAL_MAP_ZOOM_IN_TIMELINE. And zoomToLocation is not using this value but another one. We may have to change the extension method to pass the required zoom level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
mapbox.uiSettings.setAllGesturesEnabled(false)
}

safeLocationUiData.locationPinProvider.create(safeLocationUiData.locationOwnerId) { pinDrawable ->
GlideApp.with(holder.staticMapPinImageView)
Expand All @@ -124,7 +128,7 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
val timestamp by bind<TextView>(R.id.bottom_sheet_message_preview_timestamp)
val imagePreview by bind<ImageView>(R.id.bottom_sheet_message_preview_image)
val mapViewContainer by bind<FrameLayout>(R.id.mapViewContainer)
val staticMapImageView by bind<ImageView>(R.id.staticMapImageView)
val staticMapView by bind<MapView>(R.id.staticMapView)
val staticMapPinImageView by bind<ImageView>(R.id.staticMapPinImageView)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
import im.vector.app.features.VectorFeatures
import im.vector.app.features.location.UrlMapProvider
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import should be removed.

import im.vector.app.features.settings.VectorPreferences

class AttachmentTypeSelectorViewModel @AssistedInject constructor(
@Assisted initialState: AttachmentTypeSelectorViewState,
private val vectorFeatures: VectorFeatures,
private val vectorPreferences: VectorPreferences,
private val urlMapProvider: UrlMapProvider
) : VectorViewModel<AttachmentTypeSelectorViewState, AttachmentTypeSelectorAction, EmptyViewEvents>(initialState) {
@AssistedFactory
interface Factory : MavericksAssistedViewModelFactory<AttachmentTypeSelectorViewModel, AttachmentTypeSelectorViewState> {
Expand All @@ -48,7 +50,7 @@ class AttachmentTypeSelectorViewModel @AssistedInject constructor(
init {
setState {
copy(
isLocationVisible = vectorFeatures.isLocationSharingEnabled(),
isLocationVisible = vectorFeatures.isLocationSharingEnabled() && urlMapProvider.isMapConfigurationAvailable(),
isVoiceBroadcastVisible = vectorFeatures.isVoiceBroadcastEnabled(),
isTextFormattingEnabled = vectorPreferences.isTextFormattingEnabled(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import im.vector.app.features.analytics.extensions.toAnalyticsType
import im.vector.app.features.analytics.plan.Signup
import im.vector.app.features.analytics.store.AnalyticsStore
import im.vector.app.features.home.room.list.home.release.ReleaseNotesPreferencesStore
import im.vector.app.features.location.UrlMapProvider
import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.onboarding.AuthenticationDescription
import im.vector.app.features.raw.wellknown.ElementWellKnown
Expand Down Expand Up @@ -95,6 +96,7 @@ class HomeActivityViewModel @AssistedInject constructor(
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
private val ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase,
private val mapUrlProvider: UrlMapProvider,
) : VectorViewModel<HomeActivityViewState, HomeActivityViewActions, HomeActivityViewEvents>(initialState) {

@AssistedFactory
Expand Down Expand Up @@ -383,6 +385,9 @@ class HomeActivityViewModel @AssistedInject constructor(
}

val elementWellKnown = rawService.getElementWellknown(session.sessionParams)

mapUrlProvider.initWithWellknown(elementWellKnown)

val isSecureBackupRequired = elementWellKnown?.isSecureBackupRequired() ?: false

// In case of account creation, it is already done before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActi
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
import im.vector.app.features.html.PillImageSpan
import im.vector.app.features.location.LocationSharingMode
import im.vector.app.features.location.UrlMapProvider
import im.vector.app.features.poll.PollMode
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.share.SharedData
Expand Down Expand Up @@ -121,6 +122,7 @@ class MessageComposerFragment : VectorBaseFragment<FragmentComposerBinding>(), A
@Inject lateinit var buildMeta: BuildMeta
@Inject lateinit var session: Session
@Inject lateinit var errorTracker: ErrorTracker
@Inject lateinit var urlMapProvider: UrlMapProvider

private val roomId: String get() = withState(timelineViewModel) { it.roomId }

Expand Down Expand Up @@ -356,7 +358,7 @@ class MessageComposerFragment : VectorBaseFragment<FragmentComposerBinding>(), A
attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this@MessageComposerFragment)
attachmentTypeSelector.setAttachmentVisibility(
AttachmentType.LOCATION,
vectorFeatures.isLocationSharingEnabled(),
vectorFeatures.isLocationSharingEnabled() && urlMapProvider.isMapConfigurationAvailable(),
)
attachmentTypeSelector.setAttachmentVisibility(
AttachmentType.POLL, !isThreadTimeLine()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
package im.vector.app.features.home.room.detail.timeline.action

import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.location.LocationData

/**
* Data used to display Location data in the message bottom sheet.
*/
data class LocationUiData(
val locationData: LocationData?,
val locationUrl: String,
val locationOwnerId: String?,
val locationPinProvider: LocationPinProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import im.vector.app.features.home.room.detail.timeline.item.E2EDecoration
import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
import im.vector.app.features.home.room.detail.timeline.tools.linkify
import im.vector.app.features.html.SpanUtils
import im.vector.app.features.location.INITIAL_MAP_ZOOM_IN_TIMELINE
import im.vector.app.features.location.UrlMapProvider
import im.vector.app.features.location.toLocationData
import im.vector.app.features.media.ImageContentRenderer
Expand Down Expand Up @@ -228,13 +227,12 @@ class MessageActionsEpoxyController @Inject constructor(

val locationContent = state.timelineEvent()?.root?.getClearContent().toModel<MessageLocationContent>(catchError = true)
?: return null
val locationUrl = locationContent.toLocationData()
?.let { urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, 1200, 800) }
?: return null

val locationOwnerId = if (locationContent.isSelfLocation()) state.informationData.matrixItem.id else null

return LocationUiData(
locationUrl = locationUrl,
locationData = locationContent.toLocationData(),
locationUrl = urlMapProvider.getMapStyleUrl(),
locationOwnerId = locationOwnerId,
locationPinProvider = locationPinProvider,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import im.vector.app.features.home.room.detail.timeline.item.MessageLiveLocation
import im.vector.app.features.home.room.detail.timeline.item.MessageLiveLocationItem_
import im.vector.app.features.home.room.detail.timeline.item.MessageLiveLocationStartItem
import im.vector.app.features.home.room.detail.timeline.item.MessageLiveLocationStartItem_
import im.vector.app.features.location.INITIAL_MAP_ZOOM_IN_TIMELINE
import im.vector.app.features.location.UrlMapProvider
import im.vector.app.features.location.toLocationData
import org.matrix.android.sdk.api.session.Session
Expand Down Expand Up @@ -105,13 +104,12 @@ class LiveLocationShareMessageItemFactory @Inject constructor(
val width = timelineMediaSizeProvider.getMaxSize().first
val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)

val locationUrl = runningState.lastGeoUri.toLocationData()?.let {
urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, width, height)
}
val lastLocationData = runningState.lastGeoUri.toLocationData()

return MessageLiveLocationItem_()
.attributes(attributes)
.locationUrl(locationUrl)
.locationData(lastLocationData)
.mapStyleUrl(urlMapProvider.getMapStyleUrl())
.mapWidth(width)
.mapHeight(height)
.locationUserId(attributes.informationData.senderId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ 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.UrlMapProvider
import im.vector.app.features.location.toLocationData
import im.vector.app.features.media.ImageContentRenderer
Expand Down Expand Up @@ -222,15 +221,12 @@ class MessageItemFactory @Inject constructor(
val width = timelineMediaSizeProvider.getMaxSize().first
val height = dimensionConverter.dpToPx(MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)

val locationUrl = locationContent.toLocationData()?.let {
urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, width, height)
}

val locationUserId = if (locationContent.isSelfLocation()) informationData.senderId else null

return MessageLocationItem_()
.attributes(attributes)
.locationUrl(locationUrl)
.locationData(locationContent.toLocationData())
.mapStyleUrl(urlMapProvider.getMapStyleUrl())
.mapWidth(width)
.mapHeight(height)
.locationUserId(locationUserId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,34 @@

package im.vector.app.features.home.room.detail.timeline.item

import android.graphics.drawable.Drawable
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import com.airbnb.epoxy.EpoxyAttribute
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.mapbox.mapboxsdk.maps.MapView
import im.vector.app.R
import im.vector.app.core.glide.GlideApp
import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners
import im.vector.app.features.location.LocationData
import im.vector.app.features.location.MapLoadingErrorView
import im.vector.app.features.location.MapLoadingErrorViewState
import im.vector.app.features.location.zoomToLocation

abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>(
@LayoutRes layoutId: Int = R.layout.item_timeline_event_base
) : AbsMessageItem<H>(layoutId) {

@EpoxyAttribute
var locationUrl: String? = null
var locationData: LocationData? = null

@EpoxyAttribute
var mapStyleUrl: String? = null

@EpoxyAttribute
var locationUserId: String? = null
Expand All @@ -65,61 +64,52 @@ abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>(
}

private fun bindMap(holder: Holder) {
val location = locationUrl ?: return
val messageLayout = attributes.informationData.messageLayout
val imageCornerTransformation = if (messageLayout is TimelineMessageLayout.Bubble) {
messageLayout.cornersRadius.granularRoundedCorners()
} else {
val dimensionConverter = DimensionConverter(holder.view.resources)
RoundedCorners(dimensionConverter.dpToPx(8))
}
holder.staticMapImageView.updateLayoutParams {
holder.staticMapView.updateLayoutParams {
width = mapWidth
height = mapHeight
}
GlideApp.with(holder.staticMapImageView)
.load(location)
.apply(RequestOptions.centerCropTransform())
.placeholder(holder.staticMapImageView.drawable)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
holder.staticMapPinImageView.setImageDrawable(null)
holder.staticMapLoadingErrorView.isVisible = true
val mapErrorViewState = MapLoadingErrorViewState(imageCornerTransformation)
holder.staticMapLoadingErrorView.render(mapErrorViewState)
holder.staticMapCopyrightTextView.isVisible = false
return false
}

override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
locationPinProvider?.create(locationUserId) { pinDrawable ->
// we are not using Glide since it does not display it correctly when there is no user photo
holder.staticMapPinImageView.setImageDrawable(pinDrawable)
}
holder.staticMapLoadingErrorView.isVisible = false
holder.staticMapCopyrightTextView.isVisible = true
return false
}
})
.transform(imageCornerTransformation)
.into(holder.staticMapImageView)
holder.staticMapView.addOnDidFailLoadingMapListener {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some clean up about the map should be added in the unbind(holder: H) method. All listeners that can be removed should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

holder.staticMapLoadingErrorView.isVisible = true
val mapErrorViewState = MapLoadingErrorViewState(imageCornerTransformation)
holder.staticMapLoadingErrorView.render(mapErrorViewState)
}

holder.staticMapView.addOnDidFinishLoadingMapListener {
locationPinProvider?.create(locationUserId) { pinDrawable ->
holder.staticMapPinImageView.setImageDrawable(pinDrawable)
}
holder.staticMapLoadingErrorView.isVisible = false
}

holder.staticMapView.clipToOutline = true
holder.staticMapView.getMapAsync { mapbox ->
mapbox.setStyle(mapStyleUrl)
locationData?.let {
mapbox.zoomToLocation(it, animate = false)
}
mapbox.uiSettings.setAllGesturesEnabled(false)
mapbox.addOnMapClickListener {
attributes.itemClickListener?.invoke(holder.staticMapView)
true
}
mapbox.addOnMapLongClickListener {
attributes.itemLongClickListener?.onLongClick(holder.staticMapView)
true
}
}
}

abstract class Holder(@IdRes stubId: Int) : AbsMessageItem.Holder(stubId) {
val staticMapImageView by bind<ImageView>(R.id.staticMapImageView)
val staticMapView by bind<MapView>(R.id.staticMapView)
val staticMapPinImageView by bind<ImageView>(R.id.staticMapPinImageView)
val staticMapLoadingErrorView by bind<MapLoadingErrorView>(R.id.staticMapLoadingError)
val staticMapCopyrightTextView by bind<TextView>(R.id.staticMapCopyrightTextView)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class LocationSharingFragment :

lifecycleScope.launchWhenCreated {
views.mapView.initialize(
url = urlMapProvider.getMapUrl(),
url = urlMapProvider.getMapStyleUrl(),
locationTargetChangeListener = this@LocationSharingFragment
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,24 @@ import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.maps.MapboxMap

fun MapboxMap?.zoomToLocation(locationData: LocationData, preserveCurrentZoomLevel: Boolean = false) {
fun MapboxMap?.zoomToLocation(locationData: LocationData, preserveCurrentZoomLevel: Boolean = false, animate: Boolean = true) {
val zoomLevel = if (preserveCurrentZoomLevel && this?.cameraPosition != null) {
cameraPosition.zoom
} else {
INITIAL_MAP_ZOOM_IN_PREVIEW
}
this?.easeCamera {
CameraPosition.Builder()
.target(LatLng(locationData.latitude, locationData.longitude))
.zoom(zoomLevel)
.build()
val cameraPosition = CameraPosition.Builder()
.target(LatLng(locationData.latitude, locationData.longitude))
.zoom(zoomLevel)
.build()
if(animate) {
this?.easeCamera {
cameraPosition
}
} else {
this?.moveCamera {
cameraPosition
}
}
}

Expand Down
Loading