Skip to content

Commit

Permalink
Merge pull request #10638 from woocommerce/blaze/refactor-preview-vie…
Browse files Browse the repository at this point in the history
…wstate

Blaze: Preview screen state management
  • Loading branch information
JorgeMucientes authored Jan 29, 2024
2 parents 725eefb + 60a330a commit 083810b
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@ package com.woocommerce.android.extensions

import kotlinx.coroutines.flow.Flow

@Suppress("LongParameterList")
inline fun <T1, T2, T3, T4, T5, T6, R> combine(
flow: Flow<T1>,
flow2: Flow<T2>,
flow3: Flow<T3>,
flow4: Flow<T4>,
flow5: Flow<T5>,
flow6: Flow<T6>,
crossinline transform: suspend (T1, T2, T3, T4, T5, T6) -> R
): Flow<R> {
return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6) { args: Array<*> ->
@Suppress("UNCHECKED_CAST", "MagicNumber")
transform(
args[0] as T1,
args[1] as T2,
args[2] as T3,
args[3] as T4,
args[4] as T5,
args[5] as T6,
)
}
}

@Suppress("LongParameterList")
inline fun <T1, T2, T3, T4, T5, T6, T7, R> combine(
flow: Flow<T1>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.woocommerce.android.ui.blaze

import android.os.Parcelable
import com.woocommerce.android.tools.SelectedSite
import com.woocommerce.android.ui.products.ProductDetailRepository
import com.woocommerce.android.util.TimezoneProvider
import kotlinx.parcelize.Parcelize
import org.wordpress.android.fluxc.persistence.blaze.BlazeCampaignsDao.BlazeAdSuggestionEntity
import org.wordpress.android.fluxc.store.blaze.BlazeCampaignsStore
import java.util.Date
Expand Down Expand Up @@ -43,69 +45,58 @@ class BlazeRepository @Inject constructor(
val product = productDetailRepository.getProduct(productId)
return CampaignPreview(
productId = productId,
aiSuggestions = listOf(),
budget = Budget(
totalBudget = DEFAULT_CAMPAIGN_TOTAL_BUDGET,
spentBudget = 0f,
currencyCode = BLAZE_DEFAULT_CURRENCY_CODE,
durationInDays = DEFAULT_CAMPAIGN_DURATION,
startDate = Date().apply { time += ONE_DAY_IN_MILLIS }, // By default start tomorrow
),
languages = listOf(),
devices = listOf(),
locations = listOf(),
interests = listOf(),
userTimeZone = timezoneProvider.deviceTimezone.displayName,
targetUrl = product?.permalink ?: "",
urlParams = null,
campaignImageUrl = product?.firstImageUrl
)
}

@Parcelize
data class CampaignPreview(
val productId: Long,
val aiSuggestions: List<AiSuggestionForAd>,
val budget: Budget,
val languages: List<Language>,
val devices: List<Device>,
val locations: List<Location>,
val interests: List<Interest>,
val userTimeZone: String,
val targetUrl: String,
val urlParams: Pair<String, String>?,
val campaignImageUrl: String?,
)
) : Parcelable

@Parcelize
data class AiSuggestionForAd(
val tagLine: String,
val description: String,
)
) : Parcelable

@Parcelize
data class Budget(
val totalBudget: Float,
val spentBudget: Float,
val currencyCode: String,
val durationInDays: Int,
val startDate: Date,
)
) : Parcelable

@Parcelize
data class Location(
val id: String,
val name: String,
)
) : Parcelable

@Parcelize
data class Language(
val code: String,
val name: String,
)
) : Parcelable

@Parcelize
data class Device(
val id: String,
val name: String,
)
) : Parcelable

