From 5d1e5faaf87cecd5b1dd8cacd7464ee95e85b601 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Fri, 3 Jan 2025 09:59:09 +0530 Subject: [PATCH 01/65] Inject javascript and enlarge receipt content --- .../receipt/preview/ReceiptPreviewFragment.kt | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt index f0103e43069..65803bc6f6e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt @@ -5,6 +5,7 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View +import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient import androidx.core.view.MenuProvider @@ -84,12 +85,31 @@ class ReceiptPreviewFragment : BaseFragment(R.layout.fragment_receipt_preview), } else { with(binding.receiptPreviewPreviewWebview) { webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView, webResourceRequest: WebResourceRequest): Boolean { + return viewModel.isReceiptDomainTrustable(webResourceRequest.url.toString()) + } override fun onPageFinished(view: WebView, url: String) { + view.evaluateJavascript( + "document.body.style.zoom = 1.0; " + + "var meta = document.createElement('meta'); " + + "meta.name = 'viewport'; " + + "meta.content = 'width=device-width, initial-scale=1.0'; " + + "document.getElementsByTagName('head')[0].appendChild(meta);", + null + ) viewModel.onReceiptLoaded() } } - settings.loadWithOverviewMode = true - settings.useWideViewPort = true + settings.apply { + javaScriptEnabled = true + loadWithOverviewMode = true + useWideViewPort = true + builtInZoomControls = true + displayZoomControls = false + allowFileAccess = false + allowContentAccess = false + domStorageEnabled = false + } } } } From 91f67dd2461df17b2150e87c270c3d2b63e5301b Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Fri, 3 Jan 2025 09:59:41 +0530 Subject: [PATCH 02/65] Add logic to test that receipt domain is same as selected site domain before loading receipt URL for security purposes --- .../preview/ReceiptPreviewViewModel.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt index 54cf312c698..3dadf7c6ad6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.R.string +import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Content import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Loading @@ -17,6 +18,7 @@ import com.woocommerce.android.viewmodel.ScopedViewModel import com.woocommerce.android.viewmodel.navArgs import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch +import java.net.URI import javax.inject.Inject @HiltViewModel @@ -25,6 +27,7 @@ class ReceiptPreviewViewModel savedState: SavedStateHandle, private val paymentsFlowTracker: PaymentsFlowTracker, private val paymentReceiptShare: PaymentReceiptShare, + private val selectedSite: SelectedSite, ) : ScopedViewModel(savedState) { private val args: ReceiptPreviewFragmentArgs by savedState.navArgs() @@ -39,6 +42,23 @@ class ReceiptPreviewViewModel viewState.value = Content } + fun isReceiptDomainTrustable(receiptUrl: String): Boolean { + return selectedSite.getIfExists()?.let { site -> + getDomainName(site.url) == getDomainName(receiptUrl) + } ?: false + } + + private fun getDomainName(url: String): String? { + return try { + val uri = URI(url) + uri.host?.let { + if (it.startsWith("www.")) it.substring(4) else it + } + } catch (e: Exception) { + null + } + } + fun onPrintClicked() { launch { paymentsFlowTracker.trackPrintReceiptTapped() From 9bda31509b50173390a8e927389e62a49b2a887b Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Fri, 3 Jan 2025 10:00:07 +0530 Subject: [PATCH 03/65] Add test to verify that we return true when receipt url is same as selected site url --- .../preview/ReceiptPreviewViewModelTest.kt | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt index 15af89dba90..411881059f9 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt @@ -2,6 +2,7 @@ package com.woocommerce.android.ui.payments.receipt.preview import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.R +import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Content import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Loading @@ -18,6 +19,7 @@ import org.junit.Test import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever +import org.wordpress.android.fluxc.model.SiteModel @ExperimentalCoroutinesApi class ReceiptPreviewViewModelTest : BaseUnitTest() { @@ -25,6 +27,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { private val paymentsFlowTracker: PaymentsFlowTracker = mock() private val paymentReceiptShare: PaymentReceiptShare = mock() + private val selectedSite: SelectedSite = mock() private val savedState: SavedStateHandle = ReceiptPreviewFragmentArgs( receiptUrl = "testing url", @@ -34,7 +37,12 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Before fun setUp() { - viewModel = ReceiptPreviewViewModel(savedState, paymentsFlowTracker, paymentReceiptShare) + viewModel = ReceiptPreviewViewModel( + savedState, + paymentsFlowTracker, + paymentReceiptShare, + selectedSite + ) } @Test @@ -186,4 +194,18 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { verify(paymentsFlowTracker).trackPrintReceiptSucceeded() } + + @Test + fun `given valid receipt domain, then isReceiptTrustable returns true`() = + testBlocking { + whenever(selectedSite.getIfExists()).thenReturn( + SiteModel().apply { + url = "https://www.woocommerce.com" + origin = SiteModel.ORIGIN_WPAPI + } + ) + val receiptUrl = "https://www.woocommerce.com/receipt" + + assertThat(viewModel.isReceiptDomainTrustable(receiptUrl)).isTrue() + } } From 90ed272fe39dcf6346e4deec23bc809df40036f1 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Fri, 3 Jan 2025 10:03:02 +0530 Subject: [PATCH 04/65] Add test to verify that we return false when receipt url is not same as selected site url --- .../receipt/preview/ReceiptPreviewViewModelTest.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt index 411881059f9..b16db3845b8 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt @@ -208,4 +208,18 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { assertThat(viewModel.isReceiptDomainTrustable(receiptUrl)).isTrue() } + + @Test + fun `given invalid receipt domain, then isReceiptTrustable returns false`() = + testBlocking { + whenever(selectedSite.getIfExists()).thenReturn( + SiteModel().apply { + url = "https://www.woocommerce.com" + origin = SiteModel.ORIGIN_WPAPI + } + ) + val receiptUrl = "https://www.wocommerce.com/receipt" + + assertThat(viewModel.isReceiptDomainTrustable(receiptUrl)).isFalse() + } } From e1904487ef6aadf5e8f26e9a50dfaecf4fb11b99 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Fri, 3 Jan 2025 10:25:13 +0530 Subject: [PATCH 05/65] Fix detekt errors --- .../receipt/preview/ReceiptPreviewFragment.kt | 5 ++++- .../receipt/preview/ReceiptPreviewViewModel.kt | 13 ++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt index 65803bc6f6e..a1add050281 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewFragment.kt @@ -85,7 +85,10 @@ class ReceiptPreviewFragment : BaseFragment(R.layout.fragment_receipt_preview), } else { with(binding.receiptPreviewPreviewWebview) { webViewClient = object : WebViewClient() { - override fun shouldOverrideUrlLoading(view: WebView, webResourceRequest: WebResourceRequest): Boolean { + override fun shouldOverrideUrlLoading( + view: WebView, + webResourceRequest: WebResourceRequest + ): Boolean { return viewModel.isReceiptDomainTrustable(webResourceRequest.url.toString()) } override fun onPageFinished(view: WebView, url: String) { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt index 3dadf7c6ad6..1ec0915cc4a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt @@ -13,12 +13,14 @@ import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult.CANCELLED import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult.FAILED import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult.STARTED +import com.woocommerce.android.util.WooLog import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowSnackbar import com.woocommerce.android.viewmodel.ScopedViewModel import com.woocommerce.android.viewmodel.navArgs import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import java.net.URI +import java.net.URISyntaxException import javax.inject.Inject @HiltViewModel @@ -52,10 +54,11 @@ class ReceiptPreviewViewModel return try { val uri = URI(url) uri.host?.let { - if (it.startsWith("www.")) it.substring(4) else it + if (it.startsWith("www.")) it.substring(WWW_PREFIX_LENGTH) else it } - } catch (e: Exception) { - null + } catch (e: URISyntaxException) { + WooLog.e(WooLog.T.ORDERS, "Error parsing domain name from receipt url: $url") + return null } } @@ -110,4 +113,8 @@ class ReceiptPreviewViewModel object Loading : ReceiptPreviewViewState(isProgressVisible = true) object Content : ReceiptPreviewViewState(isContentVisible = true) } + + companion object { + private const val WWW_PREFIX_LENGTH = 4 + } } From bb52a3b293af3d9a7c58f931a7e53ea32bb20a15 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Thu, 9 Jan 2025 09:46:32 +0530 Subject: [PATCH 06/65] Added release notes --- RELEASE-NOTES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index ae35046fbb1..9b8b96ae0d3 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,10 @@ *** PLEASE FOLLOW THIS FORMAT: [] [] *** Use [*****] to indicate smoke tests of all critical flows should be run on the final APK before release (e.g. major library or targetSdk updates). *** For entries which are touching the Android Wear app's, start entry with `[WEAR]` too. +21.5 +----- +- [**] Enhanced WebView to dynamically scale receipt content, ensuring optimal fit across all device screen sizes. [https://github.com/woocommerce/woocommerce-android/pull/13266] + 21.4 ----- - [*] Fix Dashboard card menu sizing to fit bigger font sizes and longer text. [https://github.com/woocommerce/woocommerce-android/pull/13184] From 29eb5e581e13f12d014b245f7b429b913a8ec836 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 9 Jan 2025 10:17:52 +0100 Subject: [PATCH 07/65] Updated min sdk version --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 6506be3dedd..8c21ecd4fb5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -40,7 +40,7 @@ gradle.ext.mediaPickerSourceGifBinaryPath = "org.wordpress.mediapicker:source-gi gradle.ext.mediaPickerSourceWordPressBinaryPath = "org.wordpress.mediapicker:source-wordpress" gradle.ext { - compileSdkVersion = 34 + compileSdkVersion = 35 targetSdkVersion = 34 minSdkVersion = 26 } From 77e301fd621ca11da33eb1fd983894a544e10ef1 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 9 Jan 2025 10:18:46 +0100 Subject: [PATCH 08/65] Use compileSdk instead of compileSdkVersion in the modules that won't be deleted --- WooCommerce/build.gradle | 2 +- libs/cardreader/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/build.gradle b/WooCommerce/build.gradle index 71dc80c9291..8c8f5309ab7 100644 --- a/WooCommerce/build.gradle +++ b/WooCommerce/build.gradle @@ -107,7 +107,7 @@ def versionProperties = loadPropertiesFromFile(file("${rootDir}/version.properti android { namespace "com.woocommerce.android" - compileSdkVersion gradle.ext.compileSdkVersion + compileSdk gradle.ext.compileSdkVersion defaultConfig { applicationId "com.woocommerce.android" diff --git a/libs/cardreader/build.gradle b/libs/cardreader/build.gradle index 4a082ede46f..2521864856b 100644 --- a/libs/cardreader/build.gradle +++ b/libs/cardreader/build.gradle @@ -7,7 +7,7 @@ plugins { android { namespace "com.woocommerce.android.cardreader" - compileSdkVersion gradle.ext.compileSdkVersion + compileSdk gradle.ext.compileSdkVersion defaultConfig { minSdkVersion gradle.ext.minSdkVersion From d7c803751159908db3e0ebe498a12daa5b68a707 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 9 Jan 2025 11:39:03 +0100 Subject: [PATCH 09/65] Deprecated on low memory --- .../woocommerce/android/util/ApplicationLifecycleMonitor.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ApplicationLifecycleMonitor.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ApplicationLifecycleMonitor.kt index e1127c9532b..cf81434decf 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ApplicationLifecycleMonitor.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ApplicationLifecycleMonitor.kt @@ -46,10 +46,11 @@ class ApplicationLifecycleMonitor( override fun onActivityCreated(activity: Activity, p1: Bundle?) {} - override fun onLowMemory() {} - override fun onConfigurationChanged(configuration: Configuration) {} + @Deprecated("Parent method is deprecated, so this method has to be also deprecated") + override fun onLowMemory() {} + override fun onTrimMemory(level: Int) { if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { lastState = LastApplicationState.BACKGROUND From 4b914bbe2ce016046b528ea74aad65ae95579d37 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 10 Jan 2025 11:19:12 +0100 Subject: [PATCH 10/65] Replaced deprecated API usage with theme setting for WooPosCardReaderActivity.kt --- .../android/ui/woopos/cardreader/WooPosCardReaderActivity.kt | 2 -- WooCommerce/src/main/res/values/themes.xml | 5 +++++ build.gradle | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderActivity.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderActivity.kt index e52068b301f..b11ee284e64 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderActivity.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderActivity.kt @@ -6,7 +6,6 @@ import android.content.pm.ActivityInfo import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat @@ -37,7 +36,6 @@ class WooPosCardReaderActivity : AppCompatActivity(R.layout.activity_woo_pos_car } private fun setupTopAndBottomInsets() { - window.navigationBarColor = ContextCompat.getColor(this, android.R.color.transparent) WindowCompat.setDecorFitsSystemWindows(window, false) val rootView = findViewById(R.id.snack_root) ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, insets -> diff --git a/WooCommerce/src/main/res/values/themes.xml b/WooCommerce/src/main/res/values/themes.xml index b04f19f7cde..e81933268e0 100644 --- a/WooCommerce/src/main/res/values/themes.xml +++ b/WooCommerce/src/main/res/values/themes.xml @@ -161,5 +161,10 @@ true false true + + @android:color/transparent + @android:color/transparent + true + true diff --git a/build.gradle b/build.gradle index 6fa70f15ae0..a192270bbf4 100644 --- a/build.gradle +++ b/build.gradle @@ -68,7 +68,8 @@ allprojects { tasks.withType(KotlinCompile).all { kotlinOptions { jvmTarget = libs.versions.java.get() - allWarningsAsErrors = true + // todo revert back before merging + allWarningsAsErrors = false freeCompilerArgs += [ "-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all-compatibility", From 85dc61e044571c705e066a69fd5b74c57506ce57 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 10 Jan 2025 11:29:22 +0100 Subject: [PATCH 11/65] Replaced deprecated API usage with theme setting for WooPosActivity.kt --- WooCommerce/src/main/AndroidManifest.xml | 3 +- .../android/ui/woopos/root/WooPosActivity.kt | 11 ----- WooCommerce/src/main/res/values/themes.xml | 42 ++++++++++++++----- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/WooCommerce/src/main/AndroidManifest.xml b/WooCommerce/src/main/AndroidManifest.xml index 6b96d630962..f3e73dc44b2 100644 --- a/WooCommerce/src/main/AndroidManifest.xml +++ b/WooCommerce/src/main/AndroidManifest.xml @@ -166,10 +166,11 @@ tools:replace="android:screenOrientation" /> + android:theme="@style/Theme.WooPos.Transparent" /> - + - + + - - From 4b3057562f3192aa7ab7046ab853b470de136f5f Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:34:22 +0100 Subject: [PATCH 35/65] Use system utils to check Android version --- .../compose/component/WCModalBottomSheetLayout.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index eeafab435b2..32fbabd164a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.unit.Dp import androidx.core.view.WindowCompat import com.woocommerce.android.R import com.woocommerce.android.extensions.findActivity +import com.woocommerce.android.util.SystemVersionUtils /** * A wrapper around [ModalBottomSheetLayout] that provides default values for the sheet shape and scrim color. @@ -54,22 +55,22 @@ fun WCModalBottomSheetLayout( ), content: @Composable () -> Unit ) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM) { - ModalBottomSheetLayout( + if (SystemVersionUtils.isAtMostU()) { + ModalBottomSheetLayoutWithStatusBarWorkAround( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, - scrimColor = scrimColor(), modifier = modifier, - content = content + content = content, ) } else { - ModalBottomSheetLayoutWithStatusBarWorkAround( + ModalBottomSheetLayout( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, + scrimColor = scrimColor(), modifier = modifier, - content = content, + content = content ) } } From d58be6d69d1090b7c025b870c1b87839a24e3c38 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:34:50 +0100 Subject: [PATCH 36/65] Fix typo --- .../android/ui/compose/component/WCModalBottomSheetLayout.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 32fbabd164a..1670e6ebfa1 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -56,7 +56,7 @@ fun WCModalBottomSheetLayout( content: @Composable () -> Unit ) { if (SystemVersionUtils.isAtMostU()) { - ModalBottomSheetLayoutWithStatusBarWorkAround( + ModalBottomSheetLayoutWithStatusBarWorkaround( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, @@ -85,7 +85,7 @@ fun WCModalBottomSheetLayout( @Suppress("DEPRECATION") @OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable -private fun ModalBottomSheetLayoutWithStatusBarWorkAround( +private fun ModalBottomSheetLayoutWithStatusBarWorkaround( sheetContent: @Composable ColumnScope.() -> Unit, modifier: Modifier = Modifier, sheetState: ModalBottomSheetState, From a3f0637096fdc0a57ddd2e91e4c6a6852d5fb5e1 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:43:27 +0100 Subject: [PATCH 37/65] Remove ime nested scroll from bottomsheet modifier --- .../android/ui/compose/component/WCModalBottomSheetLayout.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 1670e6ebfa1..da58710290d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.imeNestedScroll import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.statusBarsPadding @@ -112,7 +111,6 @@ private fun ModalBottomSheetLayoutWithStatusBarWorkaround( modifier = modifier .imePadding() .navigationBarsPadding() - .imeNestedScroll(), ) { val context = LocalContext.current var statusBarColor by remember { mutableStateOf(Color.Transparent) } From 76208b377673f1d1f65d33a104c9d41bd997f3c9 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:45:38 +0100 Subject: [PATCH 38/65] Fix bottomsheet for Blaze intro screen to show content edge to edge --- .../intro/BlazeCampaignCreationIntroScreen.kt | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt index 9193744b89b..5577ed51875 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt @@ -56,6 +56,7 @@ import com.woocommerce.android.ui.compose.component.WCColoredButton import com.woocommerce.android.ui.compose.component.WCModalBottomSheetLayout import com.woocommerce.android.ui.compose.component.WCTextButton import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch @Composable @@ -78,41 +79,40 @@ fun BlazeCampaignCreationIntroScreen( onDismissClick: () -> Unit, onLearnMoreClick: () -> Unit, ) { - Scaffold( - topBar = { - Toolbar( - onNavigationButtonClick = onDismissClick, - navigationIcon = Icons.Default.Clear + val coroutineScope = rememberCoroutineScope() + val modalSheetState = rememberModalBottomSheetState( + initialValue = Hidden, + confirmValueChange = { it != HalfExpanded }, + skipHalfExpanded = true + ) + + WCModalBottomSheetLayout( + sheetContent = { + BlazeCampaignBottomSheetContent( + onDismissClick = { + coroutineScope.launch { modalSheetState.hide() } + } ) }, + sheetState = modalSheetState, modifier = Modifier.background(MaterialTheme.colors.surface) - ) { paddingValues -> - val coroutineScope = rememberCoroutineScope() - val modalSheetState = rememberModalBottomSheetState( - initialValue = Hidden, - confirmValueChange = { it != HalfExpanded }, - skipHalfExpanded = true - ) - - WCModalBottomSheetLayout( - sheetContent = { - BlazeCampaignBottomSheetContent( - onDismissClick = { - coroutineScope.launch { modalSheetState.hide() } - } + ) { + Scaffold( + topBar = { + Toolbar( + onNavigationButtonClick = onDismissClick, + navigationIcon = Icons.Default.Clear ) }, - sheetState = modalSheetState, - modifier = Modifier - .background(MaterialTheme.colors.surface) - .padding(paddingValues) - ) { + modifier = Modifier.background(MaterialTheme.colors.surface) + ) { paddingValues -> BlazeCampaignCreationIntroContent( onContinueClick = onContinueClick, onLearnMoreClick = { coroutineScope.launch { modalSheetState.show() } onLearnMoreClick() - } + }, + modifier = Modifier.padding(paddingValues) ) } } From 5c5aed723a758d14ceb232d757475880375f77af Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 19:01:17 +0100 Subject: [PATCH 39/65] Moved imeNestedScroll to the specific bottom sheet that requires it --- ...mpaignCreationAdDestinationParametersBottomSheet.kt | 10 +++++++--- .../ui/compose/component/WCModalBottomSheetLayout.kt | 4 ---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt index 3fbae44f498..5f2894e179a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt @@ -3,9 +3,11 @@ package com.woocommerce.android.ui.blaze.creation.destination import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imeNestedScroll import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape @@ -33,7 +35,7 @@ import com.woocommerce.android.ui.compose.component.WCOutlinedTextField import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground -@OptIn(ExperimentalMaterialApi::class) +@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable fun AdDestinationParametersBottomSheet( viewState: ViewState, @@ -65,10 +67,12 @@ fun AdDestinationParametersBottomSheet( paramsState = viewState.bottomSheetState, onParameterChanged = onParameterChanged, onParameterSaved = onParameterSaved, - modifier = modifier.fillMaxWidth() + modifier = modifier + .fillMaxWidth() ) } - } + }, + modifier = Modifier.imeNestedScroll(), ) { screenContent() } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index da58710290d..e2cdc3df515 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -5,14 +5,12 @@ import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.MaterialTheme import androidx.compose.material.ModalBottomSheetDefaults import androidx.compose.material.ModalBottomSheetLayout @@ -42,7 +40,6 @@ import com.woocommerce.android.util.SystemVersionUtils /** * A wrapper around [ModalBottomSheetLayout] that provides default values for the sheet shape and scrim color. */ -@OptIn(ExperimentalMaterialApi::class) @Composable fun WCModalBottomSheetLayout( sheetState: ModalBottomSheetState, @@ -82,7 +79,6 @@ fun WCModalBottomSheetLayout( * */ @Suppress("DEPRECATION") -@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable private fun ModalBottomSheetLayoutWithStatusBarWorkaround( sheetContent: @Composable ColumnScope.() -> Unit, From f62b5fea3c1391911497a0a07a8403de5698acf6 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 15 Jan 2025 11:58:32 +0530 Subject: [PATCH 40/65] Add a boolean param to indicate whether the order is free or not --- .../android/ui/woopos/home/totals/WooPosTotalsViewState.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewState.kt index 9ccfe65b940..67634f6bfde 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewState.kt @@ -12,6 +12,7 @@ sealed class WooPosTotalsViewState : Parcelable { val orderTaxText: String, val orderTotalText: String, val readerStatus: ReaderStatus, + val isFreeOrder: Boolean, ) : WooPosTotalsViewState() data class PaymentSuccess(val orderTotalText: String) : WooPosTotalsViewState() From 82710980d981bbde25f02a59666d3286a57fb4ef Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 15 Jan 2025 11:59:06 +0530 Subject: [PATCH 41/65] Update view state when there is free order added to cart --- .../android/ui/woopos/home/totals/WooPosTotalsViewModel.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt index 40da8f0109e..f341e21aa6e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt @@ -122,6 +122,7 @@ class WooPosTotalsViewModel @Inject constructor( uiState.value = state.copy(readerStatus = buildTotalsReaderNotConnectedError()) cancelPaymentAction() } + is Connected -> { val state = uiState.value if (state !is WooPosTotalsViewState.Totals) return@collect @@ -253,7 +254,10 @@ class WooPosTotalsViewModel @Inject constructor( } else { val orderId = dataState.value.orderId check(orderId != EMPTY_ORDER_ID) - if (cardReaderFacade.readerStatus.value is Connected) { + if ( + cardReaderFacade.readerStatus.value is Connected && + dataState.value.orderTotal?.compareTo(BigDecimal.ZERO) == 1 + ) { val state = uiState.value check(state is WooPosTotalsViewState.Totals) check(uiState.value is WooPosTotalsViewState.Totals) @@ -458,6 +462,7 @@ class WooPosTotalsViewModel @Inject constructor( orderTaxText = priceFormat(taxAmount), orderTotalText = priceFormat(totalAmount), readerStatus = readerStatus, + isFreeOrder = totalAmount.compareTo(BigDecimal.ZERO) == 1 ) } From a61c31e4a3e3af685eb9d9a0155a43aae94c4f5f Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 15 Jan 2025 11:59:21 +0530 Subject: [PATCH 42/65] Hide card payment screen for free orders --- .../woopos/home/totals/WooPosTotalsScreen.kt | 71 +++++++++++++------ 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsScreen.kt index a0c3b906785..bc033e7215d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsScreen.kt @@ -151,26 +151,28 @@ private fun TotalsLoaded( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { - Column( - modifier = Modifier - .fillMaxWidth() - .weight(1.1f) - .background(WooPosTheme.colors.totalsErrorBackground), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - when (val readerStatus = state.readerStatus) { - is WooPosTotalsViewState.ReaderStatus.Disconnected -> { - ReaderDisconnected(modifier = Modifier, status = readerStatus, onUIEvent = onUIEvent) - } - - is WooPosTotalsViewState.ReaderStatus.Preparing, - is WooPosTotalsViewState.ReaderStatus.CheckingOrder -> { - PreparingReader(readerStatus) - } - - is WooPosTotalsViewState.ReaderStatus.ReadyForPayment -> { - ReaderReadyForPayment(readerStatus) + if (!state.isFreeOrder) { + Column( + modifier = Modifier + .fillMaxWidth() + .weight(1.1f) + .background(WooPosTheme.colors.totalsErrorBackground), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + when (val readerStatus = state.readerStatus) { + is WooPosTotalsViewState.ReaderStatus.Disconnected -> { + ReaderDisconnected(modifier = Modifier, status = readerStatus, onUIEvent = onUIEvent) + } + + is WooPosTotalsViewState.ReaderStatus.Preparing, + is WooPosTotalsViewState.ReaderStatus.CheckingOrder -> { + PreparingReader(readerStatus) + } + + is WooPosTotalsViewState.ReaderStatus.ReadyForPayment -> { + ReaderReadyForPayment(readerStatus) + } } } } @@ -418,6 +420,7 @@ fun WooPosTotalsScreenPreview(modifier: Modifier = Modifier) { title = "Ready for payment", subtitle = "Tap, swipe or insert card" ), + isFreeOrder = false ), onUIEvent = {}, ) @@ -438,7 +441,8 @@ fun WooPosTotalsScreenPreviewReaderNotConnected(modifier: Modifier = Modifier) { title = "Reader not connected", subtitle = "To process this payment, please connect your reader.", actionButtonLabel = "Connect to a reader", - ) + ), + isFreeOrder = false ), onUIEvent = {}, ) @@ -459,7 +463,30 @@ fun WooPosTotalsScreenPreviewWithCashPaymentAvailable() { title = "Reader not connected", subtitle = "To process this payment, please connect your reader.", actionButtonLabel = "Connect to a reader", - ) + ), + isFreeOrder = false + ), + onUIEvent = {}, + ) + } +} + +@Composable +@WooPosPreview +fun WooPosTotalsScreenPreviewForFreeOrders() { + WooPosTheme { + WooPosTotalsScreen( + modifier = Modifier, + state = WooPosTotalsViewState.Totals( + orderSubtotalText = "$420.00", + orderTotalText = "$462.00", + orderTaxText = "$42.00", + readerStatus = WooPosTotalsViewState.ReaderStatus.Disconnected( + title = "Reader not connected", + subtitle = "To process this payment, please connect your reader.", + actionButtonLabel = "Connect to a reader", + ), + isFreeOrder = true ), onUIEvent = {}, ) From 5e38fc5740d5d7ec38bff8f0f59e80751953fdf1 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 15 Jan 2025 13:22:07 +0530 Subject: [PATCH 43/65] Change logic to identify whether the order is free or not. --- .../android/ui/woopos/home/totals/WooPosTotalsViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt index f341e21aa6e..04828815e95 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt @@ -462,7 +462,7 @@ class WooPosTotalsViewModel @Inject constructor( orderTaxText = priceFormat(taxAmount), orderTotalText = priceFormat(totalAmount), readerStatus = readerStatus, - isFreeOrder = totalAmount.compareTo(BigDecimal.ZERO) == 1 + isFreeOrder = totalAmount.compareTo(BigDecimal.ZERO) == 0 ) } From 601ad2eb0c54eeff7f4b726e8608f8c8bf96ff2a Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 15 Jan 2025 14:32:29 +0530 Subject: [PATCH 44/65] Remove unnecessary tests --- .../WooPosVariationsDataSourceTest.kt | 70 ------------------- 1 file changed, 70 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/variations/WooPosVariationsDataSourceTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/variations/WooPosVariationsDataSourceTest.kt index aa0ea1678ad..ba244fe8f96 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/variations/WooPosVariationsDataSourceTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/variations/WooPosVariationsDataSourceTest.kt @@ -335,74 +335,4 @@ class WooPosVariationsDataSourceTest { assertFalse(cachedResult.data.any { it.remoteVariationId == 1L }) } - - @Test - fun `given cached variations, when fetchFirstPage called, then filter out downloadable variations`() = runTest { - // GIVEN - val productId = 1L - whenever(handler.canLoadMore(5)).thenReturn(false) - whenever(handler.getVariationsFlow(productId)).thenReturn( - flowOf( - listOf( - ProductTestUtils.generateProductVariation( - variationId = 1, - amount = "0", - isDownloadable = true - ), - ProductTestUtils.generateProductVariation( - variationId = 2, - amount = "20.0", - isVirtual = false, - isDownloadable = false - ) - ) - ) - ) - whenever(handler.fetchVariations(productId, forceRefresh = false)).thenReturn(Result.success(Unit)) - whenever(variationsCache.get(productId)).thenReturn(sampleProducts) - val sut = WooPosVariationsDataSource(handler, variationsCache) - - // WHEN - val flow = sut.fetchFirstPage(productId, forceRefresh = false).toList() - - // THEN - val cachedResult = flow[0] as FetchResult.Cached - - assertFalse(cachedResult.data.any { it.remoteVariationId == 1L }) - } - - @Test - fun `given remote variations, when fetchFirstPage called, then filter out downloadable variations`() = runTest { - // GIVEN - val productId = 1L - whenever(handler.canLoadMore(5)).thenReturn(true) - whenever(handler.getVariationsFlow(productId)).thenReturn( - flowOf( - listOf( - ProductTestUtils.generateProductVariation( - variationId = 1, - amount = "0", - isDownloadable = true - ), - ProductTestUtils.generateProductVariation( - variationId = 2, - amount = "20.0", - isVirtual = false, - isDownloadable = false - ) - ) - ) - ) - whenever(handler.fetchVariations(productId, forceRefresh = true)).thenReturn(Result.success(Unit)) - whenever(variationsCache.get(productId)).thenReturn(sampleProducts) - val sut = WooPosVariationsDataSource(handler, variationsCache) - - // WHEN - val flow = sut.fetchFirstPage(productId, forceRefresh = true).toList() - - // THEN - val remoteResult = flow[1] as FetchResult.Remote - - assertThat(remoteResult.result.getOrNull()?.any { it.remoteVariationId == 1L }).isFalse() - } } From 9dfff656518b781f5bb19c2536ed54433b8a2447 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 15 Jan 2025 14:34:28 +0530 Subject: [PATCH 45/65] Remove unused import --- .../ui/woopos/home/items/products/WooPosProductsDataSource.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSource.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSource.kt index 20dbdb233e3..261e4b4786b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSource.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSource.kt @@ -2,7 +2,6 @@ package com.woocommerce.android.ui.woopos.home.items.products import com.woocommerce.android.model.Product import com.woocommerce.android.ui.products.ProductStatus -import com.woocommerce.android.ui.products.ProductType.VARIABLE import com.woocommerce.android.ui.products.selector.ProductListHandler import com.woocommerce.android.util.WooLog import kotlinx.coroutines.Dispatchers From 9a0014537b93a44c59a4f95aafc10f0bdab1e7df Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 15 Jan 2025 12:12:30 +0100 Subject: [PATCH 46/65] allWarningsAsErrors back to true as all fixed --- build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a192270bbf4..6fa70f15ae0 100644 --- a/build.gradle +++ b/build.gradle @@ -68,8 +68,7 @@ allprojects { tasks.withType(KotlinCompile).all { kotlinOptions { jvmTarget = libs.versions.java.get() - // todo revert back before merging - allWarningsAsErrors = false + allWarningsAsErrors = true freeCompilerArgs += [ "-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all-compatibility", From c930affc5545c668592f0ce01bcc328f9e10ef50 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 25 Dec 2024 13:22:28 +0100 Subject: [PATCH 47/65] Improve build fields auto declaration to support booleans --- WooCommerce/build.gradle | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/WooCommerce/build.gradle b/WooCommerce/build.gradle index 57329a1b6f4..d13e4a82c46 100644 --- a/WooCommerce/build.gradle +++ b/WooCommerce/build.gradle @@ -489,8 +489,13 @@ task copyGoogleServicesExampleFile(type: Copy) { android.buildTypes.all { buildType -> (secretProperties + developerProperties).any { property -> if (property.key.toLowerCase().startsWith("wc.")) { - buildType.buildConfigField "String", property.key.replace("wc.", "").replace(".", "_").toUpperCase(), - "\"${property.value}\"" + if (property.value == "true" || property.value == "false") { + buildType.buildConfigField "boolean", property.key.replace("wc.", "").replace(".", "_").toUpperCase(), + property.value + } else { + buildType.buildConfigField "String", property.key.replace("wc.", "").replace(".", "_").toUpperCase(), + "\"${property.value}\"" + } } if (property.key.toLowerCase().startsWith("wc.res.")) { buildType.resValue "string", property.key.replace("wc.res.", "").replace(".", "_").toLowerCase(), From 6fe3a736105bf9e265aaac859aedcd0d1e9079f3 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 25 Dec 2024 13:23:12 +0100 Subject: [PATCH 48/65] Add a new build config property to allow forcing password login --- .../woocommerce/android/ui/login/LoginActivity.kt | 7 ++++++- .../com/woocommerce/android/util/BuildConfigExt.kt | 13 +++++++++++++ developer.properties-example | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt index 0821ac46a22..4ffbab8e867 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt @@ -15,6 +15,7 @@ import androidx.lifecycle.withStarted import com.woocommerce.android.AppPrefsWrapper import com.woocommerce.android.AppUrls import com.woocommerce.android.AppUrls.LOGIN_WITH_EMAIL_WHAT_IS_WORDPRESS_COM_ACCOUNT +import com.woocommerce.android.BuildConfig import com.woocommerce.android.R import com.woocommerce.android.analytics.AnalyticsEvent import com.woocommerce.android.analytics.AnalyticsTracker @@ -55,6 +56,7 @@ import com.woocommerce.android.util.ChromeCustomTabUtils import com.woocommerce.android.util.ChromeCustomTabUtils.Height.Partial.ThreeQuarters import com.woocommerce.android.util.UrlUtils import com.woocommerce.android.util.WooLog +import com.woocommerce.android.util.getBuildConfigValueOrNull import dagger.android.AndroidInjector import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector @@ -350,7 +352,10 @@ class LoginActivity : clearCachedSites() if (authOptions != null) { - if (authOptions.isPasswordless) { + val forcePasswordLogin = BuildConfig.DEBUG && + getBuildConfigValueOrNull("FORCE_PASSWORD_LOGIN") == true + + if (authOptions.isPasswordless && !forcePasswordLogin) { showMagicLinkRequestScreen(email, verifyEmail, allowPassword = false, forceRequestAtStart = true) } else { showEmailPasswordScreen(email, verifyEmail) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt new file mode 100644 index 00000000000..61694d64210 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt @@ -0,0 +1,13 @@ +package com.woocommerce.android.util + +import com.woocommerce.android.BuildConfig + +@Suppress("SwallowedException") +inline fun getBuildConfigValueOrNull(key: String): T? { + return try { + val field = BuildConfig::class.java.getField(key) + field.get(null) as? T + } catch (e: NoSuchFileException) { + null + } +} diff --git a/developer.properties-example b/developer.properties-example index dfca1678893..c83f0fb8781 100644 --- a/developer.properties-example +++ b/developer.properties-example @@ -1,4 +1,5 @@ # The type of in app update FLEXIBLE = 0; IMMEDIATE = 1 wc.in_app_update_type = 0 wc.jitm_testing_json_file_name= +wc.force_password_login = true enable_leak_canary=true From 0d2de3cf5319cec8d28ef75ed30a66e464fdfde2 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 26 Dec 2024 10:40:20 +0100 Subject: [PATCH 49/65] fixup! Add a new build config property to allow forcing password login --- developer.properties-example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer.properties-example b/developer.properties-example index c83f0fb8781..05ee951acb0 100644 --- a/developer.properties-example +++ b/developer.properties-example @@ -1,5 +1,5 @@ # The type of in app update FLEXIBLE = 0; IMMEDIATE = 1 wc.in_app_update_type = 0 wc.jitm_testing_json_file_name= -wc.force_password_login = true +wc.force_password_login = false enable_leak_canary=true From 4b1ffa8c0cda1882abe06dee5bf5775f8f77293e Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 15 Jan 2025 12:50:37 +0100 Subject: [PATCH 50/65] Update logic of reading properties to load all default keys --- build.gradle | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f55319d32e8..e109aa90448 100644 --- a/build.gradle +++ b/build.gradle @@ -41,12 +41,20 @@ measureBuilds { } static def loadPropertiesWithFallback(Logger logger, File fallbackFile, File primaryFile) { + def defaultProperties = readPropertiesFromFile(fallbackFile) + def primaryProperties if (primaryFile.exists()) { - return readPropertiesFromFile(primaryFile) + primaryProperties = readPropertiesFromFile(primaryFile) } else { logger.warn("Primary properties file not found: ${primaryFile}. Using fallback: ${fallbackFile}.") - return readPropertiesFromFile(fallbackFile) + primaryProperties = new Properties() } + + primaryProperties.each { key, value -> + defaultProperties.setProperty(key, value) + } + + return defaultProperties } static def readPropertiesFromFile(File file) { From 1a145e50df51998448cd037a4c0b8d9b9522992e Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 15 Jan 2025 13:14:51 +0100 Subject: [PATCH 51/65] Simplify logic --- .../woocommerce/android/ui/login/LoginActivity.kt | 4 +--- .../com/woocommerce/android/util/BuildConfigExt.kt | 13 ------------- 2 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt index 4ffbab8e867..ef5c22276d0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/LoginActivity.kt @@ -56,7 +56,6 @@ import com.woocommerce.android.util.ChromeCustomTabUtils import com.woocommerce.android.util.ChromeCustomTabUtils.Height.Partial.ThreeQuarters import com.woocommerce.android.util.UrlUtils import com.woocommerce.android.util.WooLog -import com.woocommerce.android.util.getBuildConfigValueOrNull import dagger.android.AndroidInjector import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector @@ -352,8 +351,7 @@ class LoginActivity : clearCachedSites() if (authOptions != null) { - val forcePasswordLogin = BuildConfig.DEBUG && - getBuildConfigValueOrNull("FORCE_PASSWORD_LOGIN") == true + val forcePasswordLogin = BuildConfig.DEBUG && BuildConfig.FORCE_PASSWORD_LOGIN if (authOptions.isPasswordless && !forcePasswordLogin) { showMagicLinkRequestScreen(email, verifyEmail, allowPassword = false, forceRequestAtStart = true) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt deleted file mode 100644 index 61694d64210..00000000000 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/BuildConfigExt.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.woocommerce.android.util - -import com.woocommerce.android.BuildConfig - -@Suppress("SwallowedException") -inline fun getBuildConfigValueOrNull(key: String): T? { - return try { - val field = BuildConfig::class.java.getField(key) - field.get(null) as? T - } catch (e: NoSuchFileException) { - null - } -} From 542c8f4a51a23f340902f0654fd8da109c77f49b Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 15 Jan 2025 15:20:14 +0100 Subject: [PATCH 52/65] Fixed theme so there is no Translucent status and nav bar --- WooCommerce/src/main/res/values/themes.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/WooCommerce/src/main/res/values/themes.xml b/WooCommerce/src/main/res/values/themes.xml index 3d03738a495..f9b2a46ef27 100644 --- a/WooCommerce/src/main/res/values/themes.xml +++ b/WooCommerce/src/main/res/values/themes.xml @@ -38,7 +38,7 @@ @color/color_primary @color/color_primary @color/color_scrim_background - @color/nav_bar + true @color/woo_white @color/color_primary @@ -158,9 +158,6 @@