mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-16 03:08:58 +03:00
Rework the location code - WIP
This commit is contained in:
parent
e9b9406bf1
commit
1f53945031
7 changed files with 104 additions and 74 deletions
|
@ -34,6 +34,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvid
|
|||
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.LocationData
|
||||
import im.vector.app.features.location.MapState
|
||||
import im.vector.app.features.location.MapTilerMapView
|
||||
import im.vector.app.features.media.ImageContentRenderer
|
||||
import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
|
||||
|
@ -99,15 +100,25 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel<BottomSheetMessa
|
|||
|
||||
holder.mapView.isVisible = locationData != null
|
||||
holder.body.isVisible = locationData == null
|
||||
locationData?.let { location ->
|
||||
holder.mapView.initialize {
|
||||
if (holder.view.isAttachedToWindow) {
|
||||
holder.mapView.zoomToLocation(location.latitude, location.longitude, 15.0)
|
||||
locationPinProvider?.create(matrixItem.id) { pinDrawable ->
|
||||
holder.mapView.addPinToMap(matrixItem.id, pinDrawable)
|
||||
holder.mapView.updatePinLocation(matrixItem.id, location.latitude, location.longitude)
|
||||
}
|
||||
}
|
||||
holder.mapView.initialize()
|
||||
holder.mapView.render(
|
||||
MapState(
|
||||
zoomOnlyOnce = false,
|
||||
pinLocationData = locationData,
|
||||
pinId = matrixItem.id,
|
||||
pinDrawable = null
|
||||
)
|
||||
)
|
||||
locationPinProvider?.create(matrixItem.id) { pinDrawable ->
|
||||
if (holder.view.isAttachedToWindow) {
|
||||
holder.mapView.render(
|
||||
MapState(
|
||||
zoomOnlyOnce = false,
|
||||
pinLocationData = locationData,
|
||||
pinId = matrixItem.id,
|
||||
pinDrawable = pinDrawable
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import im.vector.app.R
|
|||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
|
||||
import im.vector.app.features.location.LocationData
|
||||
import im.vector.app.features.location.MapState
|
||||
import im.vector.app.features.location.MapTilerMapView
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_base)
|
||||
|
@ -56,14 +57,25 @@ abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>(
|
|||
callback?.onMapClicked()
|
||||
}
|
||||
|
||||
holder.mapView.apply {
|
||||
initialize {
|
||||
zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM)
|
||||
|
||||
locationPinProvider?.create(locationOwnerId) { pinDrawable ->
|
||||
addPinToMap(locationOwnerId, pinDrawable)
|
||||
updatePinLocation(locationOwnerId, location.latitude, location.longitude)
|
||||
}
|
||||
holder.mapView.initialize()
|
||||
holder.mapView.render(
|
||||
MapState(
|
||||
zoomOnlyOnce = false,
|
||||
pinLocationData = location,
|
||||
pinId = locationOwnerId,
|
||||
pinDrawable = null
|
||||
)
|
||||
)
|
||||
locationPinProvider?.create(locationOwnerId) { pinDrawable ->
|
||||
if (holder.view.isAttachedToWindow) {
|
||||
holder.mapView.render(
|
||||
MapState(
|
||||
zoomOnlyOnce = false,
|
||||
pinLocationData = location,
|
||||
pinId = locationOwnerId,
|
||||
pinDrawable = pinDrawable
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +90,5 @@ abstract class MessageLocationItem : AbsMessageItem<MessageLocationItem.Holder>(
|
|||
|
||||
companion object {
|
||||
private const val STUB_ID = R.id.messageContentLocationStub
|
||||
private const val INITIAL_ZOOM = 15.0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.view.LayoutInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.airbnb.mvrx.args
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import im.vector.app.R
|
||||
|
@ -52,11 +53,8 @@ class LocationPreviewFragment @Inject constructor(
|
|||
|
||||
mapView = WeakReference(views.mapView)
|
||||
views.mapView.onCreate(savedInstanceState)
|
||||
views.mapView.initialize {
|
||||
if (isAdded) {
|
||||
onMapReady()
|
||||
}
|
||||
}
|
||||
views.mapView.initialize()
|
||||
loadPinDrawable()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -112,17 +110,20 @@ class LocationPreviewFragment @Inject constructor(
|
|||
openLocation(requireActivity(), location.latitude, location.longitude)
|
||||
}
|
||||
|
||||
private fun onMapReady() {
|
||||
if (!isAdded) return
|
||||
|
||||
private fun loadPinDrawable() {
|
||||
val location = args.initialLocationData ?: return
|
||||
val userId = args.locationOwnerId
|
||||
|
||||
locationPinProvider.create(userId) { pinDrawable ->
|
||||
views.mapView.apply {
|
||||
zoomToLocation(location.latitude, location.longitude, INITIAL_MAP_ZOOM)
|
||||
addPinToMap(userId, pinDrawable)
|
||||
updatePinLocation(userId, location.latitude, location.longitude)
|
||||
lifecycleScope.launchWhenResumed {
|
||||
views.mapView.render(
|
||||
MapState(
|
||||
zoomOnlyOnce = true,
|
||||
pinLocationData = location,
|
||||
pinId = args.locationOwnerId,
|
||||
pinDrawable = pinDrawable
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,6 @@ class LocationSharingFragment @Inject constructor(
|
|||
|
||||
private val viewModel: LocationSharingViewModel by fragmentViewModel()
|
||||
|
||||
private var lastZoomValue: Double = -1.0
|
||||
|
||||
// Keep a ref to handle properly the onDestroy callback
|
||||
private var mapView: WeakReference<MapView>? = null
|
||||
|
||||
|
@ -115,7 +113,7 @@ class LocationSharingFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
views.mapView.render(state)
|
||||
views.mapView.render(state.toMapState())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -38,3 +38,10 @@ data class LocationSharingViewState(
|
|||
mode = locationSharingArgs.mode
|
||||
)
|
||||
}
|
||||
|
||||
fun LocationSharingViewState.toMapState() = MapState(
|
||||
zoomOnlyOnce = true,
|
||||
pinLocationData = lastKnownLocation,
|
||||
pinId = LocationSharingFragment.USER_PIN_NAME,
|
||||
pinDrawable = pinDrawable
|
||||
)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.graphics.drawable.Drawable
|
||||
|
||||
data class MapState(
|
||||
val zoomOnlyOnce: Boolean,
|
||||
val pinLocationData: LocationData? = null,
|
||||
val pinId: String,
|
||||
val pinDrawable: Drawable? = null
|
||||
)
|
|
@ -17,7 +17,6 @@
|
|||
package im.vector.app.features.location
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
|
@ -29,6 +28,7 @@ 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
|
||||
|
||||
class MapTilerMapView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
|
@ -36,7 +36,7 @@ class MapTilerMapView @JvmOverloads constructor(
|
|||
defStyleAttr: Int = 0
|
||||
) : MapView(context, attrs, defStyleAttr) {
|
||||
|
||||
private var pendingState: LocationSharingViewState? = null
|
||||
private var pendingState: MapState? = null
|
||||
|
||||
data class MapRefs(
|
||||
val map: MapboxMap,
|
||||
|
@ -44,43 +44,18 @@ class MapTilerMapView @JvmOverloads constructor(
|
|||
val style: Style
|
||||
)
|
||||
|
||||
private var isInitializing = AtomicBoolean(false)
|
||||
private var mapRefs: MapRefs? = null
|
||||
private var initZoomDone = false
|
||||
|
||||
// TODO Kept only for the bottom sheet usage
|
||||
fun initialize(onMapReady: () -> Unit) {
|
||||
getMapAsync { map ->
|
||||
map.setStyle(styleUrl) { style ->
|
||||
mapRefs = MapRefs(
|
||||
map,
|
||||
SymbolManager(this, map, style),
|
||||
style
|
||||
)
|
||||
onMapReady()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Kept only for the bottom sheet usage
|
||||
fun addPinToMap(pinId: String, image: Drawable) {
|
||||
mapRefs?.style?.addImage(pinId, image)
|
||||
}
|
||||
|
||||
// TODO Kept only for the bottom sheet usage
|
||||
fun updatePinLocation(pinId: String, latitude: Double, longitude: Double) {
|
||||
mapRefs?.symbolManager?.create(
|
||||
SymbolOptions()
|
||||
.withLatLng(LatLng(latitude, longitude))
|
||||
.withIconImage(pinId)
|
||||
.withIconAnchor(Property.ICON_ANCHOR_BOTTOM)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* For location fragments
|
||||
*/
|
||||
fun initialize() {
|
||||
Timber.d("## Location: initialize")
|
||||
Timber.d("## Location: initialize $isInitializing")
|
||||
if (isInitializing.getAndSet(true)) {
|
||||
return
|
||||
}
|
||||
|
||||
getMapAsync { map ->
|
||||
map.setStyle(styleUrl) { style ->
|
||||
|
@ -95,20 +70,21 @@ class MapTilerMapView @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun render(data: LocationSharingViewState) {
|
||||
fun render(state: MapState) {
|
||||
val safeMapRefs = mapRefs ?: return Unit.also {
|
||||
pendingState = data
|
||||
pendingState = state
|
||||
}
|
||||
|
||||
data.pinDrawable?.let { pinDrawable ->
|
||||
if (safeMapRefs.style.getImage(LocationSharingFragment.USER_PIN_NAME) == null) {
|
||||
state.pinDrawable?.let { pinDrawable ->
|
||||
if (safeMapRefs.style.isFullyLoaded &&
|
||||
safeMapRefs.style.getImage(LocationSharingFragment.USER_PIN_NAME) == null) {
|
||||
safeMapRefs.style.addImage(LocationSharingFragment.USER_PIN_NAME, pinDrawable)
|
||||
}
|
||||
}
|
||||
|
||||
data.lastKnownLocation?.let { locationData ->
|
||||
if (!initZoomDone) {
|
||||
zoomToLocation(locationData.latitude, locationData.longitude, INITIAL_MAP_ZOOM)
|
||||
state.pinLocationData?.let { locationData ->
|
||||
if (!initZoomDone || !state.zoomOnlyOnce) {
|
||||
zoomToLocation(locationData.latitude, locationData.longitude)
|
||||
initZoomDone = true
|
||||
}
|
||||
|
||||
|
@ -121,11 +97,11 @@ class MapTilerMapView @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun zoomToLocation(latitude: Double, longitude: Double, zoom: Double) {
|
||||
private fun zoomToLocation(latitude: Double, longitude: Double) {
|
||||
Timber.d("## Location: zoomToLocation")
|
||||
mapRefs?.map?.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(latitude, longitude))
|
||||
.zoom(zoom)
|
||||
.zoom(INITIAL_MAP_ZOOM)
|
||||
.build()
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue