Skip to content

Conversation

nuno-vieira
Copy link
Member

@nuno-vieira nuno-vieira commented Aug 12, 2025

🔗 Issue Links

https://linear.app/stream/issue/IOS-1071/fix-chat-not-resuming-in-livestream-controller-after-coming-from

🎯 Goal

Fix livestream controller not resuming chat after coming from background

🧪 Manual Testing Notes

  1. Open a Channel with "Show as Livestream Controller"
  2. Background the app
  3. Wait 1min plus
  4. Send messages to the same channel from another device
  5. Open the Channel with the original device
  6. The livestream channel should resume connection and load newer messages

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Documentation has been updated in the docs-content repo

Summary by CodeRabbit

  • Bug Fixes

    • Livestream chat now reliably reconnects and refreshes when returning from the background. This prevents stalled or blank chat views and ensures recent messages load as expected without manual action.
  • Documentation

    • Updated the changelog to include the fix for livestream chat not reconnecting after resuming the app.

@nuno-vieira nuno-vieira requested a review from a team as a code owner August 12, 2025 15:21
Copy link

coderabbitai bot commented Aug 12, 2025

Walkthrough

Adds foreground-handling to LivestreamChannelController to reload the first page when the app returns to foreground if the client is disconnected; introduces mockable connectionStatus in ChatClient_Mock; adds tests for this conditional reload; updates CHANGELOG with the fix.

Changes

