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

Update mobile connect flow and UI #1008

Merged
merged 13 commits into from
Jun 27, 2024

Conversation

jakub-rdx
Copy link
Contributor

@jakub-rdx jakub-rdx commented Jun 21, 2024

Description

For some reason strings.xml are included in the PR content, making this PR look huge. Please disregard xml changes as strings will be added to crowdin once the ui screens will appear in Zeplin.

  • update the flow to match latest sargon implementation
  • add handling of deep link requests together with high priority screens & other dapp interactions. This is expected behavior, for now:
  • missing crowding copies, this will be added before merging.
  1. when we have high priority screen opened and new deep link request comes in, we put it first into queue but display when high priority flow completes
  2. when there is no high priority screen - incoming mobile connect request should interrupt other dapp interaction handling (but not reject it), so when mobile connect handling complete, we should start over handling of the request that was on the screen before mobile connect request came in.
  • update UI of link screen and success/failure dialogs

How to test

  1. See description

@@ -61,7 +61,10 @@ class MainActivity : FragmentActivity() {
super.onCreate(savedInstanceState)
cloudBackupSyncExecutor.startPeriodicChecks(lifecycleOwner = this)

intent.data?.let { viewModel.handleDeepLink(it) }
intent.data?.let {
intent.replaceExtras(Bundle())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice that you added this here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually can someone explain me what does this line do? Because I see it in the line 103, too.
Does it "clear" the intent with an empty bundle?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it removes data from an intent, so deep link is not delivered 2nd time if you move app to background and open from recent

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the app is moved to background and re-opened from recent neither onCreate nor onNewIntent should get called in normal circumstances, unless the app task has been closed by the OS? Is that the case or there are simple repro steps for the issue that this line fixes? I'm really curious about what is happening.

Comment on lines -26 to -30
fun getUnauthorizedRequest(requestId: String): IncomingRequest.UnauthorizedRequest?

fun getTransactionWriteRequest(requestId: String): IncomingRequest.TransactionRequest?

fun getAuthorizedRequest(requestId: String): IncomingRequest.AuthorizedRequest?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice that you removed those 👍

Copy link
Contributor

@micbakos-rdx micbakos-rdx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general the flow seems nice 👍 .

Some comments regarding the experience:

  • I am not sure what will be the plan when the user doesn't have a profile. There are 2 paths here:
    1. The user goes on to create a new profile. Will they be presented with the request?
    2. The user just closes the app. Shouldn't we send a cancelation event to the dapp?
  • Even though I see that you clear the deep link when you first read it in MainActivity I have experienced this:
    • The user doesn't have a profile available
    • The dApp sends a request
    • The user is presented with the modal that they don't have a profile
    • I close the app with back or click ok on the dialog.
    • Then I open the app from recents.
    • I still get the dialog and I cannot continue.
  • As mentioned in the demo we need to cancel the request when we dismiss the verify screen.
  • For some reason I cannot dismiss a transaction while a dapp request is pending:
    • Open the app and try a transfer between 2 accounts.
    • Stay in the transaction review screen
    • Then open a dapp and perform a connect
    • This navigates back to wallet were the transaction screen is visible
    • In this case now I cannot dismiss it. Both back and X button do not perform back.
  • After doing the above steps, without trying to dismiss the pending transfer, I complete the transfer. Then I am not presented with the dapp request.

Copy link
Contributor

@giannis-rdx giannis-rdx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested and works flawlessly!

I left some comments only about code.

Comment on lines 78 to 79
* - there is no high priority screen: request is added at the top of queue and if there other request currently handled,
* we send a dismiss event for it so that UI can react and dismiss handling, without removing it from the queue.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"there is no high priority screen: request is added at the top of queue and if there other request currently handled, ..."

here you mean that if wallet receives another high priority request while another non high priority is being handled then we dismiss it and so on... right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually what I am thinking is that the term dismiss is not the right one to describe this particular business logic. "Dismiss" is like reject. We reject this request and we will never see it again.

But what if we use postpone which describes that we delay the handling of this request?
so it becomes override suspend fun requestPostponed and any other "dismiss" rename to "postpone"?

I would like to hear the opinion of others. Also any other word is welcome!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh now I think defer is even better.
override suspend fun requestDeferred

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, whenever this method is used, request added with it is supposed to go on screen while current one is deferred. This does not apply if we are in flows like creating accounts or other flows marked as high priority.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not apply if we are in flows like creating accounts or other flows marked as high priority.

wait I think I lost it here, you mean we really dismiss the request in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, we never dimiss when using addMobileConnectRequest(). It is just that we don't process it immediately. Example: when mobile connect request (MCR) comes in and we are in the middle of some other dApp login, dapp login is deferred and MCR takes over. But when we are in a wallet doing something, like account creation (high priority flow), then request is delivered after that particular screen/flow is complete.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice thank you

…flow

# Conflicts:
#	app/src/main/java/com/babylon/wallet/android/MainActivity.kt
#	app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt
#	app/src/main/res/values-en/strings.xml
#	gradle/libs.versions.toml
Copy link
Contributor

@giannis-rdx giannis-rdx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please rename the rest of the "dismiss" words in order to be consistent

* we send a defer event for it so that UI can react and defer handling, without removing it from the queue.
* Deferred request will be handled again when top priority one handling completes
*/
override suspend fun addMobileConnectRequest(incomingRequest: IncomingRequest) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe addDeferredRequest instead of naming it to mobile connect

Copy link
Contributor Author

@jakub-rdx jakub-rdx Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not deferred request, mobile connect ones take priority over others. Will rename to addPriorityRequest

}
}

