Skip to content

fix(ui): show a snackbar queued before its host mounts - #203

Merged
xsahil03x merged 4 commits into
mainfrom
fix/snackbar-stage-init-media-query
Oct 27, 2026
Merged

xsahil03x merged 4 commits into
mainfrom
fix/snackbar-stage-init-media-query

Conversation

@Brazol

@Brazol Brazol commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Submit a pull request

Linear: —
Github Issue: —

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

Description of the pull request

_SnackbarStageState.initState() syncs with its messenger. When the messenger already has a snackbar queued, that sync reads MediaQuery.accessibleNavigationOf(context), which depends on an inherited widget before initState has completed. In debug that throws:

dependOnInheritedWidgetOfExactType() or dependOnInheritedElement() was called before _SnackbarStageState.initState() completed.

An external messenger (StreamSnackbarPopup.withState, StreamSnackbarHost(messenger:)) outlives its host, so any app whose host is rebuilt while a snackbar waits hits this. It showed up in the Stream Video sample app: the call controls are rebuilt when the app returns from Android picture-in-picture, after a "You are muted" snackbar was queued in the background.

Fix: read accessibleNavigation through getInheritedWidgetOfExactType<MediaQuery>(), which doesn't register a dependency. The value is only consulted when an animation starts, so the stage never needed to rebuild when it changes.

Tests: two regression tests, both failing before the fix:

  • StreamSnackbarPopup shows a snackbar queued before it mounts.
  • With accessibleNavigation on, a snackbar queued before the host mounts still skips its animation.

Screenshots / Videos

Not applicable.

🤖 Generated with Claude Code

_SnackbarStageState synced with its messenger in initState, and when a
snackbar was already queued it read MediaQuery.accessibleNavigationOf,
which depends on an inherited widget before initState completes and
throws in debug. An external messenger outlives its host, so this hit
any app whose host is rebuilt while a snackbar waits.

Read accessibleNavigation without depending on MediaQuery; it is only
consulted when an animation starts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Brazol
Brazol requested a review from a team as a code owner October 26, 2026 16:35
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 861198d7-ab89-4fc6-abe8-3fb21ca3e188
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

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

@codecov

codecov Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.46%. Comparing base (560c729) to head (e3ebbe8).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #203   +/-   ##
=======================================
  Coverage   71.45%   71.46%           
=======================================
  Files         215      215           
  Lines        8881     8884    +3     
=======================================
+ Hits         6346     6349    +3     
  Misses       2535     2535           

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xsahil03x xsahil03x left a comment

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.

Thanks, LGTM. Both new tests fail without the fix and pass with it, and reading accessibleNavigation without a dependency is fine since it is only checked when an animation starts. A few nits inline. Optionally, a host test with accessibleNavigation off would mirror the popup one, though both go through the same stage.

Brazol and others added 3 commits October 27, 2026 10:00
…m_snackbar_messenger.dart

Co-authored-by: Sahil Kumar <xdsahil@gmail.com>
Co-authored-by: Sahil Kumar <xdsahil@gmail.com>
…nackbar_test.dart

Co-authored-by: Sahil Kumar <xdsahil@gmail.com>
@xsahil03x
xsahil03x merged commit 958a8d3 into main Oct 27, 2026
14 of 16 checks passed
@xsahil03x
xsahil03x deleted the fix/snackbar-stage-init-media-query branch October 27, 2026 11:28
Brazol added a commit to GetStream/stream-video-flutter that referenced this pull request Oct 27, 2026
Picks up GetStream/stream-core-flutter#203. A snackbar host mounted
while its messenger already had one queued threw in debug, which the
call controls hit when rebuilt on leaving Android picture-in-picture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brazol added a commit to GetStream/stream-video-flutter that referenced this pull request Oct 27, 2026
…1512)

* fix(ui): shape the Android picture-in-picture window like its video

The picture-in-picture window takes the aspect ratio of the video it
shows, within Android's 2.39:1 limit, and reshapes when that video's
size or orientation changes, instead of 9:16 or 16:9 by how the phone
is held.

On Android 12 and above the system enters picture-in-picture by itself
while it is allowed, instead of the app entering it from onUserLeaveHint
and onPause.

Part of FLU-1024

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): animate Android picture-in-picture in from the participant's tile

Hand Android a sourceRectHint: the on-screen rect of the tile showing the
participant picture-in-picture will show, so the window animates in from
it instead of covering itself with the app's icon. The aspect ratio and
the hint travel together as one set of params, offered after each frame
and debounced, and the manager hands them over between call screens.

Also from review:
- keep the last size while the shown track's renderer is replaced on
  entering picture-in-picture, so the window doesn't reshape twice
- keep picture-in-picture allowed only for the engine that allowed it
- make no native calls without picture-in-picture support or while it
  isn't allowed, and keep native exceptions out of lifecycle callbacks
- send the params again when an activity attaches to the engine
- insert the overlay into the root overlay
- drop StreamCallContent's app bar and controls in picture-in-picture

Part of FLU-1024

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): address review on Android picture-in-picture

- Only mark picture-in-picture unsupported when the activity's manifest
  doesn't declare it; other IllegalStateExceptions are transient and
  logged.
- On Android 12+, skip the manual entry only while auto-enter was
  actually armed, so rejected params no longer leave nothing to enter.
- Mark the params plumbing on AndroidPipManager @internal, and name the
  test-only resets debug…
- Keep the call screen's themes in the root-overlay PiP entry.
- Test that StreamCallContent drops and rebuilds the app bar and
  controls around picture-in-picture.
- Extract the app bar and controls from StreamCallContent.build to keep
  its cognitive complexity from rising.
- Move the behaviour changes under Changed in the changelog, and note
  the builder disposal and the root overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(repo): bump stream_core_flutter for the queued-snackbar fix

Picks up GetStream/stream-core-flutter#203. A snackbar host mounted
while its messenger already had one queued threw in debug, which the
call controls hit when rebuilt on leaving Android picture-in-picture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants