From 0c63f1d3a9f5456da12c2a3e84ec523c0d1ccbba Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Fri, 3 Oct 2025 12:32:05 +0200 Subject: [PATCH 1/8] Align icons for email&phone with the order screen --- .../android/ui/bookings/compose/BookingCustomerDetails.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt index a3b4fb07645..aadbc9b37d2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -44,7 +45,7 @@ fun BookingCustomerDetails( value = model.email, trailingIcon = { Icon( - imageVector = Icons.Outlined.FileCopy, + painter = painterResource(R.drawable.ic_email), contentDescription = stringResource(id = R.string.booking_customer_label_email), tint = MaterialTheme.colorScheme.primary ) @@ -55,7 +56,7 @@ fun BookingCustomerDetails( value = model.phone, trailingIcon = { Icon( - imageVector = Icons.Outlined.MoreHoriz, + painter = painterResource(R.drawable.ic_menu_more_vert), contentDescription = stringResource(id = R.string.booking_customer_label_phone), tint = MaterialTheme.colorScheme.primary ) From bb13aa454cde7a71fc2a066d08c15e7bdc0231df Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Fri, 3 Oct 2025 13:20:08 +0200 Subject: [PATCH 2/8] Extract sendSms function to ActivityUtils --- .../android/ui/orders/OrderCustomerHelper.kt | 11 ++--------- .../com/woocommerce/android/util/ActivityUtils.kt | 11 +++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderCustomerHelper.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderCustomerHelper.kt index 82a0bfde385..87e6ac93ac4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderCustomerHelper.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderCustomerHelper.kt @@ -1,9 +1,6 @@ package com.woocommerce.android.ui.orders -import android.content.ActivityNotFoundException import android.content.Context -import android.content.Intent -import android.net.Uri import com.woocommerce.android.R import com.woocommerce.android.analytics.AnalyticsEvent import com.woocommerce.android.analytics.AnalyticsTracker @@ -83,15 +80,11 @@ object OrderCustomerHelper { ) ) - val intent = Intent(Intent.ACTION_SENDTO) - intent.data = Uri.parse("smsto:$phone") - try { - context.startActivity(intent) - } catch (e: ActivityNotFoundException) { + ActivityUtils.sendSms(context, phone) { error -> AnalyticsTracker.track( AnalyticsEvent.ORDER_CONTACT_ACTION_FAILED, this.javaClass.simpleName, - e.javaClass.simpleName, + error.javaClass.simpleName, "No SMS app was found" ) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ActivityUtils.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ActivityUtils.kt index d5379d82a4c..8193bfa75fc 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ActivityUtils.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/ActivityUtils.kt @@ -9,6 +9,7 @@ import android.net.Uri import android.os.Build.VERSION.SDK_INT import android.os.Parcelable import androidx.core.content.FileProvider +import androidx.core.net.toUri import com.woocommerce.android.R import com.woocommerce.android.extensions.intentActivities import com.woocommerce.android.model.UiString @@ -53,6 +54,16 @@ object ActivityUtils { } } + fun sendSms(context: Context, phoneNumber: String, onError: (e: ActivityNotFoundException) -> Unit) { + val intent = Intent(Intent.ACTION_SENDTO) + intent.data = "smsto:$phoneNumber".toUri() + try { + context.startActivity(intent) + } catch (e: ActivityNotFoundException) { + onError(e) + } + } + /** * Use this only when you want to open the external browser - otherwise use * [ChromeCustomTabUtils.launchUrl] to provide a better in-app experience From 8bff5bb7cfeea280446406f0912248a3077534db Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Fri, 3 Oct 2025 13:26:12 +0200 Subject: [PATCH 3/8] Create ContactDropdownMenu composable to show contact options --- .../compose/BookingCustomerDetails.kt | 31 ++++++--- .../bookings/compose/ContactDropdownMenu.kt | 69 +++++++++++++++++++ .../bookings/details/BookingDetailsScreen.kt | 1 - 3 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt index aadbc9b37d2..685e3635772 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt @@ -2,19 +2,21 @@ package com.woocommerce.android.ui.bookings.compose import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.FileCopy -import androidx.compose.material.icons.outlined.MoreHoriz import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity @@ -30,9 +32,10 @@ import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground fun BookingCustomerDetails( model: BookingCustomerDetailsModel, onEmailClick: () -> Unit, - onPhoneClick: () -> Unit, modifier: Modifier = Modifier, ) { + var phoneMenuExpanded by remember { mutableStateOf(false) } + Column(modifier = modifier) { BookingSectionHeader(R.string.booking_customer_details_header) Column( @@ -55,13 +58,20 @@ fun BookingCustomerDetails( CustomerDetailsRow( value = model.phone, trailingIcon = { - Icon( - painter = painterResource(R.drawable.ic_menu_more_vert), - contentDescription = stringResource(id = R.string.booking_customer_label_phone), - tint = MaterialTheme.colorScheme.primary - ) + Box { + Icon( + painter = painterResource(R.drawable.ic_menu_more_vert), + contentDescription = stringResource(id = R.string.booking_customer_label_phone), + tint = MaterialTheme.colorScheme.primary + ) + ContactDropdownMenu( + expanded = phoneMenuExpanded, + phone = model.phone, + onDismissRequest = { phoneMenuExpanded = false } + ) + } }, - modifier = Modifier.clickable { onPhoneClick() } + modifier = Modifier.clickable { phoneMenuExpanded = true } ) Column( modifier = Modifier @@ -147,7 +157,6 @@ private fun BookingCustomerDetailsPreview() { ) ), onEmailClick = {}, - onPhoneClick = {}, modifier = Modifier.fillMaxWidth() ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt new file mode 100644 index 00000000000..3f9a08b6654 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt @@ -0,0 +1,69 @@ +package com.woocommerce.android.ui.bookings.compose + +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import com.woocommerce.android.R +import com.woocommerce.android.util.ActivityUtils +import org.wordpress.android.util.ToastUtils + +private const val WHATSAPP_PACKAGE_NAME = "com.whatsapp" +private const val TELEGRAM_PACKAGE_NAME = "org.telegram.messenger" + +@Composable +fun ContactDropdownMenu( + expanded: Boolean, + phone: String, + onDismissRequest: () -> Unit, +) { + val context = LocalContext.current + + DropdownMenu( + expanded = expanded, + onDismissRequest = onDismissRequest + ) { + DropdownMenuItem( + text = { Text(stringResource(R.string.orderdetail_call_customer)) }, + onClick = { + ActivityUtils.dialPhoneNumber(context, phone) { error -> + ToastUtils.showToast(context, R.string.error_no_phone_app) + } + onDismissRequest() + } + ) + DropdownMenuItem( + text = { Text(stringResource(R.string.orderdetail_message_customer)) }, + onClick = { + ActivityUtils.sendSms(context, phone) { + ToastUtils.showToast(context, R.string.error_no_sms_app) + } + onDismissRequest() + } + ) + if (ActivityUtils.isAppInstalled(context, WHATSAPP_PACKAGE_NAME)) { + DropdownMenuItem( + text = { + Text(stringResource(R.string.orderdetail_message_customer_using_whatsapp)) + }, + onClick = { + ActivityUtils.openWhatsApp(context, phone) + onDismissRequest() + } + ) + } + if (ActivityUtils.isAppInstalled(context, TELEGRAM_PACKAGE_NAME)) { + DropdownMenuItem( + text = { + Text(stringResource(R.string.orderdetail_message_customer_using_telegram)) + }, + onClick = { + ActivityUtils.openTelegram(context, phone) + onDismissRequest() + } + ) + } + } +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt index 0a5383b4884..76188e9960e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt @@ -88,7 +88,6 @@ fun BookingDetailsScreen( BookingCustomerDetails( model = viewState.bookingCustomerDetails, onEmailClick = {}, - onPhoneClick = {}, modifier = Modifier.fillMaxWidth() ) BookingAttendanceSection( From b16d61993dba001e35707cc76e1a14c07725f741 Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Fri, 3 Oct 2025 14:40:32 +0200 Subject: [PATCH 4/8] Extract logic to check for available phone contact options --- .../android/util/PhoneContactOptionsUtils.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/util/PhoneContactOptionsUtils.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/PhoneContactOptionsUtils.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/PhoneContactOptionsUtils.kt new file mode 100644 index 00000000000..564d2abde41 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/PhoneContactOptionsUtils.kt @@ -0,0 +1,33 @@ +package com.woocommerce.android.util + +import android.content.Context +import androidx.annotation.StringRes +import com.woocommerce.android.R + +private const val WHATSAPP_PACKAGE_NAME = "com.whatsapp" +private const val TELEGRAM_PACKAGE_NAME = "org.telegram.messenger" + +fun Context.getAvailablePhoneContactOptions(): List { + return buildList { + add(PhoneContactOption.CALL) + add(PhoneContactOption.SMS) + if (ActivityUtils.isAppInstalled(this@getAvailablePhoneContactOptions, WHATSAPP_PACKAGE_NAME)) { + add(PhoneContactOption.WHATSAPP) + } + if (ActivityUtils.isAppInstalled(this@getAvailablePhoneContactOptions, TELEGRAM_PACKAGE_NAME)) { + add(PhoneContactOption.TELEGRAM) + } + } +} + +enum class PhoneContactOption { + CALL, SMS, WHATSAPP, TELEGRAM +} + +val PhoneContactOption.stringRes: Int + @StringRes get() = when (this) { + PhoneContactOption.CALL -> R.string.orderdetail_call_customer + PhoneContactOption.SMS -> R.string.orderdetail_message_customer + PhoneContactOption.WHATSAPP -> R.string.orderdetail_message_customer_using_whatsapp + PhoneContactOption.TELEGRAM -> R.string.orderdetail_message_customer_using_telegram + } From f38810229feada2d8f73eb83ddfcc572b64257fe Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Fri, 3 Oct 2025 14:41:01 +0200 Subject: [PATCH 5/8] Use PhoneContactOptionsUtils in the Order screen --- .../details/views/OrderDetailCustomerInfoView.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/views/OrderDetailCustomerInfoView.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/views/OrderDetailCustomerInfoView.kt index 15cabffffef..d1071dab0e0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/views/OrderDetailCustomerInfoView.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/views/OrderDetailCustomerInfoView.kt @@ -25,7 +25,9 @@ import com.woocommerce.android.model.Order import com.woocommerce.android.ui.orders.OrderCustomerHelper import com.woocommerce.android.ui.orders.details.OrderDetailFragmentDirections import com.woocommerce.android.util.ActivityUtils +import com.woocommerce.android.util.PhoneContactOption import com.woocommerce.android.util.PhoneUtils +import com.woocommerce.android.util.getAvailablePhoneContactOptions import com.woocommerce.android.widgets.AppRatingDialog class OrderDetailCustomerInfoView @JvmOverloads constructor( @@ -36,8 +38,6 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor( private companion object { const val KEY_SUPER_STATE = "ORDER-DETAIL-CUSTOMER-INFO-VIEW-SUPER-STATE" const val KEY_IS_CUSTOMER_INFO_VIEW_EXPANDED = "ORDER-DETAIL-CUSTOMER-INFO-VIEW-IS_CUSTOMER_INFO_VIEW_EXPANDED" - private const val WHATSAPP_PACKAGE_NAME = "com.whatsapp" - private const val TELEGRAM_PACKAGE_NAME = "org.telegram.messenger" } private val binding = OrderDetailCustomerInfoBinding.inflate(LayoutInflater.from(ctx), this) @@ -281,6 +281,7 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor( binding.customerInfoMorePanel.expand() binding.customerInfoViewMore.setOnClickListener(null) } + else -> { binding.customerInfoShippingAddr.setText(shippingAddress, R.string.order_detail_add_shipping_address) binding.customerInfoShippingMethodSection.isVisible = order.shippingMethods.firstOrNull()?.let { @@ -331,6 +332,8 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor( val popup = PopupMenu(context, binding.customerInfoCallOrMessageBtn) popup.menuInflater.inflate(R.menu.menu_order_detail_phone_actions, popup.menu) + val contactOptions = context.getAvailablePhoneContactOptions() + popup.menu.findItem(R.id.menu_call)?.setOnMenuItemClickListener { AnalyticsTracker.track(AnalyticsEvent.ORDER_DETAIL_CUSTOMER_INFO_PHONE_MENU_PHONE_TAPPED) OrderCustomerHelper.dialPhone(context, order, order.billingAddress.phone) @@ -345,7 +348,7 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor( true } - if (ActivityUtils.isAppInstalled(context, WHATSAPP_PACKAGE_NAME)) { + if (contactOptions.contains(PhoneContactOption.WHATSAPP)) { popup.menu.add( 0, View.generateViewId(), @@ -359,7 +362,7 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor( } } - if (ActivityUtils.isAppInstalled(context, TELEGRAM_PACKAGE_NAME)) { + if (contactOptions.contains(PhoneContactOption.TELEGRAM)) { popup.menu.add( 0, View.generateViewId(), From fc5caaa9a8fab1b441a7a97ea6f9d98719acd48b Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Fri, 3 Oct 2025 14:41:15 +0200 Subject: [PATCH 6/8] Use PhoneContactOptionsUtils in the Booking screen --- .../bookings/compose/ContactDropdownMenu.kt | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt index 3f9a08b6654..43a58dd12ea 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt @@ -1,18 +1,20 @@ package com.woocommerce.android.ui.bookings.compose +import android.content.Context import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import com.woocommerce.android.R import com.woocommerce.android.util.ActivityUtils +import com.woocommerce.android.util.PhoneContactOption +import com.woocommerce.android.util.getAvailablePhoneContactOptions +import com.woocommerce.android.util.stringRes import org.wordpress.android.util.ToastUtils -private const val WHATSAPP_PACKAGE_NAME = "com.whatsapp" -private const val TELEGRAM_PACKAGE_NAME = "org.telegram.messenger" - @Composable fun ContactDropdownMenu( expanded: Boolean, @@ -20,50 +22,52 @@ fun ContactDropdownMenu( onDismissRequest: () -> Unit, ) { val context = LocalContext.current + val contactOptions = remember { context.getAvailablePhoneContactOptions() } DropdownMenu( expanded = expanded, onDismissRequest = onDismissRequest ) { - DropdownMenuItem( - text = { Text(stringResource(R.string.orderdetail_call_customer)) }, - onClick = { - ActivityUtils.dialPhoneNumber(context, phone) { error -> + contactOptions.forEach { contactOption -> + DropdownMenuItem( + text = { Text(stringResource(contactOption.stringRes)) }, + onClick = { + contactOption.action(context, phone) + onDismissRequest() + } + ) + } + } +} + +private val PhoneContactOption.action: (Context, String) -> Unit + get() = when (this) { + PhoneContactOption.CALL -> { + // This is the lambda being returned. It must define its parameters. + { context, phone -> + ActivityUtils.dialPhoneNumber(context, phone) { ToastUtils.showToast(context, R.string.error_no_phone_app) } - onDismissRequest() } - ) - DropdownMenuItem( - text = { Text(stringResource(R.string.orderdetail_message_customer)) }, - onClick = { + } + + PhoneContactOption.SMS -> { + { context, phone -> ActivityUtils.sendSms(context, phone) { ToastUtils.showToast(context, R.string.error_no_sms_app) } - onDismissRequest() } - ) - if (ActivityUtils.isAppInstalled(context, WHATSAPP_PACKAGE_NAME)) { - DropdownMenuItem( - text = { - Text(stringResource(R.string.orderdetail_message_customer_using_whatsapp)) - }, - onClick = { - ActivityUtils.openWhatsApp(context, phone) - onDismissRequest() - } - ) } - if (ActivityUtils.isAppInstalled(context, TELEGRAM_PACKAGE_NAME)) { - DropdownMenuItem( - text = { - Text(stringResource(R.string.orderdetail_message_customer_using_telegram)) - }, - onClick = { - ActivityUtils.openTelegram(context, phone) - onDismissRequest() - } - ) + + PhoneContactOption.WHATSAPP -> { + { context, phone -> + ActivityUtils.openWhatsApp(context, phone) + } + } + + PhoneContactOption.TELEGRAM -> { + { context, phone -> + ActivityUtils.openTelegram(context, phone) + } } } -} From ee32e2ee2161ea95ca1c0a22f23db38c16614ca3 Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Fri, 3 Oct 2025 14:46:47 +0200 Subject: [PATCH 7/8] Invoke sendEmail action on contact email tap --- .../ui/bookings/compose/BookingCustomerDetails.kt | 9 ++++++--- .../android/ui/bookings/details/BookingDetailsScreen.kt | 1 - 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt index 685e3635772..89c0e2c675f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt @@ -19,6 +19,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -27,14 +28,15 @@ import androidx.compose.ui.unit.dp import com.woocommerce.android.R import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground +import com.woocommerce.android.util.ActivityUtils @Composable fun BookingCustomerDetails( model: BookingCustomerDetailsModel, - onEmailClick: () -> Unit, modifier: Modifier = Modifier, ) { var phoneMenuExpanded by remember { mutableStateOf(false) } + val context = LocalContext.current Column(modifier = modifier) { BookingSectionHeader(R.string.booking_customer_details_header) @@ -53,7 +55,9 @@ fun BookingCustomerDetails( tint = MaterialTheme.colorScheme.primary ) }, - modifier = Modifier.clickable { onEmailClick() } + modifier = Modifier.clickable { + ActivityUtils.sendEmail(context, model.email) + } ) CustomerDetailsRow( value = model.phone, @@ -156,7 +160,6 @@ private fun BookingCustomerDetailsPreview() { "AL 36109" ) ), - onEmailClick = {}, modifier = Modifier.fillMaxWidth() ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt index 76188e9960e..5afb805d8ba 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt @@ -87,7 +87,6 @@ fun BookingDetailsScreen( ) BookingCustomerDetails( model = viewState.bookingCustomerDetails, - onEmailClick = {}, modifier = Modifier.fillMaxWidth() ) BookingAttendanceSection( From 5b0008bb8b1e3e101a55dbb9da52aa2308909b2e Mon Sep 17 00:00:00 2001 From: AdamGrzybkowski Date: Mon, 6 Oct 2025 10:59:06 +0200 Subject: [PATCH 8/8] Recaulculate contact options on each resume When an app like Telegram is installed/unistalled with Woo in the background, the list will be rechecked after entering foreground and thus preventing a crash. --- .../ui/bookings/compose/ContactDropdownMenu.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt index 43a58dd12ea..b6eaef2e232 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/ContactDropdownMenu.kt @@ -5,9 +5,14 @@ import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect import com.woocommerce.android.R import com.woocommerce.android.util.ActivityUtils import com.woocommerce.android.util.PhoneContactOption @@ -22,7 +27,12 @@ fun ContactDropdownMenu( onDismissRequest: () -> Unit, ) { val context = LocalContext.current - val contactOptions = remember { context.getAvailablePhoneContactOptions() } + var contactOptions by remember { mutableStateOf(emptyList()) } + + // Update the available contact options when the composable enters the RESUMED state + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { + contactOptions = context.getAvailablePhoneContactOptions() + } DropdownMenu( expanded = expanded,