From b2765e4b63613168a0c1c8a855e2ea2d02689566 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 10 May 2022 14:29:50 +0200 Subject: [PATCH 01/11] Adding changelog entry --- changelog.d/6012.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6012.wip diff --git a/changelog.d/6012.wip b/changelog.d/6012.wip new file mode 100644 index 0000000000..9c67d562fe --- /dev/null +++ b/changelog.d/6012.wip @@ -0,0 +1 @@ +Live location sharing: navigation from timeline to map screen From 52c0fa41c6ce56555dbc987703ddc6edd62d420c Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 10 May 2022 16:49:27 +0200 Subject: [PATCH 02/11] Creation of map view screen and basic navigation --- vector/src/main/AndroidManifest.xml | 1 + .../im/vector/app/core/di/FragmentModule.kt | 6 ++ .../home/room/detail/TimelineFragment.kt | 12 +++ .../live/map/LocationLiveMapViewActivity.kt | 68 +++++++++++++ .../live/map/LocationLiveMapViewFragment.kt | 99 +++++++++++++++++++ .../features/navigation/DefaultNavigator.kt | 10 ++ .../app/features/navigation/Navigator.kt | 2 + 7 files changed, 198 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 20b7c4908a..fc78ce90a3 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -343,6 +343,7 @@ + diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index c68a35f4e5..6d42c83ac2 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -64,6 +64,7 @@ import im.vector.app.features.home.room.list.RoomListFragment import im.vector.app.features.home.room.threads.list.views.ThreadListFragment import im.vector.app.features.location.LocationPreviewFragment import im.vector.app.features.location.LocationSharingFragment +import im.vector.app.features.location.live.map.LocationLiveMapViewFragment import im.vector.app.features.login.LoginCaptchaFragment import im.vector.app.features.login.LoginFragment import im.vector.app.features.login.LoginGenericTextInputFormFragment @@ -993,4 +994,9 @@ interface FragmentModule { @IntoMap @FragmentKey(LocationPreviewFragment::class) fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment + + @Binds + @IntoMap + @FragmentKey(LocationLiveMapViewFragment::class) + fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 2bb620623c..bf7c506d79 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -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.RoomSummary 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.MessageFormat 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) { views.locationLiveStatusIndicator.isVisible = event.isVisible } @@ -2015,6 +2023,10 @@ class TimelineFragment @Inject constructor( is MessageLocationContent -> { handleShowLocationPreview(messageContent, informationData.senderId) } + is MessageBeaconInfoContent -> { + // TODO navigate only from running live location message: possible after merge of associated PR + navigateToLocationLiveMap() + } else -> { val handled = onThreadSummaryClicked(informationData.eventId, isRootThreadEvent) if (!handled) { diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt new file mode 100644 index 0000000000..cb54e93f97 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt @@ -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.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() { + + 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) + // TODO check what should be the title and create String resource + .setTitle("Live") + .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) + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt new file mode 100644 index 0000000000..7e17712556 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -0,0 +1,99 @@ +/* + * 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.MapView +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentLocationPreviewBinding +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import im.vector.app.features.location.UrlMapProvider +import java.lang.ref.WeakReference +import javax.inject.Inject + +/** + * Screen showing a map with all the current users sharing their live location in room. + */ +class LocationLiveMapViewFragment @Inject constructor( + private val urlMapProvider: UrlMapProvider, + private val locationPinProvider: LocationPinProvider +) : VectorBaseFragment() { + + // TODO use a SupportMapFragment with FragmentManager + // TODO align design with Figma + + private val args: LocationLiveMapViewArgs by args() + + // Keep a ref to handle properly the onDestroy callback + private var mapView: WeakReference? = null + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationPreviewBinding { + return FragmentLocationPreviewBinding.inflate(layoutInflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + mapView = WeakReference(views.mapView) + views.mapView.onCreate(savedInstanceState) + + lifecycleScope.launchWhenCreated { + views.mapView.initialize(urlMapProvider.getMapUrl()) + } + } + + override fun onResume() { + super.onResume() + views.mapView.onResume() + } + + override fun onPause() { + views.mapView.onPause() + super.onPause() + } + + override fun onLowMemory() { + views.mapView.onLowMemory() + super.onLowMemory() + } + + override fun onStart() { + super.onStart() + views.mapView.onStart() + } + + override fun onStop() { + views.mapView.onStop() + super.onStop() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + views.mapView.onSaveInstanceState(outState) + } + + override fun onDestroy() { + mapView?.get()?.onDestroy() + mapView?.clear() + super.onDestroy() + } +} diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 7cc42ec57f..1ec4011289 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -68,6 +68,8 @@ import im.vector.app.features.location.LocationData import im.vector.app.features.location.LocationSharingActivity import im.vector.app.features.location.LocationSharingArgs 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.LoginConfig import im.vector.app.features.matrixto.MatrixToBottomSheet @@ -591,6 +593,14 @@ class DefaultNavigator @Inject constructor( 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) { if (buildTask) { val stackBuilder = TaskStackBuilder.create(context) diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index 075b41daf3..d4ef2b8099 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -172,6 +172,8 @@ interface Navigator { initialLocationData: LocationData?, locationOwnerId: String?) + fun openLocationLiveMap(context: Context, roomId: String) + fun openThread(context: Context, threadTimelineArgs: ThreadTimelineArgs, eventIdToNavigate: String? = null) fun openThreadList(context: Context, threadTimelineArgs: ThreadTimelineArgs) From 54d7d47dfcda4fac17b3df81703a9229df2fcddd Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 10 May 2022 17:27:41 +0200 Subject: [PATCH 03/11] Updating the title of the map view screen --- .../features/location/live/map/LocationLiveMapViewActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt index cb54e93f97..c0f07dba57 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt @@ -20,6 +20,7 @@ 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 @@ -42,8 +43,7 @@ class LocationLiveMapViewActivity : VectorBaseActivity Date: Wed, 11 May 2022 09:37:25 +0200 Subject: [PATCH 04/11] Use SupportMapFragment instead of custom fragment --- .../im/vector/app/core/di/FragmentModule.kt | 6 -- .../im/vector/app/core/extensions/Activity.kt | 6 +- .../live/map/LocationLiveMapViewActivity.kt | 34 +++++-- .../live/map/LocationLiveMapViewFragment.kt | 99 ------------------- 4 files changed, 32 insertions(+), 113 deletions(-) delete mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 6d42c83ac2..c68a35f4e5 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -64,7 +64,6 @@ import im.vector.app.features.home.room.list.RoomListFragment import im.vector.app.features.home.room.threads.list.views.ThreadListFragment import im.vector.app.features.location.LocationPreviewFragment import im.vector.app.features.location.LocationSharingFragment -import im.vector.app.features.location.live.map.LocationLiveMapViewFragment import im.vector.app.features.login.LoginCaptchaFragment import im.vector.app.features.login.LoginFragment import im.vector.app.features.login.LoginGenericTextInputFormFragment @@ -994,9 +993,4 @@ interface FragmentModule { @IntoMap @FragmentKey(LocationPreviewFragment::class) fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment - - @Binds - @IntoMap - @FragmentKey(LocationLiveMapViewFragment::class) - fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment } diff --git a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt index 6f2ea9699a..cbdf5e3573 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt @@ -39,8 +39,10 @@ fun ComponentActivity.registerStartForActivityResult(onResult: (ActivityResult) fun AppCompatActivity.addFragment( container: ViewGroup, fragment: Fragment, - allowStateLoss: Boolean = false) { - supportFragmentManager.commitTransaction(allowStateLoss) { add(container.id, fragment) } + allowStateLoss: Boolean = false, + tag: String? = null +) { + supportFragmentManager.commitTransaction(allowStateLoss) { add(container.id, fragment, tag) } } fun AppCompatActivity.addFragment( diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt index c0f07dba57..41e08dc655 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt @@ -19,21 +19,31 @@ package im.vector.app.features.location.live.map import android.content.Context import android.content.Intent import android.os.Parcelable +import androidx.lifecycle.lifecycleScope +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.addFragment import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityLocationSharingBinding +import im.vector.app.features.location.UrlMapProvider import kotlinx.parcelize.Parcelize +import javax.inject.Inject @Parcelize data class LocationLiveMapViewArgs( val roomId: String ) : Parcelable +/** + * Screen showing a map with all the current users sharing their live location in room. + */ @AndroidEntryPoint class LocationLiveMapViewActivity : VectorBaseActivity() { + @Inject lateinit var urlMapProvider: UrlMapProvider + override fun getBinding() = ActivityLocationSharingBinding.inflate(layoutInflater) override fun initUiAndData() { @@ -46,18 +56,30 @@ class LocationLiveMapViewActivity : VectorBaseActivity + lifecycleScope.launchWhenCreated { + mapBoxMap.setStyle(urlMapProvider.getMapUrl()) + } } } companion object { private const val EXTRA_LOCATION_LIVE_MAP_VIEW_ARGS = "EXTRA_LOCATION_LIVE_MAP_VIEW_ARGS" + private const val MAP_FRAGMENT_TAG = "im.vector.app.features.location.live.map" fun getIntent(context: Context, locationLiveMapViewArgs: LocationLiveMapViewArgs): Intent { return Intent(context, LocationLiveMapViewActivity::class.java).apply { diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt deleted file mode 100644 index 7e17712556..0000000000 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.MapView -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.FragmentLocationPreviewBinding -import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider -import im.vector.app.features.location.UrlMapProvider -import java.lang.ref.WeakReference -import javax.inject.Inject - -/** - * Screen showing a map with all the current users sharing their live location in room. - */ -class LocationLiveMapViewFragment @Inject constructor( - private val urlMapProvider: UrlMapProvider, - private val locationPinProvider: LocationPinProvider -) : VectorBaseFragment() { - - // TODO use a SupportMapFragment with FragmentManager - // TODO align design with Figma - - private val args: LocationLiveMapViewArgs by args() - - // Keep a ref to handle properly the onDestroy callback - private var mapView: WeakReference? = null - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationPreviewBinding { - return FragmentLocationPreviewBinding.inflate(layoutInflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - mapView = WeakReference(views.mapView) - views.mapView.onCreate(savedInstanceState) - - lifecycleScope.launchWhenCreated { - views.mapView.initialize(urlMapProvider.getMapUrl()) - } - } - - override fun onResume() { - super.onResume() - views.mapView.onResume() - } - - override fun onPause() { - views.mapView.onPause() - super.onPause() - } - - override fun onLowMemory() { - views.mapView.onLowMemory() - super.onLowMemory() - } - - override fun onStart() { - super.onStart() - views.mapView.onStart() - } - - override fun onStop() { - views.mapView.onStop() - super.onStop() - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - views.mapView.onSaveInstanceState(outState) - } - - override fun onDestroy() { - mapView?.get()?.onDestroy() - mapView?.clear() - super.onDestroy() - } -} From 23e8cad10f9f8435d847536f898f08cc06de5167 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 11 May 2022 16:53:13 +0200 Subject: [PATCH 05/11] Rollback to Fragment to be able to use Maverick capabilities --- .../im/vector/app/core/di/FragmentModule.kt | 6 ++ .../im/vector/app/core/extensions/Activity.kt | 6 +- .../im/vector/app/core/extensions/Fragment.kt | 3 +- .../live/map/LocationLiveMapViewActivity.kt | 34 ++------ .../live/map/LocationLiveMapViewFragment.kt | 77 +++++++++++++++++++ .../res/layout/fragment_live_location_map.xml | 5 ++ 6 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt create mode 100644 vector/src/main/res/layout/fragment_live_location_map.xml diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index c68a35f4e5..6d42c83ac2 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -64,6 +64,7 @@ import im.vector.app.features.home.room.list.RoomListFragment import im.vector.app.features.home.room.threads.list.views.ThreadListFragment import im.vector.app.features.location.LocationPreviewFragment import im.vector.app.features.location.LocationSharingFragment +import im.vector.app.features.location.live.map.LocationLiveMapViewFragment import im.vector.app.features.login.LoginCaptchaFragment import im.vector.app.features.login.LoginFragment import im.vector.app.features.login.LoginGenericTextInputFormFragment @@ -993,4 +994,9 @@ interface FragmentModule { @IntoMap @FragmentKey(LocationPreviewFragment::class) fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment + + @Binds + @IntoMap + @FragmentKey(LocationLiveMapViewFragment::class) + fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment } diff --git a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt index cbdf5e3573..6f2ea9699a 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt @@ -39,10 +39,8 @@ fun ComponentActivity.registerStartForActivityResult(onResult: (ActivityResult) fun AppCompatActivity.addFragment( container: ViewGroup, fragment: Fragment, - allowStateLoss: Boolean = false, - tag: String? = null -) { - supportFragmentManager.commitTransaction(allowStateLoss) { add(container.id, fragment, tag) } + allowStateLoss: Boolean = false) { + supportFragmentManager.commitTransaction(allowStateLoss) { add(container.id, fragment) } } fun AppCompatActivity.addFragment( diff --git a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt index dfbd2eba97..61c4fe2174 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt @@ -36,9 +36,10 @@ fun Fragment.registerStartForActivityResult(onResult: (ActivityResult) -> Unit): fun Fragment.addFragment( frameId: Int, fragment: Fragment, + tag: String? = null, allowStateLoss: Boolean = false ) { - parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment) } + parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment, tag) } } fun Fragment.addFragment( diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt index 41e08dc655..c0f07dba57 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewActivity.kt @@ -19,31 +19,21 @@ package im.vector.app.features.location.live.map import android.content.Context import android.content.Intent import android.os.Parcelable -import androidx.lifecycle.lifecycleScope -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.addFragment import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityLocationSharingBinding -import im.vector.app.features.location.UrlMapProvider import kotlinx.parcelize.Parcelize -import javax.inject.Inject @Parcelize data class LocationLiveMapViewArgs( val roomId: String ) : Parcelable -/** - * Screen showing a map with all the current users sharing their live location in room. - */ @AndroidEntryPoint class LocationLiveMapViewActivity : VectorBaseActivity() { - @Inject lateinit var urlMapProvider: UrlMapProvider - override fun getBinding() = ActivityLocationSharingBinding.inflate(layoutInflater) override fun initUiAndData() { @@ -56,30 +46,18 @@ class LocationLiveMapViewActivity : VectorBaseActivity - lifecycleScope.launchWhenCreated { - mapBoxMap.setStyle(urlMapProvider.getMapUrl()) - } + 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" - private const val MAP_FRAGMENT_TAG = "im.vector.app.features.location.live.map" fun getIntent(context: Context, locationLiveMapViewArgs: LocationLiveMapViewArgs): Intent { return Intent(context, LocationLiveMapViewActivity::class.java).apply { diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt new file mode 100644 index 0000000000..29c45f8945 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -0,0 +1,77 @@ +/* + * 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.MapView +import com.mapbox.mapboxsdk.maps.MapboxMapOptions +import com.mapbox.mapboxsdk.maps.SupportMapFragment +import im.vector.app.R +import im.vector.app.core.extensions.addFragment +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentLiveLocationMapBinding +import im.vector.app.databinding.FragmentLocationPreviewBinding +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import im.vector.app.features.location.UrlMapProvider +import java.lang.ref.WeakReference +import javax.inject.Inject + +/** + * Screen showing a map with all the current users sharing their live location in room. + */ +class LocationLiveMapViewFragment @Inject constructor( + private val urlMapProvider: UrlMapProvider, + private val locationPinProvider: LocationPinProvider +) : VectorBaseFragment() { + + private val args: LocationLiveMapViewArgs by args() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLiveLocationMapBinding { + return FragmentLiveLocationMapBinding.inflate(layoutInflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupMap() + } + + private fun setupMap() { + val mapFragment: SupportMapFragment = + parentFragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG) as? SupportMapFragment + ?: run { + val options = MapboxMapOptions.createFromAttributes(requireContext(), null) + val fragment = SupportMapFragment.newInstance(options) + addFragment(R.id.liveLocationMapContainer, fragment, tag = MAP_FRAGMENT_TAG) + fragment + } + + mapFragment.getMapAsync { mapBoxMap -> + lifecycleScope.launchWhenCreated { + mapBoxMap.setStyle(urlMapProvider.getMapUrl()) + } + } + } + + companion object { + private const val MAP_FRAGMENT_TAG = "im.vector.app.features.location.live.map" + } +} diff --git a/vector/src/main/res/layout/fragment_live_location_map.xml b/vector/src/main/res/layout/fragment_live_location_map.xml new file mode 100644 index 0000000000..5238508d6f --- /dev/null +++ b/vector/src/main/res/layout/fragment_live_location_map.xml @@ -0,0 +1,5 @@ + + From 4864980a5afd194fb5ce619b6c49c56ecebf0d32 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 17 May 2022 11:07:21 +0200 Subject: [PATCH 06/11] Enable navigation only from running state item --- .../app/features/home/room/detail/TimelineFragment.kt | 1 - .../timeline/factory/LiveLocationShareMessageItemFactory.kt | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index bf7c506d79..7ab3ab2adc 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -2024,7 +2024,6 @@ class TimelineFragment @Inject constructor( handleShowLocationPreview(messageContent, informationData.senderId) } is MessageBeaconInfoContent -> { - // TODO navigate only from running live location message: possible after merge of associated PR navigateToLocationLiveMap() } else -> { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/LiveLocationShareMessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/LiveLocationShareMessageItemFactory.kt index 479a742369..912702aaed 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/LiveLocationShareMessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/LiveLocationShareMessageItemFactory.kt @@ -75,7 +75,8 @@ class LiveLocationShareMessageItemFactory @Inject constructor( val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP) return MessageLiveLocationInactiveItem_() - .attributes(attributes) + // disable the click on this state item + .attributes(attributes.copy(itemClickListener = null)) .mapWidth(width) .mapHeight(height) .highlighted(highlight) @@ -90,7 +91,8 @@ class LiveLocationShareMessageItemFactory @Inject constructor( val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP) return MessageLiveLocationStartItem_() - .attributes(attributes) + // disable the click on this state item + .attributes(attributes.copy(itemClickListener = null)) .mapWidth(width) .mapHeight(height) .highlighted(highlight) From 526585677234a063f4ebcbc9a88731fc1aeacb9b Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 17 May 2022 11:11:41 +0200 Subject: [PATCH 07/11] Remove unused imports --- .../location/live/map/LocationLiveMapViewFragment.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 29c45f8945..50526f2839 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -22,17 +22,13 @@ import android.view.View import android.view.ViewGroup import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.args -import com.mapbox.mapboxsdk.maps.MapView import com.mapbox.mapboxsdk.maps.MapboxMapOptions import com.mapbox.mapboxsdk.maps.SupportMapFragment import im.vector.app.R import im.vector.app.core.extensions.addFragment import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentLiveLocationMapBinding -import im.vector.app.databinding.FragmentLocationPreviewBinding -import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.location.UrlMapProvider -import java.lang.ref.WeakReference import javax.inject.Inject /** @@ -40,7 +36,6 @@ import javax.inject.Inject */ class LocationLiveMapViewFragment @Inject constructor( private val urlMapProvider: UrlMapProvider, - private val locationPinProvider: LocationPinProvider ) : VectorBaseFragment() { private val args: LocationLiveMapViewArgs by args() From c46aaa24a56b0ea531702f3216e3925ce0394ff0 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 23 May 2022 10:40:52 +0200 Subject: [PATCH 08/11] Using @AndroidEntryPoint in Fragment --- .../main/java/im/vector/app/core/di/FragmentModule.kt | 5 ++--- .../location/live/map/LocationLiveMapViewFragment.kt | 9 ++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 6d42c83ac2..1f57031170 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -64,7 +64,6 @@ import im.vector.app.features.home.room.list.RoomListFragment import im.vector.app.features.home.room.threads.list.views.ThreadListFragment import im.vector.app.features.location.LocationPreviewFragment import im.vector.app.features.location.LocationSharingFragment -import im.vector.app.features.location.live.map.LocationLiveMapViewFragment import im.vector.app.features.login.LoginCaptchaFragment import im.vector.app.features.login.LoginFragment import im.vector.app.features.login.LoginGenericTextInputFormFragment @@ -995,8 +994,8 @@ interface FragmentModule { @FragmentKey(LocationPreviewFragment::class) fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment - @Binds + /*@Binds @IntoMap @FragmentKey(LocationLiveMapViewFragment::class) - fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment + fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment*/ } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 50526f2839..23b78e0f0f 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -24,6 +24,7 @@ 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.addFragment import im.vector.app.core.platform.VectorBaseFragment @@ -34,9 +35,11 @@ import javax.inject.Inject /** * Screen showing a map with all the current users sharing their live location in room. */ -class LocationLiveMapViewFragment @Inject constructor( - private val urlMapProvider: UrlMapProvider, -) : VectorBaseFragment() { +@AndroidEntryPoint +class LocationLiveMapViewFragment : VectorBaseFragment() { + + @Inject + lateinit var urlMapProvider: UrlMapProvider private val args: LocationLiveMapViewArgs by args() From 721d7cb6a0387925568a0acd1955fe0efd46e160 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 23 May 2022 11:30:35 +0200 Subject: [PATCH 09/11] Remove commented code --- vector/src/main/java/im/vector/app/core/di/FragmentModule.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 1f57031170..c68a35f4e5 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -993,9 +993,4 @@ interface FragmentModule { @IntoMap @FragmentKey(LocationPreviewFragment::class) fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment - - /*@Binds - @IntoMap - @FragmentKey(LocationLiveMapViewFragment::class) - fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment*/ } From b331521e933c9fa8faf2b0155dadc998eea65e0c Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 23 May 2022 11:30:57 +0200 Subject: [PATCH 10/11] Improving code in Fragment --- .../live/map/LocationLiveMapViewFragment.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 23b78e0f0f..5020687ab9 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -26,7 +26,7 @@ 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.addFragment +import im.vector.app.core.extensions.addChildFragment import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentLiveLocationMapBinding import im.vector.app.features.location.UrlMapProvider @@ -53,14 +53,7 @@ class LocationLiveMapViewFragment : VectorBaseFragment lifecycleScope.launchWhenCreated { @@ -69,6 +62,14 @@ class LocationLiveMapViewFragment : VectorBaseFragment Date: Mon, 23 May 2022 11:41:33 +0200 Subject: [PATCH 11/11] Making the layout file more generic --- .../location/live/map/LocationLiveMapViewFragment.kt | 10 +++++----- ..._location_map.xml => fragment_simple_container.xml} | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename vector/src/main/res/layout/{fragment_live_location_map.xml => fragment_simple_container.xml} (80%) diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt index 5020687ab9..32b87727d8 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt @@ -28,7 +28,7 @@ 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.FragmentLiveLocationMapBinding +import im.vector.app.databinding.FragmentSimpleContainerBinding import im.vector.app.features.location.UrlMapProvider import javax.inject.Inject @@ -36,15 +36,15 @@ import javax.inject.Inject * Screen showing a map with all the current users sharing their live location in room. */ @AndroidEntryPoint -class LocationLiveMapViewFragment : VectorBaseFragment() { +class LocationLiveMapViewFragment : VectorBaseFragment() { @Inject lateinit var urlMapProvider: UrlMapProvider private val args: LocationLiveMapViewArgs by args() - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLiveLocationMapBinding { - return FragmentLiveLocationMapBinding.inflate(layoutInflater, container, false) + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSimpleContainerBinding { + return FragmentSimpleContainerBinding.inflate(layoutInflater, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -67,7 +67,7 @@ class LocationLiveMapViewFragment : VectorBaseFragment