Skip to content

fix(ui): show no tile chrome in the Android picture-in-picture window - #1344

Open
renefloor wants to merge 10 commits into
v2from
fix/pip-window-info-display
Open

fix(ui): show no tile chrome in the Android picture-in-picture window#1344
renefloor wants to merge 10 commits into
v2from
fix/pip-window-info-display

Conversation

@renefloor

@renefloor renefloor commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

The Android PiP window drew a participant tile with its full chrome: the name pill, the connection quality indicator, and an overflow button that nothing in PiP can tap — Android routes taps to the window itself, not to the Flutter view.

The button is the new part. StreamParticipantTile grows an overflow menu whenever actions exist, and an app that registers a participantTile builder adding actions to every tile — as the dogfooding app does with Pin/Mute — got one in PiP too. On main the overlay used StreamCallParticipant, which has no menu, but it did show the name pill and the connection indicator: those two defaults are true, and both stay. What goes with the button is the camera-off icon and the sound indicator, which is also what removes the doubled overlay inside the pill — the indicator's box fills with the same 75%-black token the pill uses, so on top of it the two composite to ~94%.

Suppressed through the style rather than the props, so the app-wide builder does not put the menu back — the same way StreamLobbyView does it for its preview tile. The overlay's screen-share branch draws no chrome and needed nothing.

The window's shape is the system's, so the tile no longer draws a shape of its own: square corners, because a rounded tile inside a rounded window left the black Material showing through as wedges, and no outline, because one drawn square has its corners clipped away and reads as a border down the sides. The name pill and the indicator then sit flush in the corners, each square on the corner it occupies and rounded only on the inner one — which is also what stream-video-swift does (cornerRadius(8, corners: [.topRight]) and [.topLeft]), and it gives the name the width the inset was taking.

Both are configurable rather than fixed:

  • StreamPictureInPictureThemeData on StreamVideoTheme, whose StreamPictureInPictureStyle.tileStyle restyles the tile and can put any of the chrome back. The window is inserted into the nearest Overlay, above the route showing the call, so it has to be set on the theme or above the Navigator — a StreamPictureInPictureTheme around the call screen is not an ancestor of it.
  • StreamParticipantLabelStyle.showVideoOffIcon, for the camera-off icon, which had no switch of its own next to showAudioIndicator.

The name pill also draws nothing at all now when it has neither a name nor an indicator, rather than an empty rounded rectangle over the video. CallParticipantState.name has no userId fallback, so with both icons off an unnamed participant would have hit that.

iOS is untouched: its native PiP renders from IOSPictureInPictureConfiguration, whose showParticipantName, showMicrophoneIndicator and showConnectionQualityIndicator all default to true. stream-video-swift shows the same — name, mic and connection quality — and its name pill has no flag to turn off at all, so Android now reads closer to iOS than it did before this PR, not further from it.

Testing

Seven widget tests on the overlay: the name and indicator are drawn; the overflow button, camera icon and sound indicator are not; the tile is square and draws no outline, speaking or not; the chrome is anchored in the corners; the indicator is squared without dropping a fill an app themed it with; and everything the window suppresses comes back when the picture-in-picture theme asks for it. Three more on the label cover the new showVideoOffIcon and the empty pill.

Verified on a Pixel 8 in a real PiP window, camera on and off, cropped to the window's own bounds (128x228 dp).

🤖 Generated with Claude Code

The PiP overlay draws a StreamParticipantTile, which at the window's size
carries its full chrome: the name pill, the connection quality indicator
and — for an app registering a `participantTile` builder that adds actions,
as the dogfooding app does — an overflow button nothing in PiP can tap.

Suppressed through the style, so the app-wide builder does not put the menu
back, the same way the lobby preview does it.

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

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 92d87570-b082-4a2e-a3ba-761347d30151

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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 Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.77778% with 1 line in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (v2@ad336b1). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...ideo_flutter/lib/src/theme/stream_video_theme.dart 85.71% 1 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##             v2    #1344   +/-   ##
=====================================
  Coverage      ?   31.38%           
=====================================
  Files         ?      376           
  Lines         ?    28830           
  Branches      ?        0           
=====================================
  Hits          ?     9048           
  Misses        ?    19782           
  Partials      ?        0           

☔ 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.

renefloor and others added 2 commits September 11, 2026 15:25
`StreamPictureInPictureThemeData` on `StreamVideoTheme`, carrying a
`tileStyle` merged over the window's own choices — so an app can restyle
the tile the Android PiP window draws, and put back the name pill,
connection quality indicator or overflow button it leaves out.

The window is inserted into the nearest Overlay, which sits above the route
showing the call, so a theme wrapped around the call screen is not an
ancestor of it. Documented on the theme: set it on `StreamVideoTheme`, or
above the Navigator.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@renefloor
renefloor marked this pull request as ready for review September 11, 2026 13:29
@renefloor
renefloor requested a review from a team as a code owner September 11, 2026 13:29
renefloor and others added 7 commits September 11, 2026 16:19
…re window

The window draws the name pill and the connection quality indicator again,
without the camera-off icon or the sound indicator, and still without the
overflow button.

Adds `StreamParticipantLabelStyle.showVideoOffIcon` for the camera-off icon,
which had no switch of its own. The pill also draws nothing at all now when
it has neither a name nor an indicator to show, rather than an empty
rounded rectangle over the video.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The system rounds the window, so the tile's own corner clip left the
Material behind it showing through as black wedges, and an outline drawn
square had its corners clipped away, leaving a border down the sides.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The name pill and the connection quality indicator sit flush against the
window's edges, each square on the corner it occupies and rounded only on
the inner one, which also gives the name the width the inset was taking.

The indicator's shape comes off the decoration it would otherwise have
drawn, so an app's own fill survives the change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`StreamParticipantLabelStyle.borderRadius` takes a `BorderRadiusGeometry`,
so a corner-anchored pill no longer resolves the text direction itself. The
widget passes it to a `ClipRRect` and a `BoxDecoration`, both of which took
one already.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The theme's accessor, wrap, updateShouldNotify and lerp, and the branch
StreamVideoTheme.lerp carries it through.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
At the size Android gives it — 128x228dp — over video, with the camera off,
muted and on a poor connection. No golden rendered the window before, so
nothing in the suite noticed what its chrome did.

The style it draws with moves to `pictureInPictureTileStyle`, internal and
unexported, so the snapshot and the widget tests assert the shape the window
actually uses rather than restating it.

Co-Authored-By: Claude Opus 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.

1 participant