Skip to content

Prompt user when inviting users with uncached identities#5331

Open
kaylendog wants to merge 6 commits intodevelopfrom
kaylendog/history-sharing/prompt
Open

Prompt user when inviting users with uncached identities#5331
kaylendog wants to merge 6 commits intodevelopfrom
kaylendog/history-sharing/prompt

Conversation

@kaylendog
Copy link
Copy Markdown
Contributor

@kaylendog kaylendog commented Mar 31, 2026

If the user attempts to invite someone (to a room or creating a DM) who's identity is not cached, we prompt them to make sure this was their intention.

Part of element-hq/element-meta#3163

Pull Request Checklist

UI changes have been tested with:

  • iPhone and iPad simulators in portrait and landscape orientations.
  • Dark mode enabled and disabled.
  • Various sizes of dynamic type.
  • Voiceover enabled.

@kaylendog kaylendog self-assigned this Mar 31, 2026
@kaylendog kaylendog force-pushed the kaylendog/history-sharing/prompt branch 2 times, most recently from 6a44d49 to edeaec7 Compare March 31, 2026 16:28
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 1, 2026

Codecov Report

❌ Patch coverage is 86.92308% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.46%. Comparing base (2b8c21a) to head (11c98cb).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ens/InviteUsersScreen/View/InviteUsersScreen.swift 50.00% 3 Missing ⚠️
...ens/StartChatScreen/StartChatScreenViewModel.swift 78.57% 3 Missing ⚠️
...Screens/StartChatScreen/View/StartChatScreen.swift 0.00% 3 Missing ⚠️
...InviteUsersScreen/InviteUsersScreenViewModel.swift 92.59% 2 Missing ⚠️
...viteUsersScreen/View/ConfirmInviteUsersSheet.swift 94.73% 2 Missing ⚠️
...tailsScreen/RoomMemberDetailsScreenViewModel.swift 90.90% 1 Missing ⚠️
...erDetailsScreen/View/RoomMemberDetailsScreen.swift 66.66% 1 Missing ⚠️
...UserProfileScreen/UserProfileScreenViewModel.swift 50.00% 1 Missing ⚠️
...ens/UserProfileScreen/View/UserProfileScreen.swift 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #5331      +/-   ##
===========================================
+ Coverage    74.38%   74.46%   +0.07%     
===========================================
  Files          800      801       +1     
  Lines        53519    53639     +120     
===========================================
+ Hits         39811    39940     +129     
+ Misses       13708    13699       -9     
Flag Coverage Δ
unittests 64.62% <86.92%> (+0.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kaylendog kaylendog force-pushed the kaylendog/history-sharing/prompt branch from d6c1c97 to 2761e63 Compare April 1, 2026 17:18
@kaylendog kaylendog force-pushed the kaylendog/history-sharing/prompt branch from 2761e63 to 11c98cb Compare April 1, 2026 18:13
@kaylendog kaylendog added the T-Enhancement New features, changes in functionality, performance boosts, user-facing improvements label Apr 1, 2026
import Compound
import SwiftUI

struct ConfirmInviteUsersSheetView: View {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I am wondering if it would be better to repurpose the existing SendInviteConfirmationView to support arbitrary numbers of members, but this seems to suffice for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it's fine too keep them separate but can we maybe name it InviteUsersConfirmationView so it somewhat matches the other one?

Comment on lines +106 to +109
Task { @MainActor in
// If we do not, we will prompt the user to confirm they meant to invite them.
self.state.usersToConfirm.append(user)
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There is a potential race condition here, but I'm not sure how to fix it and since we're only loading from the store, these tasks should be very short-lived.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

these tasks should be very short-lived

I agree so why not run them directly on the current actor?

Comment on lines +99 to +100
MXLog.error("Failed to get cached user identity for \(user.userID)")
return
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It might be worth appending here even in the case of failure, like the changes to the other view models do.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Makes sense to me

@kaylendog
Copy link
Copy Markdown
Contributor Author

I can't see why the Apple CI is failing, but otherwise I believe this is ready for review.

@kaylendog kaylendog marked this pull request as ready for review April 1, 2026 18:23
@kaylendog kaylendog requested a review from a team as a code owner April 1, 2026 18:23
@kaylendog kaylendog requested review from stefanceriu and removed request for a team April 1, 2026 18:23
Copy link
Copy Markdown
Member

@stefanceriu stefanceriu left a comment

Choose a reason for hiding this comment

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

Looking good, nice start 👍

Comment on lines +20 to +23
"crypto_history_sharing_confirm_invite_dialog_title" = "Invite new contacts to this room?";
"crypto_history_sharing_confirm_invite_dialog_content" = "You currently don’t have any chats with these contacts. Confirm inviting them to this room before continuing.";
"crypto_history_sharing_confirm_start_chat_dialog_title" = "Start a chat with this new contact?";
"crypto_history_sharing_confirm_start_chat_dialog_content" = "You currently don’t have any chats with this person. Confirm inviting them before continuing.";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should these have made it to localazy already?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's on my list of things to do!

import Compound
import SwiftUI

struct ConfirmInviteUsersSheetView: View {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it's fine too keep them separate but can we maybe name it InviteUsersConfirmationView so it somewhat matches the other one?

Comment on lines +73 to +74
/// Whether we are showing the confirmation dialog.
var presentConfirmationDialog = false
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we infer this from usersToConfirm and have it be computed instead or at least set when that changes? 🤔

Comment on lines +106 to +109
Task { @MainActor in
// If we do not, we will prompt the user to confirm they meant to invite them.
self.state.usersToConfirm.append(user)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

these tasks should be very short-lived

I agree so why not run them directly on the current actor?

Comment on lines +99 to +100
MXLog.error("Failed to get cached user identity for \(user.userID)")
return
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Makes sense to me

self.state.bindings.inviteConfirmationUserIdentityKnown = switch identity {
case .success(let identity): identity != nil
default: false
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can also be written as

self.state.bindings.inviteConfirmationUserIdentityKnown = if case .success(let identity) = await self.userSession.clientProxy.userIdentity(for: roomMemberProxy.userID, fallBackToServer: false) {
    identity != nil
} else {
    false
}


struct SendInviteConfirmationView: View {
let userToInvite: UserProfileProxy
let userIdentityKnown: Bool
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would rename this to isUserIdentityKnown

SendInviteConfirmationView(userToInvite: .mockBob,
userIdentityKnown: true,
mediaProvider: nil) { }
.previewDisplayName("With Identity")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically With identity known and unknown as you're actually passing the identity in.

var alertInfo: AlertInfo<StartChatScreenErrorType>?

var selectedUserToInvite: UserProfileProxy?
var selectedUserIdentityKnown = false
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same question here, why is this a binding?

if appSettings.enableKeyShareOnInvite {
Task.detached {
let identity = await self.userSession.clientProxy.userIdentity(for: user.userID, fallBackToServer: false)
Task { @MainActor in
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-Enhancement New features, changes in functionality, performance boosts, user-facing improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants