Skip to content

Commit 55f8621

Browse files
Merge pull request #14692 from woocommerce/issue/WOOMOB-1396_custom_section_actions
[WOOMOB-1396] - Booking's customer section actions
2 parents c513ed0 + 5b0008b commit 55f8621

File tree

7 files changed

+164
-30
lines changed

7 files changed

+164
-30
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingCustomerDetails.kt

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,42 @@ package com.woocommerce.android.ui.bookings.compose
22

33
import androidx.compose.foundation.background
44
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.layout.Box
56
import androidx.compose.foundation.layout.Column
67
import androidx.compose.foundation.layout.Row
78
import androidx.compose.foundation.layout.fillMaxWidth
89
import androidx.compose.foundation.layout.height
910
import androidx.compose.foundation.layout.padding
10-
import androidx.compose.material.icons.Icons
11-
import androidx.compose.material.icons.outlined.FileCopy
12-
import androidx.compose.material.icons.outlined.MoreHoriz
1311
import androidx.compose.material3.HorizontalDivider
1412
import androidx.compose.material3.Icon
1513
import androidx.compose.material3.MaterialTheme
1614
import androidx.compose.material3.Text
1715
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.getValue
17+
import androidx.compose.runtime.mutableStateOf
18+
import androidx.compose.runtime.remember
19+
import androidx.compose.runtime.setValue
1820
import androidx.compose.ui.Alignment
1921
import androidx.compose.ui.Modifier
22+
import androidx.compose.ui.platform.LocalContext
2023
import androidx.compose.ui.platform.LocalDensity
24+
import androidx.compose.ui.res.painterResource
2125
import androidx.compose.ui.res.stringResource
2226
import androidx.compose.ui.text.style.TextOverflow
2327
import androidx.compose.ui.unit.dp
2428
import com.woocommerce.android.R
2529
import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews
2630
import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground
31+
import com.woocommerce.android.util.ActivityUtils
2732

