Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Woo POS] Add setting option to enable/disable Cha-Ching sound in POS #13809

Draft
wants to merge 9 commits into
base: issue/13636-play-cha-ching-sound-on-successfull-payment-pos
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ object AppPrefs {
CUSTOM_FIELDS_TOP_BANNER_DISMISSED,
BLAZE_CAMPAIGN_SELECTED_OBJECTIVE,
BLAZE_CAMPAIGN_OBJECTIVE_SWITCH_CHECKED,
IS_SITE_WPCOM_SUSPENDED
IS_SITE_WPCOM_SUSPENDED,
WOO_POS_PAYMENT_SOUND_ENABLED,
}

/**
Expand Down Expand Up @@ -287,6 +288,10 @@ object AppPrefs {
get() = getBoolean(DeletablePrefKey.IS_SITE_WPCOM_SUSPENDED, false)
set(value) = setBoolean(DeletablePrefKey.IS_SITE_WPCOM_SUSPENDED, value)

var isWooPosPaymentSoundEnabled: Boolean
get() = getBoolean(DeletablePrefKey.WOO_POS_PAYMENT_SOUND_ENABLED, true)
set(value) = setBoolean(DeletablePrefKey.WOO_POS_PAYMENT_SOUND_ENABLED, value)

fun getProductSortingChoice(currentSiteId: Int) = getString(getProductSortingKey(currentSiteId)).orNullIfEmpty()

fun setProductSortingChoice(currentSiteId: Int, value: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class AppPrefsWrapper @Inject constructor() {

var isSiteWPComSuspended by AppPrefs::isSiteWPComSuspended

var isWooPosPaymentSoundEnabled by AppPrefs::isWooPosPaymentSoundEnabled

fun getAppInstallationDate() = AppPrefs.installationDate

fun getReceiptUrl(localSiteId: Int, remoteSiteId: Long, selfHostedSiteId: Long, orderId: Long) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class WooPosHomeViewModel @Inject constructor(
private val parentToChildrenEventSender: WooPosParentToChildrenEventSender,
private val wooPosItemsNavigator: WooPosItemsNavigator,
private val analyticsTracker: WooPosAnalyticsTracker,
private val appPrefsWrapper: AppPrefsWrapper,
savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val _state = savedStateHandle.getStateFlow(
Expand Down Expand Up @@ -219,7 +220,9 @@ class WooPosHomeViewModel @Inject constructor(
wooPosItemsNavigator.sendNavigationEvent(
WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateBackToItemListScreen
)
_playChaChingEvent.emit("Cha-Ching")
if (appPrefsWrapper.isWooPosPaymentSoundEnabled) {
_playChaChingEvent.emit("Cha-Ching")
}
}
_state.value = _state.value.copy(
screenPositionState = ScreenPositionState.Checkout.FullScreenTotals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand All @@ -23,6 +25,7 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
Expand All @@ -32,6 +35,7 @@ import androidx.compose.runtime.collectAsState
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.graphics.Color
Expand Down Expand Up @@ -274,6 +278,9 @@ private fun PopUpMenuItem(
menuItem: Menu.MenuItem,
onClick: (Menu.MenuItem) -> Unit
) {
var isChaChingEnabled by remember {
mutableStateOf(menuItem is Menu.MenuItem.Toggleable && menuItem.isToggled)
}
TextButton(onClick = { onClick(menuItem) }) {
Spacer(modifier = Modifier.width(WooPosSpacing.Medium.value.toAdaptivePadding()))
Icon(
Expand All @@ -293,10 +300,46 @@ private fun PopUpMenuItem(
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
if (menuItem is Menu.MenuItem.Toggleable) {
ToggleSwitch(
isChecked = isChaChingEnabled,
onToggleChange = {
isChaChingEnabled = it
onClick(menuItem.copy(isToggled = !menuItem.isToggled))
}
)
}
Spacer(modifier = Modifier.width(WooPosSpacing.Medium.value.toAdaptivePadding()))
}
}

@Composable
fun ToggleSwitch(
isChecked: Boolean,
onToggleChange: (Boolean) -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
WooPosText(
modifier = Modifier
.padding(vertical = WooPosSpacing.Small.value.toAdaptivePadding())
.weight(1f),
text = stringResource(id = R.string.woopos_payment_success_sound_setting_title),
style = WooPosTypography.BodyMedium,
color = MaterialTheme.colorScheme.onSurface,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Switch(
checked = isChecked,
onCheckedChange = onToggleChange
)
}
}

@Composable
private fun CardReaderStatusButton(
modifier: Modifier,
Expand Down Expand Up @@ -484,15 +527,20 @@ fun PreviewWooPosFloatingToolbarStatusConnectedWithMenu() {
cardReaderStatus = WooPosCardReaderStatus.Connected,
menu = Menu.Visible(
listOf(
Menu.MenuItem(
Menu.MenuItem.Toggleable(
title = R.string.woopos_cart_title,
icon = R.drawable.woo_pos_info_ic,
isToggled = true
),
Menu.MenuItem.Standard(
title = R.string.woopos_documentation_title,
icon = R.drawable.woo_pos_info_ic
),
Menu.MenuItem(
Menu.MenuItem.Standard(
title = R.string.woopos_exit_confirmation_title,
icon = R.drawable.ic_woo_pos_exit,
),
Menu.MenuItem(
Menu.MenuItem.Standard(
title = R.string.woopos_get_support_title,
icon = R.drawable.woopos_ic_get_support,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ data class WooPosToolbarState(
data object Hidden : Menu()
data class Visible(val items: List<MenuItem>) : Menu()

data class MenuItem(
@StringRes val title: Int,
@DrawableRes val icon: Int,
)
sealed class MenuItem(
@StringRes open val title: Int,
@DrawableRes open val icon: Int
) {
data class Standard(
@StringRes override val title: Int,
@DrawableRes override val icon: Int
) : MenuItem(title, icon)

data class Toggleable(
@StringRes override val title: Int,
@DrawableRes override val icon: Int,
val isToggled: Boolean
) : MenuItem(title, icon)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.woocommerce.android.ui.woopos.home.toolbar

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.woocommerce.android.AppPrefsWrapper
import com.woocommerce.android.AppUrls.WOO_POS_DOCUMENTATION_URL
import com.woocommerce.android.R
import com.woocommerce.android.cardreader.connection.CardReaderStatus
Expand Down Expand Up @@ -39,6 +40,7 @@ class WooPosToolbarViewModel @Inject constructor(
private val networkStatus: WooPosNetworkStatus,
private val resourceProvider: ResourceProvider,
private val analyticsTracker: WooPosAnalyticsTracker,
private val appPrefsWrapper: AppPrefsWrapper,
) : ViewModel() {
private val _state = MutableStateFlow(
WooPosToolbarState(
Expand Down Expand Up @@ -70,8 +72,15 @@ class WooPosToolbarViewModel @Inject constructor(

when (event) {
is OnToolbarMenuClicked -> {
val updatedToolBarMenuItems = toolbarMenuItems.map {
if (it is WooPosToolbarState.Menu.MenuItem.Toggleable) {
it.copy(isToggled = appPrefsWrapper.isWooPosPaymentSoundEnabled)
} else {
it
}
}
_state.value = currentState.copy(
menu = WooPosToolbarState.Menu.Visible(toolbarMenuItems)
menu = WooPosToolbarState.Menu.Visible(updatedToolBarMenuItems)
)
}

Expand All @@ -86,7 +95,9 @@ class WooPosToolbarViewModel @Inject constructor(
}

private fun handleMenuItemClicked(event: MenuItemClicked) {
hideMenu()
if (event.menuItem !is WooPosToolbarState.Menu.MenuItem.Toggleable) {
hideMenu()
}

when (event.menuItem.title) {
R.string.woopos_get_support_title -> {
Expand All @@ -95,17 +106,25 @@ class WooPosToolbarViewModel @Inject constructor(
analyticsTracker.track(GetSupportTapped)
}
}

R.string.woopos_exit_confirmation_title ->
viewModelScope.launch {
childrenToParentEventSender.sendToParent(ChildToParentEvent.ExitPosClicked)
analyticsTracker.track(ExitTapped)
}

R.string.woopos_documentation_title -> {
viewModelScope.launch {
_openUrlEvent.emit(WOO_POS_DOCUMENTATION_URL)
analyticsTracker.track(ViewDocsTapped)
}
}

R.string.woopos_payment_success_sound_setting_title -> {
viewModelScope.launch {
appPrefsWrapper.isWooPosPaymentSoundEnabled = !appPrefsWrapper.isWooPosPaymentSoundEnabled
}
}
}
}

Expand All @@ -120,6 +139,7 @@ class WooPosToolbarViewModel @Inject constructor(
cardReaderFacade.disconnectFromReader()
}
}

WooPosToolbarState.WooPosCardReaderStatus.NotConnected -> {
if (!networkStatus.isConnected()) {
viewModelScope.launch {
Expand All @@ -143,20 +163,23 @@ class WooPosToolbarViewModel @Inject constructor(
}
}

private companion object {
val toolbarMenuItems = listOf(
WooPosToolbarState.Menu.MenuItem(
title = R.string.woopos_documentation_title,
icon = R.drawable.woo_pos_info_ic,
),
WooPosToolbarState.Menu.MenuItem(
title = R.string.woopos_get_support_title,
icon = R.drawable.woopos_ic_get_support,
),
WooPosToolbarState.Menu.MenuItem(
title = R.string.woopos_exit_confirmation_title,
icon = R.drawable.ic_woo_pos_exit,
),
)
}
private val toolbarMenuItems = listOf(
WooPosToolbarState.Menu.MenuItem.Toggleable(
title = R.string.woopos_payment_success_sound_setting_title,
icon = R.drawable.woo_pos_info_ic,
isToggled = appPrefsWrapper.isWooPosPaymentSoundEnabled
),
WooPosToolbarState.Menu.MenuItem.Standard(
title = R.string.woopos_documentation_title,
icon = R.drawable.woo_pos_info_ic,
),
WooPosToolbarState.Menu.MenuItem.Standard(
title = R.string.woopos_get_support_title,
icon = R.drawable.woopos_ic_get_support,
),
WooPosToolbarState.Menu.MenuItem.Standard(
title = R.string.woopos_exit_confirmation_title,
icon = R.drawable.ic_woo_pos_exit,
),
)
}
1 change: 1 addition & 0 deletions WooCommerce/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4279,6 +4279,7 @@
<string name="woopos_cart_item_content_description">Product in cart %s, Price %s</string>
<string name="woopos_cart_title">Cart</string>
<string name="woopos_clear_cart_button">Clear</string>
<string name="woopos_payment_success_sound_setting_title">Cha-Ching Sound</string>

<string name="woopos_banner_simple_products_only_title">Showing simple, variable and virtual products only</string>
<string name="woopos_banner_simple_products_only_message">Only simple physical, variable and virtual products are compatible with POS right now. Other product types will become available in future updates. </string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.woocommerce.android.ui.woopos.home

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.SavedStateHandle
import com.woocommerce.android.AppPrefsWrapper
import com.woocommerce.android.R
import com.woocommerce.android.ui.woopos.home.ParentToChildrenEvent.OrderSuccessfullyPaid.PaymentMethod
import com.woocommerce.android.ui.woopos.home.WooPosHomeUIEvent.ExitPosClicked
Expand Down Expand Up @@ -38,6 +39,7 @@ class WooPosHomeViewModelTest {
private val parentToChildrenEventSender: WooPosParentToChildrenEventSender = mock()
private val wooPosItemsNavigator: WooPosItemsNavigator = mock()
private val analyticsTracker: WooPosAnalyticsTracker = mock()
private val appPrefsWrapper: AppPrefsWrapper = mock()

@Test
fun `given state checkout, when SystemBackClicked passed, then BackFromCheckoutToCartClicked event should be sent`() =
Expand Down Expand Up @@ -459,6 +461,7 @@ class WooPosHomeViewModelTest {
parentToChildrenEventSender,
wooPosItemsNavigator,
analyticsTracker,
appPrefsWrapper = appPrefsWrapper,
SavedStateHandle()
)
}
Loading