-
Notifications
You must be signed in to change notification settings - Fork 186
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
Implement user verification #4294
Conversation
📱 Scan the QR code below to install the build (arm64 only) for this PR. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #4294 +/- ##
===========================================
- Coverage 80.12% 80.12% -0.01%
===========================================
Files 2058 2065 +7
Lines 54795 54953 +158
Branches 6713 6739 +26
===========================================
+ Hits 43907 44029 +122
- Misses 8592 8625 +33
- Partials 2296 2299 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
680f231
to
4ad8fa1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some first remarks on the UI. I'll continue the review.
I need to click twice on "Start verification" for something to happen. It seems that the screen is added twice on the backstack since at the end I need to press twice on the back arrow. See below:
StartVerification_press_twice.mp4
One question, the "Verified" decoration (green dot with check) for verified user in timeline top bar and room list item will come later?

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Figma says that the wording should be "Verify user"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty screen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is the 'Exit' state, it shouldn't display any UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Text(text = displayName ?: userId.value, style = ElementTheme.typography.fontBodyLgMedium, color = ElementTheme.colors.textPrimary) | ||
|
||
if (displayName != null) { | ||
Text(text = userId.value, style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textSecondary) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Figma there is a space of 2 with the text above. Add a verticalArrangement = Arrangement.spacedBy(2.dp)
to the Column
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More remarks. Doing more test now.
// Wait for the UI to be ready | ||
delay(500.milliseconds) | ||
|
||
backstack.singleTop(NavTarget.IncomingVerificationRequest(verificationRequest)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably ignore new incoming request if there is already a verification in progress. But maybe this is handled by the SDK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I can't remember the behaviour, but it was either new requests cancelled previous ones or were ignored, according to the docs.
override fun onIncomingSessionRequest(verificationRequest: VerificationRequest.Incoming) { | ||
// Without this launch the rendering and actual state of this Appyx node's children gets out of sync, resulting in a crash. | ||
// This might be because this method is called back from Rust in a background thread. | ||
MainScope().launch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can RustSessionVerificationService
ensure that onIncomingSessionRequest
is invoked on the same thread that was used when registering the listener?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so, this is due to how JNA works, it'll create a separate thread for this callback and use it when receiving data from Rust. Maybe we could somehow retain the thread instance and force the callback to somehow run some runnable in it, but it seems like an overkill.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
retain the thread instance and force the callback to somehow run some runnable in it
This is what I had in mind, but OK to keep it like this :)
// This might be because this method is called back from Rust in a background thread. | ||
MainScope().launch { | ||
// Wait until the app is in foreground to display the incoming verification request | ||
appNavigationStateService.appNavigationState.first { it.isInForeground } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a timeout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, but I'm not sure what a sensible value would be. Maybe instead of the timeout we should try to check if the request hasn't been cancelled.
@Module | ||
interface FtueModule { | ||
@Binds | ||
fun bindChooseVerificationMethodPresenter(presenter: ChooseSelfVerificationModePresenter): Presenter<ChooseSelfVerificationModeState> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big deal, but the name does not match :)
fun bindChooseVerificationMethodPresenter(presenter: ChooseSelfVerificationModePresenter): Presenter<ChooseSelfVerificationModeState> | |
fun bindChooseSelfVerificationModePresenter(presenter: ChooseSelfVerificationModePresenter): Presenter<ChooseSelfVerificationModeState> |
data object Root : NavTarget | ||
|
||
@Parcelize | ||
data class UseAnotherDevice(val showDeviceVerifiedScreen: Boolean) : NavTarget |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value for showDeviceVerifiedScreen
is always true
, so I guess this parameter can be removed.
) | ||
|
||
sealed interface ChooseSelfVerificationModeEvent { | ||
object SignOut : ChooseSelfVerificationModeEvent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
object SignOut : ChooseSelfVerificationModeEvent | |
data object SignOut : ChooseSelfVerificationModeEvent |
val eventSink: (ChooseSelfVerificationModeEvent) -> Unit, | ||
) | ||
|
||
sealed interface ChooseSelfVerificationModeEvent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extract to own file?
} | ||
} | ||
|
||
data class ChooseSelfVerificationModeState( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extract to own file?
) { | ||
val activity = LocalActivity.current | ||
BackHandler { | ||
activity?.finish() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems a bit brutal to close the app on a back press. Maybe later we will add a dialog or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This screen is displayed after logging in, or if you haven't verified your session and close and reopen the app. It can't go to a previous state, so I think closing the app is ok, but I can check why I did it like this because just pressing back should have the same effect through the usual navigation flow. Something tells me there was something weird with said navigation flow 😅 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, it's because the NoOpBackstackHandlerStrategy
used in FtueFlowNode
prevents the user from going back. I think we can remove that instead: AFAICT, pressing back here will close the app, but then again, the state should be restored when reopened.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that the user cannot go back, but a dialog would help to understand that verification is mandatory to go further maybe. Here when clicking back, user may think that the application just crashed.
Not blocking the PR though.
I confirm that the state is restored. I guess it's OK then!
} | ||
} | ||
|
||
fun createPresenter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fun createPresenter( | |
private fun createPresenter( |
I can't reproduce it 🫤 : navigation.mp4
All the status badges will come in a different PR. I'm not sure if the room list one is feasible though. |
There is a weird flash in your recording though, it seems like some other state is being displayed for a short while. Could you maybe add some logs or attach the debugger to try to understand what's happening? |
I got this log on first click on "Verify"
On the second attempt I got the same log, but the state machine goes further. Full logs are in https://github.com/element-hq/element-x-android-rageshakes/issues/4613 |
Ok, so it is caused by the error you mentioned. This line moves the state back to initial, maybe it should go to failed. It seems like it's cause by your account having some unverified session, which prevents sending the request verification in the room, AFAICT. I'm asking product/design what we can do about this issue. Either we prevent the user from starting the verification at all or we should display some helpful error messages so they know what's wrong. |
Thanks. It's strange that on second click I can go further and actually do the verification. |
Yeah, I think it's because we need the change I mentioned:
Otherwise the UI and the state machine states differ and we have that issue. |
…tate will be restored when the app is reopened.
Then, when resetting the state machine state also reset the verification service.
7a918e8
to
995a122
Compare
|
If the rest of the issues are fixed, can we move this PR forward even if it has the issue with the unverified sessions canceling the flow? iOS has the same problem, and the feature was delivered weeks ago. Also, it needs product/design feedback so it'll take a while, blocking other PRs related to user verification. EDIT: apparently, there's even some bug report so it can be fixed in the Rust SDK. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's fine, thanks!
Content
VerifySelfSessionNode
to its own navigation Node so we can have the sameInitial
state for both session verification and user verification.Motivation and context
Close #4241.
Screenshots / GIFs
There are a few new screenshots in the PR.
Tests
You'll need 2 accounts that haven't verified each other yet.
Tested devices
Checklist