@Parcelize
data class Interest(
val id: String,
val description: String,
)
) : Parcelable
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.woocommerce.android.ui.blaze.BlazeRepository
import com.woocommerce.android.ui.blaze.creation.ad.BlazeCampaignCreationEditAdViewModel.ViewState.Suggestion
import com.woocommerce.android.ui.blaze.BlazeRepository.AiSuggestionForAd
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ExitWithResult
Expand Down Expand Up @@ -45,7 +45,7 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor(
viewModelScope.launch {
blazeRepository.getAdSuggestions(navArgs.productId)?.let { list ->
val index = list.indexOfFirst { it.tagLine == navArgs.tagline && it.description == navArgs.description }
val suggestions = list.map { Suggestion(it.tagLine, it.description) }
val suggestions = list.map { AiSuggestionForAd(it.tagLine, it.description) }
if (index != -1) {
_viewState.update {
_viewState.value.copy(
Expand All @@ -56,7 +56,7 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor(
} else {
_viewState.update {
_viewState.value.copy(
suggestions = listOf(Suggestion(navArgs.tagline, navArgs.description)) + suggestions,
suggestions = listOf(AiSuggestionForAd(navArgs.tagline, navArgs.description)) + suggestions,
suggestionIndex = 0
)
}
Expand Down Expand Up @@ -109,11 +109,11 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor(
}

fun onTagLineChanged(tagLine: String) {
updateSuggestion(Suggestion(tagLine.take(TAGLINE_MAX_LENGTH), _viewState.value.description))
updateSuggestion(AiSuggestionForAd(tagLine.take(TAGLINE_MAX_LENGTH), _viewState.value.description))
}

fun onDescriptionChanged(description: String) {
updateSuggestion(Suggestion(_viewState.value.tagLine, description.take(TAGLINE_MAX_LENGTH)))
updateSuggestion(AiSuggestionForAd(_viewState.value.tagLine, description.take(TAGLINE_MAX_LENGTH)))
}

fun onImageChanged(url: String) {
Expand All @@ -122,7 +122,7 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor(
}
}

private fun updateSuggestion(suggestion: Suggestion) {
private fun updateSuggestion(suggestion: AiSuggestionForAd) {
_viewState.update {
val suggestions = _viewState.value.suggestions.toMutableList()
suggestions[_viewState.value.suggestionIndex] = suggestion
Expand All @@ -141,7 +141,7 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor(
@Parcelize
data class ViewState(
val adImageUrl: String?,
val suggestions: List<Suggestion> = emptyList(),
val suggestions: List<AiSuggestionForAd> = emptyList(),
val suggestionIndex: Int = 0,
val isMediaPickerDialogVisible: Boolean = false
) : Parcelable {
Expand All @@ -157,12 +157,6 @@ class BlazeCampaignCreationEditAdViewModel @Inject constructor(
get() = suggestionIndex > 0
val isNextSuggestionButtonEnabled: Boolean
get() = suggestionIndex < suggestions.size - 1

@Parcelize
data class Suggestion(
var tagLine: String,
var description: String
) : Parcelable
}

@Parcelize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class BlazeCampaignCreationPreviewFragment : BaseFragment() {
BlazeCampaignCreationPreviewFragmentDirections
.actionBlazeCampaignCreationPreviewFragmentToBlazeCampaignBudgetFragment()
)
is NavigateToEditAdScreen -> findNavController().navigate(
is NavigateToEditAdScreen -> findNavController().navigateSafely(
BlazeCampaignCreationPreviewFragmentDirections
.actionBlazeCampaignCreationPreviewFragmentToBlazeCampaignCreationEditAdFragment(
event.productId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.woocommerce.android.R
import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.AdDetailsUi
import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.AdDetailsUi.AdDetails
import com.woocommerce.android.ui.blaze.creation.preview.BlazeCampaignCreationPreviewViewModel.AdDetailsUi.Loading
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
Expand Down Expand Up @@ -87,10 +88,10 @@ private fun BlazeCampaignCreationPreviewScreen(
.background(color = MaterialTheme.colors.surface)
) {

when {
previewState.isLoading -> AdDetailsLoading()
when (previewState.adDetails) {
is Loading -> AdDetailsLoading()
else -> AdDetailsHeader(
state = previewState,
previewState.adDetails as AdDetails,
onEditAdClicked = onEditAdClicked
)
}
Expand All @@ -110,7 +111,7 @@ private fun BlazeCampaignCreationPreviewScreen(
.padding(bottom = 8.dp),
text = stringResource(id = R.string.blaze_campaign_preview_details_confirm_details_button),
onClick = { /*TODO*/ },
enabled = !previewState.isLoading
enabled = previewState.adDetails != Loading
)
}
}
Expand Down Expand Up @@ -177,12 +178,12 @@ private fun AdDetailsLoading(

@Composable
fun AdDetailsHeader(
state: CampaignPreviewUiState,
adDetails: AdDetails,
onEditAdClicked: () -> Unit,
modifier: Modifier = Modifier,
) {
CampaignHeader(
adDetails = state.adDetails,
adDetails = adDetails,
onEditAdClicked = onEditAdClicked,
modifier = modifier
.fillMaxWidth()
Expand All @@ -194,7 +195,7 @@ fun AdDetailsHeader(

@Composable
fun CampaignHeader(
adDetails: AdDetailsUi,
adDetails: AdDetails,
onEditAdClicked: () -> Unit,
modifier: Modifier = Modifier
) {
Expand Down Expand Up @@ -366,8 +367,7 @@ private fun CampaignPropertyItem(
fun CampaignScreenPreview() {
BlazeCampaignCreationPreviewScreen(
CampaignPreviewUiState(
isLoading = false,
adDetails = AdDetailsUi(
adDetails = AdDetails(
productId = 123,
description = "Get the latest white t-shirts",
tagLine = "From 45.00 USD",
Expand Down
Loading

0 comments on commit 083810b

Please sign in to comment.