Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons.Filled
import androidx.compose.material.icons.filled.ArrowBack
Expand All @@ -28,8 +29,10 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.woocommerce.android.R.string
import com.woocommerce.android.ui.common.wpcomwebview.WPComWebViewAuthenticator
import com.woocommerce.android.ui.compose.component.AlertDialog
import com.woocommerce.android.ui.compose.component.WCColoredButton
import com.woocommerce.android.ui.compose.component.WCWebView
import com.woocommerce.android.ui.login.storecreation.webview.WebViewStoreCreationViewModel.DialogState
import com.woocommerce.android.ui.login.storecreation.webview.WebViewStoreCreationViewModel.ViewState.ErrorState
import com.woocommerce.android.ui.login.storecreation.webview.WebViewStoreCreationViewModel.ViewState.StoreCreationState
import com.woocommerce.android.ui.login.storecreation.webview.WebViewStoreCreationViewModel.ViewState.StoreLoadingState
Expand All @@ -47,9 +50,7 @@ fun WebViewStoreCreationScreen(viewModel: WebViewStoreCreationViewModel) {
backgroundColor = MaterialTheme.colors.surface,
title = { Text(stringResource(id = string.store_creation_create_new_store_label)) },
navigationIcon = {
IconButton(onClick = {
viewModel.onBackPressed()
}) {
IconButton(onClick = viewModel::onBackPressed) {
Icon(Filled.ArrowBack, contentDescription = "Back")
}
},
Expand All @@ -73,6 +74,12 @@ fun WebViewStoreCreationScreen(viewModel: WebViewStoreCreationViewModel) {
}
}
}

viewModel.dialogViewState.observeAsState().value?.let {
if (it.isDialogVisible) {
ConfirmExitDialog(it)
}
}
}

@SuppressLint("SetJavaScriptEnabled")
Expand Down Expand Up @@ -102,9 +109,11 @@ private fun StoreCreationWebView(
viewState.onSiteAddressFound(it)
}

if (url.contains(viewState.exitTriggerKeyword, ignoreCase = true) && !storeCreationTriggered) {
if (url.contains(viewState.successTriggerKeyword, ignoreCase = true) && !storeCreationTriggered) {
storeCreationTriggered = true
viewState.onStoreCreated()
} else if (url == viewState.exitTriggerKeyword) {
viewState.onExitTriggered()
}
},
modifier = modifier.fillMaxSize()
Expand Down Expand Up @@ -152,6 +161,30 @@ private fun StoreCreationInProgress() {
}
}

@Composable
private fun ConfirmExitDialog(viewState: DialogState) {
AlertDialog(
onDismissRequest = { viewState.onDialogDismissed() },
title = {
Text(text = stringResource(id = string.store_creation_exit_dialog_title))
},
text = {
Text(text = stringResource(id = string.store_creation_exit_dialog_message))
},
confirmButton = {
TextButton(onClick = { viewState.onExitConfirmed() }) {
Text(stringResource(id = string.store_creation_confirm_and_leave))
}
},
dismissButton = {
TextButton(onClick = { viewState.onDialogDismissed() }) {
Text(stringResource(id = string.cancel))
}
},
neutralButton = {}
)
}

@Preview
@Composable
private fun PreviewStoreCreationInProgress() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit
import com.woocommerce.android.viewmodel.ScopedViewModel
import com.woocommerce.android.viewmodel.getStateFlow
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
Expand All @@ -33,10 +34,14 @@ class WebViewStoreCreationViewModel @Inject constructor(
companion object {
private const val STORE_CREATION_URL = "https://woocommerce.com/start"
private const val SITE_URL_KEYWORD = "checkout/thank-you/"
private const val WEBVIEW_EXIT_TRIGGER_KEYWORD = "calypso/images/wpcom-ecommerce"
private const val WEBVIEW_SUCCESS_TRIGGER_KEYWORD = "calypso/images/wpcom-ecommerce"
private const val WEBVIEW_EXIT_TRIGGER_KEYWORD = "https://woocommerce.com/"
private const val STORE_LOAD_RETRIES_LIMIT = 10
}

private val _dialogViewState = savedStateHandle.getStateFlow(viewModelScope, setDialogState(isVisible = false))
val dialogViewState = _dialogViewState.asStateFlow().asLiveData()

private val step = savedStateHandle.getStateFlow<Step>(viewModelScope, Step.StoreCreation)
val viewState: LiveData<ViewState> = step.map { step ->
when (step) {
Expand All @@ -51,17 +56,27 @@ class WebViewStoreCreationViewModel @Inject constructor(
private fun prepareStoreCreationState() = StoreCreationState(
storeCreationUrl = STORE_CREATION_URL,
siteUrlKeyword = SITE_URL_KEYWORD,
successTriggerKeyword = WEBVIEW_SUCCESS_TRIGGER_KEYWORD,
exitTriggerKeyword = WEBVIEW_EXIT_TRIGGER_KEYWORD,
onStoreCreated = ::onStoreCreated,
onSiteAddressFound = ::onSiteAddressFound
onSiteAddressFound = ::onSiteAddressFound,
onExitTriggered = ::exitStoreCreation
)

private fun prepareErrorState() = ErrorState(
onRetryButtonClick = {
onStoreCreated()
}
onRetryButtonClick = ::onStoreCreated
)

private fun setDialogState(isVisible: Boolean) = DialogState(
isDialogVisible = isVisible,
onExitConfirmed = ::exitStoreCreation,
onDialogDismissed = ::onDialogDismissed
)

private fun onDialogDismissed() {
_dialogViewState.value = setDialogState(isVisible = false)
}

private fun onStoreCreated() {
step.value = Step.StoreLoading
launch {
Expand Down Expand Up @@ -92,16 +107,23 @@ class WebViewStoreCreationViewModel @Inject constructor(
possibleStoreUrls.add(url)
}

fun onBackPressed() {
private fun exitStoreCreation() {
_dialogViewState.value = setDialogState(isVisible = false)
triggerEvent(Exit)
}

fun onBackPressed() {
_dialogViewState.value = setDialogState(isVisible = true)
}

sealed interface ViewState {
data class StoreCreationState(
val storeCreationUrl: String,
val siteUrlKeyword: String,
val successTriggerKeyword: String,
val exitTriggerKeyword: String,
val onStoreCreated: () -> Unit,
val onExitTriggered: () -> Unit,
val onSiteAddressFound: (url: String) -> Unit
) : ViewState

Expand All @@ -112,6 +134,13 @@ class WebViewStoreCreationViewModel @Inject constructor(
) : ViewState
}

@Parcelize
data class DialogState(
val isDialogVisible: Boolean,
val onExitConfirmed: () -> Unit,
val onDialogDismissed: () -> Unit
) : Parcelable

object NavigateToNewStore : MultiLiveEvent.Event()

private sealed interface Step : Parcelable {
Expand Down
3 changes: 3 additions & 0 deletions WooCommerce/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2686,4 +2686,7 @@
<string name="store_creation_create_new_store_label">Create a new store</string>
<string name="store_creation_cannot_load_store">Couldn\'t load your store.\nPlease try again…</string>
<string name="store_creation_in_progress">Creating your store…</string>
<string name="store_creation_exit_dialog_title">Do you want to leave?</string>
<string name="store_creation_exit_dialog_message">You will lose all your store information.</string>
<string name="store_creation_confirm_and_leave">Confirm and leave</string>
</resources>