Skip to content

Conversation

@KaterinaWire
Copy link
Contributor

@KaterinaWire KaterinaWire commented Nov 17, 2025

BugWPB-20468 [iOS] Accepting call on 2nd account doesn't open calling UI but only show green banner on top with connected timer in the conversation

Issue

When receiving a call on an inactive account, the app switches to the correct account, but only shows the green top bar.

From the UI perspective the flow is

  1. Receiving an incoming call on an inactive account and tapping the CallKit notification
  2. App opens and switches to the inactive account
  3. Calling UI briefly appears showing "Connecting..." state
  4. Calling UI is dismissed/covered when conversation view appears
  5. User sees only the conversation without the calling UI overlay

The calling UI is shown before the conversation navigation completes, and then the conversation appearing dismisses the calling UI.

func showConversation(
        _ conversation: ZMConversation,
        at message: ZMConversationMessage? = nil,
        in session: ZMUserSession
    ) {
        guard !conversation.isDeletedRemotely else {
            return
        }

        activateAccount(for: session) {
            self.presentationDelegate?.showConversation(conversation, at: message)
        }
    }

updateActiveCallPresentationState() is called inside the loadSession flow (activateAccount ->select() -> loadSession ) before the completion executes to show the conversation. The conversation navigation then interferes with the already shown calling UI.

Solution

Display the calling UI after the conversation is fully visible.

  1. Post notification when conversation view appears.
  2. Observe notification in SessionManager.activateAccount() and triggers updateActiveCallPresentationState() at the right time - after conversation is visible

Testing

  • Receive call on inactive account → ✅ Switches account and shows full call UI immediately

Checklist

  • Title contains a reference JIRA issue number like [WPB-XXX].
  • Description is filled and free of optional paragraphs.
  • Adds/updates automated tests.

UI accessibility checklist

If your PR includes UI changes, please utilize this checklist:

  • Make sure you use the API for UI elements that support large fonts.
  • All colors are taken from WireDesign.ColorTheme or constructed using WireDesign.BaseColorPalette.
  • New UI elements have Accessibility strings for VoiceOver.

@KaterinaWire KaterinaWire marked this pull request as ready for review November 24, 2025 14:16
@github-actions
Copy link
Contributor

github-actions bot commented Nov 24, 2025

Test Results

3 166 tests   3 139 ✅  3m 55s ⏱️
  450 suites     27 💤
    2 files        0 ❌

Results for commit 9e9282c.

♻️ This comment has been updated with latest results.

@KaterinaWire KaterinaWire requested a review from netbe December 2, 2025 10:35
Comment on lines 115 to 127
conversationVisibleObserver = NotificationCenter.default.addObserver(
forName: .conversationDidBecomeVisible,
object: nil,
queue: .main
) { [weak self] _ in
guard let self else { return }

if let observer = conversationVisibleObserver {
NotificationCenter.default.removeObserver(observer)
conversationVisibleObserver = nil
}
presentationDelegate?.updateActiveCallPresentationStateIfNeeded()
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

question: can we move this inside the user session? The session manager shouldn't be concerned about this so it'd be good to avoid it if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, I can share my thoughts on why I would prefer to keep it in SessionManager, but I'm open to your suggestions.
SessionManager owns presentationDelegate that already has API for UI communication in a context of account coordination/switching.
This is a use case specifically for switching between accounts and SessionManager orchestrating it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I also moved the code around and added more comments

private func notifyConversationDidBecomeVisible() {
NotificationCenter.default.post(
name: .conversationDidBecomeVisible,
object: conversation
Copy link
Collaborator

Choose a reason for hiding this comment

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

suggestion: it doesn't seem necessary to pass the conversation, perhaps you can remove it?

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, removed

Copy link
Collaborator

@johnxnguyen johnxnguyen left a comment

Choose a reason for hiding this comment

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

I'm not a big fan of posting notifications like this but I understand an alternative solution must be tricky. Just so I understand, what's stopping us from awaiting the completion of showing the conversation directly? i.e something like

showConversation(completion: {
  // do something
})

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.

3 participants