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 464a03e9baec..fbb172aa71d8 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 @@ -149,7 +149,7 @@ class BlazeRepository @Inject constructor( suspend fun fetchAdSuggestions(productId: Long): Result> { fun List.mapToUiModel(): List { - return map { AiSuggestionForAd(it.tagLine, it.description) } + return map { AiSuggestionForAd(it.tagLine, it.description, it.ctaText) } } val result = blazeCampaignsStore.fetchBlazeAdSuggestions(selectedSite.get(), productId) @@ -194,7 +194,8 @@ class BlazeRepository @Inject constructor( targetUrl = product.permalink, parameters = emptyMap() ), - objectiveId = appPrefsWrapper.blazeCampaignSelectedObjective + objectiveId = appPrefsWrapper.blazeCampaignSelectedObjective, + ctaText = "" ) } @@ -273,6 +274,7 @@ class BlazeRepository @Inject constructor( ) } + @Suppress("LongMethod") suspend fun createCampaign( campaignDetails: CampaignDetails, paymentMethodId: String @@ -297,6 +299,7 @@ class BlazeRepository @Inject constructor( targetResourceId = campaignDetails.productId, tagLine = campaignDetails.tagLine, description = campaignDetails.description, + ctaText = campaignDetails.ctaText, startDate = campaignDetails.budget.startDate, endDate = campaignDetails.budget.endDate, budget = BlazeCampaignCreationRequestBudget( @@ -394,6 +397,7 @@ class BlazeRepository @Inject constructor( val productId: Long, val tagLine: String, val description: String, + val ctaText: String, val campaignImage: BlazeCampaignImage, val budget: Budget, val targetingParameters: TargetingParameters, @@ -446,6 +450,7 @@ class BlazeRepository @Inject constructor( data class AiSuggestionForAd( val tagLine: String, val description: String, + val ctaText: String ) : Parcelable @Parcelize diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdScreen.kt index f880be2d77ad..cd396ece16ab 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdScreen.kt @@ -71,7 +71,8 @@ fun BlazeCampaignCreationPreviewScreen(viewModel: BlazeCampaignCreationEditAdVie onMediaPickerDialogDismissed = viewModel::onMediaPickerDialogDismissed, onProductImagesRequested = viewModel::onProductImagesRequested, onMediaLibraryRequested = viewModel::onMediaLibraryRequested, - onSaveTapped = viewModel::onSaveTapped + onSaveTapped = viewModel::onSaveTapped, + onCtaTextChanged = viewModel::onCtaTextChanged ) } } @@ -88,7 +89,8 @@ private fun BlazeCampaignCreationEditAdScreen( onMediaPickerDialogDismissed: () -> Unit, onProductImagesRequested: () -> Unit, onMediaLibraryRequested: (DataSource) -> Unit, - onSaveTapped: () -> Unit + onSaveTapped: () -> Unit, + onCtaTextChanged: (String) -> Unit ) { if (viewState.isMediaPickerDialogVisible) { MediaPickerDialog( @@ -123,7 +125,8 @@ private fun BlazeCampaignCreationEditAdScreen( onDescriptionChanged, onChangeImageTapped, onPreviousSuggestionTapped, - onNextSuggestionTapped + onNextSuggestionTapped, + onCtaTextChanged ) } } @@ -137,6 +140,7 @@ fun CampaignEditAdContent( onChangeImageTapped: () -> Unit, onPreviousSuggestionTapped: () -> Unit, onNextSuggestionTapped: () -> Unit, + onCtaTextChanged: (String) -> Unit ) { Column( modifier = Modifier @@ -156,7 +160,8 @@ fun CampaignEditAdContent( onTagLineChanged = onTagLineChanged, onDescriptionChanged = onDescriptionChanged, onPreviousSuggestionTapped = onPreviousSuggestionTapped, - onNextSuggestionTapped = onNextSuggestionTapped + onNextSuggestionTapped = onNextSuggestionTapped, + onCtaTextChanged = onCtaTextChanged ) } } @@ -167,7 +172,8 @@ private fun AdDataSection( onTagLineChanged: (String) -> Unit, onDescriptionChanged: (String) -> Unit, onPreviousSuggestionTapped: () -> Unit, - onNextSuggestionTapped: () -> Unit + onNextSuggestionTapped: () -> Unit, + onCtaTextChanged: (String) -> Unit ) { Column( modifier = Modifier @@ -175,62 +181,16 @@ private fun AdDataSection( .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { - Box { - WCOutlinedTextField( - value = viewState.tagLine, - onValueChange = onTagLineChanged, - label = stringResource(id = string.blaze_campaign_edit_ad_change_tagline_title), - singleLine = true, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next) - ) - - CornerCharacterWarning( - charsLeft = viewState.taglineCharactersRemaining, - modifier = Modifier.align(Alignment.TopEnd) - ) - } - - Text( - text = stringResource( - id = string.blaze_campaign_edit_ad_characters_remaining, - viewState.taglineCharactersRemaining - ), - style = MaterialTheme.typography.caption, - color = colorResource(id = color.color_on_surface_disabled), - modifier = Modifier - .padding(top = dimensionResource(id = dimen.minor_100)) - .fillMaxWidth() + TaglineInputText(viewState, onTagLineChanged) + DescriptionInputText( + viewState, + onDescriptionChanged, + modifier = Modifier.padding(top = dimensionResource(id = dimen.major_150)) ) - - Box( - modifier = Modifier - .padding(top = dimensionResource(id = dimen.major_150)) - ) { - WCOutlinedTextField( - value = viewState.description, - onValueChange = onDescriptionChanged, - label = stringResource(id = string.blaze_campaign_edit_ad_change_description_title), - maxLines = 3, - minLines = 3, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next) - ) - - CornerCharacterWarning( - charsLeft = viewState.descriptionCharactersRemaining, - modifier = Modifier.align(Alignment.TopEnd) - ) - } - - Text( - text = stringResource( - id = string.blaze_campaign_edit_ad_characters_remaining, - viewState.descriptionCharactersRemaining - ), - style = MaterialTheme.typography.caption, - color = colorResource(id = color.color_on_surface_disabled), - modifier = Modifier - .padding(top = dimensionResource(id = dimen.minor_100)) - .fillMaxWidth() + CallToActionInputText( + viewState, + onCtaTextChanged, + modifier = Modifier.padding(top = dimensionResource(id = dimen.major_150)) ) if (viewState.suggestions.size > 1) { @@ -271,6 +231,97 @@ private fun AdDataSection( } } +@Composable +private fun DescriptionInputText( + viewState: ViewState, + onDescriptionChanged: (String) -> Unit, + modifier: Modifier = Modifier +) { + val isError = viewState.description.isEmpty() + Box(modifier = modifier) { + WCOutlinedTextField( + value = viewState.description, + onValueChange = onDescriptionChanged, + label = stringResource(id = string.blaze_campaign_edit_ad_change_description_title), + maxLines = 3, + minLines = 3, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + helperText = when { + isError -> stringResource(id = string.blaze_campaign_edit_ad_change_description_empty_error) + else -> + stringResource( + id = string.blaze_campaign_edit_ad_characters_remaining, + viewState.descriptionCharactersRemaining + ) + }, + isError = isError + ) + + CornerCharacterWarning( + charsLeft = viewState.descriptionCharactersRemaining, + modifier = Modifier.align(Alignment.TopEnd) + ) + } +} + +@Composable +private fun TaglineInputText( + viewState: ViewState, + onTagLineChanged: (String) -> Unit, + modifier: Modifier = Modifier +) { + val isError = viewState.tagLine.isEmpty() + Box(modifier = modifier) { + WCOutlinedTextField( + value = viewState.tagLine, + onValueChange = onTagLineChanged, + label = stringResource(id = string.blaze_campaign_edit_ad_change_tagline_title), + singleLine = true, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + helperText = when { + isError -> stringResource(id = string.blaze_campaign_edit_ad_change_tagline_empty_error) + else -> + stringResource( + id = string.blaze_campaign_edit_ad_characters_remaining, + viewState.taglineCharactersRemaining + ) + }, + isError = isError + ) + + CornerCharacterWarning( + charsLeft = viewState.taglineCharactersRemaining, + modifier = Modifier.align(Alignment.TopEnd) + ) + } +} + +@Composable +private fun CallToActionInputText( + viewState: ViewState, + onCtaTextChanged: (String) -> Unit, + modifier: Modifier = Modifier +) { + Box(modifier = modifier) { + WCOutlinedTextField( + value = viewState.ctaText, + onValueChange = onCtaTextChanged, + label = stringResource(id = string.blaze_campaign_edit_ad_change_cta_text_title), + singleLine = true, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + helperText = stringResource( + id = string.blaze_campaign_edit_ad_characters_remaining, + viewState.ctaTextCharactersRemaining + ), + ) + + CornerCharacterWarning( + charsLeft = viewState.ctaTextCharactersRemaining, + modifier = Modifier.align(Alignment.TopEnd) + ) + } +} + @Composable private fun CornerCharacterWarning(charsLeft: Int, modifier: Modifier = Modifier) { if (charsLeft < 10) { @@ -380,7 +431,8 @@ fun PreviewCampaignEditAdContent() { onDescriptionChanged = { }, onChangeImageTapped = { }, onPreviousSuggestionTapped = { }, - onNextSuggestionTapped = { } + onNextSuggestionTapped = { }, + onCtaTextChanged = { }, ) } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdViewModel.kt index ca7fcfe6396f..46b05d7d3a8e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/ad/BlazeCampaignCreationEditAdViewModel.kt @@ -33,6 +33,7 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor( companion object { private const val TAGLINE_MAX_LENGTH = 32 private const val DESCRIPTION_MAX_LENGTH = 140 + private const val CTA_TEST_MAX_LENGTH = 26 } private val navArgs: BlazeCampaignCreationEditAdFragmentArgs by savedStateHandle.navArgs() @@ -49,7 +50,7 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor( private fun loadSuggestions() { viewModelScope.launch { - val passedDetails = AiSuggestionForAd(navArgs.tagline, navArgs.description) + val passedDetails = AiSuggestionForAd(navArgs.tagline, navArgs.description, navArgs.ctaText) val suggestions = navArgs.aiSuggestionsForAd.toList() _viewState.update { it.copy( @@ -83,7 +84,8 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor( EditAdResult( tagline = _viewState.value.tagLine, description = _viewState.value.description, - campaignImage = _viewState.value.adImage + campaignImage = _viewState.value.adImage, + ctaText = _viewState.value.ctaText ) ) ) @@ -107,11 +109,23 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor( } fun onTagLineChanged(tagLine: String) { - updateSuggestion(AiSuggestionForAd(tagLine.take(TAGLINE_MAX_LENGTH), _viewState.value.description)) + updateSuggestion( + AiSuggestionForAd( + tagLine.take(TAGLINE_MAX_LENGTH), + _viewState.value.description, + _viewState.value.ctaText + ) + ) } fun onDescriptionChanged(description: String) { - updateSuggestion(AiSuggestionForAd(_viewState.value.tagLine, description.take(DESCRIPTION_MAX_LENGTH))) + updateSuggestion( + AiSuggestionForAd( + _viewState.value.tagLine, + description.take(DESCRIPTION_MAX_LENGTH), + _viewState.value.ctaText + ) + ) } fun onLocalImageSelected(uri: String) { @@ -175,6 +189,16 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor( setMediaPickerDialogVisibility(false) } + fun onCtaTextChanged(ctaText: String) { + updateSuggestion( + AiSuggestionForAd( + _viewState.value.tagLine, + _viewState.value.description, + ctaText.take(CTA_TEST_MAX_LENGTH) + ) + ) + } + data class ShowMediaLibrary(val source: MediaPickerSetup.DataSource) : Event() data class ShowProductImagePicker(val productId: Long) : Event() @@ -189,10 +213,14 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor( get() = suggestions.getOrNull(suggestionIndex)?.tagLine ?: "" val description: String get() = suggestions.getOrNull(suggestionIndex)?.description ?: "" + val ctaText: String + get() = suggestions.getOrNull(suggestionIndex)?.ctaText ?: "" val taglineCharactersRemaining: Int get() = TAGLINE_MAX_LENGTH - (suggestions.getOrNull(suggestionIndex)?.tagLine?.length ?: 0) val descriptionCharactersRemaining: Int get() = DESCRIPTION_MAX_LENGTH - (suggestions.getOrNull(suggestionIndex)?.description?.length ?: 0) + val ctaTextCharactersRemaining: Int + get() = CTA_TEST_MAX_LENGTH - (suggestions.getOrNull(suggestionIndex)?.ctaText?.length ?: 0) val isPreviousSuggestionButtonEnabled: Boolean get() = suggestionIndex > 0 val isNextSuggestionButtonEnabled: Boolean @@ -203,6 +231,7 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor( data class EditAdResult( val tagline: String, val description: String, - val campaignImage: BlazeRepository.BlazeCampaignImage + val campaignImage: BlazeRepository.BlazeCampaignImage, + val ctaText: String ) : Parcelable } 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 29b55aad0717..e806d405725b 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 @@ -75,6 +75,7 @@ class BlazeCampaignCreationPreviewFragment : BaseFragment() { productId = event.productId, tagline = event.tagLine, description = event.description, + ctaText = event.ctaText, adImage = event.campaignImage, aiSuggestionsForAd = event.aiSuggestions.toTypedArray() ) @@ -120,7 +121,7 @@ class BlazeCampaignCreationPreviewFragment : BaseFragment() { private fun handleResults() { handleResult(BlazeCampaignCreationEditAdFragment.EDIT_AD_RESULT) { - viewModel.onAdUpdated(it.tagline, it.description, it.campaignImage) + viewModel.onAdUpdated(it) } handleResult(BlazeCampaignObjectiveFragment.BLAZE_OBJECTIVE_SELECTION_RESULT) { viewModel.onObjectiveUpdated(it.objectiveId) 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 217ae3f7218d..38a9bcf7f721 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 @@ -6,6 +6,7 @@ import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -27,6 +28,7 @@ import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos import androidx.compose.runtime.Composable import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment @@ -193,7 +195,7 @@ fun AdDetailsHeader( onEditAdClicked: () -> Unit, modifier: Modifier = Modifier, ) { - CampaignHeader( + AdPreview( adDetails = adDetails, onEditAdClicked = onEditAdClicked, modifier = modifier @@ -205,7 +207,7 @@ fun AdDetailsHeader( } @Composable -fun CampaignHeader( +fun AdPreview( adDetails: AdDetails, onEditAdClicked: () -> Unit, modifier: Modifier = Modifier @@ -263,13 +265,21 @@ fun CampaignHeader( style = MaterialTheme.typography.subtitle1, fontWeight = FontWeight.Bold, ) + if (adDetails.ctaText.isEmpty()) { + DefaultBlazeButton( + modifier = Modifier + .padding(start = 16.dp) + .align(Alignment.Top) + ) + } + } + if (adDetails.ctaText.isNotEmpty()) { WCColoredButton( - text = stringResource(id = R.string.blaze_campaign_preview_shop_now_button), - modifier = Modifier - .padding(start = 16.dp), + modifier = Modifier.padding(top = 8.dp), + text = adDetails.ctaText, colors = ButtonDefaults.buttonColors( - contentColor = colorResource(id = R.color.color_on_secondary), - backgroundColor = colorResource(id = R.color.blaze_campaign_preview_shop_now_button), + contentColor = colorResource(id = R.color.color_on_primary_surface), + backgroundColor = colorResource(id = R.color.blaze_ad_cta_background), ), onClick = { /*TODO*/ }, ) @@ -365,6 +375,26 @@ private fun CampaignPropertyGroupItem( } } +@Composable +private fun DefaultBlazeButton(modifier: Modifier = Modifier) { + Box( + modifier = modifier + .size(40.dp) + .clip(RoundedCornerShape(20.dp)) + .background(color = colorResource(id = R.color.blaze_ad_cta_background)) + ) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowForwardIos, + contentDescription = null, + tint = colorResource(id = R.color.color_on_primary_surface), + modifier = Modifier + .align(Alignment.Center) + .size(32.dp) + .padding(6.dp) + ) + } +} + @Composable private fun CampaignPropertyItem( item: CampaignDetailItemUi, @@ -418,6 +448,7 @@ fun CampaignScreenPreview() { productId = 123, description = "Get the latest white t-shirts", tagLine = "From 45.00 USD", + ctaText = "Shop Now", campaignImageUrl = "https://rb.gy/gmjuwb", isContentSuggestedByAi = true ), 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 06fa151ac0c7..e2fc24307b68 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 @@ -19,6 +19,7 @@ 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.ad.BlazeCampaignCreationEditAdViewModel.EditAdResult import com.woocommerce.android.ui.blaze.creation.targets.BlazeTargetType import com.woocommerce.android.ui.blaze.creation.targets.BlazeTargetType.DEVICE import com.woocommerce.android.ui.blaze.creation.targets.BlazeTargetType.INTEREST @@ -76,6 +77,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( productId = navArgs.productId, description = campaignDetails.description, tagLine = campaignDetails.tagLine, + ctaText = campaignDetails.ctaText, campaignImageUrl = campaignDetails.campaignImage.uri, isContentSuggestedByAi = isAdContentGeneratedByAi(campaignDetails) ) @@ -109,6 +111,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( productId = navArgs.productId, tagLine = it.tagLine, description = it.description, + ctaText = it.ctaText, campaignImage = it.campaignImage, aiSuggestions = aiSuggestions ) @@ -116,12 +119,13 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( } } - fun onAdUpdated(tagline: String, description: String, campaignImage: BlazeRepository.BlazeCampaignImage) { + fun onAdUpdated(updatedAd: EditAdResult) { campaignDetails.update { it?.copy( - tagLine = tagline, - description = description, - campaignImage = campaignImage + tagLine = updatedAd.tagline, + description = updatedAd.description, + campaignImage = updatedAd.campaignImage, + ctaText = updatedAd.ctaText ) } } @@ -242,7 +246,8 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( private fun isAdContentGeneratedByAi(campaignDetails: CampaignDetails?): Boolean = aiSuggestions.any { it.tagLine == campaignDetails?.tagLine && - it.description == campaignDetails.description + it.description == campaignDetails.description && + it.ctaText == campaignDetails.ctaText } private fun loadData() { @@ -263,6 +268,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( it?.copy( tagLine = suggestions.firstOrNull()?.tagLine.orEmpty(), description = suggestions.firstOrNull()?.description.orEmpty(), + ctaText = suggestions.firstOrNull()?.ctaText.orEmpty() ) } }, @@ -413,6 +419,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( val productId: Long, val description: String, val tagLine: String, + val ctaText: String, val campaignImageUrl: String?, val isContentSuggestedByAi: Boolean, ) : AdDetailsUi @@ -455,6 +462,7 @@ class BlazeCampaignCreationPreviewViewModel @Inject constructor( val productId: Long, val tagLine: String, val description: String, + val ctaText: String, val campaignImage: BlazeRepository.BlazeCampaignImage, val aiSuggestions: List ) : 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 616f16d53c6b..49044c7d8ba4 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 @@ -95,6 +95,10 @@ android:name="description" android:defaultValue="" app:argType="string" /> + diff --git a/WooCommerce/src/main/res/values/colors_base.xml b/WooCommerce/src/main/res/values/colors_base.xml index a19755ca5858..15a64417c572 100644 --- a/WooCommerce/src/main/res/values/colors_base.xml +++ b/WooCommerce/src/main/res/values/colors_base.xml @@ -300,8 +300,8 @@ @color/white @color/woo_gray_6 @color/woo_gray_0 - @color/woo_gray_0 @color/woo_purple_0 + @color/blaze_blue Preview Edit ad - Shop now Details Audience Budget @@ -3990,7 +3989,10 @@ --> Change image Tagline + Tagline cannot be empty + Call to action Description + Description cannot be empty %d characters remaining Suggested by AI Invalid image diff --git a/WooCommerce/src/main/res/values/wc_colors_base.xml b/WooCommerce/src/main/res/values/wc_colors_base.xml index 0bc17dfdaff5..9e65fc668bef 100644 --- a/WooCommerce/src/main/res/values/wc_colors_base.xml +++ b/WooCommerce/src/main/res/values/wc_colors_base.xml @@ -101,6 +101,8 @@ #007017 #BBE0FA #055D9C - #FACFD2 + #0038FF #B32D2E + #FACFD2 + 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 af42c4a247ed..73257ddd62e9 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 @@ -128,6 +128,7 @@ class BlazeRepositoryTest : BaseUnitTest() { productId = 1, tagLine = "", description = "", + ctaText = "", campaignImage = AD_IMAGE, budget = DEFAULT_BUDGET, targetingParameters = EMPTY_TARGETING_PARAMETERS, 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 e10ddcc2409c..ac7ee52525ce 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 @@ -28,6 +28,7 @@ class BlazeCampaignPaymentSummaryViewModelTests : BaseUnitTest() { productId = 0L, tagLine = "", description = "", + ctaText = "", campaignImage = BlazeRepository.BlazeCampaignImage.LocalImage("test"), budget = Budget( totalBudget = 10f, 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 72cb0a00d633..da65b4dd2be4 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 @@ -12,6 +12,7 @@ import com.woocommerce.android.ui.blaze.Device import com.woocommerce.android.ui.blaze.Interest import com.woocommerce.android.ui.blaze.Language import com.woocommerce.android.ui.blaze.Location +import com.woocommerce.android.ui.blaze.creation.ad.BlazeCampaignCreationEditAdViewModel.EditAdResult import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.AdDetailsUi import com.woocommerce.android.ui.blaze.creation.targets.BlazeTargetType import com.woocommerce.android.util.CurrencyFormatter @@ -45,6 +46,7 @@ class BlazeCampaignCreationPreviewViewModelTests : BaseUnitTest() { productId = PRODUCT_ID, tagLine = "", description = "", + ctaText = "", budget = BlazeRepository.Budget( totalBudget = 10f, spentBudget = 0f, @@ -106,6 +108,7 @@ class BlazeCampaignCreationPreviewViewModelTests : BaseUnitTest() { BlazeRepository.AiSuggestionForAd( tagLine = "Ad suggestion 1", description = "Ad suggestion 1 description", + ctaText = "Shop now" ) ) setup { @@ -198,9 +201,10 @@ class BlazeCampaignCreationPreviewViewModelTests : BaseUnitTest() { val newTagline = "New tagline" val newDescription = "New description" + val newCtaText = "New CTA" val newImage = BlazeCampaignImage.LocalImage("new_image") val state = viewModel.viewState.runAndCaptureValues { - viewModel.onAdUpdated(newTagline, newDescription, newImage) + viewModel.onAdUpdated(EditAdResult(newTagline, newDescription, newImage, newCtaText)) }.last() val adDetailsUi = state.adDetails as AdDetailsUi.AdDetails diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8b68c77a7a9f..80c219995b46 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -86,7 +86,7 @@ stripe-terminal = '3.7.1' tinder-statemachine = '0.2.0' wiremock = '2.26.3' wordpress-aztec = 'v2.1.4' -wordpress-fluxc = '2.99.1' +wordpress-fluxc = 'trunk-cc17141a0e910d5b808ba6bbfb4b7d393d3517a0' wordpress-login = '1.19.0' wordpress-libaddressinput = '0.0.2' wordpress-mediapicker = '0.3.1'