diff --git a/WooCommerce/src/androidTest/kotlin/com/woocommerce/android/di/MockCardReaderManagerModule.kt b/WooCommerce/src/androidTest/kotlin/com/woocommerce/android/di/MockCardReaderManagerModule.kt
index 388bb9eabea2..a00470a8384c 100644
--- a/WooCommerce/src/androidTest/kotlin/com/woocommerce/android/di/MockCardReaderManagerModule.kt
+++ b/WooCommerce/src/androidTest/kotlin/com/woocommerce/android/di/MockCardReaderManagerModule.kt
@@ -100,6 +100,8 @@ class MockCardReaderManagerModule {
override fun cancelPayment(paymentData: PaymentData) {}
+ override fun cancelReconnection() {}
+
override suspend fun startAsyncSoftwareUpdate() {}
override suspend fun clearCachedCredentials() {}
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/connect/CardReaderConnectViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/connect/CardReaderConnectViewModel.kt
index 181ec8e92119..87f2d92a967c 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/connect/CardReaderConnectViewModel.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/connect/CardReaderConnectViewModel.kt
@@ -303,6 +303,10 @@ class CardReaderConnectViewModel @Inject constructor(
connectionStarted = true
viewState.value = provideConnectingState()
}
+
+ CardReaderStatus.Reconnecting -> {
+ // Reconnecting is handled by the SDK, no action needed during connection flow
+ }
}
}
}
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailFragment.kt
index 11eb5ac98526..1420cd5f26d8 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailFragment.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailFragment.kt
@@ -27,6 +27,7 @@ import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailVie
import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.ConnectedState
import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.Loading
import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.NotConnectedState
+import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.ReconnectingState
import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderType.EXTERNAL
import com.woocommerce.android.ui.payments.cardreader.update.CardReaderUpdateDialogFragment
import com.woocommerce.android.ui.payments.cardreader.update.CardReaderUpdateViewModel.UpdateResult
@@ -180,6 +181,25 @@ class CardReaderDetailFragment : BaseFragment(R.layout.fragment_card_reader_deta
Loading -> {
}
+
+ is ReconnectingState -> {
+ with(binding.readerDisconnectedState) {
+ UiHelpers.setTextOrHide(cardReaderDetailConnectHeaderLabel, state.headerLabel)
+ UiHelpers.setImageOrHideInLandscapeOnCompactScreenHeightSizeClass(
+ cardReaderDetailIllustration,
+ state.illustration
+ )
+ cardReaderDetailFirstHintLabel.visibility = View.GONE
+ cardReaderDetailFirstHintNumberLabel.visibility = View.GONE
+ cardReaderDetailSecondHintLabel.visibility = View.GONE
+ cardReaderDetailSecondHintNumberLabel.visibility = View.GONE
+ cardReaderDetailThirdHintLabel.visibility = View.GONE
+ cardReaderDetailThirdHintNumberLabel.visibility = View.GONE
+ UiHelpers.setTextOrHide(cardReaderDetailConnectBtn, state.cancelBtnLabel)
+ cardReaderDetailConnectBtn.setOnClickListener { state.onCancelClicked.invoke() }
+ cardReaderDetailLearnMoreTv.root.visibility = View.GONE
+ }
+ }
}
}
}
@@ -192,7 +212,10 @@ class CardReaderDetailFragment : BaseFragment(R.layout.fragment_card_reader_deta
private fun makeStateVisible(binding: FragmentCardReaderDetailBinding, state: ViewState) {
UiHelpers.updateVisibility(binding.readerConnectedState.root, state is ConnectedState)
- UiHelpers.updateVisibility(binding.readerDisconnectedState.root, state is NotConnectedState)
+ UiHelpers.updateVisibility(
+ binding.readerDisconnectedState.root,
+ state is NotConnectedState || state is ReconnectingState
+ )
UiHelpers.updateVisibility(binding.readerConnectedLoading, state is Loading)
}
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModel.kt
index a77fa5141254..7aa961de8320 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModel.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModel.kt
@@ -13,6 +13,7 @@ import com.woocommerce.android.cardreader.connection.CardReader
import com.woocommerce.android.cardreader.connection.CardReaderStatus.Connected
import com.woocommerce.android.cardreader.connection.CardReaderStatus.Connecting
import com.woocommerce.android.cardreader.connection.CardReaderStatus.NotConnected
+import com.woocommerce.android.cardreader.connection.CardReaderStatus.Reconnecting
import com.woocommerce.android.cardreader.connection.ReaderType
import com.woocommerce.android.cardreader.connection.event.CardReaderBatteryStatus
import com.woocommerce.android.cardreader.connection.event.CardReaderBatteryStatus.StatusChanged
@@ -86,6 +87,9 @@ class CardReaderDetailViewModel @Inject constructor(
)
handleNotConnectedState()
}
+ Reconnecting -> {
+ handleReconnectingState()
+ }
}
}
}
@@ -134,6 +138,16 @@ class CardReaderDetailViewModel @Inject constructor(
NotConnectedState(onPrimaryActionClicked = ::onConnectBtnClicked, onLearnMoreClicked = ::onLearnMoreClicked)
}
+ private fun handleReconnectingState() {
+ viewState.value = ViewState.ReconnectingState(
+ onCancelClicked = ::onCancelReconnectionClicked
+ )
+ }
+
+ private fun onCancelReconnectionClicked() {
+ cardReaderManager.cancelReconnection()
+ }
+
private fun cancelConnectedScopeJobs() {
if (::softwareUpdateAvailabilityJob.isInitialized) softwareUpdateAvailabilityJob.cancel()
if (::batteryStatusUpdateJob.isInitialized) batteryStatusUpdateJob.cancel()
@@ -307,6 +321,16 @@ class CardReaderDetailViewModel @Inject constructor(
}
object Loading : ViewState()
+
+ data class ReconnectingState(
+ val onCancelClicked: (() -> Unit),
+ ) : ViewState() {
+ val headerLabel = UiStringRes(R.string.card_reader_detail_reconnecting_header)
+
+ @DrawableRes
+ val illustration = R.drawable.img_card_reader_not_connected
+ val cancelBtnLabel = UiStringRes(R.string.card_reader_detail_reconnecting_cancel)
+ }
}
}
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderFacade.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderFacade.kt
index 6e0f1dfaa94e..4860757cda97 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderFacade.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cardreader/WooPosCardReaderFacade.kt
@@ -49,6 +49,10 @@ class WooPosCardReaderFacade @Inject constructor(
cardReaderManager.disconnectReader()
}
+ fun cancelReconnection() {
+ cardReaderManager.cancelReconnection()
+ }
+
@Suppress("DEPRECATION")
private fun startActivity(intent: Intent) {
val options = ActivityOptionsCompat.makeCustomAnimation(
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbar.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbar.kt
index 8317d2da3e2a..57d7532baa9a 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbar.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbar.kt
@@ -309,15 +309,11 @@ private fun CardReaderStatusButton(
when (status) {
WooPosCardReaderStatus.Connected -> WooPosTheme.colors.success
WooPosCardReaderStatus.NotConnected -> WooPosTheme.colors.alert
+ WooPosCardReaderStatus.Reconnecting -> WooPosTheme.colors.alert
}
}
- val title = stringResource(
- id = when (state) {
- WooPosCardReaderStatus.Connected -> WooPosCardReaderStatus.Connected.title
- WooPosCardReaderStatus.NotConnected -> WooPosCardReaderStatus.NotConnected.title
- }
- )
+ val title = stringResource(id = state.title)
val borderColor by transition.animateColor(
transitionSpec = { tween(durationMillis = animationDuration) },
@@ -326,6 +322,7 @@ private fun CardReaderStatusButton(
when (status) {
WooPosCardReaderStatus.Connected -> Color.Transparent
WooPosCardReaderStatus.NotConnected -> MaterialTheme.colorScheme.primary
+ WooPosCardReaderStatus.Reconnecting -> WooPosTheme.colors.alert
}
}
@@ -408,6 +405,9 @@ private fun getToolbarAccessibilityLabels(
WooPosCardReaderStatus.NotConnected -> stringResource(
id = R.string.woopos_floating_toolbar_card_reader_not_connected_status_content_description
)
+ WooPosCardReaderStatus.Reconnecting -> stringResource(
+ id = R.string.woopos_reader_reconnecting
+ )
}
val floatingToolbarMenuOverlayContentDescription = when (menuCardDisabled) {
true -> {
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarState.kt
index 87fe185b1fde..eddef459c231 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarState.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarState.kt
@@ -11,6 +11,7 @@ data class WooPosHomeFloatingToolbarState(
sealed class WooPosCardReaderStatus(@StringRes val title: Int) {
data object NotConnected : WooPosCardReaderStatus(title = R.string.woopos_reader_disconnected)
data object Connected : WooPosCardReaderStatus(title = R.string.woopos_reader_connected)
+ data object Reconnecting : WooPosCardReaderStatus(title = R.string.woopos_reader_reconnecting)
}
sealed class Menu {
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModel.kt
index a0ea933f711e..38a51be68a0d 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModel.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModel.kt
@@ -11,6 +11,7 @@ import com.woocommerce.android.cardreader.connection.CardReaderStatus
import com.woocommerce.android.cardreader.connection.CardReaderStatus.Connected
import com.woocommerce.android.cardreader.connection.CardReaderStatus.Connecting
import com.woocommerce.android.cardreader.connection.CardReaderStatus.NotConnected
+import com.woocommerce.android.cardreader.connection.CardReaderStatus.Reconnecting
import com.woocommerce.android.ui.woopos.cardreader.WooPosCardReaderFacade
import com.woocommerce.android.ui.woopos.home.ChildToParentEvent
import com.woocommerce.android.ui.woopos.home.WooPosChildrenToParentEventSender
@@ -128,12 +129,17 @@ class WooPosHomeFloatingToolbarViewModel @Inject constructor(
cardReaderFacade.connectToReader()
}
}
+
+ WooPosHomeFloatingToolbarState.WooPosCardReaderStatus.Reconnecting -> {
+ cardReaderFacade.cancelReconnection()
+ }
}
}
private fun mapCardReaderStatusToUiState(status: CardReaderStatus) = when (status) {
is Connected -> WooPosHomeFloatingToolbarState.WooPosCardReaderStatus.Connected
is NotConnected, Connecting -> WooPosHomeFloatingToolbarState.WooPosCardReaderStatus.NotConnected
+ Reconnecting -> WooPosHomeFloatingToolbarState.WooPosCardReaderStatus.Reconnecting
}
private val toolbarMenuItems by lazy {
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt
index 58ca9e213fe2..4c12d5d66cf2 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt
@@ -9,6 +9,7 @@ import com.woocommerce.android.WooException
import com.woocommerce.android.cardreader.connection.CardReaderStatus.Connected
import com.woocommerce.android.cardreader.connection.CardReaderStatus.Connecting
import com.woocommerce.android.cardreader.connection.CardReaderStatus.NotConnected
+import com.woocommerce.android.cardreader.connection.CardReaderStatus.Reconnecting
import com.woocommerce.android.model.Order
import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund
import com.woocommerce.android.ui.payments.cardreader.payment.controller.CardReaderPaymentController
@@ -122,6 +123,10 @@ class WooPosTotalsViewModel @Inject constructor(
cancelPaymentAction()
}
+ Reconnecting -> {
+ // We start payment right away so this state not worth handling
+ }
+
is Connected -> {
val state = uiState.value
if (state !is WooPosTotalsViewState.Checkout) return@collect
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/details/hardware/cardreader/WooPosSettingsHardwareCardReaderViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/details/hardware/cardreader/WooPosSettingsHardwareCardReaderViewModel.kt
index 014390df8ab7..b1c29fc71cdd 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/details/hardware/cardreader/WooPosSettingsHardwareCardReaderViewModel.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/details/hardware/cardreader/WooPosSettingsHardwareCardReaderViewModel.kt
@@ -115,6 +115,11 @@ class WooPosSettingsHardwareCardReaderViewModel @Inject constructor(
currentSoftwareUpdateAvailable = false
WooPosSettingsHardwareCardReaderUiState.Disconnected
}
+
+ CardReaderStatus.Reconnecting -> {
+ // Keep current state while SDK attempts to reconnect
+ _uiState.value
+ }
}
}
}
diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml
index ac0e6093b3d0..7df88370f621 100644
--- a/WooCommerce/src/main/res/values/strings.xml
+++ b/WooCommerce/src/main/res/values/strings.xml
@@ -1634,6 +1634,8 @@
Card Reader Detail
-->
Connect your card reader
+ Reconnecting to card reader…
+ Cancel reconnection
<a href=\'\'>Learn more</a> about accepting mobile payments and ordering card readers
Make sure card reader is charged
Turn card reader on and place it next to mobile device
@@ -3590,6 +3592,7 @@
Reader connected
Connect your reader
+ Reconnecting…
Check out
Remove %s from cart
Product %s, Price %s
diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModelTest.kt
index ae04d3e00d00..c8787d222305 100644
--- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModelTest.kt
+++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/detail/CardReaderDetailViewModelTest.kt
@@ -22,6 +22,7 @@ import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailVie
import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.ConnectedState
import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.Loading
import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.NotConnectedState
+import com.woocommerce.android.ui.payments.cardreader.detail.CardReaderDetailViewModel.ViewState.ReconnectingState
import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam
import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.STRIPE_EXTENSION_GATEWAY
import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.WOOCOMMERCE_PAYMENTS
@@ -620,6 +621,33 @@ class CardReaderDetailViewModelTest : BaseUnitTest() {
.isEqualTo(AppUrls.STRIPE_LEARN_MORE_ABOUT_PAYMENTS)
}
+ @Test
+ fun `given reconnecting state, when view model init, then should emit reconnecting view state`() {
+ // GIVEN
+ val status = MutableStateFlow(CardReaderStatus.Reconnecting)
+ whenever(cardReaderManager.readerStatus).thenReturn(status)
+
+ // WHEN
+ val viewModel = createViewModel()
+
+ // THEN
+ assertThat(viewModel.viewStateData.value).isInstanceOf(ReconnectingState::class.java)
+ }
+
+ @Test
+ fun `given reconnecting state, when cancel clicked, then should call cancelReconnection`() {
+ // GIVEN
+ val status = MutableStateFlow(CardReaderStatus.Reconnecting)
+ whenever(cardReaderManager.readerStatus).thenReturn(status)
+ val viewModel = createViewModel()
+
+ // WHEN
+ (viewModel.viewStateData.value as ReconnectingState).onCancelClicked.invoke()
+
+ // THEN
+ verify(cardReaderManager).cancelReconnection()
+ }
+
private fun verifyNotConnectedState(viewModel: CardReaderDetailViewModel) {
val state = viewModel.viewStateData.value as NotConnectedState
assertThat(state.headerLabel)
diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModelTest.kt
index 597b5bc47dae..2ddf5fdaf9fe 100644
--- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModelTest.kt
+++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/toolbar/WooPosHomeFloatingToolbarViewModelTest.kt
@@ -257,6 +257,31 @@ class WooPosHomeFloatingToolbarViewModelTest {
assertThat(viewModel.state.value.menu).isEqualTo(WooPosHomeFloatingToolbarState.Menu.Hidden)
}
+ @Test
+ fun `given card reader status is Reconnecting, when initialized, then state should be Reconnecting`() = runTest {
+ // GIVEN
+ whenever(cardReaderFacade.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.Reconnecting))
+ val viewModel = createViewModel()
+
+ // THEN
+ assertThat(viewModel.state.value.cardReaderStatus)
+ .isEqualTo(WooPosHomeFloatingToolbarState.WooPosCardReaderStatus.Reconnecting)
+ }
+
+ @Test
+ fun `given card reader status is Reconnecting, when OnCardReaderStatusClicked, then cancelReconnection should be called`() =
+ runTest {
+ // GIVEN
+ whenever(cardReaderFacade.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.Reconnecting))
+ val viewModel = createViewModel()
+
+ // WHEN
+ viewModel.onUiEvent(WooPosHomeFloatingToolbarUIEvent.OnCardReaderStatusClicked)
+
+ // THEN
+ verify(cardReaderFacade).cancelReconnection()
+ }
+
private fun createViewModel() = WooPosHomeFloatingToolbarViewModel(
cardReaderFacade,
childrenToParentEventSender,
diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManager.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManager.kt
index b78dac62d069..4f11159f8b89 100644
--- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManager.kt
+++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManager.kt
@@ -47,6 +47,7 @@ interface CardReaderManager {
fun startConnectionToReader(cardReader: CardReader, locationId: String)
suspend fun disconnectReader(): Boolean
+ fun cancelReconnection()
suspend fun collectPayment(paymentInfo: PaymentInfo): Flow
suspend fun refundInteracPayment(
diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManagerFactory.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManagerFactory.kt
index 3ebd9a418695..7be658f54a60 100644
--- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManagerFactory.kt
+++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/CardReaderManagerFactory.kt
@@ -42,7 +42,7 @@ object CardReaderManagerFactory {
UpdateErrorMapper(batteryLevelProvider),
terminalListener
)
- val tapToPayReaderListener = TapToPayReaderListenerImpl(logWrapper)
+ val tapToPayReaderListener = TapToPayReaderListenerImpl(logWrapper, terminalListener)
val cardReaderConfigFactory = CardReaderConfigFactory()
val paymentUtils = PaymentUtils(logWrapper)
diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/connection/CardReaderStatus.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/connection/CardReaderStatus.kt
index e1edf87595e8..8edaee24b334 100644
--- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/connection/CardReaderStatus.kt
+++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/connection/CardReaderStatus.kt
@@ -13,4 +13,5 @@ sealed class CardReaderStatus {
}
data class Connected(val cardReader: CardReader) : CardReaderStatus()
data object Connecting : CardReaderStatus()
+ data object Reconnecting : CardReaderStatus()
}
diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/CardReaderManagerImpl.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/CardReaderManagerImpl.kt
index 6b7bfe9efb5d..0d555d206001 100644
--- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/CardReaderManagerImpl.kt
+++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/CardReaderManagerImpl.kt
@@ -103,6 +103,11 @@ internal class CardReaderManagerImpl(
return connectionManager.disconnectReader()
}
+ override fun cancelReconnection() {
+ if (!terminal.isInitialized()) error("Terminal not initialized")
+ connectionManager.cancelReconnection()
+ }
+
override suspend fun collectPayment(paymentInfo: PaymentInfo): Flow {
resetBluetoothDisplayMessage()
return paymentManager.acceptPayment(paymentInfo)
diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/BluetoothReaderListenerImpl.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/BluetoothReaderListenerImpl.kt
index 87f5c67edafb..a0ce1ba2d68f 100644
--- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/BluetoothReaderListenerImpl.kt
+++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/BluetoothReaderListenerImpl.kt
@@ -1,15 +1,18 @@
package com.woocommerce.android.cardreader.internal.connection
+import com.stripe.stripeterminal.external.callable.Callback
import com.stripe.stripeterminal.external.callable.Cancelable
import com.stripe.stripeterminal.external.callable.MobileReaderListener
import com.stripe.stripeterminal.external.models.BatteryStatus
import com.stripe.stripeterminal.external.models.DisconnectReason
+import com.stripe.stripeterminal.external.models.Reader
import com.stripe.stripeterminal.external.models.ReaderDisplayMessage
import com.stripe.stripeterminal.external.models.ReaderEvent
import com.stripe.stripeterminal.external.models.ReaderInputOptions
import com.stripe.stripeterminal.external.models.ReaderSoftwareUpdate
import com.stripe.stripeterminal.external.models.TerminalException
import com.woocommerce.android.cardreader.LogWrapper
+import com.woocommerce.android.cardreader.connection.CardReaderImpl
import com.woocommerce.android.cardreader.connection.CardReaderStatus
import com.woocommerce.android.cardreader.connection.event.BluetoothCardReaderMessages
import com.woocommerce.android.cardreader.connection.event.BluetoothCardReaderMessages.CardReaderNoMessage
@@ -45,6 +48,7 @@ internal class BluetoothReaderListenerImpl(
val batteryStatusEvents = _batteryStatusEvents.asStateFlow()
var cancelUpdateAction: Cancelable? = null
+ var cancelReconnectAction: Cancelable? = null
override fun onFinishInstallingUpdate(update: ReaderSoftwareUpdate?, e: TerminalException?) {
logWrapper.d(LOG_TAG, "onFinishInstallingUpdate: $update $e")
@@ -117,6 +121,28 @@ internal class BluetoothReaderListenerImpl(
terminalListenerImpl.updateReaderStatus(CardReaderStatus.NotConnected(errorCode = errorCode))
}
+ override fun onReaderReconnectFailed(reader: Reader) {
+ logWrapper.d(LOG_TAG, "onReaderReconnectFailed")
+ cancelReconnectAction = null
+ terminalListenerImpl.updateReaderStatus(CardReaderStatus.NotConnected())
+ }
+
+ override fun onReaderReconnectStarted(
+ reader: Reader,
+ cancelReconnect: Cancelable,
+ reason: DisconnectReason
+ ) {
+ logWrapper.d(LOG_TAG, "onReaderReconnectStarted: reason=$reason")
+ cancelReconnectAction = cancelReconnect
+ terminalListenerImpl.updateReaderStatus(CardReaderStatus.Reconnecting)
+ }
+
+ override fun onReaderReconnectSucceeded(reader: Reader) {
+ logWrapper.d(LOG_TAG, "onReaderReconnectSucceeded")
+ cancelReconnectAction = null
+ terminalListenerImpl.updateReaderStatus(CardReaderStatus.Connected(CardReaderImpl(reader)))
+ }
+
fun resetConnectionState() {
_updateStatusEvents.value = SoftwareUpdateStatus.Unknown
_updateAvailabilityEvents.value = SoftwareUpdateAvailability.NotAvailable
@@ -125,4 +151,9 @@ internal class BluetoothReaderListenerImpl(
fun resetDisplayMessage() {
_displayMessagesEvents.value = CardReaderNoMessage
}
+
+ fun cancelReconnection(callback: Callback) {
+ cancelReconnectAction?.cancel(callback)
+ cancelReconnectAction = null
+ }
}
diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/ConnectionManager.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/ConnectionManager.kt
index b3a82d2cc3f8..4f3526e2961b 100644
--- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/ConnectionManager.kt
+++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/ConnectionManager.kt
@@ -163,6 +163,20 @@ internal class ConnectionManager(
})
}
+ fun cancelReconnection() {
+ val callback = object : Callback {
+ override fun onFailure(e: TerminalException) {
+ updateReaderStatus(CardReaderStatus.NotConnected())
+ }
+
+ override fun onSuccess() {
+ updateReaderStatus(CardReaderStatus.NotConnected())
+ }
+ }
+ bluetoothReaderListener.cancelReconnection(callback)
+ tapToPayReaderListener.cancelReconnection(callback)
+ }
+
private fun startStateResettingJobIfNeeded(currentStatus: CardReaderStatus) {
if (currentStatus !is CardReaderStatus.Connecting) return
diff --git a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/TapToPayReaderListenerImpl.kt b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/TapToPayReaderListenerImpl.kt
index b5d08f4d6137..2c3c059088fa 100644
--- a/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/TapToPayReaderListenerImpl.kt
+++ b/libs/cardreader/src/main/java/com/woocommerce/android/cardreader/internal/connection/TapToPayReaderListenerImpl.kt
@@ -1,21 +1,30 @@
package com.woocommerce.android.cardreader.internal.connection
+import com.stripe.stripeterminal.external.callable.Callback
import com.stripe.stripeterminal.external.callable.Cancelable
import com.stripe.stripeterminal.external.callable.TapToPayReaderListener
import com.stripe.stripeterminal.external.models.DisconnectReason
import com.stripe.stripeterminal.external.models.Reader
import com.woocommerce.android.cardreader.LogWrapper
+import com.woocommerce.android.cardreader.connection.CardReaderImpl
+import com.woocommerce.android.cardreader.connection.CardReaderStatus
import com.woocommerce.android.cardreader.internal.LOG_TAG
-class TapToPayReaderListenerImpl(
- private val logWrapper: LogWrapper
+internal class TapToPayReaderListenerImpl(
+ private val logWrapper: LogWrapper,
+ private val terminalListenerImpl: TerminalListenerImpl
) : TapToPayReaderListener {
+ var cancelReconnectAction: Cancelable? = null
+
override fun onDisconnect(reason: DisconnectReason) {
- logWrapper.d(LOG_TAG, "onDisconnect")
+ logWrapper.d(LOG_TAG, "onDisconnect: reason=$reason")
+ terminalListenerImpl.updateReaderStatus(CardReaderStatus.NotConnected())
}
override fun onReaderReconnectFailed(reader: Reader) {
logWrapper.d(LOG_TAG, "onReaderReconnectFailed")
+ cancelReconnectAction = null
+ terminalListenerImpl.updateReaderStatus(CardReaderStatus.NotConnected())
}
override fun onReaderReconnectStarted(
@@ -23,10 +32,19 @@ class TapToPayReaderListenerImpl(
cancelReconnect: Cancelable,
reason: DisconnectReason
) {
- logWrapper.d(LOG_TAG, "onReaderReconnectStarted")
+ logWrapper.d(LOG_TAG, "onReaderReconnectStarted: reason=$reason")
+ cancelReconnectAction = cancelReconnect
+ terminalListenerImpl.updateReaderStatus(CardReaderStatus.Reconnecting)
}
override fun onReaderReconnectSucceeded(reader: Reader) {
logWrapper.d(LOG_TAG, "onReaderReconnectSucceeded")
+ cancelReconnectAction = null
+ terminalListenerImpl.updateReaderStatus(CardReaderStatus.Connected(CardReaderImpl(reader)))
+ }
+
+ fun cancelReconnection(callback: Callback) {
+ cancelReconnectAction?.cancel(callback)
+ cancelReconnectAction = null
}
}