From 59849fc93621bcd78f6815dbf00b8dae6d94ecac Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 09:48:12 +0100 Subject: [PATCH 01/19] Operator to download and share receipt file --- .../payments/receipt/PaymentReceiptShare.kt | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt new file mode 100644 index 00000000000..fbe980141a1 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt @@ -0,0 +1,52 @@ +package com.woocommerce.android.ui.payments.receipt + +import android.app.Application +import android.content.Intent +import android.os.Environment +import androidx.core.content.FileProvider +import com.woocommerce.android.media.FileUtils +import com.woocommerce.android.util.FileDownloader +import javax.inject.Inject + +class PaymentReceiptShare @Inject constructor( + private val fileUtils: FileUtils, + private val fileDownloader: FileDownloader, + private val context: Application, +) { + suspend operator fun invoke(receiptUrl: String): ReceiptShareResult { + val receiptFile = fileUtils.createTempTimeStampedFile( + storageDir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) + ?: context.filesDir, + prefix = "receipt", + fileExtension = "html" + ) ?: return ReceiptShareResult.Error.FileCreation + if (!fileDownloader.downloadFile(receiptUrl, receiptFile)) { + return ReceiptShareResult.Error.FileDownload + } + + val uri = FileProvider.getUriForFile( + context, + context.packageName + ".provider", + receiptFile + ) + val intent = Intent(Intent.ACTION_SEND).apply { + type = "application/*" + putExtra(Intent.EXTRA_STREAM, uri) + } + return try { + context.startActivity(Intent.createChooser(intent, null)) + ReceiptShareResult.Success + } catch (e: Exception) { + ReceiptShareResult.Error.Sharing + } + } + + sealed class ReceiptShareResult { + object Success : ReceiptShareResult() + sealed class Error : ReceiptShareResult() { + object Sharing : Error() + object FileCreation : Error() + object FileDownload : Error() + } + } +} From 9b8087082e7df9659c2e79970034ec5a1f7705ae Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 10:27:08 +0100 Subject: [PATCH 02/19] Handle sharing errors --- .../payment/CardReaderPaymentViewModel.kt | 2 +- .../payments/receipt/PaymentReceiptShare.kt | 10 +++- .../receipt/preview/ReceiptPreviewFragment.kt | 4 +- .../preview/ReceiptPreviewViewModel.kt | 58 +++++++++++-------- .../src/main/res/values-ar/strings.xml | 2 +- .../src/main/res/values-de/strings.xml | 2 +- .../src/main/res/values-es/strings.xml | 2 +- .../src/main/res/values-fr/strings.xml | 2 +- .../src/main/res/values-he/strings.xml | 2 +- .../src/main/res/values-id/strings.xml | 2 +- .../src/main/res/values-it/strings.xml | 2 +- .../src/main/res/values-ja/strings.xml | 2 +- .../src/main/res/values-ko/strings.xml | 2 +- .../src/main/res/values-nl/strings.xml | 2 +- .../src/main/res/values-pt-rBR/strings.xml | 2 +- .../src/main/res/values-ru/strings.xml | 2 +- .../src/main/res/values-sv/strings.xml | 2 +- .../src/main/res/values-tr/strings.xml | 2 +- .../src/main/res/values-zh-rCN/strings.xml | 2 +- .../src/main/res/values-zh-rTW/strings.xml | 2 +- WooCommerce/src/main/res/values/strings.xml | 4 +- .../preview/ReceiptPreviewViewModelTest.kt | 8 +-- 22 files changed, 68 insertions(+), 50 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 339e8b351a1..711062c7a6b 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 @@ -749,7 +749,7 @@ class CardReaderPaymentViewModel fun onEmailActivityNotFound() { tracker.trackEmailReceiptFailed() - triggerEvent(ShowSnackbarInDialog(R.string.card_reader_payment_email_client_not_found)) + triggerEvent(ShowSnackbarInDialog(R.string.card_reader_payment_receipt_app_to_share_not_found)) } fun onPrintResult(result: PrintJobResult) { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt index fbe980141a1..4fd8d553bd9 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt @@ -34,17 +34,21 @@ class PaymentReceiptShare @Inject constructor( putExtra(Intent.EXTRA_STREAM, uri) } return try { - context.startActivity(Intent.createChooser(intent, null)) + context.startActivity( + Intent.createChooser(intent, null).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + ) ReceiptShareResult.Success } catch (e: Exception) { - ReceiptShareResult.Error.Sharing + ReceiptShareResult.Error.Sharing(e) } } sealed class ReceiptShareResult { object Success : ReceiptShareResult() sealed class Error : ReceiptShareResult() { - object Sharing : Error() + data class Sharing(val exception: Exception) : Error() object FileCreation : Error() object FileDownload : Error() } 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 9523b67ec65..e6da1500a36 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 @@ -52,7 +52,7 @@ class ReceiptPreviewFragment : BaseFragment(R.layout.fragment_receipt_preview), true } R.id.menu_send -> { - viewModel.onSendEmailClicked() + viewModel.onShareClicked() true } else -> false @@ -111,7 +111,7 @@ class ReceiptPreviewFragment : BaseFragment(R.layout.fragment_receipt_preview), private fun composeEmail(event: SendReceipt) { ActivityUtils.sendEmail(requireActivity(), event.address, event.subject, event.content) { - viewModel.onEmailActivityNotFound() + viewModel.onActivityToShareNotFound() } } } 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 e609731afa8..f2ae1fcd135 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 @@ -11,9 +11,7 @@ import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_SUCCESS import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_TAPPED import com.woocommerce.android.analytics.AnalyticsTrackerWrapper -import com.woocommerce.android.model.UiString.UiStringRes -import com.woocommerce.android.model.UiString.UiStringText -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 import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult @@ -32,7 +30,7 @@ class ReceiptPreviewViewModel @Inject constructor( savedState: SavedStateHandle, private val tracker: AnalyticsTrackerWrapper, - private val selectedSite: SelectedSite, + private val paymentReceiptShare: PaymentReceiptShare, ) : ScopedViewModel(savedState) { private val args: ReceiptPreviewFragmentArgs by savedState.navArgs() @@ -52,30 +50,44 @@ class ReceiptPreviewViewModel triggerEvent(PrintReceipt(args.receiptUrl, "receipt-order-${args.orderId}")) } - fun onSendEmailClicked() { + fun onShareClicked() { launch { tracker.track(RECEIPT_EMAIL_TAPPED) - triggerEvent( - SendReceipt( - content = UiStringRes( - string.card_reader_payment_receipt_email_content, - listOf(UiStringText(args.receiptUrl)) - ), - subject = UiStringRes( - string.card_reader_payment_receipt_email_subject, - listOf(UiStringText(selectedSite.get().name.orEmpty())) - ), - address = args.billingEmail - ) - ) + when (val sharingResult = paymentReceiptShare(args.receiptUrl)) { + PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { + tracker.track( + RECEIPT_EMAIL_FAILED, + errorContext = this@ReceiptPreviewViewModel.javaClass.simpleName, + errorType = "file_creation_failed", + errorDescription = "File creation failed" + ) + triggerEvent(ShowSnackbar(string.card_reader_payment_receipt_can_not_be_stored)) + } + PaymentReceiptShare.ReceiptShareResult.Error.FileDownload -> { + tracker.track( + RECEIPT_EMAIL_FAILED, + errorContext = this@ReceiptPreviewViewModel.javaClass.simpleName, + errorType = "file_download_failed", + errorDescription = "File download failed" + ) + triggerEvent(ShowSnackbar(string.card_reader_payment_receipt_can_not_be_downloaded)) + } + is PaymentReceiptShare.ReceiptShareResult.Error.Sharing -> { + tracker.track( + RECEIPT_EMAIL_FAILED, + errorContext = this@ReceiptPreviewViewModel.javaClass.simpleName, + errorType = "no_app_found", + errorDescription = sharingResult.exception.message + ) + triggerEvent(ShowSnackbar(string.card_reader_payment_receipt_app_to_share_not_found)) + } + PaymentReceiptShare.ReceiptShareResult.Success -> { + // no-op + } + } } } - fun onEmailActivityNotFound() { - tracker.track(RECEIPT_EMAIL_FAILED) - triggerEvent(ShowSnackbar(string.card_reader_payment_email_client_not_found)) - } - fun onPrintResult(result: PrintJobResult) { tracker.track( when (result) { diff --git a/WooCommerce/src/main/res/values-ar/strings.xml b/WooCommerce/src/main/res/values-ar/strings.xml index cc49beffa7f..76aedcc43e9 100644 --- a/WooCommerce/src/main/res/values-ar/strings.xml +++ b/WooCommerce/src/main/res/values-ar/strings.xml @@ -1910,7 +1910,7 @@ Language: ar سمات المجموعات تشغيل بلوتوث الجهاز المحمول حدث خطأ في أثناء إحضار الطلب. قد تكون حالة الطلب الموجودة في التطبيق قديمة. - لا يمكن اكتشاف تطبيق عميل البريد الإلكتروني الخاص بك + لا يمكن اكتشاف تطبيق عميل البريد الإلكتروني الخاص بك إيصالك من %s تحديث الطلب تحديث حالة التطبيق diff --git a/WooCommerce/src/main/res/values-de/strings.xml b/WooCommerce/src/main/res/values-de/strings.xml index f069ba46c0f..cf4d312a3a1 100644 --- a/WooCommerce/src/main/res/values-de/strings.xml +++ b/WooCommerce/src/main/res/values-de/strings.xml @@ -1910,7 +1910,7 @@ Language: de Variantenattribute Aktiviere Bluetooth auf dem Mobilgerät Fehler beim Abrufen der Bestellung Der Bestellstatus in der App ist eventuell nicht aktuell. - E-Mail-Client-App wird nicht erkannt. + E-Mail-Client-App wird nicht erkannt. Dein Beleg vom %s Bestellung aktualisieren App-Status aktualisieren diff --git a/WooCommerce/src/main/res/values-es/strings.xml b/WooCommerce/src/main/res/values-es/strings.xml index 8e32a914850..fe0e0d5bd54 100644 --- a/WooCommerce/src/main/res/values-es/strings.xml +++ b/WooCommerce/src/main/res/values-es/strings.xml @@ -1910,7 +1910,7 @@ Language: es Atributos de variaciones Activa Bluetooth en el dispositivo móvil Error al recuperar el pedido. El estado del pedido en la aplicación podría estar desactualizado. - No se pudo detectar una aplicación cliente de correo electrónico + No se pudo detectar una aplicación cliente de correo electrónico Tu recibo de %s Actualizando pedido Actualizando estado en la aplicación diff --git a/WooCommerce/src/main/res/values-fr/strings.xml b/WooCommerce/src/main/res/values-fr/strings.xml index 2fdba76735a..f18596537c6 100644 --- a/WooCommerce/src/main/res/values-fr/strings.xml +++ b/WooCommerce/src/main/res/values-fr/strings.xml @@ -1910,7 +1910,7 @@ Language: fr Attributs des variantes Activer le Bluetooth de l’appareil mobile Erreur lors de l’extraction de la commande. L’état de la commande dans l’application est peut-être obsolète. - Aucune application de messagerie détectée + Aucune application de messagerie détectée Votre reçu de %s Actualisation de la commande Mise à jour de l’état de l’application diff --git a/WooCommerce/src/main/res/values-he/strings.xml b/WooCommerce/src/main/res/values-he/strings.xml index 4e5a67434b2..8622401ba37 100644 --- a/WooCommerce/src/main/res/values-he/strings.xml +++ b/WooCommerce/src/main/res/values-he/strings.xml @@ -1910,7 +1910,7 @@ Language: he_IL מאפייני סוגים יש להפעיל את חיבור ה-Bluetooth של המכשיר הנייד שגיאה בהבאת ההזמנה. ייתכן שמצב ההזמנה באפליקציה לא מעודכן. - לא ניתן לאתר את האפליקציה של שירות האימייל שלך + לא ניתן לאתר את האפליקציה של שירות האימייל שלך הקבלה שלך מאת %s מרענן את ההזמנה מעדכן את מצב האפליקציה diff --git a/WooCommerce/src/main/res/values-id/strings.xml b/WooCommerce/src/main/res/values-id/strings.xml index fa29a8b2c73..b7315da284f 100644 --- a/WooCommerce/src/main/res/values-id/strings.xml +++ b/WooCommerce/src/main/res/values-id/strings.xml @@ -1910,7 +1910,7 @@ Language: id Atribut variasi Aktifkan bluetooth perangkat seluler Terjadi error saat mengambil pesanan. Status pesanan pada aplikasi mungkin telah usang. - Tidak dapat mendeteksi aplikasi klien email Anda + Tidak dapat mendeteksi aplikasi klien email Anda Tanda terima Anda dari %s Menyegarkan pesanan Memperbarui status aplikasi diff --git a/WooCommerce/src/main/res/values-it/strings.xml b/WooCommerce/src/main/res/values-it/strings.xml index 4f1d803552e..cae8e5ca689 100644 --- a/WooCommerce/src/main/res/values-it/strings.xml +++ b/WooCommerce/src/main/res/values-it/strings.xml @@ -1910,7 +1910,7 @@ Language: it Attributi della variante Attiva il Bluetooth del dispositivo mobile Errore durante il recupero dell\'ordine. Lo stato nell\'ordine dell\'app potrebbe essere obsoleto. - Impossibile rilevare il client e-mail della tua app + Impossibile rilevare il client e-mail della tua app La tua ricevuta da %s Aggiornamento dell\'ordine Aggiornamento dello stato dell\'app diff --git a/WooCommerce/src/main/res/values-ja/strings.xml b/WooCommerce/src/main/res/values-ja/strings.xml index ce4d1990c3b..57f251429ea 100644 --- a/WooCommerce/src/main/res/values-ja/strings.xml +++ b/WooCommerce/src/main/res/values-ja/strings.xml @@ -1910,7 +1910,7 @@ Language: ja_JP バリエーション属性 モバイルデバイスの Bluetooth をオンにする 注文を取得する際にエラーが発生しました。 アプリの注文状態が古い可能性があります。 - メールクライアントアプリを検出できません + メールクライアントアプリを検出できません %s のレシート 注文を更新する アプリの状態を更新する diff --git a/WooCommerce/src/main/res/values-ko/strings.xml b/WooCommerce/src/main/res/values-ko/strings.xml index 70f0935b61d..f445739f0b5 100644 --- a/WooCommerce/src/main/res/values-ko/strings.xml +++ b/WooCommerce/src/main/res/values-ko/strings.xml @@ -1910,7 +1910,7 @@ Language: ko_KR 변형 속성 모바일 장치 블루투스 켜기 주문을 가져오는 중 오류가 발생했습니다. 앱의 주문 상태가 기한이 지났을 수 있습니다. - 이메일 클라이언트 앱을 감지할 수 없습니다. + 이메일 클라이언트 앱을 감지할 수 없습니다. %s에서 받은 영수증 주문 새로 고치기 앱 상태 업데이트하기 diff --git a/WooCommerce/src/main/res/values-nl/strings.xml b/WooCommerce/src/main/res/values-nl/strings.xml index e53a15e7869..b60a6ba5886 100644 --- a/WooCommerce/src/main/res/values-nl/strings.xml +++ b/WooCommerce/src/main/res/values-nl/strings.xml @@ -1903,7 +1903,7 @@ Language: nl Variatie-eigenschappen Zet de Bluetooth aan op je mobiele apparaat Fout bij ophalen bestelling. De bestellingsstatus in de app kan verouderd zijn. - Detectie van mailclient-app mislukt + Detectie van mailclient-app mislukt Je kwitantie van %s Bestelling aan het vernieuwen… Status in de app aan het bijwerken… diff --git a/WooCommerce/src/main/res/values-pt-rBR/strings.xml b/WooCommerce/src/main/res/values-pt-rBR/strings.xml index 09d637b857d..ecde05b45f3 100644 --- a/WooCommerce/src/main/res/values-pt-rBR/strings.xml +++ b/WooCommerce/src/main/res/values-pt-rBR/strings.xml @@ -1910,7 +1910,7 @@ Language: pt_BR Atributos das variações Ativar o Bluetooth do dispositivo móvel Erro ao buscar o pedido. O status do pedido pode estar desatualizado no aplicativo. - Não é possível detectar seu aplicativo cliente de e-mail + Não é possível detectar seu aplicativo cliente de e-mail Seu recibo de %s Atualizando pedido Atualizando estado do aplicativo diff --git a/WooCommerce/src/main/res/values-ru/strings.xml b/WooCommerce/src/main/res/values-ru/strings.xml index a04d66d7e2f..cc35e4e790d 100644 --- a/WooCommerce/src/main/res/values-ru/strings.xml +++ b/WooCommerce/src/main/res/values-ru/strings.xml @@ -1910,7 +1910,7 @@ Language: ru Атрибуты вариантов Включите Bluetooth на мобильном устройстве Ошибка при загрузке заказа. Состояние заказа в приложении могло устареть. - Не удалось определить ваш почтовый клиент + Не удалось определить ваш почтовый клиент Ваша квитанция от %s Обновление заказа Обновление состояния приложения diff --git a/WooCommerce/src/main/res/values-sv/strings.xml b/WooCommerce/src/main/res/values-sv/strings.xml index 977cd03c403..9e4e1cf2148 100644 --- a/WooCommerce/src/main/res/values-sv/strings.xml +++ b/WooCommerce/src/main/res/values-sv/strings.xml @@ -1917,7 +1917,7 @@ Language: sv_SE Börja sälja idag genom att lägga till din första produkt i butiken. Variationsattribut Aktivera Bluetooth på den mobila enheten - Lyckas inte hitta ditt e-postprogram + Lyckas inte hitta ditt e-postprogram Uppdaterar beställning Uppdaterar appstatusen Det gick inte att hämta beställningen. Beställningens status i appen kan vara föråldrad. diff --git a/WooCommerce/src/main/res/values-tr/strings.xml b/WooCommerce/src/main/res/values-tr/strings.xml index 70eec362196..bf6d75a1ca7 100644 --- a/WooCommerce/src/main/res/values-tr/strings.xml +++ b/WooCommerce/src/main/res/values-tr/strings.xml @@ -1910,7 +1910,7 @@ Language: tr Varyasyon nitelikleri. Mobil cihazda Bluetooth\'u açın Sipariş alınırken hata oluştu Uygulamadaki sipariş durumu eski olabilir. - E-posta istemcisi uygulamanızı tespit edemiyoruz + E-posta istemcisi uygulamanızı tespit edemiyoruz %s makbuzunuz Sipariş yenileniyor Uygulama durumu güncelleniyor diff --git a/WooCommerce/src/main/res/values-zh-rCN/strings.xml b/WooCommerce/src/main/res/values-zh-rCN/strings.xml index 2094348f61f..1a835ed6868 100644 --- a/WooCommerce/src/main/res/values-zh-rCN/strings.xml +++ b/WooCommerce/src/main/res/values-zh-rCN/strings.xml @@ -1909,7 +1909,7 @@ Language: zh_CN 添加产品 变体属性 打开移动设备蓝牙 - 未侦测到您的电子邮件客户端应用 + 未侦测到您的电子邮件客户端应用 来自 %s 的收据 刷新订单 更新应用程序状态 diff --git a/WooCommerce/src/main/res/values-zh-rTW/strings.xml b/WooCommerce/src/main/res/values-zh-rTW/strings.xml index 0c9892b1cae..2dcd4dcbef0 100644 --- a/WooCommerce/src/main/res/values-zh-rTW/strings.xml +++ b/WooCommerce/src/main/res/values-zh-rTW/strings.xml @@ -1910,7 +1910,7 @@ Language: zh_TW 款式屬性 開啟行動裝置的藍牙 擷取訂單時發生錯誤。 應用程式中的訂單狀態可能已過期。 - 無法偵測電子郵件用戶端應用程式 + 無法偵測電子郵件用戶端應用程式 你的 %s 收據 正在重新整理訂單 正在更新應用程式狀態 diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index df91217db7d..7a855966ae3 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -1507,7 +1507,9 @@ In-Person Payment for Order #%1$s for %2$s blog_id %3$s. Your receipt from %s Thank you for your purchase! Click the link below for your payment receipt.\n\n%s - Can\'t detect your email client app + Unable to detect any application to which the receipt can be shared + Unable to download the receipt + Unable to store the receipt Error fetching order. Order state in the app might be outdated. The order is already paid Please make sure that the card reader is connected. 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 e0845ba0b96..42bd8adf5e1 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 @@ -75,7 +75,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Test fun `when user clicks on send email, then send receipt event emitted`() = testBlocking { - viewModel.onSendEmailClicked() + viewModel.onShareClicked() assertThat(viewModel.event.value).isInstanceOf(SendReceipt::class.java) } @@ -83,7 +83,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Test fun `when user clicks on send email, then event tracked`() = testBlocking { - viewModel.onSendEmailClicked() + viewModel.onShareClicked() verify(tracker).track(RECEIPT_EMAIL_TAPPED) } @@ -91,7 +91,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Test fun `when email application not found, then SnackBar with error shown`() = testBlocking { - viewModel.onEmailActivityNotFound() + viewModel.onActivityToShareNotFound() assertThat(viewModel.event.value).isInstanceOf(ShowSnackbar::class.java) } @@ -99,7 +99,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Test fun `when email application not found, then event tracked`() = testBlocking { - viewModel.onEmailActivityNotFound() + viewModel.onActivityToShareNotFound() verify(tracker).track(RECEIPT_EMAIL_FAILED) } From 63d4cb733b9fc8a50f4c6b6bca983c05a874f5c2 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 10:28:14 +0100 Subject: [PATCH 03/19] Show loading when fetching --- .../ui/payments/receipt/preview/ReceiptPreviewViewModel.kt | 4 ++++ 1 file changed, 4 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 f2ae1fcd135..0b9f5ad9116 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 @@ -52,6 +52,8 @@ class ReceiptPreviewViewModel fun onShareClicked() { launch { + viewState.value = Loading + tracker.track(RECEIPT_EMAIL_TAPPED) when (val sharingResult = paymentReceiptShare(args.receiptUrl)) { PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { @@ -85,6 +87,8 @@ class ReceiptPreviewViewModel // no-op } } + + viewState.value = Content } } From 1c2b05e5cd05e745195ab95f324a5e3aa18dec7a Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 10:32:28 +0100 Subject: [PATCH 04/19] Removed SendReceipt event --- .../ui/payments/receipt/preview/ReceiptPreviewFragment.kt | 8 -------- .../receipt/preview/ReceiptPreviewViewModelEvent.kt | 3 --- 2 files changed, 11 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 e6da1500a36..30753e17d69 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 @@ -14,7 +14,6 @@ import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.databinding.FragmentReceiptPreviewBinding import com.woocommerce.android.ui.base.BaseFragment import com.woocommerce.android.ui.base.UIMessageResolver -import com.woocommerce.android.util.ActivityUtils import com.woocommerce.android.util.PrintHtmlHelper import com.woocommerce.android.util.UiHelpers import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowSnackbar @@ -102,16 +101,9 @@ class ReceiptPreviewFragment : BaseFragment(R.layout.fragment_receipt_preview), when (it) { is LoadUrl -> binding.receiptPreviewPreviewWebview.loadUrl(it.url) is PrintReceipt -> printHtmlHelper.printReceipt(requireActivity(), it.receiptUrl, it.documentName) - is SendReceipt -> composeEmail(it) is ShowSnackbar -> uiMessageResolver.showSnack(it.message) else -> it.isHandled = false } } } - - private fun composeEmail(event: SendReceipt) { - ActivityUtils.sendEmail(requireActivity(), event.address, event.subject, event.content) { - viewModel.onActivityToShareNotFound() - } - } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelEvent.kt index 5edf89f0559..de027028483 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelEvent.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelEvent.kt @@ -1,10 +1,7 @@ package com.woocommerce.android.ui.payments.receipt.preview -import com.woocommerce.android.model.UiString import com.woocommerce.android.viewmodel.MultiLiveEvent data class LoadUrl(val url: String) : MultiLiveEvent.Event() data class PrintReceipt(val receiptUrl: String, val documentName: String) : MultiLiveEvent.Event() - -data class SendReceipt(val content: UiString, val subject: UiString, val address: String) : MultiLiveEvent.Event() From ef7c5ac0c0ce784fb3a337d56cd202aad7b13d67 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 10:53:20 +0100 Subject: [PATCH 05/19] Put order number in the name of a file --- .../android/ui/payments/receipt/PaymentReceiptShare.kt | 4 ++-- .../ui/payments/receipt/preview/ReceiptPreviewViewModel.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt index 4fd8d553bd9..dfe8f406c7d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt @@ -13,11 +13,11 @@ class PaymentReceiptShare @Inject constructor( private val fileDownloader: FileDownloader, private val context: Application, ) { - suspend operator fun invoke(receiptUrl: String): ReceiptShareResult { + suspend operator fun invoke(receiptUrl: String, orderNumber: Long): ReceiptShareResult { val receiptFile = fileUtils.createTempTimeStampedFile( storageDir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) ?: context.filesDir, - prefix = "receipt", + prefix = "receipt_$orderNumber", fileExtension = "html" ) ?: return ReceiptShareResult.Error.FileCreation if (!fileDownloader.downloadFile(receiptUrl, receiptFile)) { 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 0b9f5ad9116..3262dc142dd 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 @@ -55,7 +55,7 @@ class ReceiptPreviewViewModel viewState.value = Loading tracker.track(RECEIPT_EMAIL_TAPPED) - when (val sharingResult = paymentReceiptShare(args.receiptUrl)) { + when (val sharingResult = paymentReceiptShare(args.receiptUrl, args.orderId)) { PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { tracker.track( RECEIPT_EMAIL_FAILED, From 8b52b5326aa907385f69b3fe64253d0f27daf0bd Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 11:39:38 +0100 Subject: [PATCH 06/19] Share via file after card payment --- .../CardReaderPaymentDialogFragment.kt | 9 ---- .../payment/CardReaderPaymentViewModel.kt | 43 +++++++++++-------- .../CardReaderPaymentViewModelEvent.kt | 3 -- .../payment/CardReaderPaymentViewState.kt | 9 ++++ .../payments/tracking/PaymentsFlowTracker.kt | 27 ++++++++++++ 5 files changed, 62 insertions(+), 29 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentDialogFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentDialogFragment.kt index a317c226d28..ae5b3ce8354 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentDialogFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentDialogFragment.kt @@ -22,7 +22,6 @@ import com.woocommerce.android.R import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.databinding.CardReaderPaymentDialogBinding import com.woocommerce.android.extensions.navigateBackWithNotice -import com.woocommerce.android.model.UiString import com.woocommerce.android.support.help.HelpOrigin import com.woocommerce.android.support.requests.SupportRequestFormActivity import com.woocommerce.android.ui.base.UIMessageResolver @@ -32,7 +31,6 @@ import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.BuiltInR import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.ExternalReaderPaymentSuccessfulReceiptSentAutomaticallyState import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.ExternalReaderPaymentSuccessfulState import com.woocommerce.android.ui.payments.refunds.RefundSummaryFragment.Companion.KEY_INTERAC_SUCCESS -import com.woocommerce.android.util.ActivityUtils import com.woocommerce.android.util.PrintHtmlHelper import com.woocommerce.android.util.UiHelpers import com.woocommerce.android.util.UiHelpers.getTextOfUiString @@ -86,7 +84,6 @@ class CardReaderPaymentDialogFragment : PaymentsBaseDialogFragment(R.layout.card event.documentName ) InteracRefundSuccessful -> navigateBackWithNotice(KEY_INTERAC_SUCCESS) - is SendReceipt -> composeEmail(event.address, event.subject, event.content) is ShowSnackbar -> uiMessageResolver.showSnack(event.message) is ShowSnackbarInDialog -> Snackbar.make( requireView(), event.message, BaseTransientBottomBar.LENGTH_LONG @@ -186,12 +183,6 @@ class CardReaderPaymentDialogFragment : PaymentsBaseDialogFragment(R.layout.card mp.start() } - private fun composeEmail(address: String, subject: UiString, content: UiString) { - ActivityUtils.sendEmail(requireActivity(), address, subject, content) { - viewModel.onEmailActivityNotFound() - } - } - override fun onResume() { super.onResume() AnalyticsTracker.trackViewShown(this) 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 711062c7a6b..fc52388c3f9 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 @@ -68,6 +68,7 @@ import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.ReFetchi import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.RefundLoadingDataState import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.RefundSuccessfulState import com.woocommerce.android.ui.payments.receipt.PaymentReceiptHelper +import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.tracking.CardReaderTrackingInfoKeeper import com.woocommerce.android.ui.payments.tracking.PaymentsFlowTracker import com.woocommerce.android.util.CoroutineDispatchers @@ -117,6 +118,7 @@ class CardReaderPaymentViewModel private val paymentReceiptHelper: PaymentReceiptHelper, private val cardReaderOnboardingChecker: CardReaderOnboardingChecker, private val cardReaderConfigProvider: CardReaderCountryConfigProvider, + private val paymentReceiptShare: PaymentReceiptShare, ) : ScopedViewModel(savedState) { private val arguments: CardReaderPaymentDialogFragmentArgs by savedState.navArgs() @@ -611,9 +613,7 @@ class CardReaderPaymentViewModel val onSaveUserClicked = { onSaveForLaterClicked() } - val onSendReceiptClicked = { - onSendReceiptClicked(order.billingAddress.email) - } + val onSendReceiptClicked = { onSendReceiptClicked() } if (order.billingAddress.email.isBlank()) { viewState.postValue( @@ -723,27 +723,36 @@ class CardReaderPaymentViewModel } } - private fun onSendReceiptClicked(billingEmail: String) { + private fun onSendReceiptClicked() { launch { tracker.trackEmailReceiptTapped() + val stateBeforeLoading = viewState.value!! + viewState.postValue(ViewState.SharingReceiptState) val receiptResult = paymentReceiptHelper.getReceiptUrl(orderId) + if (receiptResult.isSuccess) { - triggerEvent( - SendReceipt( - content = UiStringRes( - R.string.card_reader_payment_receipt_email_content, - listOf(UiStringText(receiptResult.getOrThrow())) - ), - subject = UiStringRes( - R.string.card_reader_payment_receipt_email_subject, - listOf(UiStringText(selectedSite.get().name.orEmpty())) - ), - address = billingEmail - ) - ) + when (val sharingResult = paymentReceiptShare(receiptResult.getOrThrow(), orderId)) { + is PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { + tracker.trackPaymentsReceiptSharingFailed(sharingResult) + triggerEvent(ShowSnackbar(R.string.card_reader_payment_receipt_can_not_be_stored)) + } + is PaymentReceiptShare.ReceiptShareResult.Error.FileDownload -> { + tracker.trackPaymentsReceiptSharingFailed(sharingResult) + triggerEvent(ShowSnackbar(R.string.card_reader_payment_receipt_can_not_be_downloaded)) + } + is PaymentReceiptShare.ReceiptShareResult.Error.Sharing -> { + tracker.trackPaymentsReceiptSharingFailed(sharingResult) + triggerEvent(ShowSnackbar(R.string.card_reader_payment_receipt_app_to_share_not_found)) + } + PaymentReceiptShare.ReceiptShareResult.Success -> { + // no-op + } + } } else { triggerEvent(ShowSnackbar(R.string.receipt_fetching_error)) } + + viewState.postValue(stateBeforeLoading) } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModelEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModelEvent.kt index 5a44a75ebb3..6ac68063777 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModelEvent.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModelEvent.kt @@ -1,7 +1,6 @@ package com.woocommerce.android.ui.payments.cardreader.payment import androidx.annotation.StringRes -import com.woocommerce.android.model.UiString import com.woocommerce.android.viewmodel.MultiLiveEvent.Event class ShowSnackbarInDialog(@StringRes val message: Int) : Event() @@ -17,5 +16,3 @@ object EnableNfc : Event() data class PurchaseCardReader(val url: String) : Event() data class PrintReceipt(val receiptUrl: String, val documentName: String) : Event() - -data class SendReceipt(val content: UiString, val subject: UiString, val address: String) : Event() diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewState.kt index d7eaa0c5446..1f73c0126df 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewState.kt @@ -219,6 +219,15 @@ sealed class ViewState( override val isProgressVisible = true } + object SharingReceiptState : ViewState( + headerLabel = R.string.card_reader_payment_completed_payment_header, + illustration = null, + primaryActionLabel = null, + secondaryActionLabel = null, + ) { + override val isProgressVisible = true + } + object ReFetchingOrderState : ViewState( headerLabel = R.string.card_reader_payment_fetch_order_loading_header, hintLabel = R.string.card_reader_payment_fetch_order_loading_hint, diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt index 0e7b2739a57..9cdce47de8a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt @@ -73,6 +73,7 @@ import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.STRIPE_EXTENSION_GATEWAY import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.WOOCOMMERCE_PAYMENTS import com.woocommerce.android.ui.payments.hub.PaymentsHubViewModel.CashOnDeliverySource +import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.taptopay.TapToPayAvailabilityStatus.Result.NotAvailable import javax.inject.Inject @@ -580,6 +581,32 @@ class PaymentsFlowTracker @Inject constructor( ) } + fun trackPaymentsReceiptSharingFailed(sharingResult: PaymentReceiptShare.ReceiptShareResult.Error) { + when (sharingResult) { + is PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { + track( + RECEIPT_EMAIL_FAILED, + errorType = "file_creation_failed", + errorDescription = "File creation failed" + ) + } + is PaymentReceiptShare.ReceiptShareResult.Error.FileDownload -> { + track( + RECEIPT_EMAIL_FAILED, + errorType = "file_download_failed", + errorDescription = "File download failed" + ) + } + is PaymentReceiptShare.ReceiptShareResult.Error.Sharing -> { + track( + RECEIPT_EMAIL_FAILED, + errorType = "no_app_found", + errorDescription = sharingResult.exception.message + ) + } + } + } + private fun getAndResetFlowsDuration(): MutableMap { val result = mutableMapOf() .also { mutableMap -> From 0a299f8c750dee683734fef066f4dc86670a782b Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 11:42:29 +0100 Subject: [PATCH 07/19] Use payment flow tracker to track sharing result --- .../preview/ReceiptPreviewViewModel.kt | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) 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 3262dc142dd..ed7aa503ec5 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,7 +4,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.R.string -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_FAILED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_TAPPED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_CANCELED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED @@ -14,6 +13,7 @@ import com.woocommerce.android.analytics.AnalyticsTrackerWrapper 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 +import com.woocommerce.android.ui.payments.tracking.PaymentsFlowTracker import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult.CANCELLED import com.woocommerce.android.util.PrintHtmlHelper.PrintJobResult.FAILED @@ -30,6 +30,7 @@ class ReceiptPreviewViewModel @Inject constructor( savedState: SavedStateHandle, private val tracker: AnalyticsTrackerWrapper, + private val paymentsFlowTracker: PaymentsFlowTracker, private val paymentReceiptShare: PaymentReceiptShare, ) : ScopedViewModel(savedState) { private val args: ReceiptPreviewFragmentArgs by savedState.navArgs() @@ -56,31 +57,16 @@ class ReceiptPreviewViewModel tracker.track(RECEIPT_EMAIL_TAPPED) when (val sharingResult = paymentReceiptShare(args.receiptUrl, args.orderId)) { - PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { - tracker.track( - RECEIPT_EMAIL_FAILED, - errorContext = this@ReceiptPreviewViewModel.javaClass.simpleName, - errorType = "file_creation_failed", - errorDescription = "File creation failed" - ) + is PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { + paymentsFlowTracker.trackPaymentsReceiptSharingFailed(sharingResult) triggerEvent(ShowSnackbar(string.card_reader_payment_receipt_can_not_be_stored)) } - PaymentReceiptShare.ReceiptShareResult.Error.FileDownload -> { - tracker.track( - RECEIPT_EMAIL_FAILED, - errorContext = this@ReceiptPreviewViewModel.javaClass.simpleName, - errorType = "file_download_failed", - errorDescription = "File download failed" - ) + is PaymentReceiptShare.ReceiptShareResult.Error.FileDownload -> { + paymentsFlowTracker.trackPaymentsReceiptSharingFailed(sharingResult) triggerEvent(ShowSnackbar(string.card_reader_payment_receipt_can_not_be_downloaded)) } is PaymentReceiptShare.ReceiptShareResult.Error.Sharing -> { - tracker.track( - RECEIPT_EMAIL_FAILED, - errorContext = this@ReceiptPreviewViewModel.javaClass.simpleName, - errorType = "no_app_found", - errorDescription = sharingResult.exception.message - ) + paymentsFlowTracker.trackPaymentsReceiptSharingFailed(sharingResult) triggerEvent(ShowSnackbar(string.card_reader_payment_receipt_app_to_share_not_found)) } PaymentReceiptShare.ReceiptShareResult.Success -> { From e3874e745ef88767a063b86cd966cc848125961b Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 11:59:49 +0100 Subject: [PATCH 08/19] Set receipt expiration days to 2 as agreed --- .../android/ui/payments/receipt/PaymentReceiptHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt index 53dea128b02..8832e65cfeb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt @@ -110,7 +110,7 @@ class PaymentReceiptHelper @Inject constructor( const val WCPAY_RECEIPTS_SENDING_SUPPORT_VERSION = "4.0.0" const val WC_CAN_GENERATE_RECEIPTS_VERSION = "8.7.0" - const val RECEIPT_EXPIRATION_DAYS = 365 + const val RECEIPT_EXPIRATION_DAYS = 2 } class IsDevSiteSupported @Inject constructor() { From aaf4a97e09c7f395ca79048df5cf8c5c304d55d6 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 12:02:12 +0100 Subject: [PATCH 09/19] Fixed detekt complains --- .../payments/receipt/PaymentReceiptShare.kt | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt index dfe8f406c7d..d2a1c502470 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShare.kt @@ -13,35 +13,38 @@ class PaymentReceiptShare @Inject constructor( private val fileDownloader: FileDownloader, private val context: Application, ) { + @Suppress("TooGenericExceptionCaught") suspend operator fun invoke(receiptUrl: String, orderNumber: Long): ReceiptShareResult { val receiptFile = fileUtils.createTempTimeStampedFile( storageDir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) ?: context.filesDir, prefix = "receipt_$orderNumber", fileExtension = "html" - ) ?: return ReceiptShareResult.Error.FileCreation - if (!fileDownloader.downloadFile(receiptUrl, receiptFile)) { - return ReceiptShareResult.Error.FileDownload - } - - val uri = FileProvider.getUriForFile( - context, - context.packageName + ".provider", - receiptFile ) - val intent = Intent(Intent.ACTION_SEND).apply { - type = "application/*" - putExtra(Intent.EXTRA_STREAM, uri) - } - return try { - context.startActivity( - Intent.createChooser(intent, null).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - } + return if (receiptFile == null) { + ReceiptShareResult.Error.FileCreation + } else if (!fileDownloader.downloadFile(receiptUrl, receiptFile)) { + ReceiptShareResult.Error.FileDownload + } else { + val uri = FileProvider.getUriForFile( + context, + context.packageName + ".provider", + receiptFile ) - ReceiptShareResult.Success - } catch (e: Exception) { - ReceiptShareResult.Error.Sharing(e) + val intent = Intent(Intent.ACTION_SEND).apply { + type = "application/*" + putExtra(Intent.EXTRA_STREAM, uri) + } + try { + context.startActivity( + Intent.createChooser(intent, null).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + ) + ReceiptShareResult.Success + } catch (e: Exception) { + ReceiptShareResult.Error.Sharing(e) + } } } From dee354de185efb50da67a6fa8cd5ce10941b73b4 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 12:27:36 +0100 Subject: [PATCH 10/19] Tests a compilable --- .../CardReaderPaymentViewModelTest.kt | 17 ++++++---- .../receipt/PaymentReceiptShareTest.kt | 27 ++++++++++++++++ .../preview/ReceiptPreviewViewModelTest.kt | 32 +++---------------- 3 files changed, 43 insertions(+), 33 deletions(-) create mode 100644 WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt 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 74bab73e34a..0bbf49ce280 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 @@ -68,7 +68,6 @@ import com.woocommerce.android.ui.payments.cardreader.payment.PaymentFlowError.U import com.woocommerce.android.ui.payments.cardreader.payment.PlayChaChing import com.woocommerce.android.ui.payments.cardreader.payment.PrintReceipt import com.woocommerce.android.ui.payments.cardreader.payment.PurchaseCardReader -import com.woocommerce.android.ui.payments.cardreader.payment.SendReceipt import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.BuiltInReaderCapturingPaymentState import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.BuiltInReaderCollectPaymentState import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.BuiltInReaderFailedPaymentState @@ -90,6 +89,7 @@ import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.ReFetchi import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.RefundLoadingDataState import com.woocommerce.android.ui.payments.cardreader.payment.ViewState.RefundSuccessfulState import com.woocommerce.android.ui.payments.receipt.PaymentReceiptHelper +import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.tracking.CardReaderTrackingInfoKeeper import com.woocommerce.android.ui.payments.tracking.PaymentsFlowTracker import com.woocommerce.android.util.CurrencyFormatter @@ -182,6 +182,7 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { private val cardReaderOnboardingChecker: CardReaderOnboardingChecker = mock() private val cardReaderConfigProvider: CardReaderCountryConfigProvider = mock() private val cardReaderConfig: CardReaderConfigForSupportedCountry = CardReaderConfigForUSA + private val paymentReceiptShare: PaymentReceiptShare = mock() @Suppress("LongMethod") @Before @@ -209,6 +210,7 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { paymentReceiptHelper = paymentReceiptHelper, cardReaderOnboardingChecker = cardReaderOnboardingChecker, cardReaderConfigProvider = cardReaderConfigProvider, + paymentReceiptShare = paymentReceiptShare, ) whenever(orderRepository.getOrderById(any())).thenReturn(mockedOrder) @@ -2356,16 +2358,19 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { } @Test - fun `given external reader and receipt fetching success, when user clicks on send receipt button, then SendReceipt event emitted`() = + fun `given external reader and receipt fetching and sharing success, when user clicks on send receipt button, then nothing emitted`() = testBlocking { whenever(cardReaderManager.collectPayment(any())).thenAnswer { - flow { emit(PaymentCompleted("")) } + flow { emit(PaymentCompleted("url")) } } + whenever(paymentReceiptShare("url", 1L)).thenReturn( + PaymentReceiptShare.ReceiptShareResult.Success + ) viewModel.start() (viewModel.viewStateData.value as ExternalReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() - assertThat(viewModel.event.value).isInstanceOf(SendReceipt::class.java) + assertThat(viewModel.event.value).isNull() } @Test @@ -2380,8 +2385,6 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { viewModel.start() (viewModel.viewStateData.value as BuiltInReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() - - assertThat(viewModel.event.value).isInstanceOf(SendReceipt::class.java) } @Test @@ -4401,6 +4404,7 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { paymentReceiptHelper = paymentReceiptHelper, cardReaderOnboardingChecker = cardReaderOnboardingChecker, cardReaderConfigProvider = cardReaderConfigProvider, + paymentReceiptShare = paymentReceiptShare, ) } @@ -4433,6 +4437,7 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { paymentReceiptHelper = paymentReceiptHelper, cardReaderOnboardingChecker = cardReaderOnboardingChecker, cardReaderConfigProvider = cardReaderConfigProvider, + paymentReceiptShare = paymentReceiptShare, ) } } diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt new file mode 100644 index 00000000000..327879d2c3b --- /dev/null +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt @@ -0,0 +1,27 @@ +package com.woocommerce.android.ui.payments.receipt + +import android.app.Application +import com.woocommerce.android.media.FileUtils +import com.woocommerce.android.util.FileDownloader +import com.woocommerce.android.viewmodel.BaseUnitTest +import kotlinx.coroutines.ExperimentalCoroutinesApi +import org.junit.Test +import org.mockito.kotlin.mock + +@ExperimentalCoroutinesApi +class PaymentReceiptShareTest : BaseUnitTest() { + private val fileUtils: FileUtils = mock() + private val fileDownloader: FileDownloader = mock() + private val context: Application = mock() + + private val sut = PaymentReceiptShare( + fileUtils = fileUtils, + fileDownloader = fileDownloader, + context = context, + ) + + @Test + fun `test receipt share`() = testBlocking { + sut.invoke("receiptUrl", 123L) + } +} 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 42bd8adf5e1..3b26237b967 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 @@ -1,7 +1,6 @@ package com.woocommerce.android.ui.payments.receipt.preview import androidx.lifecycle.SavedStateHandle -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_FAILED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_TAPPED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_CANCELED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED @@ -9,13 +8,14 @@ import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_SUCCESS import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_TAPPED import com.woocommerce.android.analytics.AnalyticsTrackerWrapper 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 +import com.woocommerce.android.ui.payments.tracking.PaymentsFlowTracker 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.viewmodel.BaseUnitTest -import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowSnackbar import kotlinx.coroutines.ExperimentalCoroutinesApi import org.assertj.core.api.Assertions.assertThat import org.junit.Before @@ -31,6 +31,8 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { private val selectedSite: SelectedSite = mock() private val tracker: AnalyticsTrackerWrapper = mock() + private val paymentsFlowTracker: PaymentsFlowTracker = mock() + private val paymentReceiptShare: PaymentReceiptShare = mock() private val savedState: SavedStateHandle = ReceiptPreviewFragmentArgs( receiptUrl = "testing url", @@ -40,7 +42,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Before fun setUp() { - viewModel = ReceiptPreviewViewModel(savedState, tracker, selectedSite) + viewModel = ReceiptPreviewViewModel(savedState, tracker, paymentsFlowTracker, paymentReceiptShare) whenever(selectedSite.get()).thenReturn(SiteModel().apply { name = "testName" }) } @@ -72,14 +74,6 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { assertThat(contentState.isContentVisible).isTrue } - @Test - fun `when user clicks on send email, then send receipt event emitted`() = - testBlocking { - viewModel.onShareClicked() - - assertThat(viewModel.event.value).isInstanceOf(SendReceipt::class.java) - } - @Test fun `when user clicks on send email, then event tracked`() = testBlocking { @@ -88,22 +82,6 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { verify(tracker).track(RECEIPT_EMAIL_TAPPED) } - @Test - fun `when email application not found, then SnackBar with error shown`() = - testBlocking { - viewModel.onActivityToShareNotFound() - - assertThat(viewModel.event.value).isInstanceOf(ShowSnackbar::class.java) - } - - @Test - fun `when email application not found, then event tracked`() = - testBlocking { - viewModel.onActivityToShareNotFound() - - verify(tracker).track(RECEIPT_EMAIL_FAILED) - } - @Test fun `when user clicks on print receipt, then print receipt event emitted`() = testBlocking { From 6bda786190f1cbe96800e8b29179aa16a0562051 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 12:39:22 +0100 Subject: [PATCH 11/19] Partial testing for PaymentReceiptShare --- .../receipt/PaymentReceiptShareTest.kt | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt index 327879d2c3b..966918a2284 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptShareTest.kt @@ -5,14 +5,23 @@ import com.woocommerce.android.media.FileUtils import com.woocommerce.android.util.FileDownloader import com.woocommerce.android.viewmodel.BaseUnitTest import kotlinx.coroutines.ExperimentalCoroutinesApi +import org.assertj.core.api.Assertions.assertThat import org.junit.Test +import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.eq import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever +import java.io.File @ExperimentalCoroutinesApi class PaymentReceiptShareTest : BaseUnitTest() { private val fileUtils: FileUtils = mock() private val fileDownloader: FileDownloader = mock() - private val context: Application = mock() + + private val file: File = mock() + private val context: Application = mock { + on { getExternalFilesDir(anyOrNull()) }.thenReturn(file) + } private val sut = PaymentReceiptShare( fileUtils = fileUtils, @@ -21,7 +30,39 @@ class PaymentReceiptShareTest : BaseUnitTest() { ) @Test - fun `test receipt share`() = testBlocking { - sut.invoke("receiptUrl", 123L) + fun `given file not created, when invoke, then FileCreation error returned`() = testBlocking { + // GIVEN + whenever( + fileUtils.createTempTimeStampedFile( + storageDir = anyOrNull(), + prefix = eq("receipt_999"), + fileExtension = eq("html"), + ) + ).thenReturn(null) + + // WHEN + val result = sut("receiptUrl", 999L) + + // THEN + assertThat(result).isInstanceOf(PaymentReceiptShare.ReceiptShareResult.Error.FileCreation::class.java) + } + + @Test + fun `given file created but not downloaded, when invoke, then FileDownload error returned`() = testBlocking { + // GIVEN + whenever( + fileUtils.createTempTimeStampedFile( + storageDir = anyOrNull(), + prefix = eq("receipt_999"), + fileExtension = eq("html"), + ) + ).thenReturn(file) + whenever(fileDownloader.downloadFile(eq("receiptUrl"), eq(file))).thenReturn(false) + + // WHEN + val result = sut("receiptUrl", 999L) + + // THEN + assertThat(result).isInstanceOf(PaymentReceiptShare.ReceiptShareResult.Error.FileDownload::class.java) } } From 207803de8676b8d4373f88c19618e7c25e513f49 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 14:37:56 +0100 Subject: [PATCH 12/19] Test for CardReaderPaymentViewModel --- .../CardReaderPaymentViewModelTest.kt | 66 +++++++++++++++++-- 1 file changed, 62 insertions(+), 4 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 0bbf49ce280..a9cbfa61c5f 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 @@ -2358,23 +2358,23 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { } @Test - fun `given external reader and receipt fetching and sharing success, when user clicks on send receipt button, then nothing emitted`() = + fun `given external reader and receipt fetching and sharing success, when user clicks on send receipt button, then PlayChaChing emitted`() = testBlocking { whenever(cardReaderManager.collectPayment(any())).thenAnswer { flow { emit(PaymentCompleted("url")) } } - whenever(paymentReceiptShare("url", 1L)).thenReturn( + whenever(paymentReceiptShare("test url", 1L)).thenReturn( PaymentReceiptShare.ReceiptShareResult.Success ) viewModel.start() (viewModel.viewStateData.value as ExternalReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() - assertThat(viewModel.event.value).isNull() + assertThat(viewModel.event.value).isEqualTo(PlayChaChing) } @Test - fun `given built in reader and receipt fetching success, when user clicks on send receipt button, then SendReceipt event emitted`() = + fun `given built in reader and receipt fetching and sharing success, when user clicks on send receipt button, then PlayChaChing emitted`() = testBlocking { whenever(cardReaderManager.collectPayment(any())).thenAnswer { flow { emit(PaymentCompleted("")) } @@ -2385,6 +2385,64 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { viewModel.start() (viewModel.viewStateData.value as BuiltInReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() + + assertThat(viewModel.event.value).isEqualTo(PlayChaChing) + } + + @Test + fun `given receipt fetching success and receipt file not created, when user clicks on send receipt button, then ShowSnackbar emitted`() = + testBlocking { + whenever(cardReaderManager.collectPayment(any())).thenAnswer { + flow { emit(PaymentCompleted("url")) } + } + whenever(paymentReceiptShare("test url", 1L)).thenReturn( + PaymentReceiptShare.ReceiptShareResult.Error.FileCreation + ) + viewModel.start() + + (viewModel.viewStateData.value as ExternalReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() + + assertThat((viewModel.event.value as ShowSnackbar).message).isEqualTo( + R.string.card_reader_payment_receipt_can_not_be_stored + ) + verify(tracker).trackPaymentsReceiptSharingFailed(PaymentReceiptShare.ReceiptShareResult.Error.FileCreation) + } + + @Test + fun `given receipt fetching success and receipt file not downloaded, when user clicks on send receipt button, then ShowSnackbar emitted`() = + testBlocking { + whenever(cardReaderManager.collectPayment(any())).thenAnswer { + flow { emit(PaymentCompleted("url")) } + } + whenever(paymentReceiptShare("test url", 1L)).thenReturn( + PaymentReceiptShare.ReceiptShareResult.Error.FileDownload + ) + viewModel.start() + + (viewModel.viewStateData.value as ExternalReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() + + assertThat((viewModel.event.value as ShowSnackbar).message).isEqualTo( + R.string.card_reader_payment_receipt_can_not_be_downloaded + ) + verify(tracker).trackPaymentsReceiptSharingFailed(PaymentReceiptShare.ReceiptShareResult.Error.FileDownload) + } + + @Test + fun `given receipt fetching success and receipt file not shared, when user clicks on send receipt button, then ShowSnackbar emitted`() = + testBlocking { + whenever(cardReaderManager.collectPayment(any())).thenAnswer { + flow { emit(PaymentCompleted("url")) } + } + val sharing = PaymentReceiptShare.ReceiptShareResult.Error.Sharing(Exception()) + whenever(paymentReceiptShare("test url", 1L)).thenReturn(sharing) + viewModel.start() + + (viewModel.viewStateData.value as ExternalReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() + + assertThat((viewModel.event.value as ShowSnackbar).message).isEqualTo( + R.string.card_reader_payment_receipt_app_to_share_not_found + ) + verify(tracker).trackPaymentsReceiptSharingFailed(sharing) } @Test From c2d1be0b728be040cef9a0a5ce69988c302ac8ad Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 14:39:25 +0100 Subject: [PATCH 13/19] Fixed PaymentReceiptHelperTest --- .../ui/payments/receipt/PaymentReceiptHelperTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelperTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelperTest.kt index 8aa5087bcc1..18b25902f08 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelperTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelperTest.kt @@ -102,7 +102,7 @@ class PaymentReceiptHelperTest : BaseUnitTest() { WooCommerceStore.WooPlugin.WOO_CORE ) ).thenReturn(plugin) - whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 365)).thenReturn( + whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 2)).thenReturn( WooPayload(OrderReceiptResponse("url", "date")) ) @@ -126,7 +126,7 @@ class PaymentReceiptHelperTest : BaseUnitTest() { WooCommerceStore.WooPlugin.WOO_CORE ) ).thenReturn(plugin) - whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 365)).thenReturn( + whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 2)).thenReturn( WooPayload( WooError( type = WooErrorType.API_ERROR, @@ -156,7 +156,7 @@ class PaymentReceiptHelperTest : BaseUnitTest() { selectedSite.get(), ) ).thenReturn(listOf(plugin)) - whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 365)).thenReturn( + whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 2)).thenReturn( WooPayload( WooError( type = WooErrorType.API_ERROR, @@ -187,7 +187,7 @@ class PaymentReceiptHelperTest : BaseUnitTest() { selectedSite.get(), ) ).thenReturn(listOf(plugin)) - whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 365)).thenReturn( + whenever(orderStore.fetchOrdersReceipt(site, 1, expirationDays = 2)).thenReturn( WooPayload(OrderReceiptResponse("url", "date")) ) whenever(isDevSiteSupported()).thenReturn(true) From 6e6bca9ab61f9c59d751df2e220a8829a4edbe98 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 14:46:11 +0100 Subject: [PATCH 14/19] Test for ReceiptPreviewViewModel --- .../preview/ReceiptPreviewViewModelTest.kt | 80 ++++++++++++++++++- 1 file changed, 76 insertions(+), 4 deletions(-) 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 3b26237b967..3a8d0fa2a80 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 @@ -1,13 +1,13 @@ package com.woocommerce.android.ui.payments.receipt.preview import androidx.lifecycle.SavedStateHandle +import com.woocommerce.android.R import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_TAPPED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_CANCELED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_SUCCESS import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_TAPPED import com.woocommerce.android.analytics.AnalyticsTrackerWrapper -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 @@ -16,6 +16,7 @@ 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.viewmodel.BaseUnitTest +import com.woocommerce.android.viewmodel.MultiLiveEvent import kotlinx.coroutines.ExperimentalCoroutinesApi import org.assertj.core.api.Assertions.assertThat import org.junit.Before @@ -23,13 +24,11 @@ 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() { private lateinit var viewModel: ReceiptPreviewViewModel - private val selectedSite: SelectedSite = mock() private val tracker: AnalyticsTrackerWrapper = mock() private val paymentsFlowTracker: PaymentsFlowTracker = mock() private val paymentReceiptShare: PaymentReceiptShare = mock() @@ -43,7 +42,6 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Before fun setUp() { viewModel = ReceiptPreviewViewModel(savedState, tracker, paymentsFlowTracker, paymentReceiptShare) - whenever(selectedSite.get()).thenReturn(SiteModel().apply { name = "testName" }) } @Test @@ -82,6 +80,80 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { verify(tracker).track(RECEIPT_EMAIL_TAPPED) } + @Test + fun `given sharing success, when onShareClicked, then no events emitted`() = + testBlocking { + // GIVEN + whenever(paymentReceiptShare("testing url", 999L)).thenReturn( + PaymentReceiptShare.ReceiptShareResult.Success + ) + + // WHEN + viewModel.onShareClicked() + + // THEN + assertThat(viewModel.event.value).isInstanceOf(LoadUrl::class.java) + } + + @Test + fun `given sharing failed with file cretion, when onShareClicked, then ShowSnackbar emitted`() = + testBlocking { + // GIVEN + whenever(paymentReceiptShare("testing url", 999L)).thenReturn( + PaymentReceiptShare.ReceiptShareResult.Error.FileCreation + ) + + // WHEN + viewModel.onShareClicked() + + // THEN + assertThat((viewModel.event.value as MultiLiveEvent.Event.ShowSnackbar).message).isEqualTo( + R.string.card_reader_payment_receipt_can_not_be_stored + ) + verify(paymentsFlowTracker).trackPaymentsReceiptSharingFailed( + PaymentReceiptShare.ReceiptShareResult.Error.FileCreation + ) + } + + @Test + fun `given sharing failed with file downloading, when onShareClicked, then ShowSnackbar emitted`() = + testBlocking { + // GIVEN + whenever(paymentReceiptShare("testing url", 999L)).thenReturn( + PaymentReceiptShare.ReceiptShareResult.Error.FileDownload + ) + + // WHEN + viewModel.onShareClicked() + + // THEN + assertThat((viewModel.event.value as MultiLiveEvent.Event.ShowSnackbar).message).isEqualTo( + R.string.card_reader_payment_receipt_can_not_be_downloaded + ) + verify(paymentsFlowTracker).trackPaymentsReceiptSharingFailed( + PaymentReceiptShare.ReceiptShareResult.Error.FileDownload + ) + } + + @Test + fun `given sharing failed with file sharing, when onShareClicked, then ShowSnackbar emitted`() = + testBlocking { + // GIVEN + val sharing = PaymentReceiptShare.ReceiptShareResult.Error.Sharing(Exception()) + whenever(paymentReceiptShare("testing url", 999L)).thenReturn(sharing) + + // WHEN + viewModel.onShareClicked() + + // THEN + assertThat((viewModel.event.value as MultiLiveEvent.Event.ShowSnackbar).message).isEqualTo( + R.string.card_reader_payment_receipt_app_to_share_not_found + ) + verify(paymentsFlowTracker).trackPaymentsReceiptSharingFailed( + sharing + ) + } + @Test fun `when user clicks on print receipt, then print receipt event emitted`() = testBlocking { From ed6b58bbebec1080c8d247a748d45ad750eb0709 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 30 Jan 2024 15:06:16 +0100 Subject: [PATCH 15/19] Updated release notes --- RELEASE-NOTES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 463fb94b49d..091f9a955bd 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,4 +1,8 @@ *** PLEASE FOLLOW THIS FORMAT: [] [] +17.2 +----- +- [**] Every order have a receipt now. The receipts can be shared via many apps installed on the phone [https://github.com/woocommerce/woocommerce-android/pull/10650] + 17.1 ----- From d143c97c57c9581cd1affb66d1034534ac167fd6 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 31 Jan 2024 18:15:56 +0100 Subject: [PATCH 16/19] Updated release notes --- RELEASE-NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 091f9a955bd..68bab4ccc5a 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,7 +1,7 @@ *** PLEASE FOLLOW THIS FORMAT: [] [] 17.2 ----- -- [**] Every order have a receipt now. The receipts can be shared via many apps installed on the phone [https://github.com/woocommerce/woocommerce-android/pull/10650] +- [**] (For users with WooCommerce version of 8.7+) Every order have a receipt now. The receipts can be shared via many apps installed on the phone [https://github.com/woocommerce/woocommerce-android/pull/10650] 17.1 ----- From 6898b8354fdf0c3d1ce39252bb7fb40f5bdc02e4 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 1 Feb 2024 10:55:26 +0100 Subject: [PATCH 17/19] Reverted string renaming to avoid unnecessary changes --- .../payments/cardreader/payment/CardReaderPaymentViewModel.kt | 4 ++-- .../ui/payments/receipt/preview/ReceiptPreviewViewModel.kt | 2 +- WooCommerce/src/main/res/values-ar/strings.xml | 2 +- WooCommerce/src/main/res/values-de/strings.xml | 2 +- WooCommerce/src/main/res/values-es/strings.xml | 2 +- WooCommerce/src/main/res/values-fr/strings.xml | 2 +- WooCommerce/src/main/res/values-he/strings.xml | 2 +- WooCommerce/src/main/res/values-id/strings.xml | 2 +- WooCommerce/src/main/res/values-it/strings.xml | 2 +- WooCommerce/src/main/res/values-ja/strings.xml | 2 +- WooCommerce/src/main/res/values-ko/strings.xml | 2 +- WooCommerce/src/main/res/values-nl/strings.xml | 2 +- WooCommerce/src/main/res/values-pt-rBR/strings.xml | 2 +- WooCommerce/src/main/res/values-ru/strings.xml | 2 +- WooCommerce/src/main/res/values-sv/strings.xml | 2 +- WooCommerce/src/main/res/values-tr/strings.xml | 2 +- WooCommerce/src/main/res/values-zh-rCN/strings.xml | 2 +- WooCommerce/src/main/res/values-zh-rTW/strings.xml | 2 +- WooCommerce/src/main/res/values/strings.xml | 2 +- .../ui/payments/cardreader/CardReaderPaymentViewModelTest.kt | 2 +- .../payments/receipt/preview/ReceiptPreviewViewModelTest.kt | 2 +- 21 files changed, 22 insertions(+), 22 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 fc52388c3f9..de62a7ab603 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 @@ -742,7 +742,7 @@ class CardReaderPaymentViewModel } is PaymentReceiptShare.ReceiptShareResult.Error.Sharing -> { tracker.trackPaymentsReceiptSharingFailed(sharingResult) - triggerEvent(ShowSnackbar(R.string.card_reader_payment_receipt_app_to_share_not_found)) + triggerEvent(ShowSnackbar(R.string.card_reader_payment_email_client_not_found)) } PaymentReceiptShare.ReceiptShareResult.Success -> { // no-op @@ -758,7 +758,7 @@ class CardReaderPaymentViewModel fun onEmailActivityNotFound() { tracker.trackEmailReceiptFailed() - triggerEvent(ShowSnackbarInDialog(R.string.card_reader_payment_receipt_app_to_share_not_found)) + triggerEvent(ShowSnackbarInDialog(R.string.card_reader_payment_email_client_not_found)) } fun onPrintResult(result: PrintJobResult) { 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 ed7aa503ec5..b74846b8e71 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 @@ -67,7 +67,7 @@ class ReceiptPreviewViewModel } is PaymentReceiptShare.ReceiptShareResult.Error.Sharing -> { paymentsFlowTracker.trackPaymentsReceiptSharingFailed(sharingResult) - triggerEvent(ShowSnackbar(string.card_reader_payment_receipt_app_to_share_not_found)) + triggerEvent(ShowSnackbar(string.card_reader_payment_email_client_not_found)) } PaymentReceiptShare.ReceiptShareResult.Success -> { // no-op diff --git a/WooCommerce/src/main/res/values-ar/strings.xml b/WooCommerce/src/main/res/values-ar/strings.xml index 76aedcc43e9..cc49beffa7f 100644 --- a/WooCommerce/src/main/res/values-ar/strings.xml +++ b/WooCommerce/src/main/res/values-ar/strings.xml @@ -1910,7 +1910,7 @@ Language: ar سمات المجموعات تشغيل بلوتوث الجهاز المحمول حدث خطأ في أثناء إحضار الطلب. قد تكون حالة الطلب الموجودة في التطبيق قديمة. - لا يمكن اكتشاف تطبيق عميل البريد الإلكتروني الخاص بك + لا يمكن اكتشاف تطبيق عميل البريد الإلكتروني الخاص بك إيصالك من %s تحديث الطلب تحديث حالة التطبيق diff --git a/WooCommerce/src/main/res/values-de/strings.xml b/WooCommerce/src/main/res/values-de/strings.xml index cf4d312a3a1..f069ba46c0f 100644 --- a/WooCommerce/src/main/res/values-de/strings.xml +++ b/WooCommerce/src/main/res/values-de/strings.xml @@ -1910,7 +1910,7 @@ Language: de Variantenattribute Aktiviere Bluetooth auf dem Mobilgerät Fehler beim Abrufen der Bestellung Der Bestellstatus in der App ist eventuell nicht aktuell. - E-Mail-Client-App wird nicht erkannt. + E-Mail-Client-App wird nicht erkannt. Dein Beleg vom %s Bestellung aktualisieren App-Status aktualisieren diff --git a/WooCommerce/src/main/res/values-es/strings.xml b/WooCommerce/src/main/res/values-es/strings.xml index fe0e0d5bd54..8e32a914850 100644 --- a/WooCommerce/src/main/res/values-es/strings.xml +++ b/WooCommerce/src/main/res/values-es/strings.xml @@ -1910,7 +1910,7 @@ Language: es Atributos de variaciones Activa Bluetooth en el dispositivo móvil Error al recuperar el pedido. El estado del pedido en la aplicación podría estar desactualizado. - No se pudo detectar una aplicación cliente de correo electrónico + No se pudo detectar una aplicación cliente de correo electrónico Tu recibo de %s Actualizando pedido Actualizando estado en la aplicación diff --git a/WooCommerce/src/main/res/values-fr/strings.xml b/WooCommerce/src/main/res/values-fr/strings.xml index f18596537c6..2fdba76735a 100644 --- a/WooCommerce/src/main/res/values-fr/strings.xml +++ b/WooCommerce/src/main/res/values-fr/strings.xml @@ -1910,7 +1910,7 @@ Language: fr Attributs des variantes Activer le Bluetooth de l’appareil mobile Erreur lors de l’extraction de la commande. L’état de la commande dans l’application est peut-être obsolète. - Aucune application de messagerie détectée + Aucune application de messagerie détectée Votre reçu de %s Actualisation de la commande Mise à jour de l’état de l’application diff --git a/WooCommerce/src/main/res/values-he/strings.xml b/WooCommerce/src/main/res/values-he/strings.xml index 8622401ba37..4e5a67434b2 100644 --- a/WooCommerce/src/main/res/values-he/strings.xml +++ b/WooCommerce/src/main/res/values-he/strings.xml @@ -1910,7 +1910,7 @@ Language: he_IL מאפייני סוגים יש להפעיל את חיבור ה-Bluetooth של המכשיר הנייד שגיאה בהבאת ההזמנה. ייתכן שמצב ההזמנה באפליקציה לא מעודכן. - לא ניתן לאתר את האפליקציה של שירות האימייל שלך + לא ניתן לאתר את האפליקציה של שירות האימייל שלך הקבלה שלך מאת %s מרענן את ההזמנה מעדכן את מצב האפליקציה diff --git a/WooCommerce/src/main/res/values-id/strings.xml b/WooCommerce/src/main/res/values-id/strings.xml index b7315da284f..fa29a8b2c73 100644 --- a/WooCommerce/src/main/res/values-id/strings.xml +++ b/WooCommerce/src/main/res/values-id/strings.xml @@ -1910,7 +1910,7 @@ Language: id Atribut variasi Aktifkan bluetooth perangkat seluler Terjadi error saat mengambil pesanan. Status pesanan pada aplikasi mungkin telah usang. - Tidak dapat mendeteksi aplikasi klien email Anda + Tidak dapat mendeteksi aplikasi klien email Anda Tanda terima Anda dari %s Menyegarkan pesanan Memperbarui status aplikasi diff --git a/WooCommerce/src/main/res/values-it/strings.xml b/WooCommerce/src/main/res/values-it/strings.xml index cae8e5ca689..4f1d803552e 100644 --- a/WooCommerce/src/main/res/values-it/strings.xml +++ b/WooCommerce/src/main/res/values-it/strings.xml @@ -1910,7 +1910,7 @@ Language: it Attributi della variante Attiva il Bluetooth del dispositivo mobile Errore durante il recupero dell\'ordine. Lo stato nell\'ordine dell\'app potrebbe essere obsoleto. - Impossibile rilevare il client e-mail della tua app + Impossibile rilevare il client e-mail della tua app La tua ricevuta da %s Aggiornamento dell\'ordine Aggiornamento dello stato dell\'app diff --git a/WooCommerce/src/main/res/values-ja/strings.xml b/WooCommerce/src/main/res/values-ja/strings.xml index 57f251429ea..ce4d1990c3b 100644 --- a/WooCommerce/src/main/res/values-ja/strings.xml +++ b/WooCommerce/src/main/res/values-ja/strings.xml @@ -1910,7 +1910,7 @@ Language: ja_JP バリエーション属性 モバイルデバイスの Bluetooth をオンにする 注文を取得する際にエラーが発生しました。 アプリの注文状態が古い可能性があります。 - メールクライアントアプリを検出できません + メールクライアントアプリを検出できません %s のレシート 注文を更新する アプリの状態を更新する diff --git a/WooCommerce/src/main/res/values-ko/strings.xml b/WooCommerce/src/main/res/values-ko/strings.xml index f445739f0b5..70f0935b61d 100644 --- a/WooCommerce/src/main/res/values-ko/strings.xml +++ b/WooCommerce/src/main/res/values-ko/strings.xml @@ -1910,7 +1910,7 @@ Language: ko_KR 변형 속성 모바일 장치 블루투스 켜기 주문을 가져오는 중 오류가 발생했습니다. 앱의 주문 상태가 기한이 지났을 수 있습니다. - 이메일 클라이언트 앱을 감지할 수 없습니다. + 이메일 클라이언트 앱을 감지할 수 없습니다. %s에서 받은 영수증 주문 새로 고치기 앱 상태 업데이트하기 diff --git a/WooCommerce/src/main/res/values-nl/strings.xml b/WooCommerce/src/main/res/values-nl/strings.xml index b60a6ba5886..e53a15e7869 100644 --- a/WooCommerce/src/main/res/values-nl/strings.xml +++ b/WooCommerce/src/main/res/values-nl/strings.xml @@ -1903,7 +1903,7 @@ Language: nl Variatie-eigenschappen Zet de Bluetooth aan op je mobiele apparaat Fout bij ophalen bestelling. De bestellingsstatus in de app kan verouderd zijn. - Detectie van mailclient-app mislukt + Detectie van mailclient-app mislukt Je kwitantie van %s Bestelling aan het vernieuwen… Status in de app aan het bijwerken… diff --git a/WooCommerce/src/main/res/values-pt-rBR/strings.xml b/WooCommerce/src/main/res/values-pt-rBR/strings.xml index ecde05b45f3..09d637b857d 100644 --- a/WooCommerce/src/main/res/values-pt-rBR/strings.xml +++ b/WooCommerce/src/main/res/values-pt-rBR/strings.xml @@ -1910,7 +1910,7 @@ Language: pt_BR Atributos das variações Ativar o Bluetooth do dispositivo móvel Erro ao buscar o pedido. O status do pedido pode estar desatualizado no aplicativo. - Não é possível detectar seu aplicativo cliente de e-mail + Não é possível detectar seu aplicativo cliente de e-mail Seu recibo de %s Atualizando pedido Atualizando estado do aplicativo diff --git a/WooCommerce/src/main/res/values-ru/strings.xml b/WooCommerce/src/main/res/values-ru/strings.xml index cc35e4e790d..a04d66d7e2f 100644 --- a/WooCommerce/src/main/res/values-ru/strings.xml +++ b/WooCommerce/src/main/res/values-ru/strings.xml @@ -1910,7 +1910,7 @@ Language: ru Атрибуты вариантов Включите Bluetooth на мобильном устройстве Ошибка при загрузке заказа. Состояние заказа в приложении могло устареть. - Не удалось определить ваш почтовый клиент + Не удалось определить ваш почтовый клиент Ваша квитанция от %s Обновление заказа Обновление состояния приложения diff --git a/WooCommerce/src/main/res/values-sv/strings.xml b/WooCommerce/src/main/res/values-sv/strings.xml index 9e4e1cf2148..977cd03c403 100644 --- a/WooCommerce/src/main/res/values-sv/strings.xml +++ b/WooCommerce/src/main/res/values-sv/strings.xml @@ -1917,7 +1917,7 @@ Language: sv_SE Börja sälja idag genom att lägga till din första produkt i butiken. Variationsattribut Aktivera Bluetooth på den mobila enheten - Lyckas inte hitta ditt e-postprogram + Lyckas inte hitta ditt e-postprogram Uppdaterar beställning Uppdaterar appstatusen Det gick inte att hämta beställningen. Beställningens status i appen kan vara föråldrad. diff --git a/WooCommerce/src/main/res/values-tr/strings.xml b/WooCommerce/src/main/res/values-tr/strings.xml index bf6d75a1ca7..70eec362196 100644 --- a/WooCommerce/src/main/res/values-tr/strings.xml +++ b/WooCommerce/src/main/res/values-tr/strings.xml @@ -1910,7 +1910,7 @@ Language: tr Varyasyon nitelikleri. Mobil cihazda Bluetooth\'u açın Sipariş alınırken hata oluştu Uygulamadaki sipariş durumu eski olabilir. - E-posta istemcisi uygulamanızı tespit edemiyoruz + E-posta istemcisi uygulamanızı tespit edemiyoruz %s makbuzunuz Sipariş yenileniyor Uygulama durumu güncelleniyor diff --git a/WooCommerce/src/main/res/values-zh-rCN/strings.xml b/WooCommerce/src/main/res/values-zh-rCN/strings.xml index 1a835ed6868..2094348f61f 100644 --- a/WooCommerce/src/main/res/values-zh-rCN/strings.xml +++ b/WooCommerce/src/main/res/values-zh-rCN/strings.xml @@ -1909,7 +1909,7 @@ Language: zh_CN 添加产品 变体属性 打开移动设备蓝牙 - 未侦测到您的电子邮件客户端应用 + 未侦测到您的电子邮件客户端应用 来自 %s 的收据 刷新订单 更新应用程序状态 diff --git a/WooCommerce/src/main/res/values-zh-rTW/strings.xml b/WooCommerce/src/main/res/values-zh-rTW/strings.xml index 2dcd4dcbef0..0c9892b1cae 100644 --- a/WooCommerce/src/main/res/values-zh-rTW/strings.xml +++ b/WooCommerce/src/main/res/values-zh-rTW/strings.xml @@ -1910,7 +1910,7 @@ Language: zh_TW 款式屬性 開啟行動裝置的藍牙 擷取訂單時發生錯誤。 應用程式中的訂單狀態可能已過期。 - 無法偵測電子郵件用戶端應用程式 + 無法偵測電子郵件用戶端應用程式 你的 %s 收據 正在重新整理訂單 正在更新應用程式狀態 diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index 7a855966ae3..7ef7a5426aa 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -1507,7 +1507,7 @@ In-Person Payment for Order #%1$s for %2$s blog_id %3$s. Your receipt from %s Thank you for your purchase! Click the link below for your payment receipt.\n\n%s - Unable to detect any application to which the receipt can be shared + Unable to detect any application to which the receipt can be shared Unable to download the receipt Unable to store the receipt Error fetching order. Order state in the app might be outdated. 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 a9cbfa61c5f..d735c8f6aa2 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 @@ -2440,7 +2440,7 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { (viewModel.viewStateData.value as ExternalReaderPaymentSuccessfulState).onSecondaryActionClicked.invoke() assertThat((viewModel.event.value as ShowSnackbar).message).isEqualTo( - R.string.card_reader_payment_receipt_app_to_share_not_found + R.string.card_reader_payment_email_client_not_found ) verify(tracker).trackPaymentsReceiptSharingFailed(sharing) } 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 3a8d0fa2a80..b4e002726cd 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 @@ -147,7 +147,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { // THEN assertThat((viewModel.event.value as MultiLiveEvent.Event.ShowSnackbar).message).isEqualTo( - R.string.card_reader_payment_receipt_app_to_share_not_found + R.string.card_reader_payment_email_client_not_found ) verify(paymentsFlowTracker).trackPaymentsReceiptSharingFailed( sharing From c283af71e87b8160fe9955471c0e3b9c332e92f9 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 1 Feb 2024 11:00:59 +0100 Subject: [PATCH 18/19] Better wording for release notes so its clear for the release manager --- RELEASE-NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 68bab4ccc5a..f72f48c6e92 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,7 +1,7 @@ *** PLEASE FOLLOW THIS FORMAT: [] [] 17.2 ----- -- [**] (For users with WooCommerce version of 8.7+) Every order have a receipt now. The receipts can be shared via many apps installed on the phone [https://github.com/woocommerce/woocommerce-android/pull/10650] +- [**] [Available for users with WooCommerce version of 8.7+, which is not released yet] Every order have a receipt now. The receipts can be shared via many apps installed on the phone [https://github.com/woocommerce/woocommerce-android/pull/10650] 17.1 ----- From bd89dfb4c2229dc1e227daf8638acb3358e08666 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 2 Feb 2024 09:08:18 +0100 Subject: [PATCH 19/19] Updated fluxc release --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 55a46108b90..47c8eb55add 100644 --- a/build.gradle +++ b/build.gradle @@ -96,7 +96,7 @@ tasks.register("installGitHooks", Copy) { } ext { - fluxCVersion = '2948-235834ae9467ae3ca367a4b13c4f9c6aea0f31bf' + fluxCVersion = 'trunk-b34cc5eed609ca5274fbb442991f657f2380de17' glideVersion = '4.13.2' coilVersion = '2.1.0' constraintLayoutVersion = '1.2.0'