Cohort / File(s) Summary
Controller: Foreground handling
Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift
Adds applicationDidMoveToForeground() that checks ChatClient.connectionStatus and calls loadFirstPage() when disconnected.
Test tools: Mock connection status
TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift
Adds public var connectionStatus_mock: ConnectionStatus? and overrides connectionStatus getter/setter to use the mock; minor cleanup of other mock initializations.
Tests: Foreground behavior
Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
Adds two tests verifying loadFirstPage() is called when disconnected and not called when connected.
Docs: Changelog
CHANGELOG.md
Adds Upcoming bug-fix entry: “Fix LivestreamChannelController not connecting chat after coming from background” (PR #3778).

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant Controller as LivestreamChannelController
  participant ChatClient
  participant API as APIClient

  App->>Controller: applicationDidMoveToForeground()
  Controller->>ChatClient: read connectionStatus
  alt connectionStatus != .connected
    Controller->>Controller: loadFirstPage()
    Controller->>API: Endpoint<ChannelPayload>.updateChannel (first page)
    API-->>Controller: response
  else connectionStatus == .connected
    Controller-->>App: no action
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Assessment against linked issues

Objective Addressed Explanation
Fix chat not resuming in Livestream Controller after coming from background (IOS-1071)

Out-of-scope changes

(No out-of-scope functional changes detected.)

Possibly related PRs

Suggested labels

🐞 Bug, 🌐 SDK: StreamChat (LLC), 🤞 Ready For QA

Suggested reviewers

  • martinmitrevski
  • laevandus

Poem

I hopped from shadow into sun,
Foreground called — the chat's begun.
If sockets sleep, I fetch the page,
Nudge the stream to re-engage.
Thump-thump! — connection wakes, hooray! 🐇📡


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a03f47 and 9199148.

📒 Files selected for processing (1)
  • Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build LLC + UI (Xcode 15)
  • GitHub Check: Automated Code Review
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/missing-messages-in-livestream-controller-after-coming-from-background

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@nuno-vieira nuno-vieira changed the title Fix LivestreamChannelController not resuming chat after coming from background Fix LivestreamChannelController not connecting chat after coming from background Aug 12, 2025
@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChat 8.04 MB 8.04 MB 0 KB 🟢
StreamChatUI 4.86 MB 4.86 MB 0 KB 🟢

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
CHANGELOG.md (1)

14-14: Wording nit: prefer “resuming chat after returning from background.”

To better reflect the behavior and the PR’s title/intent, consider rephrasing “not connecting chat” to “not resuming chat after returning from background”.

Apply this diff:

-- Fix `LivestreamChannelController` not connecting chat after coming from background [#3778](https://github.com/GetStream/stream-chat-swift/pull/3778)
+- Fix `LivestreamChannelController` not resuming chat after returning from background [#3778](https://github.com/GetStream/stream-chat-swift/pull/3778)
Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift (1)

763-767: Foreground reload when not connected — LGTM; consider scoping to “disconnected” only.

The current condition triggers a first-page reload for all non-connected states, which may include transient states like “connecting” or “waiting for network”. Functionally fine, but if you want to avoid redundant calls during transitions, consider scoping the reload to a definitively disconnected state.

Example (optional) refinement:

public func applicationDidMoveToForeground() {
    // Only reload if we're definitively disconnected
    if case .disconnected = client.connectionStatus {
        loadFirstPage()
    }
}

This keeps behavior for the reported bug while avoiding extra traffic during short-lived transitions. If other non-connected states should also force a reload, the current implementation is appropriate.

TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift (1)

79-87: Nice addition: mockable connectionStatus; add cleanup reset to avoid cross-test leakage.

Overriding connectionStatus through connectionStatus_mock is exactly what the new tests need. To make the mock safer for reuse, also reset connectionStatus_mock (and optionally mockedEventNotificationCenter) in cleanUp().

Follow-up change (outside the selected lines):

// In ChatClient_Mock.cleanUp()
func cleanUp() {
    (apiClient as? APIClient_Spy)?.cleanUp()

    fetchCurrentUserIdFromDatabase_called = false
    createBackgroundWorkers_called = false

    completeConnectionIdWaiters_called = false
    completeConnectionIdWaiters_connectionId = nil

    completeTokenWaiters_called = false
    completeTokenWaiters_token = nil

    connectionStatus_mock = nil
    mockedEventNotificationCenter = nil

    _backgroundWorkers.removeAll()
    init_completion = nil
}
Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift (1)

910-937: Good coverage for foreground behavior (disconnected vs connected).

Both paths are validated against the expected updateChannel endpoint and no-call scenario. Consider adding a third test for a transient state (e.g., .connecting or .waitingForNetwork) to lock-in the intended behavior for those cases and prevent regressions if the foreground logic changes.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cfb6d1 and 8a03f47.

📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift (3 hunks)
  • Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift (4)
Sources/StreamChat/Audio/AppStateObserving.swift (1)
  • applicationDidMoveToForeground (28-28)
Tests/StreamChatTests/Audio/StreamAppStateObserver_Tests.swift (1)
  • applicationDidMoveToForeground (180-182)
Sources/StreamChat/Controllers/MessageController/MessageController.swift (1)
  • loadFirstPage (575-585)
Sources/StreamChat/Controllers/ChannelController/ChannelController.swift (1)
  • loadFirstPage (654-661)
Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift (2)
Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift (1)
  • applicationDidMoveToForeground (763-767)
Tests/StreamChatTests/APIClient/Endpoints/ChannelEndpoints_Tests.swift (1)
  • channelQuery (48-52)
🔇 Additional comments (2)
TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift (2)

30-34: LGTM on the event center override.

Falling back to super.eventNotificationCenter keeps behavior consistent while allowing targeted test control via mockedEventNotificationCenter.


66-68: Simplified currentUserId override — LGTM.

Returning currentUserId_mock keeps tests deterministic and avoids touching internal state elsewhere.

@Stream-SDK-Bot
Copy link
Collaborator

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 5.01 ms 49.9% 🔼 🟢
Duration 2.6 s 2.55 s 1.92% 🔼 🟢
Hitch time ratio 4 ms per s 1.97 ms per s 50.75% 🔼 🟢
Frame rate 75 fps 78.81 fps 5.08% 🔼 🟢
Number of hitches 1 0.6 40.0% 🔼 🟢

@nuno-vieira nuno-vieira added the 🤞 Ready For QA A PR that is Ready for QA label Aug 12, 2025
Copy link

1 Warning
⚠️ The changes should be manually QAed before the Pull Request will be merged

Generated by 🚫 Danger

Copy link

Public Interface

 public class LivestreamChannelController: DataStoreProvider, EventsControllerDelegate, AppStateObserverDelegate  
+   public func applicationDidMoveToForeground()

@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Aug 12, 2025

SDK Size

title develop branch diff status
StreamChat 8.04 MB 8.04 MB 0 KB 🟢
StreamChatUI 4.86 MB 4.86 MB 0 KB 🟢

@testableapple testableapple added 🧪 QAing 🟢 QAed A PR that was QAed and removed 🤞 Ready For QA A PR that is Ready for QA 🧪 QAing labels Aug 12, 2025
Copy link

@nuno-vieira nuno-vieira merged commit 839f376 into develop Aug 12, 2025
13 of 14 checks passed
@nuno-vieira nuno-vieira deleted the fix/missing-messages-in-livestream-controller-after-coming-from-background branch August 12, 2025 15:50
@Stream-SDK-Bot Stream-SDK-Bot mentioned this pull request Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🟢 QAed A PR that was QAed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants