From 9a2d975b3747c7a866420e17b006b2d0051ad1da Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Thu, 26 Sep 2024 16:12:23 +0200 Subject: [PATCH 01/12] Add new objective field to campaign details --- .../com/woocommerce/android/ui/blaze/BlazeRepository.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt index 2d94bf3da21..9e3bb89bfa6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt @@ -191,7 +191,8 @@ class BlazeRepository @Inject constructor( destinationParameters = DestinationParameters( targetUrl = product.permalink, parameters = emptyMap() - ) + ), + objectiveId = "" ) } @@ -318,7 +319,8 @@ class BlazeRepository @Inject constructor( topics = it.interests.map { interest -> interest.id } ) }, - isEndlessCampaign = campaignDetails.budget.isEndlessCampaign + isEndlessCampaign = campaignDetails.budget.isEndlessCampaign, + objectiveId = campaignDetails.objectiveId ) ) @@ -384,6 +386,7 @@ class BlazeRepository @Inject constructor( val budget: Budget, val targetingParameters: TargetingParameters, val destinationParameters: DestinationParameters, + val objectiveId: String ) : Parcelable sealed interface BlazeCampaignImage : Parcelable { From f59d3fcf0e98c90c0196a554531a636549ae27eb Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Thu, 26 Sep 2024 16:18:05 +0200 Subject: [PATCH 02/12] Update FluxC changeset --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 774a74ac196..877a2437171 100644 --- a/build.gradle +++ b/build.gradle @@ -100,7 +100,7 @@ tasks.register("installGitHooks", Copy) { } ext { - fluxCVersion = 'trunk-9a51a9dfcfdb247e15dc14ad025ddee9e3285ff8' + fluxCVersion = '3103-6a3c656de5377ca7677548baa0a259edfc9c9ffe' glideVersion = '4.16.0' coilVersion = '2.1.0' constraintLayoutVersion = '1.2.0' From 408675ffcb458ac1931c49df2318e0d538651212 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 11:49:10 +0200 Subject: [PATCH 03/12] Fetch objectives for Blaze preview screen --- .../com/woocommerce/android/AppPrefs.kt | 5 +++ .../woocommerce/android/AppPrefsWrapper.kt | 2 + .../BlazeCampaignCreationPreviewScreen.kt | 7 +++- .../BlazeCampaignCreationPreviewViewModel.kt | 37 ++++++++++++++++--- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt index 4abf337fc9f..af6b06176c6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefs.kt @@ -129,6 +129,7 @@ object AppPrefs { TIMES_AI_PRODUCT_CREATION_SURVEY_DISPLAYED, AI_PRODUCT_CREATION_SURVEY_DISMISSED, CUSTOM_FIELDS_TOP_BANNER_DISMISSED, + BLAZE_CAMPAIGN_SELECTED_OBJECTIVE } /** @@ -274,6 +275,10 @@ object AppPrefs { get() = getBoolean(DeletablePrefKey.CUSTOM_FIELDS_TOP_BANNER_DISMISSED, false) set(value) = setBoolean(DeletablePrefKey.CUSTOM_FIELDS_TOP_BANNER_DISMISSED, value) + var blazeCampaignSelectedObjective: String + get() = getString(DeletablePrefKey.BLAZE_CAMPAIGN_SELECTED_OBJECTIVE, "") + set(value) = setString(DeletablePrefKey.BLAZE_CAMPAIGN_SELECTED_OBJECTIVE, value) + fun getProductSortingChoice(currentSiteId: Int) = getString(getProductSortingKey(currentSiteId)).orNullIfEmpty() fun setProductSortingChoice(currentSiteId: Int, value: String) { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt index e4d61019ff5..f423366b165 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/AppPrefsWrapper.kt @@ -40,6 +40,8 @@ class AppPrefsWrapper @Inject constructor() { var isCustomFieldsTopBannerDismissed by AppPrefs::isCustomFieldsTopBannerDismissed + var blazeCampaignSelectedObjective by AppPrefs::blazeCampaignSelectedObjective + fun getAppInstallationDate() = AppPrefs.installationDate fun getReceiptUrl(localSiteId: Int, remoteSiteId: Long, selfHostedSiteId: Long, orderId: Long) = diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt index 9865dff0cbd..34b19d9b9ba 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt @@ -50,6 +50,7 @@ import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPr import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.CampaignDetailItemUi import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.CampaignDetailsUi import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.CampaignPreviewUiState +import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.SelectedObjectiveUi import com.woocommerce.android.ui.compose.Render import com.woocommerce.android.ui.compose.animations.SkeletonView import com.woocommerce.android.ui.compose.component.ToolbarWithHelpButton @@ -449,7 +450,11 @@ fun CampaignScreenPreview() { displayValue = "https://www.myer.com.au/p/white-t-shirt-797334760-797334760", onItemSelected = {}, maxLinesValue = 1, - ) + ), + selectedObjective = SelectedObjectiveUi( + id = "sales", + displayTitle = "Sales", + ), ) ), onBackPressed = { }, diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt index 25c770092c3..4706dfebc16 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt @@ -3,6 +3,7 @@ package com.woocommerce.android.ui.blaze.creation.preview import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope +import com.woocommerce.android.AppPrefsWrapper import com.woocommerce.android.R import com.woocommerce.android.analytics.AnalyticsEvent.BLAZE_CREATION_CONFIRM_DETAILS_TAPPED import com.woocommerce.android.analytics.AnalyticsEvent.BLAZE_CREATION_EDIT_AD_TAPPED @@ -15,6 +16,7 @@ import com.woocommerce.android.support.help.HelpOrigin import com.woocommerce.android.ui.blaze.BlazeRepository import com.woocommerce.android.ui.blaze.BlazeRepository.AiSuggestionForAd import com.woocommerce.android.ui.blaze.BlazeRepository.CampaignDetails +import com.woocommerce.android.ui.blaze.BlazeRepository.Objective import com.woocommerce.android.ui.blaze.Location import com.woocommerce.android.ui.blaze.creation.targets.BlazeTargetType import com.woocommerce.android.ui.blaze.creation.targets.BlazeTargetType.DEVICE @@ -44,6 +46,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( private val resourceProvider: ResourceProvider, private val currencyFormatter: CurrencyFormatter, private val analyticsTrackerWrapper: AnalyticsTrackerWrapper, + private val appPrefsWrapper: AppPrefsWrapper ) : ScopedViewModel(savedStateHandle) { private val navArgs: BlazeCampaignCreationPreviewFragmentArgs by savedStateHandle.navArgs() private val campaignDetails = savedStateHandle.getNullableStateFlow( @@ -60,8 +63,10 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( val viewState = combine( campaignDetails.filterNotNull(), adDetailsState, - dialogState - ) { campaignDetails, adDetailsState, dialogState -> + dialogState, + blazeRepository.observeObjectives() + ) { campaignDetails, adDetailsState, dialogState, objectives -> + val selectedObjective = getSelectedObjective(objectives) CampaignPreviewUiState( adDetails = when (adDetailsState) { AdDetailsUiState.LOADING -> AdDetailsUi.Loading @@ -73,11 +78,20 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( isContentSuggestedByAi = isAdContentGeneratedByAi(campaignDetails) ) }, - campaignDetails = campaignDetails.toCampaignDetailsUi(), + campaignDetails = campaignDetails.toCampaignDetailsUi(selectedObjective), dialogState = dialogState ) }.asLiveData() + private fun getSelectedObjective(objectives: List) = + if (objectives.isNotEmpty() + && appPrefsWrapper.blazeCampaignSelectedObjective.isNotEmpty() + ) { + objectives + .find { it.id == appPrefsWrapper.blazeCampaignSelectedObjective } + ?.toSelectedObjectiveUi() + } else null + init { loadData() analyticsTrackerWrapper.track( @@ -234,10 +248,11 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( ) } } + blazeRepository.fetchObjectives() } } - private fun CampaignDetails.toCampaignDetailsUi() = CampaignDetailsUi( + private fun CampaignDetails.toCampaignDetailsUi(selectedObjective: SelectedObjectiveUi?) = CampaignDetailsUi( budget = getBudgetDetails(), targetDetails = listOf( getTargetLanguagesDetails(), @@ -245,7 +260,13 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( getTargetLocationsDetails(), getTargetInterestsDetails(), ), - destinationUrl = getTargetDestinationDetails() + destinationUrl = getTargetDestinationDetails(), + selectedObjective = selectedObjective + ) + + private fun Objective.toSelectedObjectiveUi() = SelectedObjectiveUi( + id = id, + displayTitle = title ) private fun CampaignDetails.getBudgetDetails() = @@ -365,6 +386,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( val budget: CampaignDetailItemUi, val targetDetails: List, val destinationUrl: CampaignDetailItemUi, + val selectedObjective: SelectedObjectiveUi? ) data class CampaignDetailItemUi( @@ -404,4 +426,9 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( data class NavigateToPaymentSummary( val campaignDetails: CampaignDetails ) : MultiLiveEvent.Event() + + data class SelectedObjectiveUi( + val id: String, + val displayTitle: String + ) : MultiLiveEvent.Event() } From a2163033dfe4173fa8acd6690b0cc739c0f90ba9 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 12:44:51 +0200 Subject: [PATCH 04/12] Display selected objective value --- .../BlazeCampaignCreationPreviewScreen.kt | 10 ++--- .../BlazeCampaignCreationPreviewViewModel.kt | 40 ++++++++----------- WooCommerce/src/main/res/values/strings.xml | 2 + 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt index 34b19d9b9ba..4f1e4df3051 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewScreen.kt @@ -50,7 +50,6 @@ import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPr import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.CampaignDetailItemUi import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.CampaignDetailsUi import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.CampaignPreviewUiState -import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.SelectedObjectiveUi import com.woocommerce.android.ui.compose.Render import com.woocommerce.android.ui.compose.animations.SkeletonView import com.woocommerce.android.ui.compose.component.ToolbarWithHelpButton @@ -320,7 +319,7 @@ fun CampaignDetails( style = MaterialTheme.typography.body2 ) // Budget - CampaignPropertyGroupItem(items = listOf(campaignDetails.budget)) + CampaignPropertyGroupItem(items = listOf(campaignDetails.selectedObjective, campaignDetails.budget)) Spacer(modifier = Modifier.height(16.dp)) // Ad Audience @@ -451,9 +450,10 @@ fun CampaignScreenPreview() { onItemSelected = {}, maxLinesValue = 1, ), - selectedObjective = SelectedObjectiveUi( - id = "sales", - displayTitle = "Sales", + selectedObjective = CampaignDetailItemUi( + displayTitle = stringResource(R.string.blaze_campaign_preview_details_objective), + displayValue = "Sales", + onItemSelected = {}, ), ) ), diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt index 4706dfebc16..c4eaa4e3ccc 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt @@ -56,6 +56,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( clazz = CampaignDetails::class.java ) private var aiSuggestions: List = emptyList() + private var campaignObjectives: List = emptyList() private val adDetailsState = savedStateHandle.getStateFlow(viewModelScope, AdDetailsUiState.LOADING) private val dialogState = MutableStateFlow(null) @@ -66,7 +67,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( dialogState, blazeRepository.observeObjectives() ) { campaignDetails, adDetailsState, dialogState, objectives -> - val selectedObjective = getSelectedObjective(objectives) + campaignObjectives = objectives CampaignPreviewUiState( adDetails = when (adDetailsState) { AdDetailsUiState.LOADING -> AdDetailsUi.Loading @@ -78,20 +79,11 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( isContentSuggestedByAi = isAdContentGeneratedByAi(campaignDetails) ) }, - campaignDetails = campaignDetails.toCampaignDetailsUi(selectedObjective), + campaignDetails = campaignDetails.toCampaignDetailsUi(), dialogState = dialogState ) }.asLiveData() - private fun getSelectedObjective(objectives: List) = - if (objectives.isNotEmpty() - && appPrefsWrapper.blazeCampaignSelectedObjective.isNotEmpty() - ) { - objectives - .find { it.id == appPrefsWrapper.blazeCampaignSelectedObjective } - ?.toSelectedObjectiveUi() - } else null - init { loadData() analyticsTrackerWrapper.track( @@ -252,7 +244,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( } } - private fun CampaignDetails.toCampaignDetailsUi(selectedObjective: SelectedObjectiveUi?) = CampaignDetailsUi( + private fun CampaignDetails.toCampaignDetailsUi() = CampaignDetailsUi( budget = getBudgetDetails(), targetDetails = listOf( getTargetLanguagesDetails(), @@ -261,13 +253,20 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( getTargetInterestsDetails(), ), destinationUrl = getTargetDestinationDetails(), - selectedObjective = selectedObjective + selectedObjective = getSelectedObjective(campaignObjectives) ) - private fun Objective.toSelectedObjectiveUi() = SelectedObjectiveUi( - id = id, - displayTitle = title - ) + private fun getSelectedObjective(objectives: List): CampaignDetailItemUi { + val selectedObjectiveDisplayValue = objectives + .find { it.id == appPrefsWrapper.blazeCampaignSelectedObjective } + ?.title + ?: resourceProvider.getString(R.string.blaze_campaign_preview_details_choose_objective) + return CampaignDetailItemUi( + displayTitle = resourceProvider.getString(R.string.blaze_campaign_preview_details_objective), + displayValue = selectedObjectiveDisplayValue, + onItemSelected = {} // TODO Implement navigation to objective selection screen + ) + } private fun CampaignDetails.getBudgetDetails() = CampaignDetailItemUi( @@ -386,7 +385,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( val budget: CampaignDetailItemUi, val targetDetails: List, val destinationUrl: CampaignDetailItemUi, - val selectedObjective: SelectedObjectiveUi? + val selectedObjective: CampaignDetailItemUi ) data class CampaignDetailItemUi( @@ -426,9 +425,4 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( data class NavigateToPaymentSummary( val campaignDetails: CampaignDetails ) : MultiLiveEvent.Event() - - data class SelectedObjectiveUi( - val id: String, - val displayTitle: String - ) : MultiLiveEvent.Event() } diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index db805f6d5fa..97dff7affbe 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -3899,6 +3899,8 @@ Details Audience Budget + Campaign objective + Choose campaign objective Language Devices Location From 358a57e50a47ab05cfbbbd005f7dea003a9f0d78 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 13:14:24 +0200 Subject: [PATCH 05/12] Navigate to select objective screen --- .../BlazeCampaignObjectiveFragment.kt | 35 +++++++++++++++++++ .../BlazeCampaignCreationPreviewFragment.kt | 7 ++++ .../BlazeCampaignCreationPreviewViewModel.kt | 4 ++- .../nav_graph_blaze_campaign_creation.xml | 7 ++++ 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt new file mode 100644 index 00000000000..fa905e6208e --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt @@ -0,0 +1,35 @@ +package com.woocommerce.android.ui.blaze.creation.objective + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.material.Text +import com.woocommerce.android.ui.base.BaseFragment +import com.woocommerce.android.ui.compose.composeView +import com.woocommerce.android.ui.main.AppBarStatus +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class BlazeCampaignObjectiveFragment : BaseFragment() { + override val activityAppBarStatus: AppBarStatus + get() = AppBarStatus.Hidden + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return composeView { + Text(text = "Select Campaign Objective") + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + handleEvents() + } + + private fun handleEvents() { +// viewModel.event.observe(viewLifecycleOwner) { event -> +// when (event) { +// is MultiLiveEvent.Event.Exit -> findNavController().navigateUp() +// } +// } + } +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewFragment.kt index 1554effcb12..2ce7f29ade2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewFragment.kt @@ -19,6 +19,7 @@ import com.woocommerce.android.ui.blaze.creation.destination.BlazeCampaignCreati import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.NavigateToAdDestinationScreen import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.NavigateToBudgetScreen import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.NavigateToEditAdScreen +import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.NavigateToObjectiveSelectionScreen import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.NavigateToPaymentSummary import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.NavigateToTargetLocationSelectionScreen import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.NavigateToTargetSelectionScreen @@ -99,12 +100,18 @@ class BlazeCampaignCreationPreviewFragment : BaseFragment() { event.destinationParameters ) ) + is NavigateToPaymentSummary -> findNavController().navigateSafely( BlazeCampaignCreationPreviewFragmentDirections .actionBlazeCampaignCreationPreviewFragmentToBlazeCampaignPaymentSummaryFragment( event.campaignDetails ) ) + + is NavigateToObjectiveSelectionScreen -> findNavController().navigateSafely( + BlazeCampaignCreationPreviewFragmentDirections + .actionBlazeCampaignCreationPreviewFragmentToBlazeCampaignObjectiveFragment() + ) } } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt index c4eaa4e3ccc..6794239e5a4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt @@ -264,7 +264,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( return CampaignDetailItemUi( displayTitle = resourceProvider.getString(R.string.blaze_campaign_preview_details_objective), displayValue = selectedObjectiveDisplayValue, - onItemSelected = {} // TODO Implement navigation to objective selection screen + onItemSelected = { triggerEvent(NavigateToObjectiveSelectionScreen) } ) } @@ -425,4 +425,6 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( data class NavigateToPaymentSummary( val campaignDetails: CampaignDetails ) : MultiLiveEvent.Event() + + data object NavigateToObjectiveSelectionScreen : MultiLiveEvent.Event() } diff --git a/WooCommerce/src/main/res/navigation/nav_graph_blaze_campaign_creation.xml b/WooCommerce/src/main/res/navigation/nav_graph_blaze_campaign_creation.xml index dbbfad740b8..b89e972fc52 100644 --- a/WooCommerce/src/main/res/navigation/nav_graph_blaze_campaign_creation.xml +++ b/WooCommerce/src/main/res/navigation/nav_graph_blaze_campaign_creation.xml @@ -76,6 +76,9 @@ + + From 4f3a92e5f54b06b7fb4cc26d68c1f4a145d812cc Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 17:14:17 +0200 Subject: [PATCH 06/12] Add empty BlazeCampaignObjectiveViewModel --- .../objective/BlazeCampaignObjectiveFragment.kt | 15 ++++++++++----- .../objective/BlazeCampaignObjectiveViewModel.kt | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveViewModel.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt index fa905e6208e..f5224873a8a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveFragment.kt @@ -5,9 +5,12 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.compose.material.Text +import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController import com.woocommerce.android.ui.base.BaseFragment import com.woocommerce.android.ui.compose.composeView import com.woocommerce.android.ui.main.AppBarStatus +import com.woocommerce.android.viewmodel.MultiLiveEvent import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -15,6 +18,8 @@ class BlazeCampaignObjectiveFragment : BaseFragment() { override val activityAppBarStatus: AppBarStatus get() = AppBarStatus.Hidden + val viewModel: BlazeCampaignObjectiveViewModel by viewModels() + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return composeView { Text(text = "Select Campaign Objective") @@ -26,10 +31,10 @@ class BlazeCampaignObjectiveFragment : BaseFragment() { } private fun handleEvents() { -// viewModel.event.observe(viewLifecycleOwner) { event -> -// when (event) { -// is MultiLiveEvent.Event.Exit -> findNavController().navigateUp() -// } -// } + viewModel.event.observe(viewLifecycleOwner) { event -> + when (event) { + is MultiLiveEvent.Event.Exit -> findNavController().navigateUp() + } + } } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveViewModel.kt new file mode 100644 index 00000000000..2d617ba22c9 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/objective/BlazeCampaignObjectiveViewModel.kt @@ -0,0 +1,16 @@ +package com.woocommerce.android.ui.blaze.creation.objective + +import androidx.lifecycle.SavedStateHandle +import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit +import com.woocommerce.android.viewmodel.ScopedViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class BlazeCampaignObjectiveViewModel @Inject constructor( + savedStateHandle: SavedStateHandle +) : ScopedViewModel(savedStateHandle) { + fun onDismissClick() { + triggerEvent(Exit) + } +} From 59538ad5a9f12cfbc1fa4f04a97f87effcd8e406 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 17:40:23 +0200 Subject: [PATCH 07/12] Update FluxC changeset to latest trunk --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 877a2437171..2fefc34db5c 100644 --- a/build.gradle +++ b/build.gradle @@ -100,7 +100,7 @@ tasks.register("installGitHooks", Copy) { } ext { - fluxCVersion = '3103-6a3c656de5377ca7677548baa0a259edfc9c9ffe' + fluxCVersion = 'trunk-7e2a6b2524a39103ade0b034e40a9e1a013a6d2a' glideVersion = '4.16.0' coilVersion = '2.1.0' constraintLayoutVersion = '1.2.0' From 63e78a45ffd087825209d9bc4a094e57daa750dc Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 18:04:35 +0200 Subject: [PATCH 08/12] Retrieve saved objective and use it as default --- .../com/woocommerce/android/ui/blaze/BlazeRepository.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt index 9e3bb89bfa6..e1f4b3f3064 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/BlazeRepository.kt @@ -1,6 +1,7 @@ package com.woocommerce.android.ui.blaze import android.os.Parcelable +import com.woocommerce.android.AppPrefsWrapper import com.woocommerce.android.AppUrls.FETCH_PAYMENT_METHOD_URL_PATH import com.woocommerce.android.AppUrls.WPCOM_ADD_PAYMENT_METHOD import com.woocommerce.android.BuildConfig @@ -36,7 +37,8 @@ class BlazeRepository @Inject constructor( private val selectedSite: SelectedSite, private val blazeCampaignsStore: BlazeCampaignsStore, private val productDetailRepository: ProductDetailRepository, - private val mediaFilesRepository: MediaFilesRepository + private val mediaFilesRepository: MediaFilesRepository, + private val appPrefsWrapper: AppPrefsWrapper ) { companion object { private const val BLAZE_CAMPAIGN_CREATION_ORIGIN = "wc-android" @@ -192,7 +194,7 @@ class BlazeRepository @Inject constructor( targetUrl = product.permalink, parameters = emptyMap() ), - objectiveId = "" + objectiveId = appPrefsWrapper.blazeCampaignSelectedObjective ) } From f02cbecb370859441d283fe61075f719508acacf Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 18:08:15 +0200 Subject: [PATCH 09/12] Remove unnecessary app prefs dependency --- .../preview/BlazeCampaignCreationPreviewViewModel.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt index 6794239e5a4..805d693d9b0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt @@ -45,8 +45,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( private val blazeRepository: BlazeRepository, private val resourceProvider: ResourceProvider, private val currencyFormatter: CurrencyFormatter, - private val analyticsTrackerWrapper: AnalyticsTrackerWrapper, - private val appPrefsWrapper: AppPrefsWrapper + private val analyticsTrackerWrapper: AnalyticsTrackerWrapper ) : ScopedViewModel(savedStateHandle) { private val navArgs: BlazeCampaignCreationPreviewFragmentArgs by savedStateHandle.navArgs() private val campaignDetails = savedStateHandle.getNullableStateFlow( @@ -258,7 +257,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( private fun getSelectedObjective(objectives: List): CampaignDetailItemUi { val selectedObjectiveDisplayValue = objectives - .find { it.id == appPrefsWrapper.blazeCampaignSelectedObjective } + .find { it.id == campaignDetails.value?.objectiveId } ?.title ?: resourceProvider.getString(R.string.blaze_campaign_preview_details_choose_objective) return CampaignDetailItemUi( From ae3ce1ea35d476b5b9e5251b9b58f76a473a2a20 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 18:21:07 +0200 Subject: [PATCH 10/12] Fix unit test compile issues --- .../com/woocommerce/android/ui/blaze/BlazeRepositoryTest.kt | 6 +++++- .../payment/BlazeCampaignPaymentSummaryViewModelTests.kt | 3 ++- .../preview/BlazeCampaignCreationPreviewViewModelTests.kt | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/BlazeRepositoryTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/BlazeRepositoryTest.kt index 4a510e479a7..af42c4a247e 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/BlazeRepositoryTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/BlazeRepositoryTest.kt @@ -1,5 +1,6 @@ package com.woocommerce.android.ui.blaze +import com.woocommerce.android.AppPrefsWrapper import com.woocommerce.android.media.MediaFilesRepository import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.blaze.BlazeRepository.BlazeCampaignImage.RemoteImage @@ -47,6 +48,7 @@ class BlazeRepositoryTest : BaseUnitTest() { onBlocking { fetchWordPressMedia(AD_IMAGE.mediaId) } doReturn Result.success(mediaModel) } + private val appPrefsWrapper: AppPrefsWrapper = mock() private val createCampaignRequestCaptor = argumentCaptor() @@ -54,7 +56,8 @@ class BlazeRepositoryTest : BaseUnitTest() { selectedSite, blazeCampaignsStore, productDetailRepository, - mediaFilesRepository + mediaFilesRepository, + appPrefsWrapper ) @Test @@ -129,6 +132,7 @@ class BlazeRepositoryTest : BaseUnitTest() { budget = DEFAULT_BUDGET, targetingParameters = EMPTY_TARGETING_PARAMETERS, destinationParameters = EMPTY_DESTINATION_PARAMETERS, + objectiveId = "sales", ) private val ENDLESS_CAMPAIGN_DETAILS = DEFAULT_CAMPAIGN_DETAILS.copy( budget = DEFAULT_BUDGET.copy(isEndlessCampaign = true) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/payment/BlazeCampaignPaymentSummaryViewModelTests.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/payment/BlazeCampaignPaymentSummaryViewModelTests.kt index 98786c84542..e10ddcc2409 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/payment/BlazeCampaignPaymentSummaryViewModelTests.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/payment/BlazeCampaignPaymentSummaryViewModelTests.kt @@ -41,7 +41,8 @@ class BlazeCampaignPaymentSummaryViewModelTests : BaseUnitTest() { destinationParameters = BlazeRepository.DestinationParameters( targetUrl = "https://test.com", parameters = emptyMap() - ) + ), + objectiveId = "sales" ) } diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt index 385c00127c1..2330fb7d5f8 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt @@ -57,7 +57,8 @@ class BlazeCampaignCreationPreviewViewModelTests : BaseUnitTest() { targetUrl = "http://test_url", parameters = emptyMap() ), - targetingParameters = BlazeRepository.TargetingParameters() + targetingParameters = BlazeRepository.TargetingParameters(), + objectiveId = "sales" ) private val locations = listOf(Location(1, "Location 1"), Location(2, "Location 2")) private val languages = listOf(Language("en", "English"), Language("es", "Spanish")) From 588efcf82f2d42d0de592d0b2a62e499ed265989 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 19:24:29 +0200 Subject: [PATCH 11/12] Remove unused import --- .../creation/preview/BlazeCampaignCreationPreviewViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt index 805d693d9b0..7363bb22809 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModel.kt @@ -3,7 +3,6 @@ package com.woocommerce.android.ui.blaze.creation.preview import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope -import com.woocommerce.android.AppPrefsWrapper import com.woocommerce.android.R import com.woocommerce.android.analytics.AnalyticsEvent.BLAZE_CREATION_CONFIRM_DETAILS_TAPPED import com.woocommerce.android.analytics.AnalyticsEvent.BLAZE_CREATION_EDIT_AD_TAPPED From d43c454f5767c5ab1ab4ac5f934eeb883eb0fa73 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Sep 2024 19:30:00 +0200 Subject: [PATCH 12/12] Add missing mock to fix tests --- .../preview/BlazeCampaignCreationPreviewViewModelTests.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt index 2330fb7d5f8..523e513d31e 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/blaze/creation/preview/BlazeCampaignCreationPreviewViewModelTests.kt @@ -6,6 +6,7 @@ import com.woocommerce.android.extensions.formatToMMMdd import com.woocommerce.android.model.UiString import com.woocommerce.android.ui.blaze.BlazeRepository import com.woocommerce.android.ui.blaze.BlazeRepository.BlazeCampaignImage +import com.woocommerce.android.ui.blaze.BlazeRepository.Objective import com.woocommerce.android.ui.blaze.BlazeUrlsHelper.BlazeFlowSource import com.woocommerce.android.ui.blaze.Device import com.woocommerce.android.ui.blaze.Interest @@ -64,6 +65,7 @@ class BlazeCampaignCreationPreviewViewModelTests : BaseUnitTest() { private val languages = listOf(Language("en", "English"), Language("es", "Spanish")) private val interests = listOf(Interest("1", "Interest 1"), Interest("2", "Interest 2")) private val devices = listOf(Device("1", "Device 1"), Device("2", "Device 2")) + private val objectives = listOf(Objective("sales", "Sales", "Get more sales", "")) } private val currencyFormatter: CurrencyFormatter = mock { @@ -78,6 +80,7 @@ class BlazeCampaignCreationPreviewViewModelTests : BaseUnitTest() { on { observeDevices() } doReturn flowOf(devices) on { observeInterests() } doReturn flowOf(interests) on { observeLanguages() } doReturn flowOf(languages) + on { observeObjectives() } doReturn flowOf(objectives) } private val analyticsTracker: AnalyticsTrackerWrapper = mock() private lateinit var viewModel: BlazeCampaignCreationPreviewViewModel