override suspend fun requestDeferred(requestId: String) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not actually deferred here? This is like a yield action right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is deferred, but this method works in tandem with addMobileConnectRequest. When you use the latter, new request is put in front, and calling requestDeferred is simply taking next request to handle without removing current from the queue. I couldn't do both those actions in one method as there are user interactions in between.

request = request,
error = DappWalletInteractionErrorType.INVALID_REQUEST
)
return Result.failure(RadixWalletException.DappRequestException.WrongNetwork(networkId, request.metadata.networkId))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add the names of the parameters here? We had a bug in the past were the networkId and request.metadata.networkId were reversed.

_state.update {
it.copy(isSubmitting = false)
): Result<Unit> {
return runCatching {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can inline this

Copy link
Contributor

@sergiupuhalschi-rdx sergiupuhalschi-rdx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works very nice and smooth! Great job!

@@ -61,7 +61,10 @@ class MainActivity : FragmentActivity() {
super.onCreate(savedInstanceState)
cloudBackupSyncExecutor.startPeriodicChecks(lifecycleOwner = this)

intent.data?.let { viewModel.handleDeepLink(it) }
intent.data?.let {
intent.replaceExtras(Bundle())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the app is moved to background and re-opened from recent neither onCreate nor onNewIntent should get called in normal circumstances, unless the app task has been closed by the OS? Is that the case or there are simple repro steps for the issue that this line fixes? I'm really curious about what is happening.

Comment on lines 10 to 18
private var bufferedRequest: IncomingMessage.IncomingRequest? = null

fun setBufferedRequest(request: IncomingMessage.IncomingRequest) {
bufferedRequest = request
}

fun getBufferedRequest(): IncomingMessage.IncomingRequest? {
return bufferedRequest?.also { bufferedRequest = null }
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually why not to have this in the IncomingRequestRepository ? 🤷🏽‍♂️

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking the same thing, more than that, this class just holds some data, so it looks more like a data source than a repository. The repository usually is the component abstracting the data sources, serving as an intermediary between the data sources and the business logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, will make the change

Copy link

sonarcloud bot commented Jun 27, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 40%)

See analysis details on SonarCloud

Comment on lines +64 to +66
/**
* Request that can come in via deep link before wallet is setup.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌🏽

@jakub-rdx jakub-rdx merged commit 362f82a into feature/m2m-poc Jun 27, 2024
7 of 9 checks passed
@jakub-rdx jakub-rdx deleted the feature/mobile-connect-optimized-flow branch June 27, 2024 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants