diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 2ef481b2ef2..e2de5e3738b 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -10,7 +10,9 @@ - [***] Orders: Merchants can now bulk update the status of their orders [https://github.com/woocommerce/woocommerce-android/pull/13245] - [*] Fixed a crash on the order details [https://github.com/woocommerce/woocommerce-android/pull/13191] - [**] Introduced fallback logic for the barcode scanner to use the front-facing camera when a back-facing camera is unavailable [https://github.com/woocommerce/woocommerce-android/pull/13230] +- [*] It possible to quickly open plugins page from the plugins list in the up to update an outdated plugin [https://github.com/woocommerce/woocommerce-android/pull/13246] - [**] Fixed a bug when refunded items were displayed on the refund screen [https://github.com/woocommerce/woocommerce-android/pull/13212] +- [**] Enable hiding and disabling push notification for sites from site picker [https://github.com/woocommerce/woocommerce-android/issues/13107] 21.3 ----- diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderSelectionItemKeyProvider.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderSelectionItemKeyProvider.kt index f332adcac4f..b48e6481525 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderSelectionItemKeyProvider.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderSelectionItemKeyProvider.kt @@ -18,5 +18,5 @@ class OrderSelectionItemKeyProvider(private val recyclerView: RecyclerView) : } override fun getPosition(key: Long): Int = - (recyclerView.adapter as? OrderListAdapter)?.orderIdAndPosition[key] ?: RecyclerView.NO_POSITION + (recyclerView.adapter as? OrderListAdapter)?.orderIdAndPosition?.get(key) ?: RecyclerView.NO_POSITION } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListFragment.kt index aa4c67d6f4f..0ae116830b6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListFragment.kt @@ -415,24 +415,36 @@ class OrderListFragment : } } tracker?.onSaveInstanceState(outState) - viewModel.orderIdAndPositionBackup = - ((binding.orderListView.ordersList.adapter as? OrderListAdapter)?.orderIdAndPosition ?: emptyMap()) - as MutableMap + + _binding?.let { binding -> + val adapter = binding.orderListView.ordersList.adapter as? OrderListAdapter + adapter?.let { + viewModel.orderIdAndPositionBackup = it.orderIdAndPosition + } + } } override fun onViewStateRestored(savedInstanceState: Bundle?) { tracker?.run { onRestoreInstanceState(savedInstanceState) - (binding.orderListView.ordersList.adapter as? OrderListAdapter)?.orderIdAndPosition = - viewModel.orderIdAndPositionBackup - if (hasSelection()) { - setItemsSelected(selection.toList(), true) + _binding?.let { binding -> + restoreAdapterBulkSelectionState(binding) + if (hasSelection()) { + setItemsSelected(selection.toList(), true) + } } } super.onViewStateRestored(savedInstanceState) } + private fun restoreAdapterBulkSelectionState(binding: FragmentOrderListBinding) { + val adapter = binding.orderListView.ordersList.adapter as? OrderListAdapter + if (adapter != null) { + adapter.orderIdAndPosition = viewModel.orderIdAndPositionBackup + } + } + override fun onDestroyView() { disableSearchListeners() handler.removeCallbacksAndMessages(null) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt index 5bbd956ecce..f84c0d5ac0f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt @@ -1,5 +1,6 @@ package com.woocommerce.android.ui.orders.wooshippinglabels.address +import android.content.Context import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -10,6 +11,8 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Divider import androidx.compose.material.Icon @@ -26,6 +29,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource @@ -364,20 +368,22 @@ fun AddressSelection( bottom = dimensionResource(id = R.dimen.minor_100) ) ) - originAddresses.forEach { option -> - val isSelected = option == shipFrom - AddressSelectionItem( - address = option, - isSelected = isSelected, - onClick = { - onShippingFromAddressChange(option) - }, - modifier = Modifier.padding( - top = dimensionResource(id = R.dimen.minor_100), - start = dimensionResource(id = R.dimen.major_100), - end = dimensionResource(id = R.dimen.major_100) + LazyColumn { + items(originAddresses) { option -> + val isSelected = option == shipFrom + AddressSelectionItem( + address = option, + isSelected = isSelected, + onClick = { + onShippingFromAddressChange(option) + }, + modifier = Modifier.padding( + top = dimensionResource(id = R.dimen.minor_100), + start = dimensionResource(id = R.dimen.major_100), + end = dimensionResource(id = R.dimen.major_100) + ) ) - ) + } } Spacer(modifier = Modifier.height(dimensionResource(id = R.dimen.major_100))) }, @@ -422,7 +428,7 @@ fun AddressSelectionItem( Row { Column(modifier = Modifier.weight(1f)) { Text( - text = "Address Name", + text = address.getFormattedName(LocalContext.current), fontWeight = FontWeight.Bold, modifier = Modifier ) @@ -492,3 +498,18 @@ internal fun getShipTo() = Address( country = Location("US", "USA"), state = AmbiguousLocation.Defined(Location("CA", "California", "USA")) ) + +fun OriginShippingAddress.getFormattedName(context: Context): String { + val name = when { + !firstName.isNullOrEmpty() && !lastName.isNullOrEmpty() -> "$firstName $lastName" + !firstName.isNullOrEmpty() -> firstName + !lastName.isNullOrEmpty() -> lastName + !company.isNullOrEmpty() -> company + else -> context.getString(R.string.shipping_label_select_origin_address) + } + return if (this.isDefault) { + context.getString(R.string.shipping_label_select_origin_default_address, name) + } else { + name + } +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsEvent.kt new file mode 100644 index 00000000000..ed659390759 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsEvent.kt @@ -0,0 +1,7 @@ +package com.woocommerce.android.ui.prefs.plugins + +import com.woocommerce.android.viewmodel.MultiLiveEvent + +sealed class PluginsEvent : MultiLiveEvent.Event() { + data class NavigateToPluginsWeb(val url: String) : PluginsEvent() +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsFragment.kt index b1c12d44c29..7f43878b59e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsFragment.kt @@ -7,6 +7,7 @@ import android.view.ViewGroup import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController +import com.woocommerce.android.NavGraphSettingsDirections import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.ui.base.BaseFragment import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground @@ -46,6 +47,10 @@ class PluginsFragment : BaseFragment() { viewModel.event.observe(viewLifecycleOwner) { event -> when (event) { is MultiLiveEvent.Event.Exit -> findNavController().navigateUp() + is PluginsEvent.NavigateToPluginsWeb -> { + findNavController() + .navigate(NavGraphSettingsDirections.actionGlobalWPComWebViewFragment(event.url)) + } } } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsScreen.kt index bfd66d7571c..9a7e15ed6dc 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -16,16 +17,19 @@ 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.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.Divider +import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Scaffold import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Refresh import androidx.compose.runtime.Composable import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment @@ -44,12 +48,12 @@ import com.woocommerce.android.extensions.isNotNullOrEmpty import com.woocommerce.android.ui.compose.component.Toolbar import com.woocommerce.android.ui.compose.component.WCColoredButton import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.Inactive -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.Unknown -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.UpToDate -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.UpdateAvailable +import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.Inactive +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.Unknown +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.UpToDate +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.UpdateAvailable @Composable fun PluginsScreen(viewModel: PluginsViewModel) { @@ -69,34 +73,50 @@ fun PluginsScreen(viewModel: PluginsViewModel) { .padding(paddingValues) ) { viewModel.viewState.observeAsState().value?.let { state -> - PluginsScreen(state, viewModel::onRetryClicked) + PluginsScreen( + state = state, + onRetryTapped = viewModel::onRetryClicked, + onPluginClicked = viewModel::onPluginClicked, + ) } } } } @Composable -private fun PluginsScreen(state: ViewState, onRetryTapped: () -> Unit) { +private fun PluginsScreen( + state: PluginsViewState, + onRetryTapped: () -> Unit, + onPluginClicked: (Plugin) -> Unit, +) { Crossfade(targetState = state, label = "") { when (it) { - is ViewState.Loading -> { + is PluginsViewState.Loading -> { ShimmerPluginsList() } - is ViewState.Error -> { + + is PluginsViewState.Error -> { Error(onRetryTapped) } - is ViewState.Loaded -> { - Plugins(it.plugins) + + is PluginsViewState.Loaded -> { + Plugins( + it.plugins, + onPluginClicked, + ) } } } } @Composable -private fun Plugins(plugins: List) { +private fun Plugins( + plugins: List, + onPluginClicked: (Plugin) -> Unit +) { LazyColumn { items(plugins) { plugin -> - PluginItem(plugin) + PluginItem(plugin, onPluginClicked) if (plugins.last() != plugin) { Divider() @@ -106,10 +126,14 @@ private fun Plugins(plugins: List) { } @Composable -private fun PluginItem(plugin: Plugin) { +private fun PluginItem( + plugin: Plugin, + onPluginClicked: (Plugin) -> Unit +) { Row( modifier = Modifier .fillMaxWidth() + .clickable(onClick = { onPluginClicked(plugin) }) .padding(dimensionResource(R.dimen.major_100)) ) { Column( @@ -133,12 +157,41 @@ private fun PluginItem(plugin: Plugin) { ) } - if (plugin.status !is Unknown) { - Text( + when (plugin.status) { + is Inactive -> Text( text = plugin.status.title, color = colorResource(id = plugin.status.color), fontWeight = FontWeight.Bold ) + + is UpToDate -> Text( + text = plugin.status.title, + color = colorResource(id = plugin.status.color), + fontWeight = FontWeight.Bold + ) + + is UpdateAvailable -> { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + Icon( + imageVector = Icons.Default.Refresh, + contentDescription = plugin.status.title, + tint = colorResource(id = plugin.status.color), + modifier = Modifier + .size(24.dp) + ) + + Text( + text = plugin.status.title, + color = colorResource(id = plugin.status.color), + fontWeight = FontWeight.Bold + ) + } + } + + Unknown -> {} } } } @@ -252,33 +305,47 @@ private fun Error(onRetryTapped: () -> Unit) { @LightDarkThemePreviews @Composable private fun PreviewPlugins() { - PluginsScreen( - ViewState.Loaded( - plugins = listOf( - Plugin("Plugin 1", "Automattic", "1.0", UpToDate("Up-to-date")), - Plugin("Plugin 2", null, "2.0", UpdateAvailable("Update available (4.9)")), - Plugin("Plugin 3", "Gutenberg", "3.0", Inactive("Inactive")), - Plugin("Plugin 5", "Blabla", "5.0", Unknown) - ) - ), - onRetryTapped = {} - ) + WooThemeWithBackground { + PluginsScreen( + PluginsViewState.Loaded( + plugins = listOf( + Plugin("Plugin 1", "Automattic", "1.0", UpToDate("Up-to-date", R.color.color_info)), + Plugin( + "Plugin 2", + "Something", + "2.0", + UpdateAvailable("Update available (4.9)", R.color.color_primary) + ), + Plugin("Plugin 3", "Gutenberg", "3.0", Inactive("Inactive", R.color.color_on_surface_disabled)), + Plugin("Plugin 5", "Blabla", "5.0", Unknown) + ) + ), + onRetryTapped = {}, + onPluginClicked = {}, + ) + } } @LightDarkThemePreviews @Composable private fun PreviewError() { - PluginsScreen( - ViewState.Error, - onRetryTapped = {} - ) + WooThemeWithBackground { + PluginsScreen( + PluginsViewState.Error, + onRetryTapped = {}, + onPluginClicked = {}, + ) + } } @LightDarkThemePreviews @Composable private fun PreviewLoading() { - PluginsScreen( - ViewState.Loading, - onRetryTapped = {} - ) + WooThemeWithBackground { + PluginsScreen( + PluginsViewState.Loading, + onRetryTapped = {}, + onPluginClicked = {}, + ) + } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsViewModel.kt index 591bee9769b..c3de9c8bec3 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsViewModel.kt @@ -1,25 +1,26 @@ package com.woocommerce.android.ui.prefs.plugins -import androidx.annotation.ColorRes import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import com.woocommerce.android.R +import com.woocommerce.android.extensions.adminUrlOrDefault import com.woocommerce.android.extensions.isNotNullOrEmpty import com.woocommerce.android.tools.SelectedSite -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Error -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.Inactive -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.Unknown -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.UpToDate -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loaded.Plugin.PluginStatus.UpdateAvailable -import com.woocommerce.android.ui.prefs.plugins.PluginsViewModel.ViewState.Loading +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Error +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.Inactive +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.Unknown +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.UpToDate +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loaded.Plugin.PluginStatus.UpdateAvailable +import com.woocommerce.android.ui.prefs.plugins.PluginsViewState.Loading import com.woocommerce.android.util.isGreaterThanPluginVersion import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit import com.woocommerce.android.viewmodel.ResourceProvider import com.woocommerce.android.viewmodel.ScopedViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.launch @@ -33,9 +34,10 @@ class PluginsViewModel @Inject constructor( savedStateHandle: SavedStateHandle, private val site: SelectedSite, private val wooCommerceStore: WooCommerceStore, - private val resourceProvider: ResourceProvider + private val resourceProvider: ResourceProvider, + private val dispatcher: CoroutineDispatcher = Dispatchers.IO, ) : ScopedViewModel(savedStateHandle) { - private val _viewState = MutableSharedFlow(1) + private val _viewState = MutableSharedFlow(1) val viewState = _viewState.asLiveData() init { @@ -43,7 +45,7 @@ class PluginsViewModel @Inject constructor( } private fun loadPlugins() { - viewModelScope.launch(Dispatchers.IO) { + viewModelScope.launch(dispatcher) { _viewState.emit(Loading) val response = wooCommerceStore.fetchSystemPlugins(site.get()) if (!response.isError && response.model != null) { @@ -56,7 +58,7 @@ class PluginsViewModel @Inject constructor( name = StringEscapeUtils.unescapeHtml4(it.name), authorName = StringEscapeUtils.unescapeHtml4(it.authorName), version = it.version!!, - status = it.getState() + status = it.getStatus() ) } ) @@ -67,14 +69,18 @@ class PluginsViewModel @Inject constructor( } } - private fun SystemPluginModel.getState(): Plugin.PluginStatus { + private fun SystemPluginModel.getStatus(): Plugin.PluginStatus { return when { - !isActive -> Inactive(resourceProvider.getString(R.string.plugin_state_inactive)) + !isActive -> Inactive( + resourceProvider.getString(R.string.plugin_state_inactive), + R.color.color_on_surface_disabled, + ) versionLatest.isNullOrEmpty() -> Unknown isUpdateAvailable() -> UpdateAvailable( - resourceProvider.getString(R.string.plugin_state_update_available, versionLatest!!) + resourceProvider.getString(R.string.plugin_state_update_available, versionLatest!!), + R.color.color_primary, ) - else -> UpToDate(resourceProvider.getString(R.string.plugin_state_up_to_date)) + else -> UpToDate(resourceProvider.getString(R.string.plugin_state_up_to_date), R.color.color_info) } } @@ -86,32 +92,18 @@ class PluginsViewModel @Inject constructor( loadPlugins() } - fun onBackPressed() { - triggerEvent(Exit) - } - - sealed interface ViewState { - data object Loading : ViewState - data object Error : ViewState - data class Loaded( - val plugins: List = emptyList() - ) : ViewState { - data class Plugin( - val name: String, - val authorName: String?, - val version: String, - val status: PluginStatus - ) { - sealed class PluginStatus(open val title: String, @ColorRes val color: Int) { - data class UpToDate(override val title: String) : PluginStatus(title, R.color.color_info) - data class UpdateAvailable(override val title: String) : PluginStatus(title, R.color.color_alert) - data class Inactive(override val title: String) : PluginStatus( - title, - R.color.color_on_surface_disabled - ) - data object Unknown : PluginStatus("", R.color.color_on_surface_disabled) - } + fun onPluginClicked(plugin: Plugin) { + when (plugin.status) { + is Inactive -> {} + Unknown -> {} + is UpToDate -> {} + is UpdateAvailable -> { + triggerEvent(PluginsEvent.NavigateToPluginsWeb("${site.get().adminUrlOrDefault}/plugins.php")) } } } + + fun onBackPressed() { + triggerEvent(Exit) + } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsViewState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsViewState.kt new file mode 100644 index 00000000000..256068ad217 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/prefs/plugins/PluginsViewState.kt @@ -0,0 +1,25 @@ +package com.woocommerce.android.ui.prefs.plugins + +import androidx.annotation.ColorRes + +sealed interface PluginsViewState { + data object Loading : PluginsViewState + data object Error : PluginsViewState + data class Loaded( + val plugins: List = emptyList() + ) : PluginsViewState { + data class Plugin( + val name: String, + val authorName: String?, + val version: String, + val status: PluginStatus + ) { + sealed class PluginStatus { + data class UpToDate(val title: String, @ColorRes val color: Int) : PluginStatus() + data class UpdateAvailable(val title: String, @ColorRes val color: Int) : PluginStatus() + data class Inactive(val title: String, @ColorRes val color: Int) : PluginStatus() + data object Unknown : PluginStatus() + } + } + } +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeViewModel.kt index 869e99a21b8..0cec510fd4e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeViewModel.kt @@ -8,6 +8,7 @@ import com.woocommerce.android.ui.woopos.home.ParentToChildrenEvent.OrderSuccess import com.woocommerce.android.ui.woopos.home.WooPosHomeState.ExitConfirmationDialog import com.woocommerce.android.ui.woopos.home.WooPosHomeState.ProductsInfoDialog import com.woocommerce.android.ui.woopos.home.WooPosHomeState.ScreenPositionState +import com.woocommerce.android.ui.woopos.home.items.navigation.WooPosItemsNavigator import com.woocommerce.android.viewmodel.getStateFlow import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow @@ -20,6 +21,7 @@ import javax.inject.Inject class WooPosHomeViewModel @Inject constructor( private val childrenToParentEventReceiver: WooPosChildrenToParentEventReceiver, private val parentToChildrenEventSender: WooPosParentToChildrenEventSender, + private val wooPosItemsNavigator: WooPosItemsNavigator, savedStateHandle: SavedStateHandle, ) : ViewModel() { private val _state = savedStateHandle.getStateFlow( @@ -201,6 +203,11 @@ class WooPosHomeViewModel @Inject constructor( } private fun onOrderSuccessfullyPaid(paymentMethod: PaymentMethod) { + viewModelScope.launch { + wooPosItemsNavigator.sendNavigationEvent( + WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateBackToItemListScreen + ) + } _state.value = _state.value.copy( screenPositionState = ScreenPositionState.Checkout.FullScreenTotals ) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt index 38371285624..bd5e2ac361d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt @@ -28,7 +28,6 @@ import com.woocommerce.android.ui.woopos.home.ParentToChildrenEvent.OrderSuccess import com.woocommerce.android.ui.woopos.home.WooPosChildrenToParentEventSender import com.woocommerce.android.ui.woopos.home.WooPosParentToChildrenEventReceiver import com.woocommerce.android.ui.woopos.home.items.WooPosItemsViewModel -import com.woocommerce.android.ui.woopos.home.items.navigation.WooPosItemsNavigator import com.woocommerce.android.ui.woopos.home.totals.WooPosTotalsViewState.PaymentFailed import com.woocommerce.android.ui.woopos.home.totals.WooPosTotalsViewState.PaymentInProgress import com.woocommerce.android.ui.woopos.util.WooPosNetworkStatus @@ -62,7 +61,6 @@ class WooPosTotalsViewModel @Inject constructor( private val priceFormat: WooPosFormatPrice, private val analyticsTracker: WooPosAnalyticsTracker, private val networkStatus: WooPosNetworkStatus, - private val wooPosItemsNavigator: WooPosItemsNavigator, private val isReceiptSendingSupported: WooPosEmailReceiptIsSendingSupported, private val cardReaderPaymentControllerFactory: CardReaderPaymentControllerFactory, private val uiStringParser: UiStringParser, @@ -306,9 +304,6 @@ class WooPosTotalsViewModel @Inject constructor( } is CardReaderPaymentState.PaymentSuccessful -> { - wooPosItemsNavigator.sendNavigationEvent( - WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateBackToItemListScreen - ) childrenToParentEventSender.sendToParent(OrderSuccessfullyPaidByCard) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt index 84f227607c4..ba0804d224e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt @@ -26,13 +26,13 @@ enum class FeatureFlag { WC_SHIPPING_BANNER, BETTER_CUSTOMER_SEARCH_M2, ORDER_CREATION_AUTO_TAX_RATE, - REVAMP_WOO_SHIPPING, - HIDE_SITES_FROM_SITE_PICKER -> PackageUtils.isDebugBuild() + REVAMP_WOO_SHIPPING -> PackageUtils.isDebugBuild() NEW_SHIPPING_SUPPORT, ENDLESS_CAMPAIGNS_SUPPORT, OBJECTIVE_SECTION, - BULK_UPDATE_ORDERS_STATUS -> true + BULK_UPDATE_ORDERS_STATUS, + HIDE_SITES_FROM_SITE_PICKER -> true } } } diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index 8cc104203e8..76ca64ea2d4 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -1309,6 +1309,8 @@ We currently do not support Tracking for this carrier Something went wrong with this Shipping Label, try again later We can\'t confirm the Shipping Label purchase right now, try again later + %s (default) + Address