Merge pull request #6092 from vector-im/feature/mna/PSF-888-navigation
[Location sharing] - Navigation to Map view from live location message (PSF-888)
This commit is contained in:
commit
9a38d59f9a
|
@ -0,0 +1 @@
|
||||||
|
Live location sharing: navigation from timeline to map screen
|
|
@ -343,6 +343,7 @@
|
||||||
<activity android:name=".features.spaces.leave.SpaceLeaveAdvancedActivity" />
|
<activity android:name=".features.spaces.leave.SpaceLeaveAdvancedActivity" />
|
||||||
<activity android:name=".features.poll.create.CreatePollActivity" />
|
<activity android:name=".features.poll.create.CreatePollActivity" />
|
||||||
<activity android:name=".features.location.LocationSharingActivity" />
|
<activity android:name=".features.location.LocationSharingActivity" />
|
||||||
|
<activity android:name=".features.location.live.map.LocationLiveMapViewActivity" />
|
||||||
|
|
||||||
<!-- Services -->
|
<!-- Services -->
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,10 @@ fun Fragment.registerStartForActivityResult(onResult: (ActivityResult) -> Unit):
|
||||||
fun Fragment.addFragment(
|
fun Fragment.addFragment(
|
||||||
frameId: Int,
|
frameId: Int,
|
||||||
fragment: Fragment,
|
fragment: Fragment,
|
||||||
|
tag: String? = null,
|
||||||
allowStateLoss: Boolean = false
|
allowStateLoss: Boolean = false
|
||||||
) {
|
) {
|
||||||
parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment) }
|
parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment, tag) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Fragment> Fragment.addFragment(
|
fun <T : Fragment> Fragment.addFragment(
|
||||||
|
|
|
@ -221,6 +221,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageFormat
|
import org.matrix.android.sdk.api.session.room.model.message.MessageFormat
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent
|
||||||
|
@ -647,6 +648,13 @@ class TimelineFragment @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun navigateToLocationLiveMap() {
|
||||||
|
navigator.openLocationLiveMap(
|
||||||
|
context = requireContext(),
|
||||||
|
roomId = timelineArgs.roomId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleChangeLocationIndicator(event: RoomDetailViewEvents.ChangeLocationIndicator) {
|
private fun handleChangeLocationIndicator(event: RoomDetailViewEvents.ChangeLocationIndicator) {
|
||||||
views.locationLiveStatusIndicator.isVisible = event.isVisible
|
views.locationLiveStatusIndicator.isVisible = event.isVisible
|
||||||
}
|
}
|
||||||
|
@ -2015,6 +2023,9 @@ class TimelineFragment @Inject constructor(
|
||||||
is MessageLocationContent -> {
|
is MessageLocationContent -> {
|
||||||
handleShowLocationPreview(messageContent, informationData.senderId)
|
handleShowLocationPreview(messageContent, informationData.senderId)
|
||||||
}
|
}
|
||||||
|
is MessageBeaconInfoContent -> {
|
||||||
|
navigateToLocationLiveMap()
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val handled = onThreadSummaryClicked(informationData.eventId, isRootThreadEvent)
|
val handled = onThreadSummaryClicked(informationData.eventId, isRootThreadEvent)
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
|
|
|
@ -75,7 +75,8 @@ class LiveLocationShareMessageItemFactory @Inject constructor(
|
||||||
val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)
|
val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)
|
||||||
|
|
||||||
return MessageLiveLocationInactiveItem_()
|
return MessageLiveLocationInactiveItem_()
|
||||||
.attributes(attributes)
|
// disable the click on this state item
|
||||||
|
.attributes(attributes.copy(itemClickListener = null))
|
||||||
.mapWidth(width)
|
.mapWidth(width)
|
||||||
.mapHeight(height)
|
.mapHeight(height)
|
||||||
.highlighted(highlight)
|
.highlighted(highlight)
|
||||||
|
@ -90,7 +91,8 @@ class LiveLocationShareMessageItemFactory @Inject constructor(
|
||||||
val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)
|
val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)
|
||||||
|
|
||||||
return MessageLiveLocationStartItem_()
|
return MessageLiveLocationStartItem_()
|
||||||
.attributes(attributes)
|
// disable the click on this state item
|
||||||
|
.attributes(attributes.copy(itemClickListener = null))
|
||||||
.mapWidth(width)
|
.mapWidth(width)
|
||||||
.mapHeight(height)
|
.mapHeight(height)
|
||||||
.highlighted(highlight)
|
.highlighted(highlight)
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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.live.map
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Parcelable
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.addFragment
|
||||||
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.app.databinding.ActivityLocationSharingBinding
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class LocationLiveMapViewArgs(
|
||||||
|
val roomId: String
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class LocationLiveMapViewActivity : VectorBaseActivity<ActivityLocationSharingBinding>() {
|
||||||
|
|
||||||
|
override fun getBinding() = ActivityLocationSharingBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
override fun initUiAndData() {
|
||||||
|
val mapViewArgs: LocationLiveMapViewArgs? = intent?.extras?.getParcelable(EXTRA_LOCATION_LIVE_MAP_VIEW_ARGS)
|
||||||
|
if (mapViewArgs == null) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setupToolbar(views.toolbar)
|
||||||
|
.setTitle(getString(R.string.location_activity_title_preview))
|
||||||
|
.allowBack()
|
||||||
|
|
||||||
|
if (isFirstCreation()) {
|
||||||
|
addFragment(
|
||||||
|
views.fragmentContainer,
|
||||||
|
LocationLiveMapViewFragment::class.java,
|
||||||
|
mapViewArgs
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val EXTRA_LOCATION_LIVE_MAP_VIEW_ARGS = "EXTRA_LOCATION_LIVE_MAP_VIEW_ARGS"
|
||||||
|
|
||||||
|
fun getIntent(context: Context, locationLiveMapViewArgs: LocationLiveMapViewArgs): Intent {
|
||||||
|
return Intent(context, LocationLiveMapViewActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_LOCATION_LIVE_MAP_VIEW_ARGS, locationLiveMapViewArgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.live.map
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.airbnb.mvrx.args
|
||||||
|
import com.mapbox.mapboxsdk.maps.MapboxMapOptions
|
||||||
|
import com.mapbox.mapboxsdk.maps.SupportMapFragment
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.addChildFragment
|
||||||
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import im.vector.app.databinding.FragmentSimpleContainerBinding
|
||||||
|
import im.vector.app.features.location.UrlMapProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen showing a map with all the current users sharing their live location in room.
|
||||||
|
*/
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class LocationLiveMapViewFragment : VectorBaseFragment<FragmentSimpleContainerBinding>() {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var urlMapProvider: UrlMapProvider
|
||||||
|
|
||||||
|
private val args: LocationLiveMapViewArgs by args()
|
||||||
|
|
||||||
|
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSimpleContainerBinding {
|
||||||
|
return FragmentSimpleContainerBinding.inflate(layoutInflater, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
setupMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupMap() {
|
||||||
|
val mapFragment = getOrCreateSupportMapFragment()
|
||||||
|
|
||||||
|
mapFragment.getMapAsync { mapBoxMap ->
|
||||||
|
lifecycleScope.launchWhenCreated {
|
||||||
|
mapBoxMap.setStyle(urlMapProvider.getMapUrl())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getOrCreateSupportMapFragment() =
|
||||||
|
childFragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG) as? SupportMapFragment
|
||||||
|
?: run {
|
||||||
|
val options = MapboxMapOptions.createFromAttributes(requireContext(), null)
|
||||||
|
SupportMapFragment.newInstance(options)
|
||||||
|
.also { addChildFragment(R.id.fragmentContainer, it, tag = MAP_FRAGMENT_TAG) }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val MAP_FRAGMENT_TAG = "im.vector.app.features.location.live.map"
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,8 @@ import im.vector.app.features.location.LocationData
|
||||||
import im.vector.app.features.location.LocationSharingActivity
|
import im.vector.app.features.location.LocationSharingActivity
|
||||||
import im.vector.app.features.location.LocationSharingArgs
|
import im.vector.app.features.location.LocationSharingArgs
|
||||||
import im.vector.app.features.location.LocationSharingMode
|
import im.vector.app.features.location.LocationSharingMode
|
||||||
|
import im.vector.app.features.location.live.map.LocationLiveMapViewActivity
|
||||||
|
import im.vector.app.features.location.live.map.LocationLiveMapViewArgs
|
||||||
import im.vector.app.features.login.LoginActivity
|
import im.vector.app.features.login.LoginActivity
|
||||||
import im.vector.app.features.login.LoginConfig
|
import im.vector.app.features.login.LoginConfig
|
||||||
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
||||||
|
@ -592,6 +594,14 @@ class DefaultNavigator @Inject constructor(
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openLocationLiveMap(context: Context, roomId: String) {
|
||||||
|
val intent = LocationLiveMapViewActivity.getIntent(
|
||||||
|
context = context,
|
||||||
|
locationLiveMapViewArgs = LocationLiveMapViewArgs(roomId = roomId)
|
||||||
|
)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun startActivity(context: Context, intent: Intent, buildTask: Boolean) {
|
private fun startActivity(context: Context, intent: Intent, buildTask: Boolean) {
|
||||||
if (buildTask) {
|
if (buildTask) {
|
||||||
val stackBuilder = TaskStackBuilder.create(context)
|
val stackBuilder = TaskStackBuilder.create(context)
|
||||||
|
|
|
@ -172,6 +172,8 @@ interface Navigator {
|
||||||
initialLocationData: LocationData?,
|
initialLocationData: LocationData?,
|
||||||
locationOwnerId: String?)
|
locationOwnerId: String?)
|
||||||
|
|
||||||
|
fun openLocationLiveMap(context: Context, roomId: String)
|
||||||
|
|
||||||
fun openThread(context: Context, threadTimelineArgs: ThreadTimelineArgs, eventIdToNavigate: String? = null)
|
fun openThread(context: Context, threadTimelineArgs: ThreadTimelineArgs, eventIdToNavigate: String? = null)
|
||||||
|
|
||||||
fun openThreadList(context: Context, threadTimelineArgs: ThreadTimelineArgs)
|
fun openThreadList(context: Context, threadTimelineArgs: ThreadTimelineArgs)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/fragmentContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
Loading…
Reference in New Issue