From 265a89bea1e979b8d34692d599f4c272af57d5f5 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Sun, 29 Dec 2024 21:54:03 +0100 Subject: [PATCH 1/9] Update notification settings using new API endpoint --- .../WooSitesVisibilityViewModel.kt | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt index 8ce74711a87..f245b2c5fb3 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt @@ -12,6 +12,8 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.NotificationStore +import org.wordpress.android.fluxc.store.NotificationStore.SiteNotificationSetting import javax.inject.Inject @HiltViewModel @@ -19,6 +21,7 @@ class WooSitesVisibilityViewModel @Inject constructor( private val sitePickerRepository: SitePickerRepository, private val selectedSite: SelectedSite, private val visibleSitesDataStore: VisibleWooSitesDataStore, + private val notificationsStore: NotificationStore, savedStateHandle: SavedStateHandle ) : ScopedViewModel(savedStateHandle) { private var initiallySelectedSiteIds: List = emptyList() @@ -50,11 +53,26 @@ class WooSitesVisibilityViewModel @Inject constructor( fun onSaveTapped() { launch { - visibleSitesDataStore.updateSiteVisibilityStatus( - _wooStores.value.wooStores - .associate { it.siteId to it.isSelected } + notificationsStore.updateNotificationSettingsFor( + _wooStores.value.wooStores.map { + SiteNotificationSetting( + siteId = it.siteId, + newCommentEnabled = it.isSelected, + storeOrderEnabled = it.isSelected + ) + } + ).fold( + onSuccess = { + visibleSitesDataStore.updateSiteVisibilityStatus( + _wooStores.value.wooStores + .associate { it.siteId to it.isSelected } + ) + triggerEvent(ExitWithResult(data = true)) + }, + onFailure = { + // TODO: Show error message + } ) - triggerEvent(ExitWithResult(data = true)) } } From 4a45eed395b5f484aba39b8409100dc4112b66df Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Dec 2024 10:30:20 +0100 Subject: [PATCH 2/9] Update fluxC changeset --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d2caa6f8265..21c0b86a577 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -87,7 +87,7 @@ stripe-terminal = '3.7.1' tinder-statemachine = '0.2.0' wiremock = '2.26.3' wordpress-aztec = 'v2.1.4' -wordpress-fluxc = 'trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e' +wordpress-fluxc = '3122-c8c9f508066c0c8165420dee180b7d10cafbfbb6' wordpress-login = '1.19.0' wordpress-libaddressinput = '0.0.2' wordpress-mediapicker = '0.3.1' From 9d20b87303ff3118a91ff8634f9c75e0c9e53ac3 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Dec 2024 11:22:30 +0100 Subject: [PATCH 3/9] Add loading indicator while site notifications are updated --- .../WooSitesVisibilityScreen.kt | 23 ++++++++++---- .../WooSitesVisibilityViewModel.kt | 31 +++++++++++-------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityScreen.kt index 796b85d8c32..183f5fbbf9c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityScreen.kt @@ -11,9 +11,11 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Divider import androidx.compose.material.Icon import androidx.compose.material.IconButton @@ -74,13 +76,21 @@ fun WooSitesVisibilityScreen( }, backgroundColor = colorResource(id = R.color.color_toolbar), actions = { - TextButton( - onClick = onSaveTapped, - enabled = state.isSaveButtonEnabled - ) { - Text( - text = stringResource(id = R.string.save).uppercase() + if (state.isLoading) { + CircularProgressIndicator( + modifier = Modifier + .size(width = 56.dp, height = 16.dp) + .padding(horizontal = 16.dp) ) + } else { + TextButton( + onClick = onSaveTapped, + enabled = state.isSaveButtonEnabled + ) { + Text( + text = stringResource(id = R.string.save).uppercase() + ) + } } }, elevation = 0.dp @@ -228,6 +238,7 @@ fun StoreVisibilityScreenPreview() { ), isSaveButtonEnabled = true, + isLoading = false, currentSite = WooStoreUi( siteName = "Current Store", siteUrl = "https://myselectedSite.com", diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt index f245b2c5fb3..57322a02a23 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt @@ -25,23 +25,24 @@ class WooSitesVisibilityViewModel @Inject constructor( savedStateHandle: SavedStateHandle ) : ScopedViewModel(savedStateHandle) { private var initiallySelectedSiteIds: List = emptyList() - private val _wooStores = MutableStateFlow( + private val _wooStoresState = MutableStateFlow( WooStoresUiState( wooStores = emptyList(), currentSite = selectedSite.get().toWooStoreUi(isSiteVisible = false), - isSaveButtonEnabled = false + isSaveButtonEnabled = false, + isLoading = false ) ) - val viewState = _wooStores.asLiveData() + val viewState = _wooStoresState.asLiveData() init { launch { - _wooStores.value = _wooStores.value.copy( + _wooStoresState.value = _wooStoresState.value.copy( wooStores = sitePickerRepository.getSites() .filter { it.hasWooCommerce && it.siteId != selectedSite.get().siteId } .map { it.toWooStoreUi(isSiteVisible(it.siteId)) } ) - initiallySelectedSiteIds = _wooStores.value.wooStores + initiallySelectedSiteIds = _wooStoresState.value.wooStores .filter { it.isSelected } .map { it.siteId } } @@ -52,9 +53,10 @@ class WooSitesVisibilityViewModel @Inject constructor( } fun onSaveTapped() { + _wooStoresState.value = _wooStoresState.value.copy(isLoading = true) launch { notificationsStore.updateNotificationSettingsFor( - _wooStores.value.wooStores.map { + _wooStoresState.value.wooStores.map { SiteNotificationSetting( siteId = it.siteId, newCommentEnabled = it.isSelected, @@ -64,7 +66,7 @@ class WooSitesVisibilityViewModel @Inject constructor( ).fold( onSuccess = { visibleSitesDataStore.updateSiteVisibilityStatus( - _wooStores.value.wooStores + _wooStoresState.value.wooStores .associate { it.siteId to it.isSelected } ) triggerEvent(ExitWithResult(data = true)) @@ -72,21 +74,23 @@ class WooSitesVisibilityViewModel @Inject constructor( onFailure = { // TODO: Show error message } - ) + ).also { + _wooStoresState.value = _wooStoresState.value.copy(isLoading = false) + } } } fun onSiteTapped(wooStoreUi: WooStoreUi) { - _wooStores.value = _wooStores.value.copy( - wooStores = _wooStores.value.wooStores.map { + _wooStoresState.value = _wooStoresState.value.copy( + wooStores = _wooStoresState.value.wooStores.map { when { it.siteId == wooStoreUi.siteId -> it.copy(isSelected = !it.isSelected) else -> it } } ) - _wooStores.value = _wooStores.value.copy( - isSaveButtonEnabled = _wooStores.value.wooStores + _wooStoresState.value = _wooStoresState.value.copy( + isSaveButtonEnabled = _wooStoresState.value.wooStores .filter { it.isSelected } .map { it.siteId } != initiallySelectedSiteIds ) @@ -105,7 +109,8 @@ class WooSitesVisibilityViewModel @Inject constructor( data class WooStoresUiState( val wooStores: List, val currentSite: WooStoreUi, - val isSaveButtonEnabled: Boolean + val isSaveButtonEnabled: Boolean, + val isLoading: Boolean ) data class WooStoreUi( From afc3cc2aee2fd3006a550cfd5e21603eed7e81ee Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Dec 2024 12:09:14 +0100 Subject: [PATCH 4/9] Add error handling --- .../WooSitesVisibilityFragment.kt | 2 ++ .../WooSitesVisibilityViewModel.kt | 18 +++++++++++++++++- WooCommerce/src/main/res/values/strings.xml | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityFragment.kt index b7194506f54..324b3ba1f3e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityFragment.kt @@ -12,6 +12,7 @@ import com.woocommerce.android.ui.compose.composeView import com.woocommerce.android.ui.main.AppBarStatus import com.woocommerce.android.viewmodel.MultiLiveEvent import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ExitWithResult +import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowDialog import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -40,6 +41,7 @@ class WooSitesVisibilityFragment : BaseFragment() { when (event) { is MultiLiveEvent.Event.Exit -> findNavController().navigateUp() is ExitWithResult<*> -> navigateBackWithResult(WOO_SITES_VISIBILITY_UPDATED, event.data) + is ShowDialog -> event.showDialog() } } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt index 57322a02a23..1b9f4b9d6e1 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/sitepicker/sitevisibility/WooSitesVisibilityViewModel.kt @@ -2,8 +2,10 @@ package com.woocommerce.android.ui.sitepicker.sitevisibility import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asLiveData +import com.woocommerce.android.R import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.sitepicker.SitePickerRepository +import com.woocommerce.android.viewmodel.MultiLiveEvent.Event import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ExitWithResult import com.woocommerce.android.viewmodel.ScopedViewModel @@ -72,7 +74,21 @@ class WooSitesVisibilityViewModel @Inject constructor( triggerEvent(ExitWithResult(data = true)) }, onFailure = { - // TODO: Show error message + triggerEvent( + Event.ShowDialog( + titleId = R.string.site_picker_edit_store_list_error_title, + positiveButtonId = R.string.retry, + positiveBtnAction = { dialog, _ -> + dialog.dismiss() + onSaveTapped() + }, + negativeButtonId = R.string.cancel, + negativeBtnAction = { dialog, _ -> + dialog.dismiss() + triggerEvent(Exit) + } + ) + ) } ).also { _wooStoresState.value = _wooStoresState.value.copy(isLoading = false) diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index a12fa25078c..e83cd5e645a 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -377,6 +377,7 @@ Current Store Please switch to another store if you want to hide this one Other Stores + There was an error when updating notification settings. Please try again