From 0c69cc12f0b3412680b9decbea9edb8a62557ab7 Mon Sep 17 00:00:00 2001 From: CLAUDE HANGUI Date: Wed, 16 Mar 2022 12:53:49 +0000 Subject: [PATCH 1/7] track firebase events from explore dash portal and info screens --- .../common/services/analytics/AnalyticsConstants.kt | 7 +++++++ .../features/exploredash/ui/ExploreFragment.kt | 9 ++++++++- .../exploredash/ui/dialogs/ExploreDashInfoDialog.kt | 12 ++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt b/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt index 203451befb..43a4d039bf 100644 --- a/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt +++ b/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt @@ -100,4 +100,11 @@ object AnalyticsConstants { const val TRANSACTION_FILTER = "home_transaction_filter" const val SEND_RECEIVE_BUTTON = "home_send_receive_button" } + + object ExploreDash { + const val WHERE_TO_SPEND = "portal_where_to_spend" + const val PORTAL_ATM = "portal_atm" + const val LEARN_MORE = "info_learn_more" + const val CONTINUE = "info_continue" + } } \ No newline at end of file diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreFragment.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreFragment.kt index e65c686f25..fce3b81db0 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreFragment.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreFragment.kt @@ -19,17 +19,22 @@ package org.dash.wallet.features.exploredash.ui import android.os.Bundle import android.view.View +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import dagger.hilt.android.AndroidEntryPoint +import org.dash.wallet.common.services.analytics.AnalyticsConstants +import org.dash.wallet.common.services.analytics.AnalyticsService import org.dash.wallet.common.ui.viewBinding import org.dash.wallet.common.util.safeNavigate import org.dash.wallet.features.exploredash.R import org.dash.wallet.features.exploredash.databinding.FragmentExploreBinding +import javax.inject.Inject @AndroidEntryPoint class ExploreFragment : Fragment(R.layout.fragment_explore) { private val binding by viewBinding(FragmentExploreBinding::bind) - + @Inject + lateinit var analyticsService: AnalyticsService override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -39,10 +44,12 @@ class ExploreFragment : Fragment(R.layout.fragment_explore) { } binding.merchantsBtn.setOnClickListener { + analyticsService.logEvent(AnalyticsConstants.ExploreDash.WHERE_TO_SPEND, bundleOf()) safeNavigate(ExploreFragmentDirections.exploreToSearch(ExploreTopic.Merchants)) } binding.atmsBtn.setOnClickListener { + analyticsService.logEvent(AnalyticsConstants.ExploreDash.PORTAL_ATM, bundleOf()) safeNavigate(ExploreFragmentDirections.exploreToSearch(ExploreTopic.ATMs)) } } diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/dialogs/ExploreDashInfoDialog.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/dialogs/ExploreDashInfoDialog.kt index 08286940c5..694f11ff27 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/dialogs/ExploreDashInfoDialog.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/dialogs/ExploreDashInfoDialog.kt @@ -22,16 +22,22 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.os.bundleOf +import dagger.hilt.android.AndroidEntryPoint +import org.dash.wallet.common.services.analytics.AnalyticsConstants +import org.dash.wallet.common.services.analytics.AnalyticsService import org.dash.wallet.common.ui.dialogs.OffsetDialogFragment import org.dash.wallet.common.ui.viewBinding import org.dash.wallet.common.util.dialogSafeNavigate import org.dash.wallet.features.exploredash.R import org.dash.wallet.features.exploredash.databinding.ExploreDashMainInfoBinding - +import javax.inject.Inject +@AndroidEntryPoint class ExploreDashInfoDialog : OffsetDialogFragment(){ private val binding by viewBinding(ExploreDashMainInfoBinding::bind) - + @Inject + lateinit var analyticsService: AnalyticsService override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -44,9 +50,11 @@ class ExploreDashInfoDialog : OffsetDialogFragment(){ super.onViewCreated(view, savedInstanceState) binding.learnMoreLabel.setOnClickListener { + analyticsService.logEvent(AnalyticsConstants.ExploreDash.LEARN_MORE, bundleOf()) dialogSafeNavigate(ExploreDashInfoDialogDirections.infoToGiftCardDetail()) } binding.exploreDashInfoContinueBtn.setOnClickListener { + analyticsService.logEvent(AnalyticsConstants.ExploreDash.CONTINUE, bundleOf()) dismissAllowingStateLoss() } } From 961e23db86e761c4ae2f20f46fd8b1f6d76a0eab Mon Sep 17 00:00:00 2001 From: CLAUDE HANGUI Date: Fri, 18 Mar 2022 21:28:23 +0000 Subject: [PATCH 2/7] track firebase events for merchant explore --- .../services/analytics/AnalyticsConstants.kt | 10 +++++ .../exploredash/ui/ExploreMapFragment.kt | 30 ++++++++++++++- .../exploredash/ui/ExploreViewModel.kt | 10 ++++- .../features/exploredash/ui/SearchFragment.kt | 38 ++++++++++++++++++- 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt b/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt index 43a4d039bf..770ce2d0f1 100644 --- a/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt +++ b/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt @@ -106,5 +106,15 @@ object AnalyticsConstants { const val PORTAL_ATM = "portal_atm" const val LEARN_MORE = "info_learn_more" const val CONTINUE = "info_continue" + const val ONLINE_MERCHANTS = "online_merchants" + const val NEARBY_MERCHANTS = "nearby_merchants" + const val ALL_MERCHANTS = "all_merchants" + const val FILTER_MERCHANTS_TOP = "filter_merchants_top" + const val FILTER_MERCHANTS_BOTTOM = "filter_merchants_bottom" + const val SELECT_MERCHANT_LOCATION = "select_merchant_location" + const val SELECT_MERCHANT_MARKER = "select_merchant_marker" + const val INFO_EXPLORE_MERCHANT = "info_search" + const val PAN_MERCHANT_MAP = "pan_merchant_map" + const val ZOOM_MERCHANT_MAP = "zoom_merchant_map" } } \ No newline at end of file diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt index e8bf486e1d..12c671a239 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt @@ -84,7 +84,9 @@ class ExploreMapFragment : SupportMapFragment() { @Inject lateinit var userLocationState: UserLocationStateInt - + private var previousZoomLevel: Float = -1.0f + private var cameraMovementReason: Int = -1 + private lateinit var previousCameraCenterPosition: LatLng override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -97,6 +99,25 @@ class ExploreMapFragment : SupportMapFragment() { googleMap?.let { map -> map.setOnCameraIdleListener { val bounds = map.projection.visibleRegion.latLngBounds + if (cameraMovementReason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE){ + when { + viewModel.hasZoomLevelChanged(previousZoomLevel, map.cameraPosition.zoom) -> { + viewModel.zoomLevelChangeCallback.call() + } + viewModel.hasCameraCenterChanged( + previousCameraCenterPosition.latitude, + previousCameraCenterPosition.longitude, + map.cameraPosition.target.latitude, + map.cameraPosition.target.longitude + ) -> { + viewModel.cameraCenterChangeCallback.call() + } + else -> {} + } + } + + previousZoomLevel = map.cameraPosition.zoom + previousCameraCenterPosition = map.cameraPosition.target viewModel.searchBounds = GeoBounds( bounds.northeast.latitude, bounds.northeast.longitude, @@ -107,6 +128,10 @@ class ExploreMapFragment : SupportMapFragment() { map.cameraPosition.zoom ) } + + map.setOnCameraMoveStartedListener { reason -> + cameraMovementReason = reason + } } } @@ -227,6 +252,7 @@ class ExploreMapFragment : SupportMapFragment() { if (isGooglePlayServicesAvailable()) { markerCollection = MarkerManager(googleMap).newCollection() markerCollection?.setOnMarkerClickListener { marker -> + viewModel.markerClickCallback.call() viewModel.onMapMarkerSelected(marker.tag as Int) true } @@ -351,6 +377,8 @@ class ExploreMapFragment : SupportMapFragment() { val radiusBounds = getRadiusBounds(mCurrentUserLocation, radius) map.moveCamera(radiusBounds) lastFocusedUserLocation = mCurrentUserLocation + previousZoomLevel = map.cameraPosition.zoom + previousCameraCenterPosition = map.cameraPosition.target } } diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt index abd8bcdc8b..b133557ab5 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt @@ -97,7 +97,9 @@ class ExploreViewModel @Inject constructor( private var boundedFilterJob: Job? = null private var pagingFilterJob: Job? = null private var allMerchantLocationsJob: Job? = null - + val zoomLevelChangeCallback = SingleLiveEvent() + val cameraCenterChangeCallback = SingleLiveEvent() + val markerClickCallback = SingleLiveEvent() val isMetric = Locale.getDefault().isMetric private val _searchQuery = MutableStateFlow("") @@ -703,4 +705,10 @@ class ExploreViewModel @Inject constructor( syncStatusService.setObservedLastError() } } + + fun hasZoomLevelChanged(previousZoomLevel: Float, currentZoomLevel: Float): Boolean = + previousZoomLevel != currentZoomLevel + + fun hasCameraCenterChanged(previousLat: Double, previousLng: Double, currentLat: Double, currentLng: Double) + : Boolean = locationProvider.distanceBetween(previousLat, previousLng, currentLat, currentLng) != 0.0 } \ No newline at end of file diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt index 8beaa50691..a811a2d2ee 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt @@ -31,6 +31,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.animation.doOnEnd import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat +import androidx.core.os.bundleOf import androidx.core.view.* import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -59,6 +60,8 @@ import org.dash.wallet.features.exploredash.ui.extensions.* import org.dash.wallet.common.Configuration import org.dash.wallet.common.data.Resource import org.dash.wallet.common.data.Status +import org.dash.wallet.common.services.analytics.AnalyticsConstants +import org.dash.wallet.common.services.analytics.AnalyticsService import org.dash.wallet.features.exploredash.ui.adapters.MerchantLocationsHeaderAdapter import org.dash.wallet.features.exploredash.ui.adapters.MerchantsLocationsAdapter import javax.inject.Inject @@ -73,7 +76,8 @@ class SearchFragment : Fragment(R.layout.fragment_search) { @Inject lateinit var configuration: Configuration - + @Inject + lateinit var analyticsService: AnalyticsService private val binding by viewBinding(FragmentSearchBinding::bind) private val viewModel: ExploreViewModel by activityViewModels() private val args by navArgs() @@ -107,6 +111,7 @@ class SearchFragment : Fragment(R.layout.fragment_search) { hideKeyboard() if (item is Merchant) { + analyticsService.logEvent(AnalyticsConstants.ExploreDash.SELECT_MERCHANT_LOCATION, bundleOf()) viewModel.openMerchantDetails(item, true) } else if (item is Atm) { viewModel.openAtmDetails(item) @@ -150,6 +155,9 @@ class SearchFragment : Fragment(R.layout.fragment_search) { binding.toolbar.setOnMenuItemClickListener { if (it.itemId == R.id.menu_info) { + if (args.type == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.INFO_EXPLORE_MERCHANT, bundleOf()) + } safeNavigate(SearchFragmentDirections.exploreToInfo()) } true @@ -222,6 +230,21 @@ class SearchFragment : Fragment(R.layout.fragment_search) { } } } + viewModel.markerClickCallback.observe(viewLifecycleOwner){ + if (viewModel.exploreTopic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.SELECT_MERCHANT_MARKER, bundleOf()) + } + } + viewModel.zoomLevelChangeCallback.observe(viewLifecycleOwner){ + if (viewModel.exploreTopic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.ZOOM_MERCHANT_MAP, bundleOf()) + } + } + viewModel.cameraCenterChangeCallback.observe(viewLifecycleOwner){ + if (viewModel.exploreTopic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.PAN_MERCHANT_MAP, bundleOf()) + } + } } private fun showError( @@ -304,14 +327,27 @@ class SearchFragment : Fragment(R.layout.fragment_search) { viewModel.setFilterMode(defaultMode) searchHeaderAdapter.setOnFilterOptionChosen { mode -> + if (topic == ExploreTopic.Merchants){ + when(mode){ + FilterMode.Online -> analyticsService.logEvent(AnalyticsConstants.ExploreDash.ONLINE_MERCHANTS, bundleOf()) + FilterMode.Nearby -> analyticsService.logEvent(AnalyticsConstants.ExploreDash.NEARBY_MERCHANTS, bundleOf()) + else -> analyticsService.logEvent(AnalyticsConstants.ExploreDash.ALL_MERCHANTS, bundleOf()) + } + } viewModel.setFilterMode(mode) } searchHeaderAdapter.setOnFilterButtonClicked { + if (topic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.FILTER_MERCHANTS_TOP, bundleOf()) + } openFilters() } binding.filterPanel.setOnClickListener { + if (topic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.FILTER_MERCHANTS_BOTTOM, bundleOf()) + } openFilters() } From 87b8af26dd23b3617580fcb35b49c4e4a779def0 Mon Sep 17 00:00:00 2001 From: CLAUDE HANGUI Date: Fri, 18 Mar 2022 21:58:49 +0000 Subject: [PATCH 3/7] refactor funtion to determine if center position of map has changed --- .../wallet/features/exploredash/ui/ExploreMapFragment.kt | 7 ++----- .../wallet/features/exploredash/ui/ExploreViewModel.kt | 6 ++++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt index 12c671a239..bfe524c842 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt @@ -104,11 +104,8 @@ class ExploreMapFragment : SupportMapFragment() { viewModel.hasZoomLevelChanged(previousZoomLevel, map.cameraPosition.zoom) -> { viewModel.zoomLevelChangeCallback.call() } - viewModel.hasCameraCenterChanged( - previousCameraCenterPosition.latitude, - previousCameraCenterPosition.longitude, - map.cameraPosition.target.latitude, - map.cameraPosition.target.longitude + viewModel.hasCameraCenterChanged(previousCameraCenterPosition, + map.cameraPosition.target ) -> { viewModel.cameraCenterChangeCallback.call() } diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt index b133557ab5..22446c3541 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt @@ -22,6 +22,7 @@ import androidx.annotation.VisibleForTesting import androidx.lifecycle.* import androidx.paging.* import androidx.paging.PagingData +import com.google.android.gms.maps.model.LatLng import com.google.firebase.FirebaseNetworkException import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext @@ -709,6 +710,7 @@ class ExploreViewModel @Inject constructor( fun hasZoomLevelChanged(previousZoomLevel: Float, currentZoomLevel: Float): Boolean = previousZoomLevel != currentZoomLevel - fun hasCameraCenterChanged(previousLat: Double, previousLng: Double, currentLat: Double, currentLng: Double) - : Boolean = locationProvider.distanceBetween(previousLat, previousLng, currentLat, currentLng) != 0.0 + fun hasCameraCenterChanged(previousCenterPosition: LatLng, currentCenterPosition: LatLng) + : Boolean = locationProvider.distanceBetween(previousCenterPosition.latitude, previousCenterPosition.longitude + , currentCenterPosition.latitude, currentCenterPosition.longitude) != 0.0 } \ No newline at end of file From 802cb09422fcded506718e06b992e16d4963db39 Mon Sep 17 00:00:00 2001 From: CLAUDE HANGUI Date: Fri, 18 Mar 2022 21:59:46 +0000 Subject: [PATCH 4/7] fix indentation on funtion to determine if center position of map has changed --- .../dash/wallet/features/exploredash/ui/ExploreViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt index 22446c3541..28052b1857 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt @@ -711,6 +711,6 @@ class ExploreViewModel @Inject constructor( previousZoomLevel != currentZoomLevel fun hasCameraCenterChanged(previousCenterPosition: LatLng, currentCenterPosition: LatLng) - : Boolean = locationProvider.distanceBetween(previousCenterPosition.latitude, previousCenterPosition.longitude - , currentCenterPosition.latitude, currentCenterPosition.longitude) != 0.0 + : Boolean = locationProvider.distanceBetween(previousCenterPosition.latitude, previousCenterPosition.longitude, + currentCenterPosition.latitude, currentCenterPosition.longitude) != 0.0 } \ No newline at end of file From 3d476246f26648fda4749640bccb275b572fcab9 Mon Sep 17 00:00:00 2001 From: CLAUDE HANGUI Date: Sun, 20 Mar 2022 00:50:13 +0000 Subject: [PATCH 5/7] - move map-related tracking to viewmodel - update ExploreViewModelTest.kt to handle injected dependency AnalyticsService --- .../exploredash/ui/ExploreMapFragment.kt | 51 ++++++++----------- .../exploredash/ui/ExploreViewModel.kt | 39 ++++++++++---- .../features/exploredash/ui/SearchFragment.kt | 15 ------ .../exploredash/ExploreViewModelTest.kt | 20 +++++--- 4 files changed, 65 insertions(+), 60 deletions(-) diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt index bfe524c842..c43377357f 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt @@ -84,9 +84,7 @@ class ExploreMapFragment : SupportMapFragment() { @Inject lateinit var userLocationState: UserLocationStateInt - private var previousZoomLevel: Float = -1.0f private var cameraMovementReason: Int = -1 - private lateinit var previousCameraCenterPosition: LatLng override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -98,32 +96,12 @@ class ExploreMapFragment : SupportMapFragment() { showMap() googleMap?.let { map -> map.setOnCameraIdleListener { - val bounds = map.projection.visibleRegion.latLngBounds + viewModel.searchBounds = getGeoBounds() if (cameraMovementReason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE){ - when { - viewModel.hasZoomLevelChanged(previousZoomLevel, map.cameraPosition.zoom) -> { - viewModel.zoomLevelChangeCallback.call() - } - viewModel.hasCameraCenterChanged(previousCameraCenterPosition, - map.cameraPosition.target - ) -> { - viewModel.cameraCenterChangeCallback.call() - } - else -> {} - } + viewModel.triggerPanAndZoomEvents(map.cameraPosition.zoom, getGeoBounds()) } - - previousZoomLevel = map.cameraPosition.zoom - previousCameraCenterPosition = map.cameraPosition.target - viewModel.searchBounds = GeoBounds( - bounds.northeast.latitude, - bounds.northeast.longitude, - bounds.southwest.latitude, - bounds.southwest.longitude, - bounds.center.latitude, - bounds.center.longitude, - map.cameraPosition.zoom - ) + viewModel.previousZoomLevel = map.cameraPosition.zoom + viewModel.previousCameraGeoBounds = getGeoBounds() } map.setOnCameraMoveStartedListener { reason -> @@ -249,7 +227,7 @@ class ExploreMapFragment : SupportMapFragment() { if (isGooglePlayServicesAvailable()) { markerCollection = MarkerManager(googleMap).newCollection() markerCollection?.setOnMarkerClickListener { marker -> - viewModel.markerClickCallback.call() + viewModel.triggerMarkerClickEvent() viewModel.onMapMarkerSelected(marker.tag as Int) true } @@ -374,8 +352,8 @@ class ExploreMapFragment : SupportMapFragment() { val radiusBounds = getRadiusBounds(mCurrentUserLocation, radius) map.moveCamera(radiusBounds) lastFocusedUserLocation = mCurrentUserLocation - previousZoomLevel = map.cameraPosition.zoom - previousCameraCenterPosition = map.cameraPosition.target + viewModel.previousZoomLevel = map.cameraPosition.zoom + viewModel.previousCameraGeoBounds = getGeoBounds() } } @@ -510,4 +488,19 @@ class ExploreMapFragment : SupportMapFragment() { canvas?.let { drawable.draw(it) } return bitmap } + + private fun getGeoBounds(): GeoBounds? { + return googleMap?.let { map -> + val bounds = map.projection.visibleRegion.latLngBounds + GeoBounds( + bounds.northeast.latitude, + bounds.northeast.longitude, + bounds.southwest.latitude, + bounds.southwest.longitude, + bounds.center.latitude, + bounds.center.longitude, + map.cameraPosition.zoom) + } + } + } \ No newline at end of file diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt index 28052b1857..eef88053de 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt @@ -19,6 +19,7 @@ package org.dash.wallet.features.exploredash.ui import android.content.Context import androidx.annotation.VisibleForTesting +import androidx.core.os.bundleOf import androidx.lifecycle.* import androidx.paging.* import androidx.paging.PagingData @@ -32,6 +33,8 @@ import org.dash.wallet.common.data.Resource import org.dash.wallet.common.data.SingleLiveEvent import org.dash.wallet.common.data.Status import org.dash.wallet.common.livedata.ConnectionLiveData +import org.dash.wallet.common.services.analytics.AnalyticsConstants +import org.dash.wallet.common.services.analytics.AnalyticsService import org.dash.wallet.features.exploredash.data.ExploreDataSource import org.dash.wallet.features.exploredash.data.model.* import org.dash.wallet.features.exploredash.data.model.GeoBounds @@ -78,7 +81,8 @@ class ExploreViewModel @Inject constructor( @ApplicationContext private val context: Context, private val exploreData: ExploreDataSource, private val locationProvider: UserLocationStateInt, - private val syncStatusService: DataSyncStatusService + private val syncStatusService: DataSyncStatusService, + private val analyticsService: AnalyticsService ) : ViewModel() { companion object { const val QUERY_DEBOUNCE_VALUE = 300L @@ -98,9 +102,6 @@ class ExploreViewModel @Inject constructor( private var boundedFilterJob: Job? = null private var pagingFilterJob: Job? = null private var allMerchantLocationsJob: Job? = null - val zoomLevelChangeCallback = SingleLiveEvent() - val cameraCenterChangeCallback = SingleLiveEvent() - val markerClickCallback = SingleLiveEvent() val isMetric = Locale.getDefault().isMetric private val _searchQuery = MutableStateFlow("") @@ -109,7 +110,8 @@ class ExploreViewModel @Inject constructor( var exploreTopic = ExploreTopic.Merchants private set - + var previousCameraGeoBounds: GeoBounds? = null + var previousZoomLevel: Float = -1.0f private var lastResolvedAddress: GeoBounds? = null private var _currentUserLocation: MutableStateFlow = MutableStateFlow(null) val currentUserLocation = _currentUserLocation.asLiveData() @@ -707,10 +709,29 @@ class ExploreViewModel @Inject constructor( } } - fun hasZoomLevelChanged(previousZoomLevel: Float, currentZoomLevel: Float): Boolean = + fun triggerPanAndZoomEvents(currentZoomLevel: Float, currentGeoBounds: GeoBounds?){ + when { + hasZoomLevelChanged(currentZoomLevel) -> { + if (exploreTopic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.ZOOM_MERCHANT_MAP, bundleOf()) + } + } + hasCameraCenterChanged(currentGeoBounds) -> { + if (exploreTopic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.PAN_MERCHANT_MAP, bundleOf()) + } + } + } + } + private fun hasZoomLevelChanged(currentZoomLevel: Float): Boolean = previousZoomLevel != currentZoomLevel - fun hasCameraCenterChanged(previousCenterPosition: LatLng, currentCenterPosition: LatLng) - : Boolean = locationProvider.distanceBetween(previousCenterPosition.latitude, previousCenterPosition.longitude, - currentCenterPosition.latitude, currentCenterPosition.longitude) != 0.0 + private fun hasCameraCenterChanged(currentCenterPosition: GeoBounds?): Boolean = + locationProvider.distanceBetweenCenters(previousCameraGeoBounds!!, currentCenterPosition!!) != 0.0 + + fun triggerMarkerClickEvent(){ + if (exploreTopic == ExploreTopic.Merchants){ + analyticsService.logEvent(AnalyticsConstants.ExploreDash.SELECT_MERCHANT_MARKER, bundleOf()) + } + } } \ No newline at end of file diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt index a811a2d2ee..b7de58ee9f 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/SearchFragment.kt @@ -230,21 +230,6 @@ class SearchFragment : Fragment(R.layout.fragment_search) { } } } - viewModel.markerClickCallback.observe(viewLifecycleOwner){ - if (viewModel.exploreTopic == ExploreTopic.Merchants){ - analyticsService.logEvent(AnalyticsConstants.ExploreDash.SELECT_MERCHANT_MARKER, bundleOf()) - } - } - viewModel.zoomLevelChangeCallback.observe(viewLifecycleOwner){ - if (viewModel.exploreTopic == ExploreTopic.Merchants){ - analyticsService.logEvent(AnalyticsConstants.ExploreDash.ZOOM_MERCHANT_MAP, bundleOf()) - } - } - viewModel.cameraCenterChangeCallback.observe(viewLifecycleOwner){ - if (viewModel.exploreTopic == ExploreTopic.Merchants){ - analyticsService.logEvent(AnalyticsConstants.ExploreDash.PAN_MERCHANT_MAP, bundleOf()) - } - } } private fun showError( diff --git a/features/exploredash/src/test/java/org/dash/wallet/features/exploredash/ExploreViewModelTest.kt b/features/exploredash/src/test/java/org/dash/wallet/features/exploredash/ExploreViewModelTest.kt index 4a3ea5daf2..6565316dd5 100644 --- a/features/exploredash/src/test/java/org/dash/wallet/features/exploredash/ExploreViewModelTest.kt +++ b/features/exploredash/src/test/java/org/dash/wallet/features/exploredash/ExploreViewModelTest.kt @@ -30,6 +30,7 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flow import kotlinx.coroutines.runBlocking import org.dash.wallet.common.data.Resource +import org.dash.wallet.common.services.analytics.AnalyticsService import org.dash.wallet.features.exploredash.data.ExploreDataSource import org.dash.wallet.features.exploredash.data.model.GeoBounds import org.dash.wallet.features.exploredash.data.model.Merchant @@ -124,8 +125,8 @@ class ExploreViewModelTest { on { getSyncProgressFlow() } doReturn flow { emit(Resource.loading(50.0))} on { hasObservedLastError() } doReturn flow { emit(false) } } - - val viewModel = ExploreViewModel(context, dataSource, locationState, dataSyncStatus) + val analyticsService = mock() + val viewModel = ExploreViewModel(context, dataSource, locationState, dataSyncStatus, analyticsService) viewModel.setSelectedTerritory(territory) viewModel.setFilterMode(FilterMode.All) viewModel.searchBounds = GeoBounds.noBounds @@ -169,8 +170,8 @@ class ExploreViewModelTest { on { getSyncProgressFlow() } doReturn flow { emit(Resource.loading(50.0))} on { hasObservedLastError() } doReturn flow { emit(false) } } - - val viewModel = ExploreViewModel(context, dataSource, locationState, dataSyncStatus) + val analyticsService = mock() + val viewModel = ExploreViewModel(context, dataSource, locationState, dataSyncStatus, analyticsService) viewModel.setFilterMode(FilterMode.Nearby) viewModel.searchBounds = bounds viewModel.paymentMethodFilter = PaymentMethod.DASH @@ -215,8 +216,9 @@ class ExploreViewModelTest { on { getSyncProgressFlow() } doReturn flow { emit(Resource.loading(50.0))} on { hasObservedLastError() } doReturn flow { emit(false) } } + val analyticsService = mock() - val viewModel = ExploreViewModel(context, dataSource, locationState, dataSyncStatus) + val viewModel = ExploreViewModel(context, dataSource, locationState, dataSyncStatus, analyticsService) viewModel.setSelectedTerritory(territory) viewModel.searchBounds = GeoBounds.noBounds viewModel.setFilterMode(FilterMode.All) @@ -265,7 +267,9 @@ class ExploreViewModelTest { on { getSyncProgressFlow() } doReturn flow { emit(Resource.loading(50.0))} on { hasObservedLastError() } doReturn flow { emit(false) } } - val viewModel = ExploreViewModel(context, dataSource, locationMock, dataSyncStatus) + val analyticsService = mock() + + val viewModel = ExploreViewModel(context, dataSource, locationMock, dataSyncStatus, analyticsService) viewModel.searchBounds = GeoBounds(90.0, 180.0, -90.0, -180.0, userLat, userLng) .apply { zoomLevel = ExploreViewModel.MIN_ZOOM_LEVEL + 1 } viewModel.setFilterMode(FilterMode.Nearby) @@ -297,7 +301,9 @@ class ExploreViewModelTest { on { getSyncProgressFlow() } doReturn flow { emit(Resource.loading(50.0))} on { hasObservedLastError() } doReturn flow { emit(false) } } - val viewModel = ExploreViewModel(context, dataSource, locationMock, dataSyncStatus) + val analyticsService = mock() + + val viewModel = ExploreViewModel(context, dataSource, locationMock, dataSyncStatus,analyticsService) viewModel.setPhysicalResults(merchants) viewModel.onMapMarkerSelected(5) From f022f1220167b71d1f1465d2513b9c96f8927ea9 Mon Sep 17 00:00:00 2001 From: CLAUDE HANGUI Date: Sun, 20 Mar 2022 10:03:01 +0000 Subject: [PATCH 6/7] - refactor getGeoBounds() function -> set parameter of type GoogleMap - initialize previousCameraGeoBounds var with non-nullable value --- .../exploredash/ui/ExploreMapFragment.kt | 17 +++++++---------- .../features/exploredash/ui/ExploreViewModel.kt | 8 ++++---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt index c43377357f..5d89e7cd56 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreMapFragment.kt @@ -96,12 +96,12 @@ class ExploreMapFragment : SupportMapFragment() { showMap() googleMap?.let { map -> map.setOnCameraIdleListener { - viewModel.searchBounds = getGeoBounds() + viewModel.searchBounds = getGeoBounds(map) if (cameraMovementReason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE){ - viewModel.triggerPanAndZoomEvents(map.cameraPosition.zoom, getGeoBounds()) + viewModel.triggerPanAndZoomEvents(map.cameraPosition.zoom, getGeoBounds(map)) } viewModel.previousZoomLevel = map.cameraPosition.zoom - viewModel.previousCameraGeoBounds = getGeoBounds() + viewModel.previousCameraGeoBounds = getGeoBounds(map) } map.setOnCameraMoveStartedListener { reason -> @@ -353,7 +353,7 @@ class ExploreMapFragment : SupportMapFragment() { map.moveCamera(radiusBounds) lastFocusedUserLocation = mCurrentUserLocation viewModel.previousZoomLevel = map.cameraPosition.zoom - viewModel.previousCameraGeoBounds = getGeoBounds() + viewModel.previousCameraGeoBounds = getGeoBounds(map) } } @@ -489,10 +489,9 @@ class ExploreMapFragment : SupportMapFragment() { return bitmap } - private fun getGeoBounds(): GeoBounds? { - return googleMap?.let { map -> - val bounds = map.projection.visibleRegion.latLngBounds - GeoBounds( + private fun getGeoBounds(map: GoogleMap): GeoBounds { + val bounds = map.projection.visibleRegion.latLngBounds + return GeoBounds( bounds.northeast.latitude, bounds.northeast.longitude, bounds.southwest.latitude, @@ -500,7 +499,5 @@ class ExploreMapFragment : SupportMapFragment() { bounds.center.latitude, bounds.center.longitude, map.cameraPosition.zoom) - } } - } \ No newline at end of file diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt index eef88053de..9e09dc534d 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ExploreViewModel.kt @@ -110,7 +110,7 @@ class ExploreViewModel @Inject constructor( var exploreTopic = ExploreTopic.Merchants private set - var previousCameraGeoBounds: GeoBounds? = null + var previousCameraGeoBounds = GeoBounds.noBounds var previousZoomLevel: Float = -1.0f private var lastResolvedAddress: GeoBounds? = null private var _currentUserLocation: MutableStateFlow = MutableStateFlow(null) @@ -709,7 +709,7 @@ class ExploreViewModel @Inject constructor( } } - fun triggerPanAndZoomEvents(currentZoomLevel: Float, currentGeoBounds: GeoBounds?){ + fun triggerPanAndZoomEvents(currentZoomLevel: Float, currentGeoBounds: GeoBounds){ when { hasZoomLevelChanged(currentZoomLevel) -> { if (exploreTopic == ExploreTopic.Merchants){ @@ -726,8 +726,8 @@ class ExploreViewModel @Inject constructor( private fun hasZoomLevelChanged(currentZoomLevel: Float): Boolean = previousZoomLevel != currentZoomLevel - private fun hasCameraCenterChanged(currentCenterPosition: GeoBounds?): Boolean = - locationProvider.distanceBetweenCenters(previousCameraGeoBounds!!, currentCenterPosition!!) != 0.0 + private fun hasCameraCenterChanged(currentCenterPosition: GeoBounds): Boolean = + locationProvider.distanceBetweenCenters(previousCameraGeoBounds, currentCenterPosition) != 0.0 fun triggerMarkerClickEvent(){ if (exploreTopic == ExploreTopic.Merchants){ From e8492503f6ecb0ae0ad864d99e1ae38db45862b4 Mon Sep 17 00:00:00 2001 From: CLAUDE HANGUI Date: Mon, 21 Mar 2022 09:43:32 +0000 Subject: [PATCH 7/7] add explore prefix to explore dash tracing event names --- .../services/analytics/AnalyticsConstants.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt b/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt index 770ce2d0f1..c0222ce44e 100644 --- a/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt +++ b/common/src/main/java/org/dash/wallet/common/services/analytics/AnalyticsConstants.kt @@ -102,19 +102,19 @@ object AnalyticsConstants { } object ExploreDash { - const val WHERE_TO_SPEND = "portal_where_to_spend" - const val PORTAL_ATM = "portal_atm" - const val LEARN_MORE = "info_learn_more" - const val CONTINUE = "info_continue" - const val ONLINE_MERCHANTS = "online_merchants" - const val NEARBY_MERCHANTS = "nearby_merchants" - const val ALL_MERCHANTS = "all_merchants" - const val FILTER_MERCHANTS_TOP = "filter_merchants_top" - const val FILTER_MERCHANTS_BOTTOM = "filter_merchants_bottom" - const val SELECT_MERCHANT_LOCATION = "select_merchant_location" - const val SELECT_MERCHANT_MARKER = "select_merchant_marker" - const val INFO_EXPLORE_MERCHANT = "info_search" - const val PAN_MERCHANT_MAP = "pan_merchant_map" - const val ZOOM_MERCHANT_MAP = "zoom_merchant_map" + const val WHERE_TO_SPEND = "explore_portal_where_to_spend" + const val PORTAL_ATM = "explore_portal_atm" + const val LEARN_MORE = "explore_info_learn_more" + const val CONTINUE = "explore_info_continue" + const val ONLINE_MERCHANTS = "explore_online_merchants" + const val NEARBY_MERCHANTS = "explore_nearby_merchants" + const val ALL_MERCHANTS = "explore_all_merchants" + const val FILTER_MERCHANTS_TOP = "explore_filter_merchants_top" + const val FILTER_MERCHANTS_BOTTOM = "explore_filter_merchants_bottom" + const val SELECT_MERCHANT_LOCATION = "explore_select_merchant_location" + const val SELECT_MERCHANT_MARKER = "explore_select_merchant_marker" + const val INFO_EXPLORE_MERCHANT = "explore_info_search" + const val PAN_MERCHANT_MAP = "explore_pan_merchant_map" + const val ZOOM_MERCHANT_MAP = "explore_zoom_merchant_map" } } \ No newline at end of file