2833
@Composable
2934
fun BookingCustomerDetails(
3035
model: BookingCustomerDetailsModel,
31-
onEmailClick: () -> Unit,
32-
onPhoneClick: () -> Unit,
3336
modifier: Modifier = Modifier,
3437
) {
38+
var phoneMenuExpanded by remember { mutableStateOf(false) }
39+
val context = LocalContext.current
40+
3541
Column(modifier = modifier) {
3642
BookingSectionHeader(R.string.booking_customer_details_header)
3743
Column(
@@ -44,23 +50,32 @@ fun BookingCustomerDetails(
4450
value = model.email,
4551
trailingIcon = {
4652
Icon(
47-
imageVector = Icons.Outlined.FileCopy,
53+
painter = painterResource(R.drawable.ic_email),
4854
contentDescription = stringResource(id = R.string.booking_customer_label_email),
4955
tint = MaterialTheme.colorScheme.primary
5056
)
5157
},
52-
modifier = Modifier.clickable { onEmailClick() }
58+
modifier = Modifier.clickable {
59+
ActivityUtils.sendEmail(context, model.email)
60+
}
5361
)
5462
CustomerDetailsRow(
5563
value = model.phone,
5664
trailingIcon = {
57-
Icon(
58-
imageVector = Icons.Outlined.MoreHoriz,
59-
contentDescription = stringResource(id = R.string.booking_customer_label_phone),
60-
tint = MaterialTheme.colorScheme.primary
61-
)
65+
Box {
66+
Icon(
67+
painter = painterResource(R.drawable.ic_menu_more_vert),
68+
contentDescription = stringResource(id = R.string.booking_customer_label_phone),
69+
tint = MaterialTheme.colorScheme.primary
70+
)
71+
ContactDropdownMenu(
72+
expanded = phoneMenuExpanded,
73+
phone = model.phone,
74+
onDismissRequest = { phoneMenuExpanded = false }
75+
)
76+
}
6277
},
63-
modifier = Modifier.clickable { onPhoneClick() }
78+
modifier = Modifier.clickable { phoneMenuExpanded = true }
6479
)
6580
Column(
6681
modifier = Modifier
@@ -145,8 +160,6 @@ private fun BookingCustomerDetailsPreview() {
145160
"AL 36109"
146161
)
147162
),
148-
onEmailClick = {},
149-
onPhoneClick = {},
150163
modifier = Modifier.fillMaxWidth()
151164
)
152165
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.woocommerce.android.ui.bookings.compose
2+
3+
import android.content.Context
4+
import androidx.compose.material3.DropdownMenu
5+
import androidx.compose.material3.DropdownMenuItem
6+
import androidx.compose.material3.Text
7+
import androidx.compose.runtime.Composable
8+
import androidx.compose.runtime.getValue
9+
import androidx.compose.runtime.mutableStateOf
10+
import androidx.compose.runtime.remember
11+
import androidx.compose.runtime.setValue
12+
import androidx.compose.ui.platform.LocalContext
13+
import androidx.compose.ui.res.stringResource
14+
import androidx.lifecycle.Lifecycle
15+
import androidx.lifecycle.compose.LifecycleEventEffect
16+
import com.woocommerce.android.R
17+
import com.woocommerce.android.util.ActivityUtils
18+
import com.woocommerce.android.util.PhoneContactOption
19+
import com.woocommerce.android.util.getAvailablePhoneContactOptions
20+
import com.woocommerce.android.util.stringRes
21+
import org.wordpress.android.util.ToastUtils
22+
23+
@Composable
24+
fun ContactDropdownMenu(
25+
expanded: Boolean,
26+
phone: String,
27+
onDismissRequest: () -> Unit,
28+
) {
29+
val context = LocalContext.current
30+
var contactOptions by remember { mutableStateOf(emptyList<PhoneContactOption>()) }
31+
32+
// Update the available contact options when the composable enters the RESUMED state
33+
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
34+
contactOptions = context.getAvailablePhoneContactOptions()
35+
}
36+
37+
DropdownMenu(
38+
expanded = expanded,
39+
onDismissRequest = onDismissRequest
40+
) {
41+
contactOptions.forEach { contactOption ->
42+
DropdownMenuItem(
43+
text = { Text(stringResource(contactOption.stringRes)) },
44+
onClick = {
45+
contactOption.action(context, phone)
46+
onDismissRequest()
47+
}
48+
)
49+
}
50+
}
51+
}
52+
53+
private val PhoneContactOption.action: (Context, String) -> Unit
54+
get() = when (this) {
55+
PhoneContactOption.CALL -> {
56+
// This is the lambda being returned. It must define its parameters.
57+
{ context, phone ->
58+
ActivityUtils.dialPhoneNumber(context, phone) {
59+
ToastUtils.showToast(context, R.string.error_no_phone_app)
60+
}
61+
}
62+
}
63+
64+
PhoneContactOption.SMS -> {
65+
{ context, phone ->
66+
ActivityUtils.sendSms(context, phone) {
67+
ToastUtils.showToast(context, R.string.error_no_sms_app)
68+
}
69+
}
70+
}
71+
72+
PhoneContactOption.WHATSAPP -> {
73+
{ context, phone ->
74+
ActivityUtils.openWhatsApp(context, phone)
75+
}
76+
}
77+
78+
PhoneContactOption.TELEGRAM -> {
79+
{ context, phone ->
80+
ActivityUtils.openTelegram(context, phone)
81+
}
82+
}
83+
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ fun BookingDetailsScreen(
8787
)
8888
BookingCustomerDetails(
8989
model = viewState.bookingCustomerDetails,
90-
onEmailClick = {},
91-
onPhoneClick = {},
9290
modifier = Modifier.fillMaxWidth()
9391
)
9492
BookingAttendanceSection(

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/OrderCustomerHelper.kt

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com.woocommerce.android.ui.orders
22

3-
import android.content.ActivityNotFoundException
43
import android.content.Context
5-
import android.content.Intent
6-
import android.net.Uri
74
import com.woocommerce.android.R
85
import com.woocommerce.android.analytics.AnalyticsEvent
96
import com.woocommerce.android.analytics.AnalyticsTracker
@@ -83,15 +80,11 @@ object OrderCustomerHelper {
8380
)
8481
)
8582

86-
val intent = Intent(Intent.ACTION_SENDTO)
87-
intent.data = Uri.parse("smsto:$phone")
88-
try {
89-
context.startActivity(intent)
90-
} catch (e: ActivityNotFoundException) {
83+
ActivityUtils.sendSms(context, phone) { error ->
9184
AnalyticsTracker.track(
9285
AnalyticsEvent.ORDER_CONTACT_ACTION_FAILED,
9386
this.javaClass.simpleName,
94-
e.javaClass.simpleName,
87+
error.javaClass.simpleName,
9588
"No SMS app was found"
9689
)
9790

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/views/OrderDetailCustomerInfoView.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ import com.woocommerce.android.model.Order
2525
import com.woocommerce.android.ui.orders.OrderCustomerHelper
2626
import com.woocommerce.android.ui.orders.details.OrderDetailFragmentDirections
2727
import com.woocommerce.android.util.ActivityUtils
28+
import com.woocommerce.android.util.PhoneContactOption
2829
import com.woocommerce.android.util.PhoneUtils
30+
import com.woocommerce.android.util.getAvailablePhoneContactOptions
2931
import com.woocommerce.android.widgets.AppRatingDialog
3032

3133
class OrderDetailCustomerInfoView @JvmOverloads constructor(
@@ -36,8 +38,6 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor(
3638
private companion object {
3739
const val KEY_SUPER_STATE = "ORDER-DETAIL-CUSTOMER-INFO-VIEW-SUPER-STATE"
3840
const val KEY_IS_CUSTOMER_INFO_VIEW_EXPANDED = "ORDER-DETAIL-CUSTOMER-INFO-VIEW-IS_CUSTOMER_INFO_VIEW_EXPANDED"
39-
private const val WHATSAPP_PACKAGE_NAME = "com.whatsapp"
40-
private const val TELEGRAM_PACKAGE_NAME = "org.telegram.messenger"
4141
}
4242

4343
private val binding = OrderDetailCustomerInfoBinding.inflate(LayoutInflater.from(ctx), this)
@@ -281,6 +281,7 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor(
281281
binding.customerInfoMorePanel.expand()
282282
binding.customerInfoViewMore.setOnClickListener(null)
283283
}
284+
284285
else -> {
285286
binding.customerInfoShippingAddr.setText(shippingAddress, R.string.order_detail_add_shipping_address)
286287
binding.customerInfoShippingMethodSection.isVisible = order.shippingMethods.firstOrNull()?.let {
@@ -331,6 +332,8 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor(
331332
val popup = PopupMenu(context, binding.customerInfoCallOrMessageBtn)
332333
popup.menuInflater.inflate(R.menu.menu_order_detail_phone_actions, popup.menu)
333334

335+
val contactOptions = context.getAvailablePhoneContactOptions()
336+
334337
popup.menu.findItem(R.id.menu_call)?.setOnMenuItemClickListener {
335338
AnalyticsTracker.track(AnalyticsEvent.ORDER_DETAIL_CUSTOMER_INFO_PHONE_MENU_PHONE_TAPPED)
336339
OrderCustomerHelper.dialPhone(context, order, order.billingAddress.phone)
@@ -345,7 +348,7 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor(
345348
true
346349
}
347350

348-
if (ActivityUtils.isAppInstalled(context, WHATSAPP_PACKAGE_NAME)) {
351+
if (contactOptions.contains(PhoneContactOption.WHATSAPP)) {
349352
popup.menu.add(
350353
0,
351354
View.generateViewId(),
@@ -359,7 +362,7 @@ class OrderDetailCustomerInfoView @JvmOverloads constructor(
359362
}
360363
}
361364

362-
if (ActivityUtils.isAppInstalled(context, TELEGRAM_PACKAGE_NAME)) {
365+
if (contactOptions.contains(PhoneContactOption.TELEGRAM)) {
363366
popup.menu.add(
364367
0,
365368
View.generateViewId(),

WooCommerce/src/main/kotlin/com/woocommerce/android/util/ActivityUtils.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import android.net.Uri
99
import android.os.Build.VERSION.SDK_INT
1010
import android.os.Parcelable
1111
import androidx.core.content.FileProvider
12+
import androidx.core.net.toUri
1213
import com.woocommerce.android.R
1314
import com.woocommerce.android.extensions.intentActivities
1415
import com.woocommerce.android.model.UiString
@@ -53,6 +54,16 @@ object ActivityUtils {
5354
}
5455
}
5556

57+
fun sendSms(context: Context, phoneNumber: String, onError: (e: ActivityNotFoundException) -> Unit) {
58+
val intent = Intent(Intent.ACTION_SENDTO)
59+
intent.data = "smsto:$phoneNumber".toUri()
60+
try {
61+
context.startActivity(intent)
62+
} catch (e: ActivityNotFoundException) {
63+
onError(e)
64+
}
65+
}
66+
5667
/**
5768
* Use this only when you want to open the external browser - otherwise use
5869
* [ChromeCustomTabUtils.launchUrl] to provide a better in-app experience
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.woocommerce.android.util
2+
3+
import android.content.Context
4+
import androidx.annotation.StringRes
5+
import com.woocommerce.android.R
6+
7+
private const val WHATSAPP_PACKAGE_NAME = "com.whatsapp"
8+
private const val TELEGRAM_PACKAGE_NAME = "org.telegram.messenger"
9+
10+
fun Context.getAvailablePhoneContactOptions(): List<PhoneContactOption> {
11+
return buildList {
12+
add(PhoneContactOption.CALL)
13+
add(PhoneContactOption.SMS)
14+
if (ActivityUtils.isAppInstalled(this@getAvailablePhoneContactOptions, WHATSAPP_PACKAGE_NAME)) {
15+
add(PhoneContactOption.WHATSAPP)
16+
}
17+
if (ActivityUtils.isAppInstalled(this@getAvailablePhoneContactOptions, TELEGRAM_PACKAGE_NAME)) {
18+
add(PhoneContactOption.TELEGRAM)
19+
}
20+
}
21+
}
22+
23+
enum class PhoneContactOption {
24+
CALL, SMS, WHATSAPP, TELEGRAM
25+
}
26+
27+
val PhoneContactOption.stringRes: Int
28+
@StringRes get() = when (this) {
29+
PhoneContactOption.CALL -> R.string.orderdetail_call_customer
30+
PhoneContactOption.SMS -> R.string.orderdetail_message_customer
31+
PhoneContactOption.WHATSAPP -> R.string.orderdetail_message_customer_using_whatsapp
32+
PhoneContactOption.TELEGRAM -> R.string.orderdetail_message_customer_using_telegram
33+
}

0 commit comments

Comments
 (0)