From fb7dde0e3d990170adc83a8743580c67664e823a Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 17 Jul 2024 14:26:56 +0200 Subject: [PATCH 01/99] Bump AGP to 8.5.0 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 3e833887b51..11434282077 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ pluginManagement { - gradle.ext.agpVersion = '8.1.0' + gradle.ext.agpVersion = '8.5.0' gradle.ext.googleServicesVersion = '4.4.0' gradle.ext.daggerVersion = '2.50' gradle.ext.detektVersion = '1.23.5' From 53f089935249cf298c7a7e2392a2657e96b03cac Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 17 Jul 2024 14:29:38 +0200 Subject: [PATCH 02/99] Do not minify libraries, minify app builds only Starting from Gradle 8.4, shrinking at library level is now respected. Library modules will be now shrinked in isolation, removing code that might be used by other modules. The solution is to not shrink each library module (no need as we don't publish them in isolation) and shrink only app modules. --- libs/cardreader/build.gradle | 2 +- libs/iap/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/cardreader/build.gradle b/libs/cardreader/build.gradle index 9fac17e5d2a..3ade581c456 100644 --- a/libs/cardreader/build.gradle +++ b/libs/cardreader/build.gradle @@ -22,7 +22,7 @@ android { buildTypes { release { - minifyEnabled true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } diff --git a/libs/iap/build.gradle b/libs/iap/build.gradle index 7c277cf3e72..12e7d54b1e6 100644 --- a/libs/iap/build.gradle +++ b/libs/iap/build.gradle @@ -21,7 +21,7 @@ android { buildTypes { release { - minifyEnabled true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } From ac213cfeda4ff19a097eaeb5b59a66e20f2cb7ba Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 17 Jul 2024 14:30:45 +0200 Subject: [PATCH 03/99] Remove release build type from library modules They're not used --- libs/cardreader/build.gradle | 6 ------ libs/commons/build.gradle | 5 ----- libs/iap/build.gradle | 6 ------ 3 files changed, 17 deletions(-) diff --git a/libs/cardreader/build.gradle b/libs/cardreader/build.gradle index 3ade581c456..7c0a459548a 100644 --- a/libs/cardreader/build.gradle +++ b/libs/cardreader/build.gradle @@ -20,12 +20,6 @@ android { buildConfig = false } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 diff --git a/libs/commons/build.gradle b/libs/commons/build.gradle index 82cde2b607d..b52e2241fd6 100644 --- a/libs/commons/build.gradle +++ b/libs/commons/build.gradle @@ -12,11 +12,6 @@ android { targetSdk gradle.ext.targetSdkVersion } - buildTypes { - release { - minifyEnabled false - } - } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 diff --git a/libs/iap/build.gradle b/libs/iap/build.gradle index 12e7d54b1e6..54032e4795a 100644 --- a/libs/iap/build.gradle +++ b/libs/iap/build.gradle @@ -19,12 +19,6 @@ android { buildConfig = false } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 From a97f677319b5f397d5ecd75056ba358d693add9a Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Tue, 23 Jul 2024 11:29:11 +0200 Subject: [PATCH 04/99] Add `POST_NOTIFICATIONS` persmisson to Wear manifest To address `NotificationPermission` lint error. Actually, this permission is not needed at this moment, as the wear module doesn't use org.wordpress.android.util.AutoForeground or classes that overrides from it so it seems to be a false positive from lint. I don't want to suppress this issue though, as we might use AutoForeground in the future, and the POST_NOTIFICATIONS will be necessary then. --- WooCommerce-Wear/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/WooCommerce-Wear/src/main/AndroidManifest.xml b/WooCommerce-Wear/src/main/AndroidManifest.xml index 127a5259c4e..6b41fc06979 100644 --- a/WooCommerce-Wear/src/main/AndroidManifest.xml +++ b/WooCommerce-Wear/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ + Date: Tue, 23 Jul 2024 13:29:56 +0200 Subject: [PATCH 05/99] Address `StringFormatMatches` lint warning - unwrap `String#format(Context#getString` calls. Having two formats is unnecessary and can be confusing - update format arguments to reflect type declared in strings.xml --- .../woocommerce/android/ui/orders/list/OrderListAdapter.kt | 2 +- .../android/ui/orders/taxes/OrderTaxesAdapter.kt | 2 +- .../ui/payments/customamounts/CustomAmountsFragment.kt | 4 +--- .../android/ui/products/ProductItemViewHolder.kt | 5 +---- .../com/woocommerce/android/ui/reviews/ReviewListAdapter.kt | 6 +++--- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListAdapter.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListAdapter.kt index 81681b1a808..8208a26daa8 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListAdapter.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListAdapter.kt @@ -184,7 +184,7 @@ class OrderListAdapter( viewBinding.root, String.format( ctx.getString(R.string.order_card_transition_name), - orderItemUI.orderId + orderItemUI.orderId.toString() ) ) extras.clear() diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/taxes/OrderTaxesAdapter.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/taxes/OrderTaxesAdapter.kt index 89c251537a7..893713f113c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/taxes/OrderTaxesAdapter.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/taxes/OrderTaxesAdapter.kt @@ -44,7 +44,7 @@ class OrderTaxesAdapter( fun bind(tax: Order.TaxLine) { val context = viewBinding.root.context viewBinding.taxLabel.text = - String.format(context.getString(R.string.tax_name_with_tax_percent), tax.label, tax.ratePercent) + context.getString(R.string.tax_name_with_tax_percent, tax.label, tax.ratePercent.toString()) viewBinding.taxValue.text = currencyFormatter.formatCurrency(tax.taxTotal, currencyCode) } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/customamounts/CustomAmountsFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/customamounts/CustomAmountsFragment.kt index 1910aed9b0a..ab6fa9b5cd1 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/customamounts/CustomAmountsFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/customamounts/CustomAmountsFragment.kt @@ -109,9 +109,7 @@ class CustomAmountsFragment : BaseFragment(R.layout.dialog_custom_amounts) { private fun bindPercentageLabel(binding: DialogCustomAmountsBinding) { with(binding.percentageLabel) { - text = String.format( - context.getString(R.string.custom_amounts_percentage_label, arguments.orderTotal) - ) + text = context.getString(R.string.custom_amounts_percentage_label, arguments.orderTotal) } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductItemViewHolder.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductItemViewHolder.kt index 1738baa1cbb..cc132fa79f0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductItemViewHolder.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductItemViewHolder.kt @@ -40,10 +40,7 @@ class ProductItemViewHolder(val viewBinding: ProductListItemBinding) : ViewCompat.setTransitionName( viewBinding.root, - String.format( - context.getString(R.string.order_card_transition_name), - product.remoteId - ) + context.getString(R.string.order_card_transition_name, product.remoteId.toString()), ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/reviews/ReviewListAdapter.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/reviews/ReviewListAdapter.kt index 38bbacc7094..e54b759f479 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/reviews/ReviewListAdapter.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/reviews/ReviewListAdapter.kt @@ -243,9 +243,9 @@ class ReviewListAdapter(private val clickListener: OnReviewClickListener) : Sect ViewCompat.setTransitionName( viewBinding.root, - String.format( - context.getString(R.string.review_card_transition_name), - review.remoteId + context.getString( + R.string.review_card_transition_name, + review.remoteId.toString() ) ) From 8d45720b9b66eb19a50c621ec913de6b3d3df08d Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 24 Jul 2024 15:27:04 +0200 Subject: [PATCH 06/99] Bump AGP to 8.5.1 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 11434282077..08816a898e7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ pluginManagement { - gradle.ext.agpVersion = '8.5.0' + gradle.ext.agpVersion = '8.5.1' gradle.ext.googleServicesVersion = '4.4.0' gradle.ext.daggerVersion = '2.50' gradle.ext.detektVersion = '1.23.5' From 08610defed0fbc7d877a01a3f17600706d9a7687 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 2 Aug 2024 16:10:15 +0200 Subject: [PATCH 07/99] Remove redundant Box element --- .../ui/woopos/home/products/WooPosProductsScreen.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt index 58ca1c8692c..07da674a8af 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt @@ -146,13 +146,11 @@ private fun WooPosProductsScreen( onSimpleProductsBannerLearnMoreClicked, onSimpleProductsBannerClosed ) - Box { - ProductsList( - productsState, - onItemClicked, - onEndOfProductListReached, - ) - } + ProductsList( + productsState, + onItemClicked, + onEndOfProductListReached, + ) } } From 5e7835805caa2ef00456bf3729ed5ce64e961f86 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 2 Aug 2024 16:16:31 +0200 Subject: [PATCH 08/99] Increase bottom Spacer in the products list --- .../android/ui/woopos/home/products/WooPosProductsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt index 07da674a8af..3be25c9fe26 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt @@ -266,7 +266,7 @@ private fun ProductsList( } } item { - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(112.dp)) } } InfiniteListHandler(listState) { From 7eb47a8505270b4afb02754342b151f68dbb725b Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 16:26:46 +0100 Subject: [PATCH 09/99] Bump fluxc --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 74989839778..29b5665c841 100644 --- a/build.gradle +++ b/build.gradle @@ -99,7 +99,7 @@ tasks.register("installGitHooks", Copy) { } ext { - fluxCVersion = 'trunk-cc6b2f85546a844b13d99bc0ad6ceabd1af131d3' + fluxCVersion = '3070-42c9f5d76d859ad555a815e9acc1641b134faf0e' glideVersion = '4.16.0' coilVersion = '2.1.0' constraintLayoutVersion = '1.2.0' From 460519234581f16d3f41ac87a70391f8ca1f3771 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 16:19:28 +0100 Subject: [PATCH 10/99] Update usage of metadata for tracking --- .../woocommerce/android/ui/orders/list/OrderListViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt index f03600f3da2..eafebf73832 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt @@ -413,7 +413,7 @@ class OrderListViewModel @Inject constructor( fun trackOrderClickEvent(orderId: Long, orderStatus: String, windowSize: WindowSizeClass) = launch { val (customFieldsCount, customFieldsSize) = orderDetailRepository.getOrderMetadata(orderId) - .map { it.value.utf8Size() } + .map { it.valueAsString.utf8Size() } .let { Pair( // amount of custom fields in the order From 7a6ba6d52008f76de6c200b64dd8c4a8ff131200 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 16:20:00 +0100 Subject: [PATCH 11/99] Update custom fields screen to use WCMetaData directly --- .../ui/orders/details/OrderDetailViewModel.kt | 4 +-- .../customfields/CustomOrderFieldsScreen.kt | 29 +++++++------------ 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt index 2f4b2ea606d..c1313a83492 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt @@ -85,7 +85,7 @@ import kotlinx.coroutines.flow.withIndex import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.wordpress.android.fluxc.model.OrderAttributionInfo -import org.wordpress.android.fluxc.persistence.entity.OrderMetaDataEntity +import org.wordpress.android.fluxc.model.WCMetaData import org.wordpress.android.fluxc.store.WCOrderStore.UpdateOrderResult.OptimisticUpdateResult import org.wordpress.android.fluxc.store.WCOrderStore.UpdateOrderResult.RemoteUpdateResult import org.wordpress.android.fluxc.store.WooCommerceStore @@ -333,7 +333,7 @@ class OrderDetailViewModel @Inject constructor( triggerEvent(MultiLiveEvent.Event.Exit) } - fun getOrderMetadata(): List = runBlocking { + fun getOrderMetadata(): List = runBlocking { orderDetailRepository.getOrderMetadata(navArgs.orderId) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt index df0892d98e5..c8a78cf72a6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt @@ -39,8 +39,7 @@ import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground import com.woocommerce.android.ui.orders.details.OrderDetailViewModel import com.woocommerce.android.ui.orders.details.customfields.CustomOrderFieldsHelper.CustomOrderFieldClickListener import com.woocommerce.android.ui.orders.details.customfields.CustomOrderFieldsHelper.CustomOrderFieldType -import org.wordpress.android.fluxc.model.LocalOrRemoteId -import org.wordpress.android.fluxc.persistence.entity.OrderMetaDataEntity +import org.wordpress.android.fluxc.model.WCMetaData private var clickListener: CustomOrderFieldClickListener? = null @@ -55,7 +54,7 @@ fun CustomOrderFieldsScreen(viewModel: OrderDetailViewModel, listener: CustomOrd @Composable fun CustomFieldsScreen( - metadataList: List, + metadataList: List, onBackPressed: () -> Unit ) { Box( @@ -91,7 +90,7 @@ fun CustomFieldsScreen( } @Composable -private fun CustomFieldListItem(metadata: OrderMetaDataEntity) { +private fun CustomFieldListItem(metadata: WCMetaData) { Column( verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.minor_50)), modifier = Modifier @@ -116,10 +115,10 @@ private fun CustomFieldListItem(metadata: OrderMetaDataEntity) { ) } SelectionContainer { - if (CustomOrderFieldType.fromMetadataValue(metadata.value) == CustomOrderFieldType.TEXT) { - textValueItem(metadata.value) + if (CustomOrderFieldType.fromMetadataValue(metadata.valueStrippedHtml) == CustomOrderFieldType.TEXT) { + textValueItem(metadata.valueStrippedHtml) } else { - clickableTextValueItem(metadata.value) + clickableTextValueItem(metadata.valueStrippedHtml) } } } @@ -174,31 +173,23 @@ private fun CustomFieldsPreview() { WooThemeWithBackground { CustomFieldsScreen( listOf( - OrderMetaDataEntity( + WCMetaData( id = 1, - localSiteId = LocalOrRemoteId.LocalId(0), - orderId = 0, key = "text key", value = "text value" ), - OrderMetaDataEntity( + WCMetaData( id = 2, - localSiteId = LocalOrRemoteId.LocalId(0), - orderId = 0, key = "url key", value = "https://automattic.com/" ), - OrderMetaDataEntity( + WCMetaData( id = 3, - localSiteId = LocalOrRemoteId.LocalId(0), - orderId = 0, key = "email key", value = "example@example.com" ), - OrderMetaDataEntity( + WCMetaData( id = 4, - localSiteId = LocalOrRemoteId.LocalId(0), - orderId = 0, key = "phone key", value = "tel://1234567890" ) From 28aacb2d28b62e1bf70eb1f1629a154c34608659 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 16:21:25 +0100 Subject: [PATCH 12/99] Fix usage of WCMetaData in GetOrderSubscriptions --- .../android/ui/orders/details/GetOrderSubscriptions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt index a1acae7edaf..d0492d22044 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt @@ -32,7 +32,7 @@ class GetOrderSubscriptions @Inject constructor( val renewal = metadataList.find { metadata -> metadata.key == WCMetaData.SubscriptionMetadataKeys.SUBSCRIPTION_RENEWAL } - return renewal?.value?.toLongOrNull() + return renewal?.value?.takeIf { it.isJsonPrimitive && it.asJsonPrimitive.isNumber }?.asLong } private suspend fun getRenewalSubscription(subscriptionId: Long): Result> { From 69f83333b09f802a8e3645c01048da229285e2cd Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 16:21:57 +0100 Subject: [PATCH 13/99] Simplify expression --- .../android/ui/products/details/ProductDetailRepository.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt index d0e3115ecaf..6e063aef4e2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt @@ -307,8 +307,7 @@ class ProductDetailRepository @Inject constructor( val metadata = getCachedWCProductModel(remoteProductId)?.metadata ?: return null val metadataArray = gson.fromJson(metadata, Array::class.java) - return metadataArray?.filter { metadataItem -> metadataItem.key.isNullOrEmpty().not() } - ?.associate { metadataItem -> metadataItem.key!! to metadataItem.value } + return metadataArray?.associate { metadataItem -> metadataItem.key to metadataItem.value } } @SuppressWarnings("unused") From a6c1288ef92bc1f18c8f93dfc3469b6f7aecd4aa Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 18:35:08 +0100 Subject: [PATCH 14/99] Update the order mapper --- .../main/kotlin/com/woocommerce/android/model/OrderMapper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt index e5b2070049e..5bf32a518db 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt @@ -25,7 +25,7 @@ class OrderMapper @Inject constructor( private val dateUtils: DateUtils, ) { fun toAppModel(databaseEntity: OrderEntity): Order { - val metaDataList = databaseEntity.getMetaDataList() + val metaDataList = databaseEntity.metaData return Order( id = databaseEntity.orderId, number = databaseEntity.number, From 505ccf2ebfe3667d6764ed637d6daa5c6843026d Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 20:23:43 +0100 Subject: [PATCH 15/99] Simplify logic using parsedMetadata --- .../android/ui/orders/creation/GetProductRules.kt | 7 ++++--- .../android/ui/products/details/ProductDetailRepository.kt | 7 ++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/creation/GetProductRules.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/creation/GetProductRules.kt index 86438d34c79..62d9c98abb7 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/creation/GetProductRules.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/creation/GetProductRules.kt @@ -8,6 +8,7 @@ import com.woocommerce.android.ui.products.ProductType import com.woocommerce.android.ui.products.details.ProductDetailRepository import kotlinx.coroutines.flow.first import org.wordpress.android.fluxc.model.WCMetaData +import org.wordpress.android.fluxc.model.get import javax.inject.Inject class GetProductRules @Inject constructor( @@ -29,9 +30,9 @@ class GetProductRules @Inject constructor( val builder = ProductRules.Builder().apply { productType = ProductType.BUNDLE } - productDetailRepository.getProductMetadata(product.remoteId)?.let { map -> - val maxSize = map[WCMetaData.BundleMetadataKeys.BUNDLE_MAX_SIZE].toString().toFloatOrNull() - val minSize = map[WCMetaData.BundleMetadataKeys.BUNDLE_MIN_SIZE].toString().toFloatOrNull() + productDetailRepository.getProductMetadata(product.remoteId)?.let { list -> + val maxSize = list[WCMetaData.BundleMetadataKeys.BUNDLE_MAX_SIZE]?.valueAsString?.toFloatOrNull() + val minSize = list[WCMetaData.BundleMetadataKeys.BUNDLE_MIN_SIZE]?.valueAsString?.toFloatOrNull() builder.setQuantityRules(minSize, maxSize) } getBundledProducts(product.remoteId).first().forEach { bundledProduct -> diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt index 6e063aef4e2..6c9775d46c1 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt @@ -303,11 +303,8 @@ class ProductDetailRepository @Inject constructor( } } - fun getProductMetadata(remoteProductId: Long): Map? { - val metadata = getCachedWCProductModel(remoteProductId)?.metadata ?: return null - val metadataArray = gson.fromJson(metadata, Array::class.java) - - return metadataArray?.associate { metadataItem -> metadataItem.key to metadataItem.value } + fun getProductMetadata(remoteProductId: Long): List? { + return getCachedWCProductModel(remoteProductId)?.parsedMetaData ?: return null } @SuppressWarnings("unused") From 62b1ad9a6bbf234a8398159b69380caf9d5432b2 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Fri, 2 Aug 2024 20:27:24 +0100 Subject: [PATCH 16/99] Fix unit tests --- .../android/ui/orders/OrderTestUtils.kt | 3 +- .../refunds/IssueRefundViewModelTest.kt | 49 ++++++++++--------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderTestUtils.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderTestUtils.kt index f9346163963..9f6f2683ccc 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderTestUtils.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderTestUtils.kt @@ -10,6 +10,7 @@ import com.woocommerce.android.model.ShippingLabel import com.woocommerce.android.model.toAppModel import org.wordpress.android.fluxc.model.LocalOrRemoteId import org.wordpress.android.fluxc.model.OrderEntity +import org.wordpress.android.fluxc.model.WCMetaData import org.wordpress.android.fluxc.model.WCOrderShipmentProviderModel import org.wordpress.android.fluxc.model.WCOrderShipmentTrackingModel import org.wordpress.android.fluxc.model.WCOrderStatusModel @@ -24,7 +25,7 @@ object OrderTestUtils { private const val TEST_ORDER_STATUS_COUNT = 20 fun generateOrder( - metadata: String = "", + metadata: List = emptyList(), paymentMethod: String = "", datePaid: String = "2018-02-02T16:11:13Z", lineItems: String = "" diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModelTest.kt index 007517b8280..f4e38466109 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModelTest.kt @@ -27,6 +27,7 @@ import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.model.WCMetaData import org.wordpress.android.fluxc.model.refunds.WCRefundModel import org.wordpress.android.fluxc.network.BaseRequest import org.wordpress.android.fluxc.network.rest.wpcom.wc.WooError @@ -168,7 +169,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -198,7 +199,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(networkStatus.isConnected()).thenReturn(true) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -231,7 +232,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(networkStatus.isConnected()).thenReturn(true) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -264,7 +265,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(networkStatus.isConnected()).thenReturn(true) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -297,7 +298,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -331,7 +332,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -365,7 +366,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -416,7 +417,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -467,7 +468,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -518,7 +519,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(networkStatus.isConnected()).thenReturn(true) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -549,7 +550,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val chargeId = "charge_id" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(networkStatus.isConnected()).thenReturn(true) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -576,7 +577,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val chargeId = "charge_id" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -600,7 +601,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val chargeId = "charge_id" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -622,7 +623,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val chargeId = "charge_id" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -645,7 +646,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { testBlocking { val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[]" + metaData = emptyList() ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(resourceProvider.getString(R.string.order_refunds_manual_refund)) @@ -665,7 +666,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { testBlocking { val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[]" + metaData = emptyList() ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(resourceProvider.getString(R.string.order_refunds_manual_refund)) @@ -689,7 +690,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { testBlocking { val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[]" + metaData = emptyList() ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(resourceProvider.getString(any())).thenReturn("") @@ -715,7 +716,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(networkStatus.isConnected()).thenReturn(true) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -755,7 +756,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(networkStatus.isConnected()).thenReturn(false) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -784,7 +785,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -839,7 +840,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { val cardLast4 = "1234" val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[{\"key\"=\"_charge_id\", \"value\"=\"$chargeId\"}]" + metaData = listOf(WCMetaData(id = 0, key = "_charge_id", value = chargeId)) ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(paymentChargeRepository.fetchCardDataUsedForOrderPayment(chargeId)).thenReturn( @@ -893,7 +894,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { testBlocking { val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[]" + metaData = emptyList() ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) whenever(resourceProvider.getString(any())).thenReturn("") @@ -915,7 +916,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { testBlocking { val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[]" + metaData = emptyList() ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) @@ -934,7 +935,7 @@ class IssueRefundViewModelTest : BaseUnitTest() { testBlocking { val orderWithMultipleShipping = OrderTestUtils.generateOrderWithMultipleShippingLines().copy( paymentMethod = "cod", - metaData = "[]" + metaData = emptyList() ) whenever(orderStore.getOrderByIdAndSite(any(), any())).thenReturn(orderWithMultipleShipping) From a6c52fd071056d2d66c5dab736a727014c57d9a7 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Sat, 3 Aug 2024 13:18:05 +0100 Subject: [PATCH 17/99] Update usage to align with WCMetaDataValue --- .../android/ui/orders/details/GetOrderSubscriptions.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt index d0492d22044..bd4b0a3b09a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/GetOrderSubscriptions.kt @@ -7,6 +7,7 @@ import com.woocommerce.android.ui.common.subscription.SubscriptionRepository import com.woocommerce.android.util.CoroutineDispatchers import kotlinx.coroutines.withContext import org.wordpress.android.fluxc.model.WCMetaData +import org.wordpress.android.fluxc.model.WCMetaDataValue import org.wordpress.android.fluxc.store.WCOrderStore import javax.inject.Inject @@ -32,7 +33,7 @@ class GetOrderSubscriptions @Inject constructor( val renewal = metadataList.find { metadata -> metadata.key == WCMetaData.SubscriptionMetadataKeys.SUBSCRIPTION_RENEWAL } - return renewal?.value?.takeIf { it.isJsonPrimitive && it.asJsonPrimitive.isNumber }?.asLong + return (renewal?.value as? WCMetaDataValue.NumberValue)?.number?.toLong() } private suspend fun getRenewalSubscription(subscriptionId: Long): Result> { From 025b687a2525bcd57186797146910fe27f4337c9 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Sat, 3 Aug 2024 13:19:47 +0100 Subject: [PATCH 18/99] Simplify logic --- .../com/woocommerce/android/model/OrderMapper.kt | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt index 5bf32a518db..47f35750389 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/model/OrderMapper.kt @@ -7,6 +7,7 @@ import com.woocommerce.android.util.DateUtils import com.woocommerce.android.util.StringUtils import org.wordpress.android.fluxc.model.OrderEntity import org.wordpress.android.fluxc.model.WCMetaData +import org.wordpress.android.fluxc.model.get import org.wordpress.android.fluxc.model.order.FeeLineTaxStatus import org.wordpress.android.fluxc.model.order.OrderAddress import org.wordpress.android.fluxc.model.order.TaxLine @@ -69,17 +70,9 @@ class OrderMapper @Inject constructor( ) } - private fun List.getOrNull(key: String): String? = firstOrNull { - it.key == key - }.let { - it?.value?.toString() - } + private fun List.getOrNull(key: String): String? = get(key)?.valueAsString - private fun List.getOrEmpty(key: String): String = find { - it.key == key - }.let { - it?.value?.toString().orEmpty() - } + private fun List.getOrEmpty(key: String): String = getOrNull(key).orEmpty() private fun List.mapFeesLines(): List = map { Order.FeeLine( From 09b6265bd7110d5091f9539330eb9ce4382da856 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Mon, 5 Aug 2024 09:05:51 +0100 Subject: [PATCH 19/99] Fix detekt issues --- .../ui/orders/details/customfields/CustomOrderFieldsScreen.kt | 4 +++- .../android/ui/products/details/ProductDetailRepository.kt | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt index c8a78cf72a6..528444e96d4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/customfields/CustomOrderFieldsScreen.kt @@ -115,7 +115,9 @@ private fun CustomFieldListItem(metadata: WCMetaData) { ) } SelectionContainer { - if (CustomOrderFieldType.fromMetadataValue(metadata.valueStrippedHtml) == CustomOrderFieldType.TEXT) { + if ( + CustomOrderFieldType.fromMetadataValue(metadata.valueStrippedHtml) == CustomOrderFieldType.TEXT + ) { textValueItem(metadata.valueStrippedHtml) } else { clickableTextValueItem(metadata.valueStrippedHtml) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt index 6c9775d46c1..2787e4ca116 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/details/ProductDetailRepository.kt @@ -1,6 +1,5 @@ package com.woocommerce.android.ui.products.details -import com.google.gson.Gson import com.woocommerce.android.AppConstants import com.woocommerce.android.analytics.AnalyticsEvent.PRODUCT_DETAIL_UPDATE_ERROR import com.woocommerce.android.analytics.AnalyticsEvent.PRODUCT_DETAIL_UPDATE_SUCCESS @@ -57,8 +56,7 @@ class ProductDetailRepository @Inject constructor( private val globalAttributeStore: WCGlobalAttributeStore, private val selectedSite: SelectedSite, private val taxStore: WCTaxStore, - private val coroutineDispatchers: CoroutineDispatchers, - private val gson: Gson + private val coroutineDispatchers: CoroutineDispatchers ) { private var continuationUpdateProduct: Continuation>? = null private var continuationFetchProductPassword = ContinuationWrapper(PRODUCTS) From c688862def272f1aedb02621e9992ddfdafb4ae1 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 15:49:46 +0200 Subject: [PATCH 20/99] Paddings as on the design --- .../WooPosTotalsPaymentSuccessScreen.kt | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index 8736a02005a..8528501c862 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer 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 @@ -39,48 +38,39 @@ fun WooPosPaymentSuccessScreen( ) { Column( modifier = Modifier + .padding(24.dp.toAdaptivePadding()) .fillMaxSize() + .verticalScroll(rememberScrollState()) .background(Color(0xFF98F179)), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { - Column( - modifier = Modifier - .padding(24.dp.toAdaptivePadding()) - .weight(1f) - .fillMaxWidth() - .verticalScroll(rememberScrollState()), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - Icon( - painter = painterResource(id = R.drawable.woo_pos_ic_payment_success), - tint = Color.Unspecified, - contentDescription = null, - ) - Spacer(modifier = Modifier.height(16.dp.toAdaptivePadding())) - Text( - text = stringResource(R.string.woopos_payment_successful_label), - style = MaterialTheme.typography.h4, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - color = MaterialTheme.colors.onSurface - ) + Icon( + painter = painterResource(id = R.drawable.woo_pos_ic_payment_success), + tint = Color.Unspecified, + contentDescription = null, + ) + Spacer(modifier = Modifier.height(56.dp.toAdaptivePadding())) + Text( + text = stringResource(R.string.woopos_payment_successful_label), + style = MaterialTheme.typography.h4, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + color = MaterialTheme.colors.onSurface + ) - Text( - text = stringResource(R.string.woopos_success_screen_total, state.orderTotalText), - style = MaterialTheme.typography.subtitle1, - textAlign = TextAlign.Center, - color = MaterialTheme.colors.onSurface, - modifier = Modifier.padding(24.dp.toAdaptivePadding()) - ) + Spacer(modifier = Modifier.height(16.dp.toAdaptivePadding())) - Spacer(modifier = Modifier.weight(1f)) - } + Text( + text = stringResource(R.string.woopos_success_screen_total, state.orderTotalText), + style = MaterialTheme.typography.subtitle1, + textAlign = TextAlign.Center, + color = MaterialTheme.colors.onSurface, + ) - Spacer(modifier = Modifier.height(24.dp.toAdaptivePadding())) + Spacer(modifier = Modifier.height(80.dp.toAdaptivePadding())) OutlinedButton( modifier = Modifier @@ -106,6 +96,8 @@ fun WooPosPaymentSuccessScreen( textAlign = TextAlign.Center ) } + + Spacer(modifier = Modifier.weight(1f)) } } From fd9ebd7e5c20b493f13cc0524dce52c1758f1d83 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:06:15 +0200 Subject: [PATCH 21/99] CheckMarkIcon --- .../WooPosTotalsPaymentSuccessScreen.kt | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index 8528501c862..dcc51802f5e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -2,6 +2,7 @@ package com.woocommerce.android.ui.woopos.home.totals.payment.success import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -10,15 +11,19 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.ButtonDefaults import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.OutlinedButton import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -47,12 +52,10 @@ fun WooPosPaymentSuccessScreen( ) { Spacer(modifier = Modifier.weight(1f)) - Icon( - painter = painterResource(id = R.drawable.woo_pos_ic_payment_success), - tint = Color.Unspecified, - contentDescription = null, - ) + CheckMarkIcon() + Spacer(modifier = Modifier.height(56.dp.toAdaptivePadding())) + Text( text = stringResource(R.string.woopos_payment_successful_label), style = MaterialTheme.typography.h4, @@ -101,6 +104,26 @@ fun WooPosPaymentSuccessScreen( } } +@Composable +private fun CheckMarkIcon() { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .size(156.dp) + .shadow(8.dp, CircleShape) + .background( + MaterialTheme.colors.background, CircleShape + ) + ) { + Icon( + imageVector = Icons.Default.Check, + tint = WooPosTheme.colors.success, + contentDescription = null, + modifier = Modifier.size(72.dp) + ) + } +} + @WooPosPreview @Composable fun WooPosPaymentSuccessScreenPreview() { From 6b04faaaabb233356e1cba984581a74d94c4a6d8 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:07:06 +0200 Subject: [PATCH 22/99] contentDescription for the icon --- .../totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index dcc51802f5e..3d120e2d0bd 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -118,7 +118,7 @@ private fun CheckMarkIcon() { Icon( imageVector = Icons.Default.Check, tint = WooPosTheme.colors.success, - contentDescription = null, + contentDescription = stringResource(id = R.string.woopos_payment_successful_label), modifier = Modifier.size(72.dp) ) } From da57c62c9e17895d9221ef758e05a59578f33704 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:08:34 +0200 Subject: [PATCH 23/99] paymentSuccessBackground color --- .../android/ui/woopos/common/composeui/WooPosTheme.kt | 3 +++ .../totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt index 3a095053997..276424a7c86 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt @@ -18,6 +18,7 @@ data class CustomColors( val border: Color, val success: Color, val error: Color, + val paymentSuccessBackground: Color, ) private val DarkColorPalette = darkColors( @@ -49,6 +50,7 @@ private val DarkCustomColors = CustomColors( border = Color(0xFF8D8D8D), success = Color(0xFF06B166), error = Color(0xFFBE4400), + paymentSuccessBackground = Color(0xFF74C758), ) private val LightCustomColors = CustomColors( @@ -56,6 +58,7 @@ private val LightCustomColors = CustomColors( border = Color(0xFFC6C6C8), success = Color(0xFF03D479), error = Color(0xFFF16618), + paymentSuccessBackground = Color(0xFF98F179), ) private val LocalCustomColors = staticCompositionLocalOf { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index 3d120e2d0bd..edee4d01980 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -24,7 +24,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -46,7 +45,7 @@ fun WooPosPaymentSuccessScreen( .padding(24.dp.toAdaptivePadding()) .fillMaxSize() .verticalScroll(rememberScrollState()) - .background(Color(0xFF98F179)), + .background(WooPosTheme.colors.paymentSuccessBackground), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { From 4bc9a8692f66d1f86679c031d846d5f94a1ee664 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:21:48 +0200 Subject: [PATCH 24/99] Fixed naming of WooPosHomeProductInfoDialog --- .../{ProductInfoDialog.kt => WooPosHomeProductInfoDialog.kt} | 4 ++-- .../woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/{ProductInfoDialog.kt => WooPosHomeProductInfoDialog.kt} (99%) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/ProductInfoDialog.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeProductInfoDialog.kt similarity index 99% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/ProductInfoDialog.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeProductInfoDialog.kt index 657052fa686..27793f791b6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/ProductInfoDialog.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeProductInfoDialog.kt @@ -47,7 +47,7 @@ import com.woocommerce.android.ui.woopos.common.composeui.WooPosTheme import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding @Composable -fun ProductInfoDialog( +fun WooPosProductInfoDialog( state: WooPosHomeState.ProductsInfoDialog.Visible, onDismissRequest: () -> Unit, ) { @@ -214,7 +214,7 @@ fun ProductInfoDialogPreview() { modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - ProductInfoDialog( + WooPosProductInfoDialog( state = WooPosHomeState.ProductsInfoDialog.Visible( header = R.string.woopos_dialog_products_info_heading, primaryMessage = R.string.woopos_dialog_products_info_primary_message, diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt index 0e8756c33da..b6e20f3441d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt @@ -236,7 +236,7 @@ private fun HandleProductsInfoDialog( BoxOverlay(state = currentState) { // no op } - ProductInfoDialog( + WooPosProductInfoDialog( state = currentState, onDismissRequest = { isDialogVisible = false From 852373bc3d38d2796a63aa1a8f5974a272a54efd Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:23:05 +0200 Subject: [PATCH 25/99] Fixed sizes of the button --- .../success/WooPosTotalsPaymentSuccessScreen.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index edee4d01980..cf665749103 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.ButtonDefaults import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.OutlinedButton @@ -77,22 +76,20 @@ fun WooPosPaymentSuccessScreen( OutlinedButton( modifier = Modifier .padding(24.dp.toAdaptivePadding()) - .height(80.dp.toAdaptivePadding()) - .width(600.dp.toAdaptivePadding()), - colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colors.onSurface - ), + .height(80.dp) + .width(604.dp), onClick = onNewTransactionClicked ) { Icon( - modifier = Modifier.size(20.dp.toAdaptivePadding()), + modifier = Modifier.size(24.dp), painter = painterResource(id = R.drawable.woo_pos_ic_return_home), - contentDescription = null + tint = MaterialTheme.colors.onSurface, + contentDescription = stringResource(id = R.string.woopos_new_order_button) ) - Spacer(modifier = Modifier.width(8.dp.toAdaptivePadding())) + Spacer(modifier = Modifier.width(12.dp.toAdaptivePadding())) Text( text = stringResource(R.string.woopos_new_order_button), - style = MaterialTheme.typography.h6, + style = MaterialTheme.typography.h5, fontWeight = FontWeight.SemiBold, color = MaterialTheme.colors.onSurface, textAlign = TextAlign.Center From 99d14ab43c607f4f3a12bb854c726e59d49037f1 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:26:54 +0200 Subject: [PATCH 26/99] Fixed color text --- .../android/ui/woopos/common/composeui/WooPosTheme.kt | 3 +++ .../totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt index 276424a7c86..4dad524cca5 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt @@ -19,6 +19,7 @@ data class CustomColors( val success: Color, val error: Color, val paymentSuccessBackground: Color, + val paymentSuccessText: Color, ) private val DarkColorPalette = darkColors( @@ -51,6 +52,7 @@ private val DarkCustomColors = CustomColors( success = Color(0xFF06B166), error = Color(0xFFBE4400), paymentSuccessBackground = Color(0xFF74C758), + paymentSuccessText = Color(0xFFF2EBFF), ) private val LightCustomColors = CustomColors( @@ -59,6 +61,7 @@ private val LightCustomColors = CustomColors( success = Color(0xFF03D479), error = Color(0xFFF16618), paymentSuccessBackground = Color(0xFF98F179), + paymentSuccessText = Color(0xFF271B3D), ) private val LocalCustomColors = staticCompositionLocalOf { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index cf665749103..dce01ec043c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -91,7 +91,7 @@ fun WooPosPaymentSuccessScreen( text = stringResource(R.string.woopos_new_order_button), style = MaterialTheme.typography.h5, fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colors.onSurface, + color = WooPosTheme.colors.paymentSuccessText, textAlign = TextAlign.Center ) } From e7f17729417931f71034c9230f2b67cf8142834e Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:32:33 +0200 Subject: [PATCH 27/99] Button as per design --- .../success/WooPosTotalsPaymentSuccessScreen.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index dce01ec043c..79651141824 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -1,5 +1,6 @@ package com.woocommerce.android.ui.woopos.home.totals.payment.success +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -12,7 +13,9 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ButtonDefaults import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.OutlinedButton @@ -23,6 +26,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -66,8 +70,9 @@ fun WooPosPaymentSuccessScreen( Text( text = stringResource(R.string.woopos_success_screen_total, state.orderTotalText), - style = MaterialTheme.typography.subtitle1, + style = MaterialTheme.typography.h6, textAlign = TextAlign.Center, + fontWeight = FontWeight.Normal, color = MaterialTheme.colors.onSurface, ) @@ -75,10 +80,15 @@ fun WooPosPaymentSuccessScreen( OutlinedButton( modifier = Modifier - .padding(24.dp.toAdaptivePadding()) .height(80.dp) .width(604.dp), - onClick = onNewTransactionClicked + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.Transparent, + contentColor = Color.Transparent, + ), + onClick = onNewTransactionClicked, + border = BorderStroke(1.dp, MaterialTheme.colors.onSurface), + shape = RoundedCornerShape(8.dp), ) { Icon( modifier = Modifier.size(24.dp), From 32d51dbb50caca17bcb834ce40c27b3277540dd6 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:35:01 +0200 Subject: [PATCH 28/99] Fixed formatting --- .../payment/success/WooPosTotalsPaymentSuccessScreen.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index 79651141824..2a1a45633a3 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -117,9 +117,7 @@ private fun CheckMarkIcon() { modifier = Modifier .size(156.dp) .shadow(8.dp, CircleShape) - .background( - MaterialTheme.colors.background, CircleShape - ) + .background(MaterialTheme.colors.background, CircleShape) ) { Icon( imageVector = Icons.Default.Check, From f35717937b14f2c07464ddb9b6e732bb94da4bb9 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 5 Aug 2024 16:44:34 +0200 Subject: [PATCH 29/99] Removed redundant padding --- .../totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index 2a1a45633a3..8045cdcf823 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize 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.rememberScrollState @@ -45,7 +44,6 @@ fun WooPosPaymentSuccessScreen( ) { Column( modifier = Modifier - .padding(24.dp.toAdaptivePadding()) .fillMaxSize() .verticalScroll(rememberScrollState()) .background(WooPosTheme.colors.paymentSuccessBackground), From 00866f58a233ed55ac1d9b53570c0055f880455f Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 11:24:58 +0200 Subject: [PATCH 30/99] Add an animation --- .../WooPosTotalsPaymentSuccessScreen.kt | 197 ++++++++++++------ 1 file changed, 137 insertions(+), 60 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index 8045cdcf823..cdd1075a6a6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -1,19 +1,18 @@ package com.woocommerce.android.ui.woopos.home.totals.payment.success +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.spring import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll import androidx.compose.material.ButtonDefaults import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme @@ -22,6 +21,11 @@ import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow @@ -31,89 +35,159 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout import com.woocommerce.android.R import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview import com.woocommerce.android.ui.woopos.common.composeui.WooPosTheme import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding import com.woocommerce.android.ui.woopos.home.totals.WooPosTotalsViewState +import kotlinx.coroutines.delay @Composable fun WooPosPaymentSuccessScreen( state: WooPosTotalsViewState.PaymentSuccess, onNewTransactionClicked: () -> Unit, ) { - Column( + var bottomAnimationStarted by remember { mutableStateOf(false) } + var iconAnimationStarted by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + delay(300) + bottomAnimationStarted = true + delay(300) + iconAnimationStarted = true + } + + WooPosPaymentSuccessScreen( + state = state, + iconAnimationStarted = iconAnimationStarted, + bottomAnimationStarted = bottomAnimationStarted, + onNewTransactionClicked = onNewTransactionClicked, + ) +} + +@Composable +fun WooPosPaymentSuccessScreen( + state: WooPosTotalsViewState.PaymentSuccess, + iconAnimationStarted: Boolean, + bottomAnimationStarted: Boolean, + onNewTransactionClicked: () -> Unit, +) { + Box( modifier = Modifier .fillMaxSize() - .verticalScroll(rememberScrollState()) .background(WooPosTheme.colors.paymentSuccessBackground), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, + contentAlignment = Alignment.Center ) { - Spacer(modifier = Modifier.weight(1f)) - - CheckMarkIcon() - - Spacer(modifier = Modifier.height(56.dp.toAdaptivePadding())) - - Text( - text = stringResource(R.string.woopos_payment_successful_label), - style = MaterialTheme.typography.h4, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - color = MaterialTheme.colors.onSurface - ) - - Spacer(modifier = Modifier.height(16.dp.toAdaptivePadding())) - - Text( - text = stringResource(R.string.woopos_success_screen_total, state.orderTotalText), - style = MaterialTheme.typography.h6, - textAlign = TextAlign.Center, - fontWeight = FontWeight.Normal, - color = MaterialTheme.colors.onSurface, + val marginBetweenButtonAndText by animateDpAsState( + targetValue = if (bottomAnimationStarted) 80.dp else 16.dp, + label = "Check mark size" ) + ConstraintLayout { + val (icon, title, message, button) = createRefs() - Spacer(modifier = Modifier.height(80.dp.toAdaptivePadding())) + val checkMarkIconMargin = 56.dp.toAdaptivePadding() + CheckMarkIcon( + animationStarted = iconAnimationStarted, + modifier = Modifier.constrainAs(icon) { + start.linkTo(parent.start) + end.linkTo(parent.end) + bottom.linkTo(title.top, margin = checkMarkIconMargin) + } + ) - OutlinedButton( - modifier = Modifier - .height(80.dp) - .width(604.dp), - colors = ButtonDefaults.buttonColors( - backgroundColor = Color.Transparent, - contentColor = Color.Transparent, - ), - onClick = onNewTransactionClicked, - border = BorderStroke(1.dp, MaterialTheme.colors.onSurface), - shape = RoundedCornerShape(8.dp), - ) { - Icon( - modifier = Modifier.size(24.dp), - painter = painterResource(id = R.drawable.woo_pos_ic_return_home), - tint = MaterialTheme.colors.onSurface, - contentDescription = stringResource(id = R.string.woopos_new_order_button) + val textsMargin = 16.dp.toAdaptivePadding() + Text( + text = stringResource(R.string.woopos_payment_successful_label), + style = MaterialTheme.typography.h4, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + color = MaterialTheme.colors.onSurface, + modifier = Modifier.constrainAs(title) { + start.linkTo(parent.start) + end.linkTo(parent.end) + bottom.linkTo(message.top, margin = textsMargin) + } ) - Spacer(modifier = Modifier.width(12.dp.toAdaptivePadding())) + + val marginBetweenButtonAndTextAdaptive = marginBetweenButtonAndText.toAdaptivePadding() Text( - text = stringResource(R.string.woopos_new_order_button), - style = MaterialTheme.typography.h5, - fontWeight = FontWeight.SemiBold, - color = WooPosTheme.colors.paymentSuccessText, - textAlign = TextAlign.Center + text = stringResource(R.string.woopos_success_screen_total, state.orderTotalText), + style = MaterialTheme.typography.h6, + textAlign = TextAlign.Center, + fontWeight = FontWeight.Normal, + color = MaterialTheme.colors.onSurface, + modifier = Modifier.constrainAs(message) { + start.linkTo(parent.start) + end.linkTo(parent.end) + bottom.linkTo(button.top, margin = marginBetweenButtonAndTextAdaptive) + } ) - } - Spacer(modifier = Modifier.weight(1f)) + OutlinedButton( + modifier = Modifier + .constrainAs(button) { + bottom.linkTo(parent.bottom) + start.linkTo(parent.start) + end.linkTo(parent.end) + } + .height(80.dp) + .width(604.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.Transparent, + contentColor = Color.Transparent, + ), + onClick = onNewTransactionClicked, + border = BorderStroke(1.dp, MaterialTheme.colors.onSurface), + shape = RoundedCornerShape(8.dp), + ) { + Icon( + modifier = Modifier.size(24.dp), + painter = painterResource(id = R.drawable.woo_pos_ic_return_home), + tint = MaterialTheme.colors.onSurface, + contentDescription = stringResource(id = R.string.woopos_new_order_button) + ) + Spacer(modifier = Modifier.width(12.dp.toAdaptivePadding())) + Text( + text = stringResource(R.string.woopos_new_order_button), + style = MaterialTheme.typography.h5, + fontWeight = FontWeight.SemiBold, + color = WooPosTheme.colors.paymentSuccessText, + textAlign = TextAlign.Center + ) + } + } } } @Composable -private fun CheckMarkIcon() { +private fun CheckMarkIcon( + animationStarted: Boolean, + modifier: Modifier = Modifier, +) { + val size by animateDpAsState( + targetValue = if (animationStarted) 156.dp else 0.dp, + label = "Check mark size" + ) + + var iconAnimationStarted by remember { mutableStateOf(false) } + val iconSize by animateDpAsState( + targetValue = if (iconAnimationStarted) 72.dp else 0.dp, + animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy), + label = "Icon Size" + ) + + LaunchedEffect(animationStarted) { + if (animationStarted) { + delay(300) + iconAnimationStarted = true + } + } + Box( contentAlignment = Alignment.Center, - modifier = Modifier - .size(156.dp) + modifier = modifier + .size(size) .shadow(8.dp, CircleShape) .background(MaterialTheme.colors.background, CircleShape) ) { @@ -121,7 +195,8 @@ private fun CheckMarkIcon() { imageVector = Icons.Default.Check, tint = WooPosTheme.colors.success, contentDescription = stringResource(id = R.string.woopos_payment_successful_label), - modifier = Modifier.size(72.dp) + modifier = Modifier + .size(iconSize) ) } } @@ -136,6 +211,8 @@ fun WooPosPaymentSuccessScreenPreview() { orderTotalText = "$13.18", orderTaxText = "$1.20" ), + bottomAnimationStarted = true, + iconAnimationStarted = true, onNewTransactionClicked = {} ) } From 535e122703e1fd7d0317e8066f6c71d4547d763f Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 11:26:33 +0200 Subject: [PATCH 31/99] Supressed detekt complain about Destructuring --- .../totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index cdd1075a6a6..e2aeb5e679f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -83,6 +83,7 @@ fun WooPosPaymentSuccessScreen( targetValue = if (bottomAnimationStarted) 80.dp else 16.dp, label = "Check mark size" ) + @Suppress("DestructuringDeclarationWithTooManyEntries") ConstraintLayout { val (icon, title, message, button) = createRefs() From 517a8860353a77057bc88bc78b1fdce010a94559 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 11:36:31 +0200 Subject: [PATCH 32/99] Fixed typo in Retry --- WooCommerce/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index f4d3c4b9092..16ba52d1172 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -4237,7 +4237,7 @@ Error loading products Give it another go? Error indication icon - Rerty + Retry Couldn\'t create order A payment of %1$s was successfully made From 825d35298cb8a44d05f4880bf31b5d76ace6a041 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 12:01:22 +0200 Subject: [PATCH 33/99] Fix Rerty typo --- WooCommerce/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index f4d3c4b9092..16ba52d1172 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -4237,7 +4237,7 @@ Error loading products Give it another go? Error indication icon - Rerty + Retry Couldn\'t create order A payment of %1$s was successfully made From 70a7915c7511b5ef7f2af7ab486df875f7fcf932 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 12:15:36 +0200 Subject: [PATCH 34/99] Use in memory cache --- .../home/products/WooPosProductsDataSource.kt | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt index 82f8a49e9ef..b29b9790024 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt @@ -1,7 +1,6 @@ package com.woocommerce.android.ui.woopos.home.products import com.woocommerce.android.model.Product -import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.products.ProductType import com.woocommerce.android.ui.products.selector.ProductListHandler import com.woocommerce.android.util.WooLog @@ -17,37 +16,31 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class WooPosProductsDataSource @Inject constructor( - private val handler: ProductListHandler, - private val productStore: WCProductStore, - private val site: SelectedSite, -) { +class WooPosProductsDataSource @Inject constructor(private val handler: ProductListHandler) { + private val productCache = mutableListOf() + val hasMorePages: Boolean get() = handler.canLoadMore.get() fun loadSimpleProducts(forceRefreshProducts: Boolean): Flow = flow { if (forceRefreshProducts) { - productStore.deleteProductsForSite(site.get()) + productCache.clear() } + emit(ProductsResult.Cached(productCache)) + val result = handler.loadFromCacheAndFetch( searchType = ProductListHandler.SearchType.DEFAULT, filters = mapOf(WCProductStore.ProductFilterOption.TYPE to ProductType.SIMPLE.value) ) - emit( - ProductsResult.Cached( - handler.productsFlow.first().filter { product -> product.price != null } - ) - ) - if (result.isSuccess) { val remoteProducts = handler.productsFlow.first().filter { it.price != null } + productCache.clear() + productCache.addAll(remoteProducts) emit(ProductsResult.Remote(Result.success(remoteProducts))) } else { - val error = result.exceptionOrNull() - val errorMessage = error?.message ?: "Unknown error" - WooLog.e(WooLog.T.POS, "Loading simple products failed - $errorMessage", error) + result.logFailure() emit(ProductsResult.Remote(Result.failure(result.exceptionOrNull()!!))) } }.flowOn(Dispatchers.IO).take(2) @@ -55,15 +48,21 @@ class WooPosProductsDataSource @Inject constructor( suspend fun loadMore(): Result> = withContext(Dispatchers.IO) { val result = handler.loadMore() if (result.isSuccess) { - Result.success(handler.productsFlow.first().filter { it.price != null }) + val moreProducts = handler.productsFlow.first().filter { it.price != null } + productCache.addAll(moreProducts) + Result.success(moreProducts) } else { - val error = result.exceptionOrNull() - val errorMessage = error?.message ?: "Unknown error" - WooLog.e(WooLog.T.POS, "Loading more products failed - $errorMessage", error) - Result.failure(error!!) + result.logFailure() + Result.failure(result.exceptionOrNull()!!) } } + private fun Result.logFailure() { + val error = exceptionOrNull() + val errorMessage = error?.message ?: "Unknown error" + WooLog.e(WooLog.T.POS, "Loading products failed - $errorMessage", error) + } + sealed class ProductsResult { data class Cached(val products: List) : ProductsResult() data class Remote(val productsResult: Result>) : ProductsResult() From 237b1072fc2e1c07197dc14da090fd5fa7789573 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 12:30:29 +0200 Subject: [PATCH 35/99] Removed redundant logging --- .../ui/woopos/home/products/WooPosProductsViewModel.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsViewModel.kt index bfd0356f52e..3dc995a2db9 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsViewModel.kt @@ -8,7 +8,6 @@ import com.woocommerce.android.ui.woopos.home.ChildToParentEvent import com.woocommerce.android.ui.woopos.home.WooPosChildrenToParentEventSender import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository import com.woocommerce.android.ui.woopos.util.format.WooPosFormatPrice -import com.woocommerce.android.util.WooLog import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow @@ -134,12 +133,7 @@ class WooPosProductsViewModel @Inject constructor( } } - else -> { - val error = result.productsResult.exceptionOrNull() - val errorMessage = error?.message ?: "Unknown error" - WooLog.e(WooLog.T.POS, "Loading simple products failed - $errorMessage", error) - WooPosProductsViewState.Error() - } + else -> WooPosProductsViewState.Error() } } } From a08fdcb952d649005c32443a86d80a6b76be9079 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 12:53:10 +0200 Subject: [PATCH 36/99] Fixed tests --- .../products/WooPosProductsDataSourceTest.kt | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt index 4852346a1f8..21cb00f7772 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt @@ -1,7 +1,6 @@ package com.woocommerce.android.ui.woopos.home.products import com.woocommerce.android.model.Product -import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.products.selector.ProductListHandler import com.woocommerce.android.ui.woopos.util.WooPosCoroutineTestRule import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -12,12 +11,8 @@ import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat import org.junit.Rule import org.mockito.kotlin.any -import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.mock -import org.mockito.kotlin.verify import org.mockito.kotlin.whenever -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.fluxc.store.WCProductStore import java.math.BigDecimal import java.util.concurrent.atomic.AtomicBoolean import kotlin.test.Test @@ -35,34 +30,36 @@ class WooPosProductsDataSourceTest { ) private val handler: ProductListHandler = mock() - private val productStore: WCProductStore = mock() - private val site: SelectedSite = mock { - on { getOrNull() }.thenReturn(SiteModel()) - } @Test - fun `given force refresh, when loadSimpleProducts called, then should wipe products table`() = runTest { + fun `given force refresh, when loadSimpleProducts called, then should clear cache`() = runTest { // GIVEN whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) - whenever(site.getOrNull()).thenReturn(SiteModel()) whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) - val sut = WooPosProductsDataSource(handler, productStore, site) + val sut = WooPosProductsDataSource(handler) + + // Pre-populate the cache + sut.loadSimpleProducts(forceRefreshProducts = false).first() + assertThat(sut.loadSimpleProducts(forceRefreshProducts = false).first()).isInstanceOf(WooPosProductsDataSource.ProductsResult.Cached::class.java) // WHEN sut.loadSimpleProducts(forceRefreshProducts = true).first() // THEN - verify(productStore).deleteProductsForSite(anyOrNull()) + // Ensure the cache is cleared (by checking that the cache was reloaded) + val result = sut.loadSimpleProducts(forceRefreshProducts = false).first() + assertThat(result).isInstanceOf(WooPosProductsDataSource.ProductsResult.Cached::class.java) + val cachedResult = result as WooPosProductsDataSource.ProductsResult.Cached + assertThat(cachedResult.products).containsExactlyElementsOf(sampleProducts) } @Test fun `given cached products, when loadSimpleProducts called, then should emit cached products first`() = runTest { // GIVEN whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) - whenever(site.getOrNull()).thenReturn(SiteModel()) whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) - val sut = WooPosProductsDataSource(handler, productStore, site) + val sut = WooPosProductsDataSource(handler) // WHEN val result = sut.loadSimpleProducts(forceRefreshProducts = false).first() @@ -74,34 +71,39 @@ class WooPosProductsDataSourceTest { } @Test - fun `given cached and remote products, when loadSimpleProducts called, then should emit remote products after cached products`() = - runTest { - // GIVEN - whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) - whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) - whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) - val sut = WooPosProductsDataSource(handler, productStore, site) - - // WHEN - val flow = sut.loadSimpleProducts(forceRefreshProducts = false).toList() - - // THEN - val cachedResult = flow[0] as WooPosProductsDataSource.ProductsResult.Cached - val remoteResult = flow[1] as WooPosProductsDataSource.ProductsResult.Remote - - assertThat(cachedResult.products).containsExactlyElementsOf(sampleProducts) - assertThat(remoteResult.productsResult.isSuccess).isTrue() - assertThat(remoteResult.productsResult.getOrNull()).containsExactlyElementsOf(sampleProducts) - } + fun `given cached and remote products, when loadSimpleProducts called, then should emit remote products after cached products`() = runTest { + // GIVEN + whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) + whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) + whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) + val sut = WooPosProductsDataSource(handler) + + // WHEN + val flow = sut.loadSimpleProducts(forceRefreshProducts = false).toList() + + // THEN + val cachedResult = flow[0] as WooPosProductsDataSource.ProductsResult.Cached + val remoteResult = flow[1] as WooPosProductsDataSource.ProductsResult.Remote + + assertThat(cachedResult.products).containsExactlyElementsOf(sampleProducts) + assertThat(remoteResult.productsResult.isSuccess).isTrue() + assertThat(remoteResult.productsResult.getOrNull()).containsExactlyElementsOf(sampleProducts) + } @Test - fun `given remote load fails, when loadSimpleProducts called, then should emit error`() = runTest { + fun `given remote load fails, when loadSimpleProducts called, then should emit cached products and then error`() = runTest { // GIVEN whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) val exception = Exception("Remote load failed") + whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) + + val sut = WooPosProductsDataSource(handler) + + // Prepopulate the cache by calling loadSimpleProducts once + sut.loadSimpleProducts(forceRefreshProducts = false).first() + whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.failure(exception)) - val sut = WooPosProductsDataSource(handler, productStore, site) // WHEN val flow = sut.loadSimpleProducts(forceRefreshProducts = false).toList() From 40c10a5ffa63dbfcbb82ee1f1153073578e13611 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 12:54:09 +0200 Subject: [PATCH 37/99] Tests on loadMore functionality --- .../products/WooPosProductsDataSourceTest.kt | 135 +++++++++++++----- 1 file changed, 98 insertions(+), 37 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt index 21cb00f7772..76a9627d1f3 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSourceTest.kt @@ -29,6 +29,11 @@ class WooPosProductsDataSourceTest { mock { on { price }.thenReturn(BigDecimal(3)) }, ) + private val additionalProducts = listOf( + mock { on { price }.thenReturn(BigDecimal(4)) }, + mock { on { price }.thenReturn(BigDecimal(5)) } + ) + private val handler: ProductListHandler = mock() @Test @@ -40,7 +45,9 @@ class WooPosProductsDataSourceTest { // Pre-populate the cache sut.loadSimpleProducts(forceRefreshProducts = false).first() - assertThat(sut.loadSimpleProducts(forceRefreshProducts = false).first()).isInstanceOf(WooPosProductsDataSource.ProductsResult.Cached::class.java) + assertThat( + sut.loadSimpleProducts(forceRefreshProducts = false).first() + ).isInstanceOf(WooPosProductsDataSource.ProductsResult.Cached::class.java) // WHEN sut.loadSimpleProducts(forceRefreshProducts = true).first() @@ -71,49 +78,103 @@ class WooPosProductsDataSourceTest { } @Test - fun `given cached and remote products, when loadSimpleProducts called, then should emit remote products after cached products`() = runTest { - // GIVEN - whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) - whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) - whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) - val sut = WooPosProductsDataSource(handler) + fun `given cached and remote products, when loadSimpleProducts called, then should emit remote products after cached products`() = + runTest { + // GIVEN + whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) + whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) + whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) + val sut = WooPosProductsDataSource(handler) + + // WHEN + val flow = sut.loadSimpleProducts(forceRefreshProducts = false).toList() + + // THEN + val cachedResult = flow[0] as WooPosProductsDataSource.ProductsResult.Cached + val remoteResult = flow[1] as WooPosProductsDataSource.ProductsResult.Remote + + assertThat(cachedResult.products).containsExactlyElementsOf(sampleProducts) + assertThat(remoteResult.productsResult.isSuccess).isTrue() + assertThat(remoteResult.productsResult.getOrNull()).containsExactlyElementsOf(sampleProducts) + } - // WHEN - val flow = sut.loadSimpleProducts(forceRefreshProducts = false).toList() - - // THEN - val cachedResult = flow[0] as WooPosProductsDataSource.ProductsResult.Cached - val remoteResult = flow[1] as WooPosProductsDataSource.ProductsResult.Remote + @Test + fun `given remote load fails, when loadSimpleProducts called, then should emit cached products and then error`() = + runTest { + // GIVEN + whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) + whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) + val exception = Exception("Remote load failed") + whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) - assertThat(cachedResult.products).containsExactlyElementsOf(sampleProducts) - assertThat(remoteResult.productsResult.isSuccess).isTrue() - assertThat(remoteResult.productsResult.getOrNull()).containsExactlyElementsOf(sampleProducts) - } + val sut = WooPosProductsDataSource(handler) - @Test - fun `given remote load fails, when loadSimpleProducts called, then should emit cached products and then error`() = runTest { - // GIVEN - whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) - whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) - val exception = Exception("Remote load failed") - whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.success(Unit)) + // Prepopulate the cache by calling loadSimpleProducts once + sut.loadSimpleProducts(forceRefreshProducts = false).first() - val sut = WooPosProductsDataSource(handler) + whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.failure(exception)) - // Prepopulate the cache by calling loadSimpleProducts once - sut.loadSimpleProducts(forceRefreshProducts = false).first() + // WHEN + val flow = sut.loadSimpleProducts(forceRefreshProducts = false).toList() - whenever(handler.loadFromCacheAndFetch(any(), any(), any())).thenReturn(Result.failure(exception)) + // THEN + val cachedResult = flow[0] as WooPosProductsDataSource.ProductsResult.Cached + val remoteResult = flow[1] as WooPosProductsDataSource.ProductsResult.Remote - // WHEN - val flow = sut.loadSimpleProducts(forceRefreshProducts = false).toList() + assertThat(cachedResult.products).containsExactlyElementsOf(sampleProducts) + assertThat(remoteResult.productsResult.isFailure).isTrue() + assertThat(remoteResult.productsResult.exceptionOrNull()).isEqualTo(exception) + } - // THEN - val cachedResult = flow[0] as WooPosProductsDataSource.ProductsResult.Cached - val remoteResult = flow[1] as WooPosProductsDataSource.ProductsResult.Remote + @Test + fun `given successful loadMore, when loadMore called, then should add products to cache and return them`() = + runTest { + // GIVEN + whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) + whenever(handler.productsFlow).thenReturn( + flowOf(sampleProducts), + flowOf(sampleProducts + additionalProducts) + ) + whenever(handler.loadMore()).thenReturn(Result.success(Unit)) + val sut = WooPosProductsDataSource(handler) + + sut.loadSimpleProducts(forceRefreshProducts = false).first() + + // WHEN + val result = sut.loadMore() + + // THEN + assertThat(result.isSuccess).isTrue() + assertThat(result.getOrNull()).containsExactlyElementsOf(sampleProducts + additionalProducts) + + val cachedResult = sut.loadSimpleProducts(forceRefreshProducts = false).first() + assertThat(cachedResult).isInstanceOf(WooPosProductsDataSource.ProductsResult.Cached::class.java) + val cachedProducts = (cachedResult as WooPosProductsDataSource.ProductsResult.Cached).products + assertThat(cachedProducts).containsExactlyElementsOf(sampleProducts + additionalProducts) + } - assertThat(cachedResult.products).containsExactlyElementsOf(sampleProducts) - assertThat(remoteResult.productsResult.isFailure).isTrue() - assertThat(remoteResult.productsResult.exceptionOrNull()).isEqualTo(exception) - } + @Test + fun `given failed loadMore, when loadMore called, then should return error and cache remains unchanged`() = + runTest { + // GIVEN + whenever(handler.canLoadMore).thenReturn(AtomicBoolean(true)) + whenever(handler.productsFlow).thenReturn(flowOf(sampleProducts)) + val exception = Exception("Load more failed") + whenever(handler.loadMore()).thenReturn(Result.failure(exception)) + val sut = WooPosProductsDataSource(handler) + + sut.loadSimpleProducts(forceRefreshProducts = false).first() + + // WHEN + val result = sut.loadMore() + + // THEN + assertThat(result.isFailure).isTrue() + assertThat(result.exceptionOrNull()).isEqualTo(exception) + + val cachedResult = sut.loadSimpleProducts(forceRefreshProducts = false).first() + assertThat(cachedResult).isInstanceOf(WooPosProductsDataSource.ProductsResult.Cached::class.java) + val cachedProducts = (cachedResult as WooPosProductsDataSource.ProductsResult.Cached).products + assertThat(cachedProducts).containsExactlyElementsOf(sampleProducts) + } } From 866294c052bbc287cc31a33929700871213ec1b7 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Tue, 6 Aug 2024 13:23:05 +0200 Subject: [PATCH 38/99] Adjust Spacer's height --- .../android/ui/woopos/home/products/WooPosProductsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt index 3be25c9fe26..cd635efd947 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt @@ -266,7 +266,7 @@ private fun ProductsList( } } item { - Spacer(modifier = Modifier.height(112.dp)) + Spacer(modifier = Modifier.height(104.dp)) } } InfiniteListHandler(listState) { From 75872e6a24c6d23936f2b300cd28c65890516067 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 6 Aug 2024 13:28:20 +0200 Subject: [PATCH 39/99] Fixed potential NPE --- .../woopos/home/products/WooPosProductsDataSource.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt index b29b9790024..d8708222a49 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsDataSource.kt @@ -41,7 +41,13 @@ class WooPosProductsDataSource @Inject constructor(private val handler: ProductL emit(ProductsResult.Remote(Result.success(remoteProducts))) } else { result.logFailure() - emit(ProductsResult.Remote(Result.failure(result.exceptionOrNull()!!))) + emit( + ProductsResult.Remote( + Result.failure( + result.exceptionOrNull() ?: Exception("Unknown error") + ) + ) + ) } }.flowOn(Dispatchers.IO).take(2) @@ -53,7 +59,7 @@ class WooPosProductsDataSource @Inject constructor(private val handler: ProductL Result.success(moreProducts) } else { result.logFailure() - Result.failure(result.exceptionOrNull()!!) + Result.failure(result.exceptionOrNull() ?: Exception("Unknown error")) } } From e55d068c6d82434cdb89c35063de235ee2089aa9 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 17:22:15 +0200 Subject: [PATCH 40/99] Update android-core from 1.12.0 to 1.13.1 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 69fb80ece10..8bbfbd37a7d 100644 --- a/build.gradle +++ b/build.gradle @@ -75,7 +75,7 @@ def detektAutoCorrectPrompt = tasks.register("detektAutoCorrectPrompt") { } } -detektAll.configure{ +detektAll.configure { finalizedBy detektAutoCorrectPrompt } @@ -112,7 +112,7 @@ ext { aztecVersion = 'v1.3.45' flipperVersion = '0.176.1' stateMachineVersion = '0.2.0' - coreKtxVersion = '1.12.0' + coreKtxVersion = '1.13.1' appCompatVersion = '1.4.2' materialVersion = '1.10.0' hiltJetpackVersion = '1.1.0' From 91baad31799d5c6a3175c1cf0df1bf7daeeacd7f Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 17:58:36 +0200 Subject: [PATCH 41/99] Remove obsolete and deprecated usages of ViewCompat --- .../android/widgets/AlignedDividerDecoration.kt | 3 +-- .../com/woocommerce/android/widgets/FlowLayout.kt | 13 ++++++------- .../android/widgets/WCSelectableTextView.kt | 3 +-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/AlignedDividerDecoration.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/AlignedDividerDecoration.kt index 7d34e63804f..167345c41bc 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/AlignedDividerDecoration.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/AlignedDividerDecoration.kt @@ -6,7 +6,6 @@ import android.graphics.Rect import android.graphics.drawable.Drawable import android.view.View import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.view.ViewCompat import androidx.recyclerview.widget.RecyclerView /** @@ -95,7 +94,7 @@ class AlignedDividerDecoration @JvmOverloads constructor( private fun drawForVertical(canvas: Canvas, parent: RecyclerView) { val adjustedChildCount = parent.childCount - 2 - val isRtl = ViewCompat.getLayoutDirection(parent) == ViewCompat.LAYOUT_DIRECTION_RTL + val isRtl = parent.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL (0..adjustedChildCount) .map { parent.getChildAt(it) } .forEach { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/FlowLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/FlowLayout.kt index e6f604c96ee..fda539bd6fc 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/FlowLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/FlowLayout.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.content.Context import android.util.AttributeSet import android.view.ViewGroup -import androidx.core.view.ViewCompat import com.woocommerce.android.R /** @@ -36,13 +35,13 @@ open class FlowLayout @JvmOverloads constructor( } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - val widthSize = MeasureSpec.getSize(widthMeasureSpec) - ViewCompat.getPaddingEnd(this) - - ViewCompat.getPaddingStart(this) + val widthSize = MeasureSpec.getSize(widthMeasureSpec) - this.getPaddingEnd() - + this.getPaddingStart() val widthMode = MeasureSpec.getMode(widthMeasureSpec) val growHeight = widthMode != MeasureSpec.UNSPECIFIED var width = 0 var height = paddingTop - var currentWidth = ViewCompat.getPaddingStart(this) + var currentWidth = this.getPaddingStart() var currentHeight = 0 var newLine = false var spacing = 0 @@ -62,7 +61,7 @@ open class FlowLayout @JvmOverloads constructor( height += currentHeight + mVerticalSpacing currentHeight = 0 width = Math.max(width, currentWidth - spacing) - currentWidth = ViewCompat.getPaddingStart(this) + currentWidth = this.getPaddingStart() newLine = true } else { newLine = false @@ -77,7 +76,7 @@ open class FlowLayout @JvmOverloads constructor( if (!newLine) { width = Math.max(width, currentWidth - spacing) } - width += ViewCompat.getPaddingEnd(this) + width += this.getPaddingEnd() height += currentHeight + paddingBottom setMeasuredDimension(resolveSize(width, widthMeasureSpec), resolveSize(height, heightMeasureSpec)) } @@ -106,7 +105,7 @@ open class FlowLayout @JvmOverloads constructor( override fun generateLayoutParams(p: ViewGroup.LayoutParams): LayoutParams { return LayoutParams(p.width, p.height) } - class LayoutParams : ViewGroup.MarginLayoutParams { + class LayoutParams : MarginLayoutParams { internal var x: Int = 0 internal var y: Int = 0 var horizontalSpacing: Int = -1 diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/WCSelectableTextView.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/WCSelectableTextView.kt index d88dcea371e..c73c85a0d5c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/WCSelectableTextView.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/widgets/WCSelectableTextView.kt @@ -7,7 +7,6 @@ import android.view.Menu import android.view.MenuItem import android.view.MotionEvent import android.view.View -import androidx.core.view.GestureDetectorCompat import com.google.android.material.textview.MaterialTextView import com.woocommerce.android.R import com.woocommerce.android.extensions.selectAllText @@ -24,7 +23,7 @@ class WCSelectableTextView @JvmOverloads constructor( ) : MaterialTextView(context, attrs, defStyleAttr), android.view.ActionMode.Callback, GestureDetector.OnDoubleTapListener { - private val detector = GestureDetectorCompat(context, GestureDetector.SimpleOnGestureListener()) + private val detector = GestureDetector(context, GestureDetector.SimpleOnGestureListener()) // when text is selectable, TextView intercepts the click event even if there's no OnClickListener, // requiring this workaround to pass the click to a parent view From f8c9904d4334a47ef3915e1ff5d99f926ff78632 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 18:04:32 +0200 Subject: [PATCH 42/99] Update release notes --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 8db33e31ccf..d367b2ae48f 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -4,6 +4,7 @@ 19.9 ----- - [*] [Internal] Update Android material from 1.9.0 to 1.10.0 [https://github.com/woocommerce/woocommerce-android/pull/12186] +- [*] [Internal] Update Android-core from 1.12.0 to 1.13.1 [https://github.com/woocommerce/woocommerce-android/pull/12229] 19.8 ----- From 38e25e742faa89519039fe8ba8cd5bf27f66d41e Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 18:15:41 +0200 Subject: [PATCH 43/99] Update android-lifecycle from 2.6.2 to 2.7.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8bbfbd37a7d..e3385fb35db 100644 --- a/build.gradle +++ b/build.gradle @@ -108,7 +108,7 @@ ext { googlePlayCoreVersion = '1.10.3' googlePlayWearableVersion = '18.1.0' coroutinesVersion = '1.8.1' - lifecycleVersion = '2.6.2' + lifecycleVersion = '2.7.0' aztecVersion = 'v1.3.45' flipperVersion = '0.176.1' stateMachineVersion = '0.2.0' From 325953f4be723e40794f4b4b241be269e079430a Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 18:23:56 +0200 Subject: [PATCH 44/99] Update release notes --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index d367b2ae48f..c78a892270a 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -5,6 +5,7 @@ ----- - [*] [Internal] Update Android material from 1.9.0 to 1.10.0 [https://github.com/woocommerce/woocommerce-android/pull/12186] - [*] [Internal] Update Android-core from 1.12.0 to 1.13.1 [https://github.com/woocommerce/woocommerce-android/pull/12229] +- [*] [Internal] Update Android-lifecycle from 2.6.2 to 2.7.0 [https://github.com/woocommerce/woocommerce-android/pull/12230] 19.8 ----- From 1406f7f6bc42520366a5991ae8b78fa5a61b6cc4 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 18:50:42 +0200 Subject: [PATCH 45/99] Update androidx-fragment from 1.6.2 to 1.8.2 --- WooCommerce/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/build.gradle b/WooCommerce/build.gradle index b022c27933f..e44b5628a90 100644 --- a/WooCommerce/build.gradle +++ b/WooCommerce/build.gradle @@ -400,7 +400,7 @@ dependencies { } // ViewModel and LiveData - implementation "androidx.fragment:fragment-ktx:1.6.1" + implementation "androidx.fragment:fragment-ktx:1.8.2" implementation "androidx.activity:activity-ktx:1.8.0" implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycleVersion" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion" From 931181a655ffdc086a5bef17a7903878c4941dda Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 6 Aug 2024 18:55:42 +0200 Subject: [PATCH 46/99] Update release notes --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index c78a892270a..44fcbc0eea4 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -6,6 +6,7 @@ - [*] [Internal] Update Android material from 1.9.0 to 1.10.0 [https://github.com/woocommerce/woocommerce-android/pull/12186] - [*] [Internal] Update Android-core from 1.12.0 to 1.13.1 [https://github.com/woocommerce/woocommerce-android/pull/12229] - [*] [Internal] Update Android-lifecycle from 2.6.2 to 2.7.0 [https://github.com/woocommerce/woocommerce-android/pull/12230] +- [*] [Internal] Update Androidx-fragment from 1.6.2 to 1.8.2 [https://github.com/woocommerce/woocommerce-android/pull/12231] 19.8 ----- From 81d9beaf4c6b740e025d6c453c52a5b3efa8f9cb Mon Sep 17 00:00:00 2001 From: samiuelson Date: Tue, 6 Aug 2024 19:19:27 +0200 Subject: [PATCH 47/99] Return to POS right after payment success --- .../payment/CardReaderPaymentViewModel.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt index b0ca3b3662b..2df6fc8f136 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt @@ -464,9 +464,17 @@ class CardReaderPaymentViewModel ) { paymentReceiptHelper.storeReceiptUrl(orderId, paymentStatus.receiptUrl) appPrefs.setCardReaderSuccessfulPaymentTime() - triggerEvent(PlayChaChing) - showPaymentSuccessfulState() - reFetchOrder() + val flowParam: CardReaderFlowParam.PaymentOrRefund = arguments.paymentOrRefund + if (flowParam is CardReaderFlowParam.PaymentOrRefund.Payment && + flowParam.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS + ) { + reFetchOrder() + onCancelPaymentFlow() + } else { + triggerEvent(PlayChaChing) + showPaymentSuccessfulState() + reFetchOrder() + } } @VisibleForTesting From 11b4dc37fbadc04518263347137f04881655422a Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 7 Aug 2024 00:24:53 +0300 Subject: [PATCH 48/99] Add subtotal and taxes lines to refund product list item --- .../res/layout/refunds_product_list_item.xml | 63 +++++++++++++++---- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/WooCommerce/src/main/res/layout/refunds_product_list_item.xml b/WooCommerce/src/main/res/layout/refunds_product_list_item.xml index 02d3c534125..eb856bff857 100644 --- a/WooCommerce/src/main/res/layout/refunds_product_list_item.xml +++ b/WooCommerce/src/main/res/layout/refunds_product_list_item.xml @@ -4,7 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:paddingBottom="@dimen/major_75"> + app:layout_constraintBottom_toBottomOf="@id/refundItem_description" + app:layout_constraintTop_toTopOf="@id/refundItem_productName"> @@ -46,11 +46,9 @@ style="@style/Woo.ListItem.Body" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/major_75" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@+id/refundItem_quantity" - app:layout_constraintStart_toEndOf="@+id/refundItem_iconFrame" - app:layout_constraintTop_toBottomOf="@+id/refundItem_productName" + app:layout_constraintEnd_toStartOf="@id/refundItem_quantity" + app:layout_constraintStart_toEndOf="@id/refundItem_iconFrame" + app:layout_constraintTop_toBottomOf="@id/refundItem_productName" tools:text="2 x $15.00 each" /> + + + + + + + From 8a1392e06cff7aa73e35ccdbfb7ddbd6307bff4a Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 7 Aug 2024 00:41:37 +0300 Subject: [PATCH 49/99] Hide common subtotal and taxes lines for products from refund screen --- .../payments/refunds/RefundByItemsFragment.kt | 8 ++---- .../res/layout/refund_by_items_products.xml | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundByItemsFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundByItemsFragment.kt index 72d62a64a63..9aeecc037a1 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundByItemsFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundByItemsFragment.kt @@ -151,12 +151,6 @@ class RefundByItemsFragment : new.feesTaxes?.takeIfNotEqualTo(old?.feesTaxes) { feeLinesBinding.issueRefundFeesTax.text = it } - new.taxes?.takeIfNotEqualTo(old?.taxes) { - productsBinding.issueRefundTaxesTotal.text = it - } - new.subtotal?.takeIfNotEqualTo(old?.subtotal) { - productsBinding.issueRefundSubtotal.text = it - } new.selectedItemsHeader?.takeIfNotEqualTo(old?.selectedItemsHeader) { binding.issueRefundSelectedItems.text = it } @@ -202,8 +196,10 @@ class RefundByItemsFragment : new.isRefundNoticeVisible.takeIfNotEqualTo(old?.isRefundNoticeVisible) { isVisible -> if (isVisible) { productsBinding.issueRefundRefundNotice.show() + productsBinding.issueRefundDividerBelowList.show() } else { productsBinding.issueRefundRefundNotice.hide() + productsBinding.issueRefundDividerBelowList.hide() } } new.refundNotice.takeIfNotEqualTo(old?.refundNotice) { notice -> diff --git a/WooCommerce/src/main/res/layout/refund_by_items_products.xml b/WooCommerce/src/main/res/layout/refund_by_items_products.xml index 13cc361410c..0c69fbe9f7a 100644 --- a/WooCommerce/src/main/res/layout/refund_by_items_products.xml +++ b/WooCommerce/src/main/res/layout/refund_by_items_products.xml @@ -24,7 +24,7 @@ android:layout_marginEnd="@dimen/minor_00" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/issueRefund_products" - app:layout_constraintBottom_toTopOf="@+id/issueRefund_lblSubtotal"/> + app:layout_constraintBottom_toTopOf="@id/issueRefund_lblSubtotal"/> @@ -72,15 +72,12 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/major_100" - android:layout_marginStart="@dimen/minor_00" - android:layout_marginEnd="@dimen/minor_00" android:drawableStart="@drawable/ic_deprecated_info_outline_24dp" android:drawablePadding="@dimen/major_100" - tools:text="@string/order_refunds_shipping_refund_variable_notice" - android:visibility="visible" - app:layout_constraintEnd_toEndOf="@+id/issueRefund_taxesTotal" - app:layout_constraintStart_toStartOf="@+id/issueRefund_lblTaxes" - app:layout_constraintTop_toBottomOf="@id/issueRefund_taxesTotal" /> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/issueRefund_taxesTotal" + tools:text="@string/order_refunds_shipping_refund_variable_notice" /> @@ -102,7 +99,7 @@ android:layout_marginBottom="@dimen/major_75" android:text="@string/order_refunds_products_refund" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@+id/issueRefund_productsTotal" + app:layout_constraintEnd_toStartOf="@id/issueRefund_productsTotal" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/issueRefund_dividerBelowTaxes" /> @@ -124,4 +121,10 @@ android:layout_height="wrap_content" app:constraint_referenced_ids="issueRefund_refundNotice,issueRefund_dividerBelowList,issueRefund_dividerBelowTaxes,issueRefund_taxesTotal,issueRefund_subtotal,issueRefund_productsTotal,issueRefund_lblProductsTotal,issueRefund_lblTaxes,issueRefund_lblSubtotal" /> + From 1294f0fea98cbab9aefacfdfa90a33b1d06f3f71 Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 7 Aug 2024 00:42:58 +0300 Subject: [PATCH 50/99] Add ProductRefundListItem.calculateTotal() and use in calculateTotals --- .../android/extensions/RefundsExt.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt index b0365501d22..66d4696947d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt @@ -8,15 +8,18 @@ fun List.calculateTotals(): Pair var taxes = BigDecimal.ZERO var subtotal = BigDecimal.ZERO this.forEach { item -> - val quantity = item.quantity.toBigDecimal() - subtotal += quantity.times(item.orderItem.price) - - val singleItemTax = item.orderItem.totalTax.divide( - item.orderItem.quantity.toBigDecimal(), - 2, - HALF_UP - ) - taxes += quantity.times(singleItemTax) + val (itemSubtotal, itemTaxes) = item.calculateTotal() + subtotal += itemSubtotal + taxes += itemTaxes } return Pair(subtotal, taxes) } + +fun ProductRefundListItem.calculateTotal(): Pair { + val quantity = quantity.toBigDecimal() + val subtotal = quantity.times(orderItem.price) + + val singleItemTax = orderItem.totalTax.divide(orderItem.quantity.toBigDecimal(), 2, HALF_UP) + val taxes = quantity.times(singleItemTax) + return Pair(subtotal, taxes) +} From 8684ac01f5f927fa3ec0456d845867aea324cb1e Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 7 Aug 2024 00:47:11 +0300 Subject: [PATCH 51/99] Fill subtotal, taxes fields in the refund list item --- .../payments/refunds/IssueRefundViewModel.kt | 23 +++++++++++++------ .../refunds/RefundProductListAdapter.kt | 10 +++++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt index 352a93535bd..3ead2becf0d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt @@ -18,6 +18,7 @@ import com.woocommerce.android.analytics.AnalyticsEvent.REFUND_CREATE_SUCCESS import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.analytics.AnalyticsTrackerWrapper import com.woocommerce.android.extensions.adminUrlOrDefault +import com.woocommerce.android.extensions.calculateTotal import com.woocommerce.android.extensions.calculateTotals import com.woocommerce.android.extensions.isCashPayment import com.woocommerce.android.extensions.isEqualTo @@ -285,7 +286,13 @@ class IssueRefundViewModel @Inject constructor( val items = order.items.map { val maxQuantity = maxQuantities[it.itemId] ?: 0f val selectedQuantity = min(selectedQuantities[it.itemId] ?: 0, maxQuantity.toInt()) - ProductRefundListItem(it, maxQuantity, selectedQuantity) + ProductRefundListItem( + it, + maxQuantity, + selectedQuantity, + formatCurrency(BigDecimal.ZERO), + formatCurrency(BigDecimal.ZERO) + ) } updateRefundItems(items) @@ -649,12 +656,14 @@ class IssueRefundViewModel @Inject constructor( val newItems = mutableListOf() _refundItems.value?.forEach { if (it.orderItem.itemId == uniqueId) { - newItems.add( - it.copy( - quantity = newQuantity, - maxQuantity = maxQuantities[uniqueId] ?: 0f - ) - ) + // Update the quantity + var newItem = it.copy(quantity = newQuantity, maxQuantity = maxQuantities[uniqueId] ?: 0f) + + // Update the subtotal and taxes based on the new quantity + val (subtotal, taxes) = newItem.calculateTotal() + newItem = newItem.copy(subtotal = formatCurrency(subtotal), taxes = formatCurrency(taxes)) + + newItems.add(newItem) } else { newItems.add(it) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundProductListAdapter.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundProductListAdapter.kt index 9bb2d32b5f4..0ce0e28f1fb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundProductListAdapter.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/RefundProductListAdapter.kt @@ -140,6 +140,8 @@ class RefundProductListAdapter( private val descriptionTextView: TextView = itemView.findViewById(R.id.refundItem_description) private val quantityTextView: TextView = itemView.findViewById(R.id.refundItem_quantity) private val productImageView: ImageView = itemView.findViewById(R.id.refundItem_icon) + private val subtotalTextView: TextView = itemView.findViewById(R.id.refundItemSubtotal) + private val taxesTextView: TextView = itemView.findViewById(R.id.refundItemTaxes) @SuppressLint("SetTextI18n") override fun bind(item: ProductRefundListItem) { @@ -166,6 +168,10 @@ class RefundProductListAdapter( .placeholder(R.drawable.ic_product) .into(productImageView) } ?: productImageView.setImageResource(R.drawable.ic_product) + + subtotalTextView.text = item.subtotal + + taxesTextView.text = item.taxes } } @@ -173,7 +179,9 @@ class RefundProductListAdapter( data class ProductRefundListItem( val orderItem: Order.Item, val maxQuantity: Float = 0f, - val quantity: Int = 0 + val quantity: Int = 0, + val subtotal: String? = null, + val taxes: String? = null ) : Parcelable { @IgnoredOnParcel val availableRefundQuantity From 0e3d3f150c3c16aea35bb6e4972a3ebc9e3a1cda Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 7 Aug 2024 01:20:38 +0300 Subject: [PATCH 52/99] Update RELEASE-NOTES.txt --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 8db33e31ccf..6af0d7f6238 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -4,6 +4,7 @@ 19.9 ----- - [*] [Internal] Update Android material from 1.9.0 to 1.10.0 [https://github.com/woocommerce/woocommerce-android/pull/12186] +- [*] Added subtotal and taxes fields to each refund item on the refund screen. [https://github.com/woocommerce/woocommerce-android/pull/12235] 19.8 ----- From cf99eb617f8a24baadb8d59636b0d4338822fefb Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 07:10:13 +0200 Subject: [PATCH 53/99] Update Android Transition from 1.4.0 to 1.5.0 --- WooCommerce/build.gradle | 1 + build.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/WooCommerce/build.gradle b/WooCommerce/build.gradle index e44b5628a90..29a5e00a18e 100644 --- a/WooCommerce/build.gradle +++ b/WooCommerce/build.gradle @@ -240,6 +240,7 @@ dependencies { implementation "androidx.recyclerview:recyclerview-selection:1.1.0" implementation "androidx.appcompat:appcompat:$appCompatVersion" implementation "com.google.android.material:material:$materialVersion" + implementation "androidx.transition:transition:$transitionVersion" implementation "androidx.cardview:cardview:1.0.0" implementation("androidx.browser:browser:1.5.0") { exclude group: 'com.google.guava', module: 'listenablefuture' diff --git a/build.gradle b/build.gradle index e3385fb35db..a52f34f5567 100644 --- a/build.gradle +++ b/build.gradle @@ -115,6 +115,7 @@ ext { coreKtxVersion = '1.13.1' appCompatVersion = '1.4.2' materialVersion = '1.10.0' + transitionVersion = '1.5.0' hiltJetpackVersion = '1.1.0' wordPressUtilsVersion = '3.5.0' mediapickerVersion = '0.3.1' From 5dc879037808b3dbe65ca97db8f18f66c15c4c67 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 07:10:36 +0200 Subject: [PATCH 54/99] Update Android Material from 1.10.0 to 1.12.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a52f34f5567..fdf1809022d 100644 --- a/build.gradle +++ b/build.gradle @@ -114,7 +114,7 @@ ext { stateMachineVersion = '0.2.0' coreKtxVersion = '1.13.1' appCompatVersion = '1.4.2' - materialVersion = '1.10.0' + materialVersion = '1.12.0' transitionVersion = '1.5.0' hiltJetpackVersion = '1.1.0' wordPressUtilsVersion = '3.5.0' From f998372573e348cefda5c2fdacb78db99673bccc Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 07:17:40 +0200 Subject: [PATCH 55/99] Use ktx version of androidx transition --- WooCommerce/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/build.gradle b/WooCommerce/build.gradle index 29a5e00a18e..0f2b0bc9487 100644 --- a/WooCommerce/build.gradle +++ b/WooCommerce/build.gradle @@ -240,7 +240,7 @@ dependencies { implementation "androidx.recyclerview:recyclerview-selection:1.1.0" implementation "androidx.appcompat:appcompat:$appCompatVersion" implementation "com.google.android.material:material:$materialVersion" - implementation "androidx.transition:transition:$transitionVersion" + implementation "androidx.transition:transition-ktx:$transitionVersion" implementation "androidx.cardview:cardview:1.0.0" implementation("androidx.browser:browser:1.5.0") { exclude group: 'com.google.guava', module: 'listenablefuture' From 5a3186cd83d493159ee894ce4a3e9ffbcb130e6d Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 07:17:58 +0200 Subject: [PATCH 56/99] Update androidx transition to 1.5.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fdf1809022d..06508ed2575 100644 --- a/build.gradle +++ b/build.gradle @@ -115,7 +115,7 @@ ext { coreKtxVersion = '1.13.1' appCompatVersion = '1.4.2' materialVersion = '1.12.0' - transitionVersion = '1.5.0' + transitionVersion = '1.5.1' hiltJetpackVersion = '1.1.0' wordPressUtilsVersion = '3.5.0' mediapickerVersion = '0.3.1' From 356bc3f53eaef9eea44cc87159bd939d404d54a3 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 07:20:27 +0200 Subject: [PATCH 57/99] Update release notes --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 44fcbc0eea4..a14ca016124 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -7,6 +7,7 @@ - [*] [Internal] Update Android-core from 1.12.0 to 1.13.1 [https://github.com/woocommerce/woocommerce-android/pull/12229] - [*] [Internal] Update Android-lifecycle from 2.6.2 to 2.7.0 [https://github.com/woocommerce/woocommerce-android/pull/12230] - [*] [Internal] Update Androidx-fragment from 1.6.2 to 1.8.2 [https://github.com/woocommerce/woocommerce-android/pull/12231] +- [*] [Internal] Update Material to 1.12.0 and Transition to 1.5.1 [https://github.com/woocommerce/woocommerce-android/pull/12237] 19.8 ----- From ede2bf235a3fa52e88605f280a969de7ede73add Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 08:37:38 +0200 Subject: [PATCH 58/99] Revert "Revert explicit specification of service type" This reverts commit c5d5bee87b573adbfb24b0b0b492858b8d3df1d5. --- WooCommerce/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/WooCommerce/src/main/AndroidManifest.xml b/WooCommerce/src/main/AndroidManifest.xml index d08db657360..281612f6271 100644 --- a/WooCommerce/src/main/AndroidManifest.xml +++ b/WooCommerce/src/main/AndroidManifest.xml @@ -199,6 +199,7 @@ Date: Wed, 7 Aug 2024 08:37:39 +0200 Subject: [PATCH 59/99] Revert "Downgrade targetSdkVersion back to 33" This reverts commit ba70d60195aebbc7047e6240c5d67354ffa31316. --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 48c9f36156e..a5bdc1b2553 100644 --- a/settings.gradle +++ b/settings.gradle @@ -73,7 +73,7 @@ gradle.ext.mediaPickerSourceWordPressBinaryPath = "org.wordpress.mediapicker:sou gradle.ext { compileSdkVersion = 34 - targetSdkVersion = 33 + targetSdkVersion = 34 minSdkVersion = 26 } From 92c0107fd0c485a940cab7c0f8a110678d2c9598 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 08:59:12 +0200 Subject: [PATCH 60/99] Update Stripe Terminal Sdk from 3.1.1 to 3.7.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 06508ed2575..0ac3bcf5a57 100644 --- a/build.gradle +++ b/build.gradle @@ -124,7 +124,7 @@ ext { automatticTracksVersion = '5.0.0' workManagerVersion = '2.7.1' billingVersion = '5.0.0' - stripeTerminalVersion = '3.1.1' + stripeTerminalVersion = '3.7.1' mlkitBarcodeScanningVersion = '17.2.0' mlkitTextRecognitionVersion = '16.0.0' androidxCameraVersion = '1.2.3' From 4da88f6d3659f2c825a7932eb3827074b6ca8a33 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 08:59:40 +0200 Subject: [PATCH 61/99] Update RefundParams to use new constructor for id --- .../woocommerce/android/cardreader/payments/RefundParams.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/payments/RefundParams.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/payments/RefundParams.kt index 8525f9f5404..6c9c6864dd7 100644 --- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/payments/RefundParams.kt +++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/payments/RefundParams.kt @@ -1,6 +1,7 @@ package com.woocommerce.android.cardreader.payments import com.stripe.stripeterminal.external.models.RefundParameters +import com.stripe.stripeterminal.external.models.RefundParameters.Id import com.woocommerce.android.cardreader.internal.payments.PaymentUtils import java.math.BigDecimal @@ -12,7 +13,7 @@ data class RefundParams( internal fun RefundParams.toStripeRefundParameters(paymentUtils: PaymentUtils): RefundParameters { return RefundParameters.Builder( - chargeId = this.chargeId, + Id.Charge(id = this.chargeId), amount = paymentUtils.convertToSmallestCurrencyUnit(this.amount, this.currency), currency = this.currency ).build() From 6e7cf7f81bba8e2ddd5d30e2b64436496ae767d0 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 09:12:29 +0200 Subject: [PATCH 62/99] Update release notes --- RELEASE-NOTES.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index a14ca016124..b344f9e8b44 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -3,11 +3,12 @@ *** For entries which are touching the Android Wear app's, start entry with `[WEAR]` too. 19.9 ----- -- [*] [Internal] Update Android material from 1.9.0 to 1.10.0 [https://github.com/woocommerce/woocommerce-android/pull/12186] -- [*] [Internal] Update Android-core from 1.12.0 to 1.13.1 [https://github.com/woocommerce/woocommerce-android/pull/12229] -- [*] [Internal] Update Android-lifecycle from 2.6.2 to 2.7.0 [https://github.com/woocommerce/woocommerce-android/pull/12230] -- [*] [Internal] Update Androidx-fragment from 1.6.2 to 1.8.2 [https://github.com/woocommerce/woocommerce-android/pull/12231] -- [*] [Internal] Update Material to 1.12.0 and Transition to 1.5.1 [https://github.com/woocommerce/woocommerce-android/pull/12237] +- [*****] [Internal] Update Android material from 1.9.0 to 1.10.0 [https://github.com/woocommerce/woocommerce-android/pull/12186] +- [*****] [Internal] Update Android-core from 1.12.0 to 1.13.1 [https://github.com/woocommerce/woocommerce-android/pull/12229] +- [*****] [Internal] Update Android-lifecycle from 2.6.2 to 2.7.0 [https://github.com/woocommerce/woocommerce-android/pull/12230] +- [*****] [Internal] Update Androidx-fragment from 1.6.2 to 1.8.2 [https://github.com/woocommerce/woocommerce-android/pull/12231] +- [*****] [Internal] Update Material to 1.12.0 and Transition to 1.5.1 [https://github.com/woocommerce/woocommerce-android/pull/12237] +- [*****] [Internal] Update Stripe Terminal SDK from 3.1.1 to 3.7.1 [https://github.com/woocommerce/woocommerce-android/pull/12239] 19.8 ----- From 9370d2a88badcb797f6e0461212153cf642bf834 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Mon, 5 Aug 2024 15:52:09 +0200 Subject: [PATCH 63/99] Hide TTP on Android 10 as it is no longer supported --- .../android/ui/payments/taptopay/TapToPayAvailabilityStatus.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatus.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatus.kt index cadf34a04af..d899424a39a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatus.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatus.kt @@ -19,7 +19,7 @@ class TapToPayAvailabilityStatus @Inject constructor( ) { operator fun invoke() = when { - !systemVersionUtilsWrapper.isAtLeastQ() -> Result.NotAvailable.SystemVersionNotSupported + !systemVersionUtilsWrapper.isAtLeastR() -> Result.NotAvailable.SystemVersionNotSupported !deviceFeatures.isGooglePlayServicesAvailable() -> Result.NotAvailable.GooglePlayServicesNotAvailable !deviceFeatures.isNFCAvailable() -> Result.NotAvailable.NfcNotAvailable !isTppSupportedInCountry() -> Result.NotAvailable.CountryNotSupported From 8f89955df55a1a39c66318c105e4889c3c8e9395 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Mon, 5 Aug 2024 15:53:26 +0200 Subject: [PATCH 64/99] Update unit tests for TTP supported OS versions --- .../ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt index 8b2b2dcbc72..067f4d23a5d 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt @@ -64,10 +64,10 @@ class TapToPayAvailabilityStatusTest { } @Test - fun `given device has os less than Android 9, when invoking, then system is not supported returned`() { + fun `given device has os less than Android 10, when invoking, then system is not supported returned`() { whenever(deviceFeatures.isNFCAvailable()).thenReturn(true) whenever(deviceFeatures.isGooglePlayServicesAvailable()).thenReturn(true) - whenever(systemVersionUtilsWrapper.isAtLeastQ()).thenReturn(false) + whenever(systemVersionUtilsWrapper.isAtLeastR()).thenReturn(false) val result = availabilityStatus.invoke() From 512c0dcadd4e51782ebf7efa44a0a64180bdb713 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 09:51:57 +0200 Subject: [PATCH 65/99] Update name of TTP process definition --- .../src/main/kotlin/com/woocommerce/android/WooCommerce.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt index ed601d1cc1a..3c0036d3f30 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt @@ -55,6 +55,6 @@ open class WooCommerce : Application(), HasAndroidInjector, Configuration.Provid override fun androidInjector(): AndroidInjector = androidInjector companion object { - private const val TAP_TO_PAY_STRIPE_PROCESS_NAME = "com.stripe.cots.aidlservice" + private const val TAP_TO_PAY_STRIPE_PROCESS_NAME = "com.woocommerce.android:stripelocalmobile" } } From 54b3dccc1ba8e57bd0bd67f2dabf723c551ae24c Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 10:06:54 +0200 Subject: [PATCH 66/99] Update TTP process name on debug builds --- .../src/main/kotlin/com/woocommerce/android/WooCommerce.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt index 3c0036d3f30..136977f66e0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt @@ -30,7 +30,7 @@ open class WooCommerce : Application(), HasAndroidInjector, Configuration.Provid // > Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process // > com.stripe.cots.aidlservice. Make sure to call FirebaseApp.initializeApp(Context) first. // In this case we don't want to initialize any Firebase (or any at all) features of the app in their process. - if (getCurrentProcessName() == TAP_TO_PAY_STRIPE_PROCESS_NAME) return + if (getCurrentProcessName() == "$packageName:$TAP_TO_PAY_STRIPE_PROCESS_NAME_SUFFIX") return // Disables Volley debug logging on release build and prevents the "Marker added to finished log" crash // https://github.com/woocommerce/woocommerce-android/issues/817 @@ -55,6 +55,6 @@ open class WooCommerce : Application(), HasAndroidInjector, Configuration.Provid override fun androidInjector(): AndroidInjector = androidInjector companion object { - private const val TAP_TO_PAY_STRIPE_PROCESS_NAME = "com.woocommerce.android:stripelocalmobile" + private const val TAP_TO_PAY_STRIPE_PROCESS_NAME_SUFFIX = "stripelocalmobile" } } From 47d53c338d194d6491c613b34da6300c8bdc0868 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 10:11:27 +0200 Subject: [PATCH 67/99] Update comment --- .../src/main/kotlin/com/woocommerce/android/WooCommerce.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt index 136977f66e0..58859aed1b2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt @@ -28,7 +28,7 @@ open class WooCommerce : Application(), HasAndroidInjector, Configuration.Provid // Stripe Tap to Pay library starts it's own process. That causes the crash: // > Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process - // > com.stripe.cots.aidlservice. Make sure to call FirebaseApp.initializeApp(Context) first. + // > com.woocommerce.android:stripelocalmobile Make sure to call FirebaseApp.initializeApp(Context) first. // In this case we don't want to initialize any Firebase (or any at all) features of the app in their process. if (getCurrentProcessName() == "$packageName:$TAP_TO_PAY_STRIPE_PROCESS_NAME_SUFFIX") return From 590cd660c3e7ab03a8c76e277434dde6ad243cc5 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 10:13:56 +0200 Subject: [PATCH 68/99] Replace packageName with Application ID --- .../src/main/kotlin/com/woocommerce/android/WooCommerce.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt index 58859aed1b2..f7226a6e3aa 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/WooCommerce.kt @@ -30,7 +30,7 @@ open class WooCommerce : Application(), HasAndroidInjector, Configuration.Provid // > Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process // > com.woocommerce.android:stripelocalmobile Make sure to call FirebaseApp.initializeApp(Context) first. // In this case we don't want to initialize any Firebase (or any at all) features of the app in their process. - if (getCurrentProcessName() == "$packageName:$TAP_TO_PAY_STRIPE_PROCESS_NAME_SUFFIX") return + if (getCurrentProcessName() == "${BuildConfig.APPLICATION_ID}:$TAP_TO_PAY_STRIPE_PROCESS_NAME_SUFFIX") return // Disables Volley debug logging on release build and prevents the "Marker added to finished log" crash // https://github.com/woocommerce/woocommerce-android/issues/817 From c808dcbe6578656b64d3b6ca9fae06b99b70893c Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Wed, 7 Aug 2024 11:02:32 +0200 Subject: [PATCH 69/99] Adds text recognition for Japanese, Korean, and Chinese --- WooCommerce/build.gradle | 4 ++++ .../ui/products/ai/TextRecognitionEngine.kt | 24 ++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/WooCommerce/build.gradle b/WooCommerce/build.gradle index b022c27933f..d4d2b2627f0 100644 --- a/WooCommerce/build.gradle +++ b/WooCommerce/build.gradle @@ -325,6 +325,10 @@ dependencies { implementation 'com.google.android.gms:play-services-code-scanner:16.1.0' implementation "com.google.mlkit:text-recognition:$mlkitTextRecognitionVersion" + implementation "com.google.android.gms:play-services-mlkit-text-recognition-japanese:$mlkitTextRecognitionVersion" + implementation "com.google.android.gms:play-services-mlkit-text-recognition-chinese:$mlkitTextRecognitionVersion" + implementation "com.google.android.gms:play-services-mlkit-text-recognition-korean:$mlkitTextRecognitionVersion" + implementation "com.google.mlkit:barcode-scanning:$mlkitBarcodeScanningVersion" implementation "com.google.zxing:core:3.5.3" diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt index 31acebd22fe..23a616516e7 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt @@ -8,24 +8,42 @@ import coil.request.ImageRequest.Builder import coil.request.SuccessResult import com.google.mlkit.vision.common.InputImage import com.google.mlkit.vision.text.TextRecognition +import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions +import com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions +import com.google.mlkit.vision.text.korean.KoreanTextRecognizerOptions import com.google.mlkit.vision.text.latin.TextRecognizerOptions import com.woocommerce.android.util.WooLog import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.tasks.await +import java.util.Locale import javax.inject.Inject class TextRecognitionEngine @Inject constructor( @ApplicationContext private val appContext: Context ) { - private val textRecognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) + private companion object { + const val JAPANESE_LANGUAGE_CODE = "ja" + const val CHINESE_LANGUAGE_CODE = "zh" + const val KOREAN_LANGUAGE_CODE = "ko" + } + + private val generalTextRecognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) + private val japaneseTextRecognizer = TextRecognition.getClient(JapaneseTextRecognizerOptions.Builder().build()) + private val chineseTextRecognizer = TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build()) + private val koreanTextRecognizer = TextRecognition.getClient(KoreanTextRecognizerOptions.Builder().build()) @Suppress("TooGenericExceptionCaught") suspend fun processImage(imageUrl: String): Result> { return try { val bitmap = loadBitmap(imageUrl) val image = InputImage.fromBitmap(requireNotNull(bitmap), 0) - - val result = textRecognizer.process(image).await() + val deviceLocale = Locale.getDefault().language + val result = when (deviceLocale) { + JAPANESE_LANGUAGE_CODE -> japaneseTextRecognizer + CHINESE_LANGUAGE_CODE -> chineseTextRecognizer + KOREAN_LANGUAGE_CODE -> koreanTextRecognizer + else -> generalTextRecognizer + }.process(image).await() Result.success(result.textBlocks.map { it.text }) } catch (e: Exception) { WooLog.d(WooLog.T.AI, "Failed to scan text from image: ${e.message}") From ba426a45d1ef23615f5792f6999e7912bad73900 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 7 Aug 2024 12:13:57 +0200 Subject: [PATCH 70/99] Improve code style --- .../cardreader/payment/CardReaderPaymentViewModel.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt index 2df6fc8f136..49e307370b7 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt @@ -464,10 +464,7 @@ class CardReaderPaymentViewModel ) { paymentReceiptHelper.storeReceiptUrl(orderId, paymentStatus.receiptUrl) appPrefs.setCardReaderSuccessfulPaymentTime() - val flowParam: CardReaderFlowParam.PaymentOrRefund = arguments.paymentOrRefund - if (flowParam is CardReaderFlowParam.PaymentOrRefund.Payment && - flowParam.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS - ) { + if (arguments.paymentOrRefund.isPOS()) { reFetchOrder() onCancelPaymentFlow() } else { @@ -477,6 +474,11 @@ class CardReaderPaymentViewModel } } + private fun CardReaderFlowParam.PaymentOrRefund.isPOS(): Boolean { + return this is CardReaderFlowParam.PaymentOrRefund.Payment && + this.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS + } + @VisibleForTesting fun reFetchOrder() { refetchOrderJob = launch { From b24f9a8794f6c89ec638d24a365a8e4038ad0518 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 7 Aug 2024 12:02:05 +0100 Subject: [PATCH 71/99] Bump fluxc --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 69fb80ece10..54955ecb2af 100644 --- a/build.gradle +++ b/build.gradle @@ -99,7 +99,7 @@ tasks.register("installGitHooks", Copy) { } ext { - fluxCVersion = '2.91.0' + fluxCVersion = 'trunk-06355b8e708b8303653a5e1afb751c25d469c40e' glideVersion = '4.16.0' coilVersion = '2.1.0' constraintLayoutVersion = '1.2.0' From b251b3a652d0c6323332b2dbf55191ec90b70158 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Wed, 7 Aug 2024 13:06:17 +0200 Subject: [PATCH 72/99] Remove feature flag product creation with AI V2 - M3 --- .../ai/productinfo/AiProductPromptScreen.kt | 16 +++++----------- .../com/woocommerce/android/util/FeatureFlag.kt | 2 -- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/productinfo/AiProductPromptScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/productinfo/AiProductPromptScreen.kt index 3af8e1b0ba2..4e9709a49a5 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/productinfo/AiProductPromptScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/productinfo/AiProductPromptScreen.kt @@ -74,7 +74,6 @@ import com.woocommerce.android.ui.products.ai.components.ImageAction import com.woocommerce.android.ui.products.ai.components.SelectImageSection import com.woocommerce.android.ui.products.ai.productinfo.AiProductPromptViewModel.AiProductPromptState import com.woocommerce.android.ui.products.ai.productinfo.AiProductPromptViewModel.PromptSuggestionBar -import com.woocommerce.android.util.FeatureFlag import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.wordpress.android.mediapicker.api.MediaPickerSetup.DataSource @@ -340,21 +339,16 @@ private fun ProductPromptTextField( modifier = Modifier .onFocusChanged { focusState -> isFocused = focusState.isFocused - if (isFocused && FeatureFlag.PRODUCT_CREATION_WITH_AI_V2_M3.isEnabled()) { - coroutineScope.launch { - @Suppress("MagicNumber") - delay(200) // Delay to ensure advice box is shown before scrolling. - scrollState.animateScrollTo(scrollToPosition.roundToInt()) - } + coroutineScope.launch { + @Suppress("MagicNumber") + delay(200) // Delay to ensure advice box is shown before scrolling. + scrollState.animateScrollTo(scrollToPosition.roundToInt()) } } ) } } - AnimatedVisibility( - (isFocused || state.productPrompt.isNotEmpty()) && - FeatureFlag.PRODUCT_CREATION_WITH_AI_V2_M3.isEnabled() - ) { + AnimatedVisibility((isFocused || state.productPrompt.isNotEmpty())) { PromptSuggestions( promptSuggestionBarState = state.promptSuggestionBarState, modifier = Modifier.padding(top = 8.dp) 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 c48706cea2c..3587597746f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt @@ -18,7 +18,6 @@ enum class FeatureFlag { GOOGLE_ADS_M1, GOOGLE_ADS_ANALYTICS_HUB_M1, PRODUCT_CREATION_WITH_AI_V2, - PRODUCT_CREATION_WITH_AI_V2_M3, SHOW_INBOX_CTA; fun isEnabled(context: Context? = null): Boolean { @@ -39,7 +38,6 @@ enum class FeatureFlag { INBOX, GOOGLE_ADS_ANALYTICS_HUB_M1, SHOW_INBOX_CTA, - PRODUCT_CREATION_WITH_AI_V2_M3, GOOGLE_ADS_M1 -> true } } From bbc844a3a4d1bffa4366eea54a81745d960aceba Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 7 Aug 2024 14:30:35 +0200 Subject: [PATCH 73/99] Add unit tests --- .../CardReaderPaymentViewModelTest.kt | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt index b8b05c6c7d0..dcab52ca408 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt @@ -4427,6 +4427,58 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { verify(cardReaderManager, never()).collectPayment(any()) } + @Test + fun `given point of sale, when payment captured, then should not show success state`() { + testBlocking { + whenever(cardReaderManager.collectPayment(any())).thenAnswer { + flow { emit(PaymentCompleted("")) } + } + + initViewModel( + readerType = EXTERNAL, + cardReaderFlowParam = CardReaderFlowParam.PaymentOrRefund.Payment( + orderId = ORDER_ID, + paymentType = CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS + ) + ) + + viewModel.start() + + assertThat(viewModel.viewStateData.value).isNotInstanceOfAny( + BuiltInReaderPaymentSuccessfulState::class.java, + ExternalReaderPaymentSuccessfulState::class.java, + ExternalReaderPaymentSuccessfulReceiptSentAutomaticallyState::class.java, + BuiltInReaderPaymentSuccessfulReceiptSentAutomaticallyState::class.java, + ) + } + } + + @Test + fun `given point of sale, when payment captured, then should exit`() { + testBlocking { + whenever(cardReaderManager.collectPayment(any())).thenAnswer { + flow { emit(PaymentCompleted("")) } + } + + initViewModel( + readerType = EXTERNAL, + cardReaderFlowParam = CardReaderFlowParam.PaymentOrRefund.Payment( + orderId = ORDER_ID, + paymentType = CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS + ) + ) + + val events = mutableListOf() + viewModel.event.observeForever { + events.add(it) + } + + viewModel.start() + + assertThat(events[0]).isInstanceOf(Exit::class.java) + } + } + private suspend fun simulateFetchOrderJobState(inProgress: Boolean) { if (inProgress) { whenever(orderRepository.fetchOrderById(any())).doSuspendableAnswer { @@ -4466,11 +4518,13 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { private fun initViewModel( readerType: CardReaderType, - savedStateValue: Pair? = null + savedStateValue: Pair? = null, + cardReaderFlowParam: CardReaderFlowParam.PaymentOrRefund = + CardReaderFlowParam.PaymentOrRefund.Payment(ORDER_ID, ORDER), ) { viewModel = CardReaderPaymentViewModel( CardReaderPaymentDialogFragmentArgs( - CardReaderFlowParam.PaymentOrRefund.Payment(ORDER_ID, ORDER), + cardReaderFlowParam, readerType, ).toSavedStateHandle().also { if (savedStateValue != null) it[savedStateValue.first] = savedStateValue.second From c698207574f3971e08d424420a69c025f11e738b Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 7 Aug 2024 14:37:00 +0200 Subject: [PATCH 74/99] Atempt to emulate shadow manually --- .../composeui/component/WooPosLazyColumn.kt | 119 ++++++++++++++++++ .../home/products/WooPosProductsScreen.kt | 3 +- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt new file mode 100644 index 00000000000..89353041fc7 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt @@ -0,0 +1,119 @@ +package com.woocommerce.android.ui.woopos.common.composeui.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.Card +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview +import com.woocommerce.android.ui.woopos.common.composeui.WooPosTheme +import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding + +@Composable +fun WooPosLazyColumn( + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues(0.dp), + verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(8.dp), + state: LazyListState = rememberLazyListState(), + content: LazyListScope.() -> Unit +) { + Box { + LazyColumn( + modifier = modifier, + contentPadding = contentPadding, + verticalArrangement = verticalArrangement, + state = state, + content = content + ) + + val showShadow = remember { + derivedStateOf { + state.firstVisibleItemIndex > 0 || state.firstVisibleItemScrollOffset > 0 + } + } + + if (showShadow.value) { + val height = 16.dp.toAdaptivePadding() + Box( + modifier = Modifier + .fillMaxWidth() + .height(height) + .align(Alignment.TopCenter) + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(height) + .background( + brush = Brush.horizontalGradient( + colors = listOf( + Color.Transparent, + MaterialTheme.colors.onSurface.copy(alpha = .03f), + MaterialTheme.colors.onSurface.copy(alpha = .03f), + MaterialTheme.colors.onSurface.copy(alpha = .03f), + MaterialTheme.colors.onSurface.copy(alpha = .03f), + Color.Transparent, + ), + startX = 0f, + endX = Float.POSITIVE_INFINITY + ) + ) + ) + Box( + modifier = Modifier + .fillMaxWidth() + .height(height) + .background( + brush = Brush.verticalGradient( + colors = listOf( + MaterialTheme.colors.onSurface.copy(alpha = .1f), + Color.Transparent, + ), + startY = 0f, + endY = height.value + ) + ) + ) + } + } + } +} + +@WooPosPreview +@Composable +fun WooPosLazyColumnPreview() { + WooPosTheme + WooPosLazyColumn { + items(10) { i -> + Card( + modifier = Modifier.fillMaxWidth(), + elevation = 4.dp, + ) { + Text( + "Item $i", + modifier = Modifier + .height(64.dp) + .fillMaxWidth(), + style = MaterialTheme.typography.h6, + color = MaterialTheme.colors.onSurface, + ) + } + } + } +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt index cd635efd947..ec1e91ddfe1 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt @@ -64,6 +64,7 @@ import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview import com.woocommerce.android.ui.woopos.common.composeui.WooPosTheme import com.woocommerce.android.ui.woopos.common.composeui.component.Button import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosErrorState +import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosLazyColumn import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosShimmerBox import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding import com.woocommerce.android.ui.woopos.home.products.WooPosProductsUIEvent.EndOfProductListReached @@ -244,7 +245,7 @@ private fun ProductsList( onEndOfProductsListReached: () -> Unit, ) { val listState = rememberLazyListState() - LazyColumn( + WooPosLazyColumn( verticalArrangement = Arrangement.spacedBy(8.dp), contentPadding = PaddingValues(2.dp), state = listState, From 110f745997f806624ef783fac6eaa6f1ac8aa573 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 7 Aug 2024 15:17:28 +0200 Subject: [PATCH 75/99] Use card for better shadow --- .../composeui/component/WooPosLazyColumn.kt | 51 +++---------------- 1 file changed, 8 insertions(+), 43 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt index 89353041fc7..0e46155434c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt @@ -1,11 +1,11 @@ package com.woocommerce.android.ui.woopos.common.composeui.component -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues 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.LazyListScope import androidx.compose.foundation.lazy.LazyListState @@ -18,8 +18,6 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview import com.woocommerce.android.ui.woopos.common.composeui.WooPosTheme @@ -49,48 +47,15 @@ fun WooPosLazyColumn( } if (showShadow.value) { - val height = 16.dp.toAdaptivePadding() - Box( + Card( modifier = Modifier .fillMaxWidth() - .height(height) - .align(Alignment.TopCenter) - ) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(height) - .background( - brush = Brush.horizontalGradient( - colors = listOf( - Color.Transparent, - MaterialTheme.colors.onSurface.copy(alpha = .03f), - MaterialTheme.colors.onSurface.copy(alpha = .03f), - MaterialTheme.colors.onSurface.copy(alpha = .03f), - MaterialTheme.colors.onSurface.copy(alpha = .03f), - Color.Transparent, - ), - startX = 0f, - endX = Float.POSITIVE_INFINITY - ) - ) - ) - Box( - modifier = Modifier - .fillMaxWidth() - .height(height) - .background( - brush = Brush.verticalGradient( - colors = listOf( - MaterialTheme.colors.onSurface.copy(alpha = .1f), - Color.Transparent, - ), - startY = 0f, - endY = height.value - ) - ) - ) - } + .height(0.5.dp) + .padding(horizontal = .5.dp) + .align(Alignment.TopCenter), + elevation = 4.dp.toAdaptivePadding(), + backgroundColor = MaterialTheme.colors.onBackground.copy(alpha = 0.1f) + ) {} } } } From 4dbcb6e1a3be8f71499dda35d021d53b7abb8bfb Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Wed, 7 Aug 2024 15:25:03 +0200 Subject: [PATCH 76/99] Instantiate the text recognition clients exactly when needed --- .../android/ui/products/ai/TextRecognitionEngine.kt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt index 23a616516e7..3da346e322d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ai/TextRecognitionEngine.kt @@ -27,11 +27,6 @@ class TextRecognitionEngine @Inject constructor( const val KOREAN_LANGUAGE_CODE = "ko" } - private val generalTextRecognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) - private val japaneseTextRecognizer = TextRecognition.getClient(JapaneseTextRecognizerOptions.Builder().build()) - private val chineseTextRecognizer = TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build()) - private val koreanTextRecognizer = TextRecognition.getClient(KoreanTextRecognizerOptions.Builder().build()) - @Suppress("TooGenericExceptionCaught") suspend fun processImage(imageUrl: String): Result> { return try { @@ -39,10 +34,10 @@ class TextRecognitionEngine @Inject constructor( val image = InputImage.fromBitmap(requireNotNull(bitmap), 0) val deviceLocale = Locale.getDefault().language val result = when (deviceLocale) { - JAPANESE_LANGUAGE_CODE -> japaneseTextRecognizer - CHINESE_LANGUAGE_CODE -> chineseTextRecognizer - KOREAN_LANGUAGE_CODE -> koreanTextRecognizer - else -> generalTextRecognizer + JAPANESE_LANGUAGE_CODE -> TextRecognition.getClient(JapaneseTextRecognizerOptions.Builder().build()) + CHINESE_LANGUAGE_CODE -> TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build()) + KOREAN_LANGUAGE_CODE -> TextRecognition.getClient(KoreanTextRecognizerOptions.Builder().build()) + else -> TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) }.process(image).await() Result.success(result.textBlocks.map { it.text }) } catch (e: Exception) { From ee28af5c272a4a9eaceb290d6863a1b9ad12f35d Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 7 Aug 2024 15:33:39 +0200 Subject: [PATCH 77/99] Use WooPosLazyColumn for the rest of the lists --- .../woopos/common/composeui/component/WooPosLazyColumn.kt | 6 +++--- .../android/ui/woopos/home/cart/WooPosCartScreen.kt | 6 +++--- .../android/ui/woopos/home/products/WooPosProductsScreen.kt | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt index 0e46155434c..6defe09c0f8 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/component/WooPosLazyColumn.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues 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.LazyListScope import androidx.compose.foundation.lazy.LazyListState @@ -28,6 +27,7 @@ fun WooPosLazyColumn( modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues(0.dp), verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(8.dp), + horizontalAlignment: Alignment.Horizontal = Alignment.Start, state: LazyListState = rememberLazyListState(), content: LazyListScope.() -> Unit ) { @@ -36,6 +36,7 @@ fun WooPosLazyColumn( modifier = modifier, contentPadding = contentPadding, verticalArrangement = verticalArrangement, + horizontalAlignment = horizontalAlignment, state = state, content = content ) @@ -48,10 +49,9 @@ fun WooPosLazyColumn( if (showShadow.value) { Card( - modifier = Modifier + modifier = modifier .fillMaxWidth() .height(0.5.dp) - .padding(horizontal = .5.dp) .align(Alignment.TopCenter), elevation = 4.dp.toAdaptivePadding(), backgroundColor = MaterialTheme.colors.onBackground.copy(alpha = 0.1f) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt index 69bb3b2d8b4..11cf2638ee2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt @@ -19,7 +19,6 @@ 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.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -57,6 +56,7 @@ import com.woocommerce.android.R import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview import com.woocommerce.android.ui.woopos.common.composeui.WooPosTheme import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosButton +import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosLazyColumn import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosOutlinedButton import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding @@ -81,6 +81,7 @@ private fun WooPosCartScreen( top = 40.dp.toAdaptivePadding(), bottom = 16.dp.toAdaptivePadding() ) + .fillMaxSize() .background(MaterialTheme.colors.surface) ) { Column { @@ -151,9 +152,8 @@ private fun CartBodyWithItems( val listState = rememberLazyListState() ScrollToBottomHandler(items, listState) - LazyColumn( + WooPosLazyColumn( modifier = Modifier - .fillMaxSize() .padding(horizontal = 16.dp.toAdaptivePadding()), state = listState, verticalArrangement = Arrangement.spacedBy(8.dp.toAdaptivePadding()), diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt index ec1e91ddfe1..69309063a3a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/WooPosProductsScreen.kt @@ -19,7 +19,6 @@ 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.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -277,7 +276,7 @@ private fun ProductsList( @Composable fun ProductsLoadingIndicator() { - LazyColumn( + WooPosLazyColumn( verticalArrangement = Arrangement.spacedBy(8.dp), contentPadding = PaddingValues(2.dp), ) { From cbd0f76cceff96bdfa347f3e23538a65726c5dff Mon Sep 17 00:00:00 2001 From: Alejo Date: Wed, 7 Aug 2024 07:56:19 -0600 Subject: [PATCH 78/99] update last update on background sync --- .../UpdateAnalyticsDataByRangeSelection.kt | 57 ++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt index 6ff43402c7f..70a93d51412 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt @@ -3,6 +3,7 @@ package com.woocommerce.android.background import com.woocommerce.android.model.AnalyticsCards import com.woocommerce.android.ui.analytics.hub.ObserveAnalyticsCardsConfiguration import com.woocommerce.android.ui.analytics.hub.sync.AnalyticsRepository +import com.woocommerce.android.ui.analytics.hub.sync.AnalyticsUpdateDataStore import com.woocommerce.android.ui.analytics.ranges.StatsTimeRangeSelection import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -12,7 +13,8 @@ import javax.inject.Inject class UpdateAnalyticsDataByRangeSelection @Inject constructor( private val analyticsCardsConfiguration: ObserveAnalyticsCardsConfiguration, - private val analyticsRepository: AnalyticsRepository + private val analyticsRepository: AnalyticsRepository, + private val analyticsUpdateDataStore: AnalyticsUpdateDataStore ) { @Suppress("LongMethod") suspend operator fun invoke( @@ -34,49 +36,90 @@ class UpdateAnalyticsDataByRangeSelection @Inject constructor( selectedRange, AnalyticsRepository.FetchStrategy.ForceNew ) - result is AnalyticsRepository.RevenueResult.RevenueData + if (result is AnalyticsRepository.RevenueResult.RevenueData) { + analyticsUpdateDataStore.storeLastAnalyticsUpdate( + selectedRange, + AnalyticsUpdateDataStore.AnalyticData.REVENUE + ) + true + } else { + false + } } } + AnalyticsCards.Orders -> { async { val result = analyticsRepository.fetchOrdersData( selectedRange, AnalyticsRepository.FetchStrategy.ForceNew ) - result is AnalyticsRepository.OrdersResult.OrdersData + if (result is AnalyticsRepository.OrdersResult.OrdersData) { + analyticsUpdateDataStore.storeLastAnalyticsUpdate( + selectedRange, + AnalyticsUpdateDataStore.AnalyticData.ORDERS + ) + true + } else { + false + } } } + AnalyticsCards.Products -> { async { val result = analyticsRepository.fetchProductsData( selectedRange, AnalyticsRepository.FetchStrategy.ForceNew ) - result is AnalyticsRepository.ProductsResult.ProductsData + if (result is AnalyticsRepository.ProductsResult.ProductsData) { + analyticsUpdateDataStore.storeLastAnalyticsUpdate( + selectedRange, + AnalyticsUpdateDataStore.AnalyticData.TOP_PERFORMERS + ) + true + } else { + false + } } } + AnalyticsCards.Session -> { async { val result = analyticsRepository.fetchVisitorsData( selectedRange, AnalyticsRepository.FetchStrategy.ForceNew ) - result is AnalyticsRepository.VisitorsResult.VisitorsData || - result is AnalyticsRepository.VisitorsResult.VisitorsNotSupported + when (result) { + is AnalyticsRepository.VisitorsResult.VisitorsData -> { + analyticsUpdateDataStore.storeLastAnalyticsUpdate( + selectedRange, + AnalyticsUpdateDataStore.AnalyticData.VISITORS + ) + true + } + is AnalyticsRepository.VisitorsResult.VisitorsNotSupported -> true + else -> { + false + } + } } } + AnalyticsCards.Bundles -> { async { val result = analyticsRepository.fetchProductBundlesStats(selectedRange) result is AnalyticsRepository.BundlesResult.BundlesData } } + AnalyticsCards.GiftCards -> { async { val result = analyticsRepository.fetchGiftCardsStats(selectedRange) result is AnalyticsRepository.GiftCardResult.GiftCardData } } + AnalyticsCards.GoogleAds -> { async { val result = analyticsRepository.fetchGoogleAdsStats(selectedRange) @@ -85,7 +128,7 @@ class UpdateAnalyticsDataByRangeSelection @Inject constructor( } } } - asyncCalls.awaitAll().all { succeed -> succeed } + asyncCalls.awaitAll().all { it } } } } From c7887baea223eb8a18f66a5d08165a36ee9a5f57 Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 7 Aug 2024 16:21:31 +0200 Subject: [PATCH 79/99] Update ci toolkit to `3.5.1` Tests with apostrophes, in case of failure, will be now annotated successfully by `annotate_test_failures` --- .buildkite/shared-pipeline-vars | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/shared-pipeline-vars b/.buildkite/shared-pipeline-vars index 2dbbc02e791..279aa805e58 100644 --- a/.buildkite/shared-pipeline-vars +++ b/.buildkite/shared-pipeline-vars @@ -3,5 +3,5 @@ # This file is `source`'d before calling `buildkite-agent pipeline upload`, and can be used # to set up some variables that will be interpolated in the `.yml` pipeline before uploading it. - export CI_TOOLKIT="automattic/a8c-ci-toolkit#3.4.2" + export CI_TOOLKIT="automattic/a8c-ci-toolkit#3.5.1" export TEST_COLLECTOR="test-collector#v1.10.1" From a7160446cf952e346f6ad5393f9eee1a97645507 Mon Sep 17 00:00:00 2001 From: Alejo Date: Wed, 7 Aug 2024 09:41:45 -0600 Subject: [PATCH 80/99] add unit test --- ...UpdateAnalyticsDataByRangeSelectionTest.kt | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelectionTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelectionTest.kt index 9a0c0211aa2..7c7ed3f6e02 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelectionTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelectionTest.kt @@ -4,6 +4,7 @@ import com.woocommerce.android.model.AnalyticCardConfiguration import com.woocommerce.android.model.AnalyticsCards import com.woocommerce.android.ui.analytics.hub.ObserveAnalyticsCardsConfiguration import com.woocommerce.android.ui.analytics.hub.sync.AnalyticsRepository +import com.woocommerce.android.ui.analytics.hub.sync.AnalyticsUpdateDataStore import com.woocommerce.android.ui.analytics.ranges.StatsTimeRangeSelection import com.woocommerce.android.viewmodel.BaseUnitTest import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -26,6 +27,7 @@ class UpdateAnalyticsDataByRangeSelectionTest : BaseUnitTest() { private val analyticsCardsConfiguration: ObserveAnalyticsCardsConfiguration = mock() private val analyticsRepository: AnalyticsRepository = mock() + private val analyticsUpdateDataStore: AnalyticsUpdateDataStore = mock() private val defaultVisibleCards = listOf( AnalyticCardConfiguration( @@ -62,7 +64,8 @@ class UpdateAnalyticsDataByRangeSelectionTest : BaseUnitTest() { private val sut = UpdateAnalyticsDataByRangeSelection( analyticsCardsConfiguration = analyticsCardsConfiguration, - analyticsRepository = analyticsRepository + analyticsRepository = analyticsRepository, + analyticsUpdateDataStore = analyticsUpdateDataStore ) private val defaultRangeSelection = StatsTimeRangeSelection.SelectionType.TODAY.generateSelectionData( @@ -214,4 +217,48 @@ class UpdateAnalyticsDataByRangeSelectionTest : BaseUnitTest() { assertTrue(result) } + + @Test + fun `save last update only for success requests`() = runTest { + whenever(analyticsCardsConfiguration.invoke()).doReturn(flowOf(defaultVisibleCards)) + whenever( + analyticsRepository.fetchRevenueData( + defaultRangeSelection, + AnalyticsRepository.FetchStrategy.ForceNew + ) + ).doReturn(AnalyticsRepository.RevenueResult.RevenueData(mock())) + whenever(analyticsRepository.fetchGiftCardsStats(defaultRangeSelection)) + .doReturn(AnalyticsRepository.GiftCardResult.GiftCardData(mock())) + whenever(analyticsRepository.fetchProductBundlesStats(defaultRangeSelection)) + .doReturn(AnalyticsRepository.BundlesResult.BundlesData(mock())) + whenever( + analyticsRepository.fetchOrdersData( + defaultRangeSelection, + AnalyticsRepository.FetchStrategy.ForceNew + ) + ).doReturn(AnalyticsRepository.OrdersResult.OrdersError) + whenever( + analyticsRepository.fetchProductsData( + defaultRangeSelection, + AnalyticsRepository.FetchStrategy.ForceNew + ) + ).doReturn(AnalyticsRepository.ProductsResult.ProductsData(mock())) + + val result = sut.invoke(defaultRangeSelection, listOf(AnalyticsCards.Products)) + + assertFalse(result) + + verify(analyticsUpdateDataStore).storeLastAnalyticsUpdate( + defaultRangeSelection, + AnalyticsUpdateDataStore.AnalyticData.REVENUE + ) + verify(analyticsUpdateDataStore).storeLastAnalyticsUpdate( + defaultRangeSelection, + AnalyticsUpdateDataStore.AnalyticData.TOP_PERFORMERS + ) + verify(analyticsUpdateDataStore, never()).storeLastAnalyticsUpdate( + defaultRangeSelection, + AnalyticsUpdateDataStore.AnalyticData.ORDERS + ) + } } From 58c1a9d6a2504a09aa3ea918e9b39c6ff6172513 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 7 Aug 2024 18:11:23 +0200 Subject: [PATCH 81/99] Clean up the code --- .../payment/CardReaderPaymentViewModel.kt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt index 49e307370b7..854b829715f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt @@ -146,6 +146,10 @@ class CardReaderPaymentViewModel private var refetchOrderJob: Job? = null + private val CardReaderFlowParam.PaymentOrRefund.isPOS: Boolean + get() = this is CardReaderFlowParam.PaymentOrRefund.Payment && + this.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS + fun start() { if (cardReaderManager.readerStatus.value is CardReaderStatus.Connected) { startFlowWhenReaderConnected() @@ -464,9 +468,11 @@ class CardReaderPaymentViewModel ) { paymentReceiptHelper.storeReceiptUrl(orderId, paymentStatus.receiptUrl) appPrefs.setCardReaderSuccessfulPaymentTime() - if (arguments.paymentOrRefund.isPOS()) { - reFetchOrder() - onCancelPaymentFlow() + if (arguments.paymentOrRefund.isPOS) { + launch { + orderRepository.fetchOrderById(orderId) + triggerEvent(Exit) + } } else { triggerEvent(PlayChaChing) showPaymentSuccessfulState() @@ -474,11 +480,6 @@ class CardReaderPaymentViewModel } } - private fun CardReaderFlowParam.PaymentOrRefund.isPOS(): Boolean { - return this is CardReaderFlowParam.PaymentOrRefund.Payment && - this.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS - } - @VisibleForTesting fun reFetchOrder() { refetchOrderJob = launch { From 0e35ada75c278b065744b5ebdcf4f3fa1d63ae4f Mon Sep 17 00:00:00 2001 From: Alejo Date: Wed, 7 Aug 2024 10:32:49 -0600 Subject: [PATCH 82/99] refactor sync data result --- .../UpdateAnalyticsDataByRangeSelection.kt | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt index 70a93d51412..4044cca5002 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/background/UpdateAnalyticsDataByRangeSelection.kt @@ -36,15 +36,14 @@ class UpdateAnalyticsDataByRangeSelection @Inject constructor( selectedRange, AnalyticsRepository.FetchStrategy.ForceNew ) - if (result is AnalyticsRepository.RevenueResult.RevenueData) { + val isSuccess = result is AnalyticsRepository.RevenueResult.RevenueData + if (isSuccess) { analyticsUpdateDataStore.storeLastAnalyticsUpdate( selectedRange, AnalyticsUpdateDataStore.AnalyticData.REVENUE ) - true - } else { - false } + isSuccess } } @@ -54,15 +53,14 @@ class UpdateAnalyticsDataByRangeSelection @Inject constructor( selectedRange, AnalyticsRepository.FetchStrategy.ForceNew ) - if (result is AnalyticsRepository.OrdersResult.OrdersData) { + val isSuccess = result is AnalyticsRepository.OrdersResult.OrdersData + if (isSuccess) { analyticsUpdateDataStore.storeLastAnalyticsUpdate( selectedRange, AnalyticsUpdateDataStore.AnalyticData.ORDERS ) - true - } else { - false } + isSuccess } } @@ -72,15 +70,14 @@ class UpdateAnalyticsDataByRangeSelection @Inject constructor( selectedRange, AnalyticsRepository.FetchStrategy.ForceNew ) - if (result is AnalyticsRepository.ProductsResult.ProductsData) { + val isSuccess = result is AnalyticsRepository.ProductsResult.ProductsData + if (isSuccess) { analyticsUpdateDataStore.storeLastAnalyticsUpdate( selectedRange, AnalyticsUpdateDataStore.AnalyticData.TOP_PERFORMERS ) - true - } else { - false } + isSuccess } } From eb68724d9d62240989e3ce2950e6565fb8ee7ff6 Mon Sep 17 00:00:00 2001 From: Spencer Transier Date: Wed, 7 Aug 2024 11:20:41 -0700 Subject: [PATCH 83/99] Update Ruby Gems --- Gemfile.lock | 68 +++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2da0446bb68..f31f3a70516 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,26 +15,26 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) artifactory (3.0.17) ast (2.4.2) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.942.0) - aws-sdk-core (3.197.0) + aws-partitions (1.962.0) + aws-sdk-core (3.201.3) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.83.0) - aws-sdk-core (~> 3, >= 3.197.0) - aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.152.1) - aws-sdk-core (~> 3, >= 3.197.0) + aws-sdk-kms (1.88.0) + aws-sdk-core (~> 3, >= 3.201.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.157.0) + aws-sdk-core (~> 3, >= 3.201.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.8) - aws-sigv4 (1.8.0) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.9.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -55,7 +55,7 @@ GEM connection_pool (2.4.1) cork (0.3.0) colored2 (~> 3.1) - danger (9.4.3) + danger (9.5.0) claide (~> 1.0) claide-plugins (>= 0.9.2) colored2 (~> 3.1) @@ -65,10 +65,9 @@ GEM git (~> 1.13) kramdown (~> 2.3) kramdown-parser-gfm (~> 1.0) - no_proxy_fix octokit (>= 4.0) terminal-table (>= 1, < 4) - danger-dangermattic (1.1.1) + danger-dangermattic (1.1.2) danger (~> 9.4) danger-plugin-api (~> 1.0) danger-rubocop (~> 0.13) @@ -86,7 +85,7 @@ GEM dotenv (2.8.1) drb (2.2.1) emoji_regex (3.2.3) - excon (0.110.0) + excon (0.111.0) faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -110,7 +109,7 @@ GEM faraday-httpclient (1.0.1) faraday-multipart (1.0.4) multipart-post (~> 2) - faraday-net_http (1.0.1) + faraday-net_http (1.0.2) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) faraday-rack (1.0.0) @@ -118,7 +117,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.220.0) + fastlane (2.222.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -159,7 +158,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) - fastlane-plugin-wpmreleasetoolkit (11.0.2) + fastlane-plugin-wpmreleasetoolkit (11.1.0) activesupport (>= 6.1.7.1) buildkit (~> 1.5) chroma (= 0.2.0) @@ -196,7 +195,7 @@ GEM google-apis-core (>= 0.11.0, < 2.a) google-apis-storage_v1 (0.31.0) google-apis-core (>= 0.11.0, < 2.a) - google-cloud-core (1.7.0) + google-cloud-core (1.7.1) google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) @@ -225,17 +224,17 @@ GEM java-properties (0.3.0) jmespath (1.6.2) json (2.7.2) - jwt (2.8.1) + jwt (2.8.2) base64 kramdown (2.4.0) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) language_server-protocol (3.17.0.3) - mini_magick (4.12.0) + mini_magick (4.13.2) mini_mime (1.1.5) mini_portile2 (2.8.7) - minitest (5.23.1) + minitest (5.24.1) multi_json (1.15.0) multipart-post (2.4.1) mutex_m (0.2.0) @@ -243,8 +242,7 @@ GEM nap (1.1.0) naturally (2.2.1) nkf (0.2.0) - no_proxy_fix (0.1.2) - nokogiri (1.16.6) + nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) octokit (6.1.1) @@ -255,43 +253,43 @@ GEM optparse (0.5.0) os (1.1.4) parallel (1.25.1) - parser (3.3.0.5) + parser (3.3.4.1) ast (~> 2.4.1) racc plist (3.7.1) progress_bar (1.3.4) highline (>= 1.6) options (~> 2.3.0) - public_suffix (5.0.5) - racc (1.8.0) + public_suffix (6.0.1) + racc (1.8.1) rainbow (3.1.1) rake (13.2.1) rake-compiler (1.2.7) rake rchardet (1.8.0) - regexp_parser (2.9.0) + regexp_parser (2.9.2) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.9) + rexml (3.3.4) strscan rmagick (4.3.0) rouge (2.0.7) - rubocop (1.63.5) + rubocop (1.65.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) + regexp_parser (>= 2.4, < 3.0) rexml (>= 3.2.5, < 4.0) rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.31.2) - parser (>= 3.3.0.4) + rubocop-ast (1.32.0) + parser (>= 3.3.1.0) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) @@ -321,13 +319,13 @@ GEM uber (0.1.0) unicode-display_width (2.5.0) word_wrap (1.0.0) - xcodeproj (1.24.0) + xcodeproj (1.25.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) nanaimo (~> 0.3.0) - rexml (~> 3.2.4) + rexml (>= 3.3.2, < 4.0) xcpretty (0.3.0) rouge (~> 2.0.7) xcpretty-travis-formatter (1.0.1) From e63c14fab0856cee91c2d0e0da6a2c17c8d94e12 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 22:24:37 +0200 Subject: [PATCH 84/99] Ensure InstantTaskExecutorRule is evaluated before VM creation --- .../editing/address/AddressViewModelTest.kt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/details/editing/address/AddressViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/details/editing/address/AddressViewModelTest.kt index 684f319280f..305c1fb6da0 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/details/editing/address/AddressViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/details/editing/address/AddressViewModelTest.kt @@ -56,12 +56,8 @@ class AddressViewModelTest : BaseUnitTest() { on { getStates(newCountry.code) } doReturn listOf(newState) } - private val addressViewModel = AddressViewModel( - savedStateHandle, - selectedSite, - dataStore, - GetLocations(dataStore) - ) + private lateinit var addressViewModel: AddressViewModel + private val viewStateObserver: Observer = mock() private val shippingAddress = CreateShippingLabelTestUtils.generateAddress().copy( country = testCountry, @@ -70,6 +66,12 @@ class AddressViewModelTest : BaseUnitTest() { @Before fun setup() { + addressViewModel = AddressViewModel( + savedStateHandle, + selectedSite, + dataStore, + GetLocations(dataStore) + ) addressViewModel.viewStateData.liveData.observeForever(viewStateObserver) addressViewModel.shouldEnableDoneButton.observeForever(mock()) } From e51bb4141cf0493a0a589c4b4056db437ceff368 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Aug 2024 17:38:05 -0300 Subject: [PATCH 85/99] Adjust analytics_call_to_action_view.xml margins --- .../src/main/res/layout/analytics_call_to_action_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml b/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml index 09a5fbc704a..89ab4013827 100644 --- a/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml +++ b/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml @@ -9,7 +9,7 @@ android:id="@+id/analyticsCallToActionCard" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="@dimen/major_75" + android:layout_marginTop="@dimen/major_75" android:orientation="vertical"> Date: Wed, 7 Aug 2024 17:41:25 -0300 Subject: [PATCH 86/99] Remove CTA from AnalyticsHub main view --- .../android/ui/analytics/hub/AnalyticsHubFragment.kt | 1 - .../android/ui/analytics/hub/AnalyticsHubViewModel.kt | 5 +---- .../android/ui/analytics/hub/AnalyticsHubViewState.kt | 1 - WooCommerce/src/main/res/layout/fragment_analytics.xml | 9 --------- 4 files changed, 1 insertion(+), 15 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubFragment.kt index 46cda4682fb..b5d8451394c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubFragment.kt @@ -162,7 +162,6 @@ class AnalyticsHubFragment : BaseFragment(R.layout.fragment_analytics) { binding.analyticsDateSelectorCard.updatePreviousRange(viewState.analyticsDateRangeSelectorState.previousRange) binding.analyticsDateSelectorCard.updateCurrentRange(viewState.analyticsDateRangeSelectorState.currentRange) binding.analyticsDateSelectorCard.updateLastUpdateTimestamp(viewState.lastUpdateTimestamp) - binding.analyticsCallToActionCard.updateInformation(viewState.ctaState) binding.analyticsRefreshLayout.isRefreshing = viewState.refreshIndicator == ShowIndicator displayFeedbackBanner(viewState.showFeedBackBanner) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt index b64f354a36a..3e3eda3fced 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt @@ -118,7 +118,6 @@ class AnalyticsHubViewModel @Inject constructor( refreshIndicator = NotShowIndicator, analyticsDateRangeSelectorState = AnalyticsHubDateRangeSelectorViewState.EMPTY, cards = AnalyticsHubCardViewState.LoadingCardsConfiguration, - ctaState = AnalyticsHubUserCallToActionViewState.EMPTY, showFeedBackBanner = false, lastUpdateTimestamp = "" ) @@ -830,9 +829,7 @@ class AnalyticsHubViewModel @Inject constructor( callToActionText = resourceProvider.getString(R.string.analytics_google_ads_cta_action), isVisible = isVisible, onCallToActionClickListener = { onGoogleAdsCTAClicked() } - ).let { newState -> - mutableState.update { it.copy(ctaState = newState) } - } + ) if (isVisible) { tracker.track( diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewState.kt index 3a48da178c5..6c42bc19c4f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewState.kt @@ -7,7 +7,6 @@ data class AnalyticsViewState( val refreshIndicator: RefreshIndicator, val analyticsDateRangeSelectorState: AnalyticsHubDateRangeSelectorViewState, val cards: AnalyticsHubCardViewState, - val ctaState: AnalyticsHubUserCallToActionViewState, val showFeedBackBanner: Boolean, val lastUpdateTimestamp: String ) diff --git a/WooCommerce/src/main/res/layout/fragment_analytics.xml b/WooCommerce/src/main/res/layout/fragment_analytics.xml index cf01e402aca..edaaca58333 100644 --- a/WooCommerce/src/main/res/layout/fragment_analytics.xml +++ b/WooCommerce/src/main/res/layout/fragment_analytics.xml @@ -50,15 +50,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/divider" /> - - Date: Wed, 7 Aug 2024 17:47:27 -0300 Subject: [PATCH 87/99] Update AnalyticsHubCustomSelectionCardView states to work with the CTA visibility --- .../ui/analytics/hub/AnalyticsHubCardState.kt | 9 ++++- .../ui/analytics/hub/AnalyticsHubViewModel.kt | 40 ++++++++----------- .../AnalyticsHubCustomSelectionCardView.kt | 4 +- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt index fa1783068cd..c6ee4ff4d59 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt @@ -85,8 +85,13 @@ sealed class AnalyticsHubCustomSelectionListViewState : AnalyticsCardViewState { } } - data class HiddenState( - override val card: AnalyticsCards + data class ShowCTAState( + override val card: AnalyticsCards, + val title: String, + val description: String, + val callToActionText: String, + val isVisible: Boolean, + val onCallToActionClickListener: () -> Unit ) : AnalyticsHubCustomSelectionListViewState() } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt index 3e3eda3fced..2d59bd8948b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt @@ -28,7 +28,7 @@ import com.woocommerce.android.model.SessionStat import com.woocommerce.android.model.StatType import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.CustomListViewState -import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.HiddenState +import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.ShowCTAState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.LoadingAdsViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubInformationViewState.DataViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubInformationViewState.LoadingViewState @@ -485,16 +485,27 @@ class AnalyticsHubViewModel @Inject constructor( private fun observeGoogleAdsChanges() { googleAdsObservationJob = updateStats.googleAdsState.onEach { state -> - updateGoogleAdsCTAVisibility(isVisible = false) - when (state) { is GoogleAdsState.Available -> { updateCardStatus(AnalyticsCards.GoogleAds, buildGoogleAdsDataViewState(state.googleAdsStat)) } is GoogleAdsState.Empty -> { - updateGoogleAdsCTAVisibility(isVisible = true) - updateCardStatus(AnalyticsCards.GoogleAds, HiddenState(AnalyticsCards.GoogleAds)) + tracker.track( + stat = AnalyticsEvent.GOOGLEADS_ENTRY_POINT_DISPLAYED, + properties = mapOf( + KEY_GOOGLEADS_SOURCE to VALUE_GOOGLEADS_ENTRY_POINT_TYPE_ANALYTICS_HUB + ) + ) + val ctaState = ShowCTAState( + card = AnalyticsCards.GoogleAds, + title = resourceProvider.getString(R.string.analytics_google_ads_cta_title), + description = resourceProvider.getString(R.string.analytics_google_ads_cta_description), + callToActionText = resourceProvider.getString(R.string.analytics_google_ads_cta_action), + isVisible = true, + onCallToActionClickListener = { onGoogleAdsCTAClicked() } + ) + updateCardStatus(AnalyticsCards.GoogleAds, ctaState) } is GoogleAdsState.Error -> { @@ -822,25 +833,6 @@ class AnalyticsHubViewModel @Inject constructor( giftCardsObservationJob?.cancel() } - private fun updateGoogleAdsCTAVisibility(isVisible: Boolean) { - AnalyticsHubUserCallToActionViewState( - title = resourceProvider.getString(R.string.analytics_google_ads_cta_title), - description = resourceProvider.getString(R.string.analytics_google_ads_cta_description), - callToActionText = resourceProvider.getString(R.string.analytics_google_ads_cta_action), - isVisible = isVisible, - onCallToActionClickListener = { onGoogleAdsCTAClicked() } - ) - - if (isVisible) { - tracker.track( - stat = AnalyticsEvent.GOOGLEADS_ENTRY_POINT_DISPLAYED, - properties = mapOf( - KEY_GOOGLEADS_SOURCE to VALUE_GOOGLEADS_ENTRY_POINT_TYPE_ANALYTICS_HUB - ) - ) - } - } - private fun onGoogleAdsCTAClicked() { selectedSite.getOrNull()?.let { it.adminUrlOrDefault + GOOGLE_ADMIN_CAMPAIGN_CREATION_SUFFIX diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt index e563419f94c..2a2e0f736be 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt @@ -13,7 +13,7 @@ import com.woocommerce.android.R import com.woocommerce.android.databinding.AnalyticsCustomSelectionCardViewBinding import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.CustomListViewState -import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.HiddenState +import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.ShowCTAState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.LoadingAdsViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.NoAdsState import com.woocommerce.android.ui.analytics.hub.informationcard.SeeReportClickListener @@ -37,7 +37,7 @@ class AnalyticsHubCustomSelectionCardView @JvmOverloads constructor( is LoadingAdsViewState -> setSkeleton() is NoAdsState -> setNoAdsViewState(viewState) is CustomListViewState -> setDataViewState(viewState) - is HiddenState -> setHiddenState() + is ShowCTAState -> setHiddenState() } } From d062a86f89298532aadcf0baf2d9a8c73cfc041f Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Aug 2024 18:01:27 -0300 Subject: [PATCH 88/99] Introduce the AnalyticsHubCustomSelectionCardView to analytics_custom_selection_card_view.xml --- .../res/layout/analytics_custom_selection_card_view.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WooCommerce/src/main/res/layout/analytics_custom_selection_card_view.xml b/WooCommerce/src/main/res/layout/analytics_custom_selection_card_view.xml index 1addd6c5bd2..87e4df11cab 100644 --- a/WooCommerce/src/main/res/layout/analytics_custom_selection_card_view.xml +++ b/WooCommerce/src/main/res/layout/analytics_custom_selection_card_view.xml @@ -6,6 +6,12 @@ android:layout_height="wrap_content" tools:context=".ui.analytics.hub.customlistcard.AnalyticsHubCustomSelectionCardView"> + + Date: Wed, 7 Aug 2024 18:01:46 -0300 Subject: [PATCH 89/99] Handle CTAState inside the AnalyticsHubCustomSelectionCardView --- .../android/ui/analytics/hub/AnalyticsHubCardState.kt | 11 ++++++++++- .../AnalyticsHubCustomSelectionCardView.kt | 9 +++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt index c6ee4ff4d59..57361a584ac 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubCardState.kt @@ -92,7 +92,16 @@ sealed class AnalyticsHubCustomSelectionListViewState : AnalyticsCardViewState { val callToActionText: String, val isVisible: Boolean, val onCallToActionClickListener: () -> Unit - ) : AnalyticsHubCustomSelectionListViewState() + ) : AnalyticsHubCustomSelectionListViewState() { + val asAnalyticsHubUserCallToActionViewState + get() = AnalyticsHubUserCallToActionViewState( + title = title, + description = description, + callToActionText = callToActionText, + isVisible = isVisible, + onCallToActionClickListener = onCallToActionClickListener + ) + } } data class AnalyticsHubUserCallToActionViewState( diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt index 2a2e0f736be..848b3774e4e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt @@ -37,13 +37,15 @@ class AnalyticsHubCustomSelectionCardView @JvmOverloads constructor( is LoadingAdsViewState -> setSkeleton() is NoAdsState -> setNoAdsViewState(viewState) is CustomListViewState -> setDataViewState(viewState) - is ShowCTAState -> setHiddenState() + is ShowCTAState -> setCtaState(viewState) } } - private fun setHiddenState() { + private fun setCtaState(state: ShowCTAState) { skeletonView.hide() binding.analyticsCustomCardListContainer.visibility = GONE + binding.analyticsCallToActionCard.visibility = VISIBLE + binding.analyticsCallToActionCard.updateInformation(state.asAnalyticsHubUserCallToActionViewState) } private fun setDataViewState(viewState: CustomListViewState) { @@ -78,6 +80,7 @@ class AnalyticsHubCustomSelectionCardView @JvmOverloads constructor( binding.analyticsListLeftHeader.visibility = VISIBLE binding.analyticsListRightHeader.visibility = VISIBLE binding.noDataText.visibility = GONE + binding.analyticsCallToActionCard.visibility = GONE viewState.reportUrl?.let { binding.reportGroup.visibility = VISIBLE @@ -121,6 +124,7 @@ class AnalyticsHubCustomSelectionCardView @JvmOverloads constructor( binding.analyticsListRightHeader.visibility = GONE binding.analyticsItemsTag.visibility = GONE binding.analyticsFilterButton.visibility = GONE + binding.analyticsCallToActionCard.visibility = GONE binding.noDataText.visibility = VISIBLE binding.noDataText.text = viewState.message } @@ -140,6 +144,7 @@ class AnalyticsHubCustomSelectionCardView @JvmOverloads constructor( binding.analyticsItemsTag.visibility = GONE binding.noDataText.visibility = GONE binding.analyticsFilterButton.visibility = GONE + binding.analyticsCallToActionCard.visibility = GONE } private fun getDeltaTagText(viewState: CustomListViewState) = From fdf5f9471455bd3b120bbbf04d705a39c832178a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Aug 2024 18:08:34 -0300 Subject: [PATCH 90/99] Fix incorrect constraints in fragment_analytics.xml --- WooCommerce/src/main/res/layout/fragment_analytics.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/res/layout/fragment_analytics.xml b/WooCommerce/src/main/res/layout/fragment_analytics.xml index edaaca58333..09b8f3aaca2 100644 --- a/WooCommerce/src/main/res/layout/fragment_analytics.xml +++ b/WooCommerce/src/main/res/layout/fragment_analytics.xml @@ -57,7 +57,7 @@ android:layout_marginTop="@dimen/major_100" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/analyticsCallToActionCard" /> + app:layout_constraintTop_toBottomOf="@+id/analyticsDateSelectorCard" /> From 2b54be0a38645f79e0db41066d5eee3416cea265 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Aug 2024 18:13:19 -0300 Subject: [PATCH 91/99] Update CTA margins in analytics_custom_selection_card_view.xml --- .../src/main/res/layout/analytics_call_to_action_view.xml | 2 +- .../main/res/layout/analytics_custom_selection_card_view.xml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml b/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml index 89ab4013827..87c6bb01364 100644 --- a/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml +++ b/WooCommerce/src/main/res/layout/analytics_call_to_action_view.xml @@ -9,7 +9,7 @@ android:id="@+id/analyticsCallToActionCard" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/major_75" + android:layout_marginVertical="@dimen/major_75" android:orientation="vertical"> + android:layout_height="wrap_content" /> Date: Wed, 7 Aug 2024 18:15:39 -0300 Subject: [PATCH 92/99] Fix lint issues --- .../android/ui/analytics/hub/AnalyticsHubViewModel.kt | 2 +- .../hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt index 2d59bd8948b..7f18b1f9f49 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt @@ -28,8 +28,8 @@ import com.woocommerce.android.model.SessionStat import com.woocommerce.android.model.StatType import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.CustomListViewState -import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.ShowCTAState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.LoadingAdsViewState +import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.ShowCTAState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubInformationViewState.DataViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubInformationViewState.LoadingViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubInformationViewState.NoDataState diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt index 848b3774e4e..e3a7786f695 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/customlistcard/AnalyticsHubCustomSelectionCardView.kt @@ -13,9 +13,9 @@ import com.woocommerce.android.R import com.woocommerce.android.databinding.AnalyticsCustomSelectionCardViewBinding import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.CustomListViewState -import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.ShowCTAState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.LoadingAdsViewState import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.NoAdsState +import com.woocommerce.android.ui.analytics.hub.AnalyticsHubCustomSelectionListViewState.ShowCTAState import com.woocommerce.android.ui.analytics.hub.informationcard.SeeReportClickListener import com.woocommerce.android.ui.analytics.hub.listcard.AnalyticsHubListAdapter import com.woocommerce.android.ui.analytics.hub.listcard.AnalyticsHubListCardView From b300df22e3d8a8faafd7a7a9b3632e2fae5c2c0e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Aug 2024 18:18:52 -0300 Subject: [PATCH 93/99] Refactor GoogleAds CTA state creation --- .../ui/analytics/hub/AnalyticsHubViewModel.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt index 7f18b1f9f49..c905effc0bf 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/analytics/hub/AnalyticsHubViewModel.kt @@ -497,15 +497,7 @@ class AnalyticsHubViewModel @Inject constructor( KEY_GOOGLEADS_SOURCE to VALUE_GOOGLEADS_ENTRY_POINT_TYPE_ANALYTICS_HUB ) ) - val ctaState = ShowCTAState( - card = AnalyticsCards.GoogleAds, - title = resourceProvider.getString(R.string.analytics_google_ads_cta_title), - description = resourceProvider.getString(R.string.analytics_google_ads_cta_description), - callToActionText = resourceProvider.getString(R.string.analytics_google_ads_cta_action), - isVisible = true, - onCallToActionClickListener = { onGoogleAdsCTAClicked() } - ) - updateCardStatus(AnalyticsCards.GoogleAds, ctaState) + updateCardStatus(AnalyticsCards.GoogleAds, buildGoogleAdsCTAViewState()) } is GoogleAdsState.Error -> { @@ -752,6 +744,17 @@ class AnalyticsHubViewModel @Inject constructor( ) } + private fun buildGoogleAdsCTAViewState(): ShowCTAState { + return ShowCTAState( + card = AnalyticsCards.GoogleAds, + title = resourceProvider.getString(R.string.analytics_google_ads_cta_title), + description = resourceProvider.getString(R.string.analytics_google_ads_cta_description), + callToActionText = resourceProvider.getString(R.string.analytics_google_ads_cta_action), + isVisible = true, + onCallToActionClickListener = { onGoogleAdsCTAClicked() } + ) + } + private fun onGoogleCampaignFilterSelected( googleAdsStats: GoogleAdsStat, selectedFilterName: String From 18bb28150eeef513c8b97aa7058876025348c7c1 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Aug 2024 23:25:36 +0200 Subject: [PATCH 94/99] Fix unit tests after TTP min OS version update --- .../taptopay/TapToPayAvailabilityStatusTest.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt index 067f4d23a5d..e564abf575f 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/taptopay/TapToPayAvailabilityStatusTest.kt @@ -16,7 +16,7 @@ import org.wordpress.android.fluxc.store.WooCommerceStore class TapToPayAvailabilityStatusTest { private val systemVersionUtilsWrapper = mock { - on { isAtLeastQ() }.thenReturn(true) + on { isAtLeastR() }.thenReturn(true) } private val cardReaderCountryConfigProvider: CardReaderCountryConfigProvider = mock { on { provideCountryConfigFor("US") }.thenReturn(CardReaderConfigForUSA) @@ -45,7 +45,7 @@ class TapToPayAvailabilityStatusTest { fun `given device has no NFC, when invoking, then nfc disabled returned`() { whenever(deviceFeatures.isNFCAvailable()).thenReturn(false) whenever(deviceFeatures.isGooglePlayServicesAvailable()).thenReturn(true) - whenever(systemVersionUtilsWrapper.isAtLeastQ()).thenReturn(true) + whenever(systemVersionUtilsWrapper.isAtLeastR()).thenReturn(true) val result = availabilityStatus.invoke() @@ -56,7 +56,7 @@ class TapToPayAvailabilityStatusTest { fun `given device has no Google Play Services, when invoking, then GPS not available`() { whenever(deviceFeatures.isNFCAvailable()).thenReturn(true) whenever(deviceFeatures.isGooglePlayServicesAvailable()).thenReturn(false) - whenever(systemVersionUtilsWrapper.isAtLeastQ()).thenReturn(true) + whenever(systemVersionUtilsWrapper.isAtLeastR()).thenReturn(true) val result = availabilityStatus.invoke() @@ -78,7 +78,7 @@ class TapToPayAvailabilityStatusTest { fun `given country other than US, when invoking, then country is not supported returned`() { whenever(deviceFeatures.isNFCAvailable()).thenReturn(true) whenever(deviceFeatures.isGooglePlayServicesAvailable()).thenReturn(true) - whenever(systemVersionUtilsWrapper.isAtLeastQ()).thenReturn(true) + whenever(systemVersionUtilsWrapper.isAtLeastR()).thenReturn(true) whenever(wooStore.getStoreCountryCode(siteModel)).thenReturn("RU") val result = availabilityStatus.invoke() @@ -90,7 +90,7 @@ class TapToPayAvailabilityStatusTest { fun `given device satisfies all the requirements, when invoking, then tpp available returned`() { whenever(deviceFeatures.isNFCAvailable()).thenReturn(true) whenever(deviceFeatures.isGooglePlayServicesAvailable()).thenReturn(true) - whenever(systemVersionUtilsWrapper.isAtLeastQ()).thenReturn(true) + whenever(systemVersionUtilsWrapper.isAtLeastR()).thenReturn(true) val result = availabilityStatus.invoke() From 719e688d8fbf194c34d97291ad9dda2a224b6685 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Thu, 8 Aug 2024 09:40:39 +0200 Subject: [PATCH 95/99] Fix detekt's complaints --- .../payments/cardreader/payment/CardReaderPaymentViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt index 854b829715f..eca9b2789c5 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt @@ -148,7 +148,7 @@ class CardReaderPaymentViewModel private val CardReaderFlowParam.PaymentOrRefund.isPOS: Boolean get() = this is CardReaderFlowParam.PaymentOrRefund.Payment && - this.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS + this.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS fun start() { if (cardReaderManager.readerStatus.value is CardReaderStatus.Connected) { From 792fce41eae044e93d543f3796e0d6f4df26e471 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 8 Aug 2024 10:22:11 +0200 Subject: [PATCH 96/99] Changed size of the check mark --- .../totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt index e2aeb5e679f..4e486fa669f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/payment/success/WooPosTotalsPaymentSuccessScreen.kt @@ -167,7 +167,7 @@ private fun CheckMarkIcon( modifier: Modifier = Modifier, ) { val size by animateDpAsState( - targetValue = if (animationStarted) 156.dp else 0.dp, + targetValue = if (animationStarted) 164.dp else 0.dp, label = "Check mark size" ) From ab16fefc7a97b0d9583507de4f679268d207d18a Mon Sep 17 00:00:00 2001 From: samiuelson Date: Thu, 8 Aug 2024 12:29:35 +0200 Subject: [PATCH 97/99] Clean up the code --- .../cardreader/payment/CardReaderPaymentViewModel.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt index eca9b2789c5..617c78d01a3 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt @@ -470,7 +470,7 @@ class CardReaderPaymentViewModel appPrefs.setCardReaderSuccessfulPaymentTime() if (arguments.paymentOrRefund.isPOS) { launch { - orderRepository.fetchOrderById(orderId) + syncOrderStatus(orderId) triggerEvent(Exit) } } else { @@ -480,6 +480,10 @@ class CardReaderPaymentViewModel } } + private suspend fun syncOrderStatus(orderId: Long) { + orderRepository.fetchOrderById(orderId) + } + @VisibleForTesting fun reFetchOrder() { refetchOrderJob = launch { From 3795ca614fb9e5e076d00c2cdc827c04159ed2d2 Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Thu, 8 Aug 2024 14:40:52 +0300 Subject: [PATCH 98/99] Add names to call arguments of ProductRefundListItem --- .../ui/payments/refunds/IssueRefundViewModel.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt index 3ead2becf0d..ee3fdc5d19c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt @@ -287,11 +287,11 @@ class IssueRefundViewModel @Inject constructor( val maxQuantity = maxQuantities[it.itemId] ?: 0f val selectedQuantity = min(selectedQuantities[it.itemId] ?: 0, maxQuantity.toInt()) ProductRefundListItem( - it, - maxQuantity, - selectedQuantity, - formatCurrency(BigDecimal.ZERO), - formatCurrency(BigDecimal.ZERO) + orderItem = it, + maxQuantity = maxQuantity, + quantity = selectedQuantity, + subtotal = formatCurrency(BigDecimal.ZERO), + taxes = formatCurrency(BigDecimal.ZERO) ) } updateRefundItems(items) From d5ba73732401fe0a924f034767939743da5eb1c7 Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Thu, 8 Aug 2024 15:04:22 +0300 Subject: [PATCH 99/99] Split ProductRefundListItem.calculateTotal() into two functions --- .../woocommerce/android/extensions/RefundsExt.kt | 16 +++++++++------- .../ui/payments/refunds/IssueRefundViewModel.kt | 8 +++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt index 66d4696947d..f7a32524773 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/RefundsExt.kt @@ -8,18 +8,20 @@ fun List.calculateTotals(): Pair var taxes = BigDecimal.ZERO var subtotal = BigDecimal.ZERO this.forEach { item -> - val (itemSubtotal, itemTaxes) = item.calculateTotal() - subtotal += itemSubtotal - taxes += itemTaxes + subtotal += item.calculateTotalSubtotal() + taxes += item.calculateTotalTaxes() } return Pair(subtotal, taxes) } -fun ProductRefundListItem.calculateTotal(): Pair { +fun ProductRefundListItem.calculateTotalSubtotal(): BigDecimal { + val quantity = quantity.toBigDecimal() + return quantity.times(orderItem.price) +} + +fun ProductRefundListItem.calculateTotalTaxes(): BigDecimal { val quantity = quantity.toBigDecimal() - val subtotal = quantity.times(orderItem.price) val singleItemTax = orderItem.totalTax.divide(orderItem.quantity.toBigDecimal(), 2, HALF_UP) - val taxes = quantity.times(singleItemTax) - return Pair(subtotal, taxes) + return quantity.times(singleItemTax) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt index ee3fdc5d19c..9f0be15d165 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/refunds/IssueRefundViewModel.kt @@ -18,7 +18,8 @@ import com.woocommerce.android.analytics.AnalyticsEvent.REFUND_CREATE_SUCCESS import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.analytics.AnalyticsTrackerWrapper import com.woocommerce.android.extensions.adminUrlOrDefault -import com.woocommerce.android.extensions.calculateTotal +import com.woocommerce.android.extensions.calculateTotalSubtotal +import com.woocommerce.android.extensions.calculateTotalTaxes import com.woocommerce.android.extensions.calculateTotals import com.woocommerce.android.extensions.isCashPayment import com.woocommerce.android.extensions.isEqualTo @@ -660,8 +661,9 @@ class IssueRefundViewModel @Inject constructor( var newItem = it.copy(quantity = newQuantity, maxQuantity = maxQuantities[uniqueId] ?: 0f) // Update the subtotal and taxes based on the new quantity - val (subtotal, taxes) = newItem.calculateTotal() - newItem = newItem.copy(subtotal = formatCurrency(subtotal), taxes = formatCurrency(taxes)) + val subtotal = formatCurrency(newItem.calculateTotalSubtotal()) + val taxes = formatCurrency(newItem.calculateTotalTaxes()) + newItem = newItem.copy(subtotal = subtotal, taxes = taxes) newItems.add(newItem) } else {