From 28aebab0b61e7007f9a91b77788d5590adcae8b8 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Tue, 14 May 2024 13:01:08 +0100 Subject: [PATCH 1/3] Make sure custom range is not applied when date picker is dismissed --- .../ui/dashboard/stats/DashboardStatsViewModel.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/DashboardStatsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/DashboardStatsViewModel.kt index 2b28b355e2c..9bee6071ed6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/DashboardStatsViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/DashboardStatsViewModel.kt @@ -115,12 +115,13 @@ class DashboardStatsViewModel @AssistedInject constructor( fun onTabSelected(selectionType: SelectionType) { usageTracksEventEmitter.interacted() - appPrefsWrapper.setActiveStatsTab(selectionType.name) - - if (selectionType == SelectionType.CUSTOM) { + if (selectionType != SelectionType.CUSTOM) { + appPrefsWrapper.setActiveStatsTab(selectionType.name) + } else { if (dateRangeState.value?.customRange == null) { onAddCustomRangeClicked() } else { + appPrefsWrapper.setActiveStatsTab(SelectionType.CUSTOM.name) analyticsTrackerWrapper.track( AnalyticsEvent.DASHBOARD_STATS_CUSTOM_RANGE_TAB_SELECTED ) @@ -136,11 +137,11 @@ class DashboardStatsViewModel @AssistedInject constructor( ) ) - if (dateRangeState.value?.rangeSelection?.selectionType != SelectionType.CUSTOM) { - onTabSelected(SelectionType.CUSTOM) - } viewModelScope.launch { customDateRangeDataStore.updateDateRange(range) + if (dateRangeState.value?.rangeSelection?.selectionType != SelectionType.CUSTOM) { + onTabSelected(SelectionType.CUSTOM) + } } } From 1a9018ad4b42b594e855be0a7cdf477d0cc3c6a1 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Tue, 14 May 2024 13:01:35 +0100 Subject: [PATCH 2/3] Align top performers custom range selection with stats card The changes allow for showing the date picker when no custom range is saved. --- .../DashboardTopPerformersViewModel.kt | 46 +++++++++++++------ .../DashboardTopPerformersWidgetCard.kt | 23 +++++----- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt index 4b368679650..802da1f4480 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt @@ -46,6 +46,7 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge @@ -81,10 +82,14 @@ class DashboardTopPerformersViewModel @AssistedInject constructor( getSelectedDateRange: GetSelectedRangeForTopPerformers, ) : ScopedViewModel(savedState) { private val _selectedDateRange = getSelectedDateRange() - val selectedDateRange: LiveData = _selectedDateRange.map { + val selectedDateRange: LiveData = combine( + _selectedDateRange, + customDateRangeDataStore.dateRange + ) { selectedRange, customRange -> TopPerformersDateRange( - rangeSelection = it, - dateFormatted = dateFormatter.formatRangeDate(it) + rangeSelection = selectedRange, + customRange = customRange, + dateFormatted = dateFormatter.formatRangeDate(selectedRange) ) }.asLiveData() @@ -102,8 +107,6 @@ class DashboardTopPerformersViewModel @AssistedInject constructor( ) }.asLiveData() - private val customRange = customDateRangeDataStore.dateRange.asLiveData() - private val refreshTrigger = MutableSharedFlow(extraBufferCapacity = 1) init { @@ -152,21 +155,32 @@ class DashboardTopPerformersViewModel @AssistedInject constructor( } } - fun onGranularityChanged(selectionType: SelectionType) { + fun onTabSelected(selectionType: SelectionType) { usageTracksEventEmitter.interacted() - appPrefsWrapper.setActiveTopPerformersGranularity(selectionType.name) - if (selectionType == SelectionType.CUSTOM) { - analyticsTrackerWrapper.track( - AnalyticsEvent.DASHBOARD_STATS_CUSTOM_RANGE_TAB_SELECTED - ) + if (selectionType != SelectionType.CUSTOM) { + appPrefsWrapper.setActiveTopPerformersGranularity(selectionType.name) + } else { + if (selectedDateRange.value?.customRange == null) { + onEditCustomRangeTapped() + } else { + appPrefsWrapper.setActiveTopPerformersGranularity(SelectionType.CUSTOM.name) + analyticsTrackerWrapper.track(AnalyticsEvent.DASHBOARD_STATS_CUSTOM_RANGE_TAB_SELECTED) + } } } fun onEditCustomRangeTapped() { + val event = if (selectedDateRange.value?.customRange == null) { + AnalyticsEvent.DASHBOARD_STATS_CUSTOM_RANGE_ADD_BUTTON_TAPPED + } else { + AnalyticsEvent.DASHBOARD_STATS_CUSTOM_RANGE_EDIT_BUTTON_TAPPED + } + analyticsTrackerWrapper.track(event) + triggerEvent( OpenDatePicker( - fromDate = customRange.value?.start ?: Date(), - toDate = customRange.value?.end ?: Date() + fromDate = selectedDateRange.value?.customRange?.start ?: Date(), + toDate = selectedDateRange.value?.customRange?.end ?: Date() ) ) } @@ -247,11 +261,14 @@ class DashboardTopPerformersViewModel @AssistedInject constructor( analyticsTrackerWrapper.track( AnalyticsEvent.DASHBOARD_STATS_CUSTOM_RANGE_CONFIRMED, mapOf( - AnalyticsTracker.KEY_IS_EDITING to (customRange.value != null), + AnalyticsTracker.KEY_IS_EDITING to (selectedDateRange.value?.customRange != null), ) ) viewModelScope.launch { customDateRangeDataStore.updateDateRange(statsTimeRange) + if (selectedDateRange.value?.rangeSelection?.selectionType != SelectionType.CUSTOM) { + onTabSelected(SelectionType.CUSTOM) + } } } @@ -264,6 +281,7 @@ class DashboardTopPerformersViewModel @AssistedInject constructor( data class TopPerformersDateRange( val rangeSelection: StatsTimeRangeSelection, + val customRange: StatsTimeRange?, val dateFormatted: String ) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersWidgetCard.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersWidgetCard.kt index 5c25fd46444..b433f031527 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersWidgetCard.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersWidgetCard.kt @@ -90,11 +90,11 @@ fun DashboardTopPerformersWidgetCard( ) else -> DashboardTopPerformersContent( - topPerformersState, - selectedDateRange, - lastUpdateState, - topPerformersViewModel::onGranularityChanged, - topPerformersViewModel::onEditCustomRangeTapped + topPerformersState = topPerformersState, + selectedDateRange = selectedDateRange, + lastUpdateState = lastUpdateState, + onTabSelected = topPerformersViewModel::onTabSelected, + onEditCustomRangeTapped = topPerformersViewModel::onEditCustomRangeTapped ) } } @@ -120,7 +120,7 @@ fun DashboardTopPerformersContent( topPerformersState: TopPerformersState?, selectedDateRange: TopPerformersDateRange?, lastUpdateState: String?, - onGranularityChanged: (SelectionType) -> Unit, + onTabSelected: (SelectionType) -> Unit, onEditCustomRangeTapped: () -> Unit, ) { Column { @@ -129,7 +129,7 @@ fun DashboardTopPerformersContent( rangeSelection = it.rangeSelection, dateFormatted = it.dateFormatted, onCustomRangeClick = onEditCustomRangeTapped, - onTabSelected = onGranularityChanged + onTabSelected = onTabSelected ) } Divider(modifier = Modifier.padding(bottom = 16.dp)) @@ -377,6 +377,7 @@ private fun TopPerformersWidgetCardPreview() { calendar = Calendar.getInstance(), locale = Locale.getDefault(), ), + customRange = null, dateFormatted = "Today" ) val topPerformersState = TopPerformersState( @@ -420,28 +421,28 @@ private fun TopPerformersWidgetCardPreview() { topPerformersState = topPerformersState, lastUpdateState = "Last update: 8:52 AM", selectedDateRange = selectedDateRange, - onGranularityChanged = {}, + onTabSelected = {}, onEditCustomRangeTapped = {} ) DashboardTopPerformersContent( topPerformersState = topPerformersState.copy(isLoading = true), lastUpdateState = "Last update: 8:52 AM", selectedDateRange = selectedDateRange, - onGranularityChanged = {}, + onTabSelected = {}, onEditCustomRangeTapped = {} ) DashboardTopPerformersContent( topPerformersState = topPerformersState.copy(isError = true), lastUpdateState = "Last update: 8:52 AM", selectedDateRange = selectedDateRange, - onGranularityChanged = {}, + onTabSelected = {}, onEditCustomRangeTapped = {} ) DashboardTopPerformersContent( topPerformersState = topPerformersState.copy(topPerformers = emptyList()), lastUpdateState = "Last update: 8:52 AM", selectedDateRange = selectedDateRange, - onGranularityChanged = {}, + onTabSelected = {}, onEditCustomRangeTapped = {} ) } From ec699eef9518968095614c8e426419cea3713ae1 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Tue, 14 May 2024 13:02:27 +0100 Subject: [PATCH 3/3] Rename functions for more clarity --- .../src/main/kotlin/com/woocommerce/android/AppPrefs.kt | 4 ++-- .../kotlin/com/woocommerce/android/AppPrefsWrapper.kt | 8 ++++---- .../dashboard/stats/GetSelectedRangeForTopPerformers.kt | 2 +- .../topperformers/DashboardTopPerformersViewModel.kt | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt index 2ba29685aef..6305687b97b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt @@ -861,11 +861,11 @@ object AppPrefs { fun getActiveStatsTab() = getString(DeletablePrefKey.ACTIVE_STATS_GRANULARITY) - fun setActiveTopPerformersGranularity(selectionName: String) { + fun setActiveTopPerformersTab(selectionName: String) { setString(DeletablePrefKey.ACTIVE_TOP_PERFORMERS_GRANULARITY, selectionName) } - fun getActiveTopPerformersGranularity() = getString(DeletablePrefKey.ACTIVE_TOP_PERFORMERS_GRANULARITY) + fun getActiveTopPerformersTab() = getString(DeletablePrefKey.ACTIVE_TOP_PERFORMERS_GRANULARITY) fun setCustomDomainsSource(source: String) { setString(DeletablePrefKey.CUSTOM_DOMAINS_SOURCE, source) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt index a06b3c1ba44..8d2c1a971c4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt @@ -212,12 +212,12 @@ class AppPrefsWrapper @Inject constructor() { fun getActiveStoreStatsTab() = AppPrefs.getActiveStatsTab() - fun setActiveTopPerformersGranularity(selectionName: String) { - AppPrefs.setActiveTopPerformersGranularity(selectionName) + fun setActiveTopPerformersTab(selectionName: String) { + AppPrefs.setActiveTopPerformersTab(selectionName) } - fun getActiveTopPerformersGranularity() = - AppPrefs.getActiveTopPerformersGranularity() + fun getActiveTopPerformersTab() = + AppPrefs.getActiveTopPerformersTab() fun setCustomDomainsSource(source: DomainFlowSource) { AppPrefs.setCustomDomainsSource(source.name) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/GetSelectedRangeForTopPerformers.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/GetSelectedRangeForTopPerformers.kt index f298496d1c2..c37b6d62b14 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/GetSelectedRangeForTopPerformers.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/stats/GetSelectedRangeForTopPerformers.kt @@ -13,6 +13,6 @@ class GetSelectedRangeForTopPerformers @Inject constructor( ) : GetSelectedDateRange(appPrefs, customDateRangeDataStore, dateUtils) { override fun getSelectedRange(): SelectionType = runCatching { - SelectionType.valueOf(appPrefs.getActiveTopPerformersGranularity()) + SelectionType.valueOf(appPrefs.getActiveTopPerformersTab()) }.getOrDefault(SelectionType.TODAY) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt index 802da1f4480..3a93c7378e9 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topperformers/DashboardTopPerformersViewModel.kt @@ -158,12 +158,12 @@ class DashboardTopPerformersViewModel @AssistedInject constructor( fun onTabSelected(selectionType: SelectionType) { usageTracksEventEmitter.interacted() if (selectionType != SelectionType.CUSTOM) { - appPrefsWrapper.setActiveTopPerformersGranularity(selectionType.name) + appPrefsWrapper.setActiveTopPerformersTab(selectionType.name) } else { if (selectedDateRange.value?.customRange == null) { onEditCustomRangeTapped() } else { - appPrefsWrapper.setActiveTopPerformersGranularity(SelectionType.CUSTOM.name) + appPrefsWrapper.setActiveTopPerformersTab(SelectionType.CUSTOM.name) analyticsTrackerWrapper.track(AnalyticsEvent.DASHBOARD_STATS_CUSTOM_RANGE_TAB_SELECTED) } }