From afc6d1340e296de5224a7ef7966e46c376ebb89b Mon Sep 17 00:00:00 2001 From: Vlad Kozarez Date: Thu, 14 Nov 2024 19:52:07 +0300 Subject: [PATCH 1/2] AND-8958 fixed scan dialog double show (3d try) --- .../tangem/sdk/DefaultSessionViewDelegate.kt | 28 ++++++++++++------- .../com/tangem/sdk/ui/NfcSessionDialog.kt | 15 ++++++---- .../com/tangem/common/core/CardSession.kt | 2 +- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt b/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt index 50f65184..f466d464 100644 --- a/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt +++ b/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt @@ -76,36 +76,39 @@ class DefaultSessionViewDelegate( override fun onSessionStopped(message: Message?) { Log.view { "session stopped" } stoppedBySession = true - readingDialog?.show(SessionViewDelegateState.Success(message)) + readingDialog?.show(SessionViewDelegateState.Success(message), ::onDialogShown) } override fun onSecurityDelay(ms: Int, totalDurationSeconds: Int, productType: ProductType) { Log.view { "showing security delay: $ms, $totalDurationSeconds" } - readingDialog?.show(SessionViewDelegateState.SecurityDelay(ms, totalDurationSeconds, productType)) + readingDialog?.show( + SessionViewDelegateState.SecurityDelay(ms, totalDurationSeconds, productType), + ::onDialogShown, + ) } override fun onDelay(total: Int, current: Int, step: Int, productType: ProductType) { Log.view { "showing delay" } - readingDialog?.show(SessionViewDelegateState.Delay(total, current, step, productType)) + readingDialog?.show(SessionViewDelegateState.Delay(total, current, step, productType), ::onDialogShown) } override fun onTagLost(productType: ProductType) { Log.view { "tag lost" } - readingDialog?.show(SessionViewDelegateState.TagLost(productType)) + readingDialog?.show(SessionViewDelegateState.TagLost(productType), ::onDialogShown) } override fun onTagConnected() { Log.view { "tag connected" } - readingDialog?.show(SessionViewDelegateState.TagConnected) + readingDialog?.show(SessionViewDelegateState.TagConnected, ::onDialogShown) } override fun onWrongCard(wrongValueType: WrongValueType) { Log.view { "wrong card detected" } - readingDialog?.show(SessionViewDelegateState.WrongCard(wrongValueType)) + readingDialog?.show(SessionViewDelegateState.WrongCard(wrongValueType), ::onDialogShown) } override fun onError(error: TangemError) { - readingDialog?.show(SessionViewDelegateState.Error(error)) + readingDialog?.show(SessionViewDelegateState.Error(error), ::onDialogShown) } override fun requestUserCode( @@ -129,6 +132,7 @@ class DefaultSessionViewDelegate( cardId = cardId, callback = callback, ), + ::onDialogShown, ) } } @@ -137,7 +141,7 @@ class DefaultSessionViewDelegate( Log.view { "showing pin change request with type: $type" } val dialog = readingDialog ?: createReadingDialog(activity) - dialog.show(SessionViewDelegateState.PinChangeRequested(type, cardId, callback)) + dialog.show(SessionViewDelegateState.PinChangeRequested(type, cardId, callback), ::onDialogShown) } override fun dismiss() { @@ -176,6 +180,10 @@ class DefaultSessionViewDelegate( AttestationFailedDialog.completedWithWarnings(activity, positive) } + private fun onDialogShown() { + readingDialog = null + } + private fun createAndShowState( state: SessionViewDelegateState, enableHowTo: Boolean, @@ -187,7 +195,7 @@ class DefaultSessionViewDelegate( // before old one is dismissed, that leads to 2 dialogs on screen. // Create new one in onDismiss callback postUI { - if (readingDialog != null) { + if (readingDialog != null && readingDialog?.isShowing == true) { readingDialog?.setOnDismissListener { Log.view { "old readingDialog onDismiss callback" } createAndConfigureDialog(state, enableHowTo, message, iconScanRes) @@ -211,7 +219,7 @@ class DefaultSessionViewDelegate( showHowTo(enableHowTo) setInitialMessage(message) setScanImage(sdkConfig.scanTagImage) - show(state) + show(state, ::onDialogShown) } } diff --git a/tangem-sdk-android/src/main/java/com/tangem/sdk/ui/NfcSessionDialog.kt b/tangem-sdk-android/src/main/java/com/tangem/sdk/ui/NfcSessionDialog.kt index 10d88508..28b84926 100644 --- a/tangem-sdk-android/src/main/java/com/tangem/sdk/ui/NfcSessionDialog.kt +++ b/tangem-sdk-android/src/main/java/com/tangem/sdk/ui/NfcSessionDialog.kt @@ -87,7 +87,7 @@ class NfcSessionDialog( stateWidgets.add(messageWidget) stateWidgets.add(howToTapWidget) - headerWidget.onHowTo = { show(SessionViewDelegateState.HowToTap) } + headerWidget.onHowTo = { show(SessionViewDelegateState.HowToTap) {} } behavior.state = BottomSheetBehavior.STATE_COLLAPSED } @@ -112,7 +112,7 @@ class NfcSessionDialog( } @Suppress("LongMethod", "ComplexMethod") - fun show(state: SessionViewDelegateState) { + fun show(state: SessionViewDelegateState, onDialogShowed: () -> Unit) { postUI { if (ownerActivity?.isFinishing == true) return@postUI if (!this.isShowing) { @@ -121,7 +121,7 @@ class NfcSessionDialog( when (state) { is SessionViewDelegateState.Ready -> onReady(state) - is SessionViewDelegateState.Success -> onSuccess(state) + is SessionViewDelegateState.Success -> onSuccess(state, onDialogShowed) is SessionViewDelegateState.Error -> onError(state) is SessionViewDelegateState.SecurityDelay -> onSecurityDelay(state) is SessionViewDelegateState.Delay -> onDelay(state) @@ -144,10 +144,13 @@ class NfcSessionDialog( setStateAndShow(state, headerWidget, touchCardWidget, messageWidget) } - private fun onSuccess(state: SessionViewDelegateState.Success) { + private fun onSuccess(state: SessionViewDelegateState.Success, onDialogShowed: () -> Unit) { setStateAndShow(state, headerWidget, progressStateWidget, messageWidget) performHapticFeedback() - postUI(msTime = 1000) { dismissInternal() } + postUI(msTime = 100) { + dismissInternal() + onDialogShowed() + } } private fun onError(state: SessionViewDelegateState.Error) { @@ -274,7 +277,7 @@ class NfcSessionDialog( howToTapWidget.previousState?.let { howToTapWidget.setState(it) - show(it) + show(it) {} } howToTapWidget.previousState = null } diff --git a/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt b/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt index 8d4e933b..5e2a5456 100644 --- a/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt +++ b/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt @@ -359,8 +359,8 @@ class CardSession( * @param message If null, the default message will be shown. */ private fun stop(message: Message? = null) { - stopSessionIfActive() viewDelegate.onSessionStopped(message) + stopSessionIfActive() } /** From f6fc9d5aceedde8727648290ed03687cbb3801fa Mon Sep 17 00:00:00 2001 From: Vlad Kozarez Date: Fri, 15 Nov 2024 14:12:28 +0300 Subject: [PATCH 2/2] AND-8958 fix scan dialog (4th try) --- .../ui/tasksLogger/CommandsTesterFragment.kt | 2 +- .../ui/viewDelegate/ViewDelegateAction.kt | 2 +- .../tangem/sdk/DefaultSessionViewDelegate.kt | 20 ++++++++----------- .../java/com/tangem/SessionViewDelegate.kt | 2 +- .../com/tangem/common/core/CardSession.kt | 5 +++-- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/tasksLogger/CommandsTesterFragment.kt b/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/tasksLogger/CommandsTesterFragment.kt index 483529ea..431acfb6 100644 --- a/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/tasksLogger/CommandsTesterFragment.kt +++ b/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/tasksLogger/CommandsTesterFragment.kt @@ -189,7 +189,7 @@ class SdkTaskSpinnerFragment : BaseFragment() { override fun onTagLost(productType: ProductType) {} override fun onTagConnected() {} override fun onWrongCard(wrongValueType: WrongValueType) {} - override fun onSessionStopped(message: Message?) {} + override fun onSessionStopped(message: Message?, onDialogHidden: () -> Unit) {} override fun onError(error: TangemError) {} override fun requestUserCode( type: UserCodeType, diff --git a/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/viewDelegate/ViewDelegateAction.kt b/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/viewDelegate/ViewDelegateAction.kt index c3e11fbe..6bd63c3b 100644 --- a/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/viewDelegate/ViewDelegateAction.kt +++ b/tangem-sdk-android-demo/src/main/java/com/tangem/demo/ui/viewDelegate/ViewDelegateAction.kt @@ -149,7 +149,7 @@ class SecurityDelay : BaseDelegateAction() { } } - withMainContext { delegate.onSessionStopped(null) } + withMainContext { delegate.onSessionStopped(null) {} } } } diff --git a/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt b/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt index f466d464..bfef8182 100644 --- a/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt +++ b/tangem-sdk-android/src/main/java/com/tangem/sdk/DefaultSessionViewDelegate.kt @@ -73,10 +73,13 @@ class DefaultSessionViewDelegate( } } - override fun onSessionStopped(message: Message?) { + override fun onSessionStopped(message: Message?, onDialogHidden: () -> Unit) { Log.view { "session stopped" } stoppedBySession = true - readingDialog?.show(SessionViewDelegateState.Success(message), ::onDialogShown) + readingDialog?.show(SessionViewDelegateState.Success(message)) { + onDialogShown() + onDialogHidden() + } } override fun onSecurityDelay(ms: Int, totalDurationSeconds: Int, productType: ProductType) { @@ -191,19 +194,12 @@ class DefaultSessionViewDelegate( iconScanRes: Int? = null, ) { Log.view { "createAndShowState" } - // Under the hood dialog dismiss could work async and new dialog could be created - // before old one is dismissed, that leads to 2 dialogs on screen. - // Create new one in onDismiss callback postUI { - if (readingDialog != null && readingDialog?.isShowing == true) { - readingDialog?.setOnDismissListener { - Log.view { "old readingDialog onDismiss callback" } - createAndConfigureDialog(state, enableHowTo, message, iconScanRes) - } - readingDialog?.dismissInternal() - } else { + if (readingDialog == null) { Log.view { "createAndConfigDialog" } createAndConfigureDialog(state, enableHowTo, message, iconScanRes) + } else { + readingDialog?.show(state, ::onDialogShown) } } } diff --git a/tangem-sdk-core/src/main/java/com/tangem/SessionViewDelegate.kt b/tangem-sdk-core/src/main/java/com/tangem/SessionViewDelegate.kt index 44fd3135..1742ebe0 100644 --- a/tangem-sdk-core/src/main/java/com/tangem/SessionViewDelegate.kt +++ b/tangem-sdk-core/src/main/java/com/tangem/SessionViewDelegate.kt @@ -55,7 +55,7 @@ interface SessionViewDelegate { /** * It is called when NFC session was completed and a user can take the card away from the Android device. */ - fun onSessionStopped(message: Message? = null) + fun onSessionStopped(message: Message? = null, onDialogHidden: () -> Unit) /** * It is called when some error occur during NFC session. diff --git a/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt b/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt index 5e2a5456..068b9a27 100644 --- a/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt +++ b/tangem-sdk-core/src/main/java/com/tangem/common/core/CardSession.kt @@ -359,8 +359,9 @@ class CardSession( * @param message If null, the default message will be shown. */ private fun stop(message: Message? = null) { - viewDelegate.onSessionStopped(message) - stopSessionIfActive() + viewDelegate.onSessionStopped(message) { + stopSessionIfActive() + } } /**