-
Notifications
You must be signed in to change notification settings - Fork 46
feat(ui): added option to prioritise track to display in Picture in Picture mode #1127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds a PiP track-priority option and threads a consolidated PictureInPictureConfiguration through iOS/Android PiP views; introduces CallParticipantsSortingMixin and refactors participant selection/rendering to use computed sortedParticipants and screenShareParticipant. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (2)
⏰ 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). (8)
🔇 Additional comments (15)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
packages/stream_video_flutter/CHANGELOG.md(1 hunks)packages/stream_video_flutter/lib/src/call_participants/call_participants.dart(3 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/call_content.dart(1 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart(2 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/picture_in_picture_configuration.dart(2 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_android_view.dart(1 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_ui_kit_view.dart(3 hunks)packages/stream_video_flutter/lib/src/livestream/livestream_content.dart(1 hunks)
⏰ 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). (8)
- GitHub Check: analyze_legacy_version
- GitHub Check: stream_video_screen_sharing
- GitHub Check: stream_video_push_notification
- GitHub Check: stream_video_noise_cancellation
- GitHub Check: stream_video
- GitHub Check: stream_video_flutter
- GitHub Check: analyze
- GitHub Check: build
🔇 Additional comments (12)
packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_android_view.dart (1)
154-156: LGTM!The
prioritiseScreenSharingTrackparameter is correctly propagated from the configuration to theAndroidPipOverlaywidget, maintaining consistency with the iOS implementation path.packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart (2)
13-19: LGTM!The new
prioritiseScreenSharingTrackparameter is properly declared with a sensible default (true) for backward compatibility. The public field is correctly exposed.
37-39: LGTM!The parameter is correctly propagated to
StreamCallParticipantsvia theprioritiseScreenSharingInPictureInPictureparameter.packages/stream_video_flutter/CHANGELOG.md (1)
1-5: LGTM!The changelog entry is clear and accurately describes the new
prioritiseScreenSharingTrackparameter behavior. The "Upcoming" section is appropriately used for unreleased changes.packages/stream_video_flutter/lib/src/livestream/livestream_content.dart (1)
187-190: LGTM!The
prioritiseScreenSharingTrackparameter is correctly propagated toStreamPictureInPictureUiKitViewfor the iOS PiP path, consistent with the implementation incall_content.dart.packages/stream_video_flutter/lib/src/call_screen/call_content/call_content.dart (1)
149-152: LGTM!The
prioritiseScreenSharingTrackparameter is correctly propagated toStreamPictureInPictureUiKitViewfor the iOS PiP path, aligning with the Android implementation inStreamPictureInPictureAndroidView.packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/picture_in_picture_configuration.dart (1)
17-17: LGTM! Clear documentation and sensible default.The new configuration option is well-documented, explaining both the prioritization behavior and the fallback logic when video is disabled. The default value of
trueis reasonable for maintaining existing behavior.Also applies to: 29-37
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart (1)
206-234: PiP prioritization logic is correct.The implementation correctly handles the prioritization behavior:
- When
prioritiseScreenSharingInPictureInPictureistrueand screen share is available → displays screen share- When
falseand screen share is available but video is enabled → displays camera feed- Fallback: when video is disabled but screen share is available → displays screen share regardless of the flag
The logic aligns with the documented behavior.
packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_ui_kit_view.dart (4)
44-44: LGTM! Parameter declaration is consistent.The parameter naming
prioritiseScreenSharingTrackmatches the configuration field inPictureInPictureConfiguration, maintaining consistency in the iOS PiP implementation.Also applies to: 50-50
84-100: Priority logic correctly implemented for iOS PiP.The prioritization logic matches the Android implementation in
call_participants.dart, ensuring consistent behavior across platforms. ThepriorityTrackis correctly set to screen share when prioritized or as fallback, otherwise defaults to video.
102-121: Track subscription logic handles prioritization correctly.The code properly retrieves the appropriate track based on
priorityTrackand updates subscriptions when needed. The early return ensures the platform channel isn't invoked until the track is available.
123-143: Platform channel payload correctly reflects prioritization.The participant data sent to the iOS native layer properly uses
pipParticipantand correctly setsisVideoEnabledto include theshouldShowScreenSharecondition (line 134), ensuring the platform UI accurately reflects when screen sharing is being displayed.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1127 +/- ##
========================================
- Coverage 6.30% 6.29% -0.01%
========================================
Files 593 594 +1
Lines 40894 40948 +54
========================================
Hits 2578 2578
- Misses 38316 38370 +54 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart (1)
116-159: Missing subscription disposal indispose()method.The
_participantsSubscriptionis created ininitState()and conditionally cancelled indidUpdateWidget(), but there's nodispose()override to cancel the subscription when the widget is removed from the tree. This could cause a memory leak.Add a dispose method:
+ @override + void dispose() { + _participantsSubscription?.cancel(); + super.dispose(); + } + @override Widget build(BuildContext context) {
🧹 Nitpick comments (5)
packages/stream_video_flutter/lib/src/call_participants/call_participants_sorting_mixin.dart (3)
18-27: Provide default implementations forparticipantFilter/participantSortto avoid forced overrides
Right now these are abstract getters, so every consumer mixing this in must implement both (even if they just want “no filter / default sort”). Consider defaulting them tonullin the mixin.- Filter<CallParticipantState>? get participantFilter; + Filter<CallParticipantState>? get participantFilter => null; - Sort<CallParticipantState>? get participantSort; + Sort<CallParticipantState>? get participantSort => null;
30-75: Avoid O(n²)indexOfhot-path in stable ordering
_sortedParticipantKeys.indexOf(...)is used in (1) the “add new keys” loop and (2) the sort comparator, which can get costly with frequent updates. Consider building aMap<String,int>once per recalculation.void recalculateParticipants(List<CallParticipantState> newParticipants) { final participants = [ ...newParticipants, ].where(participantFilter ?? (_) => true).toList(); + final keyIndex = <String, int>{ + for (var i = 0; i < _sortedParticipantKeys.length; i++) + _sortedParticipantKeys[i]: i, + }; + for (final participant in participants) { - final index = _sortedParticipantKeys.indexOf( - participant.uniqueParticipantKey, - ); - if (index == -1) { + if (!keyIndex.containsKey(participant.uniqueParticipantKey)) { _sortedParticipantKeys.add(participant.uniqueParticipantKey); + keyIndex[participant.uniqueParticipantKey] = _sortedParticipantKeys.length - 1; } } // First apply previous sorting on new participants list participants.sort( - (a, b) => _sortedParticipantKeys - .indexOf(a.uniqueParticipantKey) - .compareTo(_sortedParticipantKeys.indexOf(b.uniqueParticipantKey)), + (a, b) => + (keyIndex[a.uniqueParticipantKey] ?? 1 << 30) + .compareTo(keyIndex[b.uniqueParticipantKey] ?? 1 << 30), );
78-80: Consider clearing_participants/_screenShareParticipantwhen clearing cache (if callers expect a full reset)
As-is,clearParticipantSortingCache()only resets ordering keys; UI will keep rendering the last_participantsuntil the nextrecalculateParticipants(). If “reset” semantics are desired, clear the rest too.packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_ui_kit_view.dart (2)
124-137: Subscription update condition should match the chosenpriorityTrack
Right now you may callupdateSubscription(... trackType: priorityTrack ...)even when the other track is what’s enabled (because the condition is(isVideoEnabled || isScreenShareEnabled)). Consider tightening to the selected track’s enabled flag to reduce unnecessary updates / surprising behavior.- if (videoTrack == null && - (pipParticipant.isVideoEnabled || - pipParticipant.isScreenShareEnabled)) { + final shouldSubscribePriorityTrack = priorityTrack == SfuTrackType.video + ? pipParticipant.isVideoEnabled + : pipParticipant.isScreenShareEnabled; + + if (videoTrack == null && shouldSubscribePriorityTrack) { await widget.call.updateSubscription( userId: pipParticipant.userId, sessionId: pipParticipant.sessionId, trackIdPrefix: pipParticipant.trackIdPrefix, trackType: priorityTrack, videoDimension: RtcVideoDimensionPresets.h360_169, );
189-199: Considerunawaited(...)(or error handling) for_handleParticipantsChangein the listener
Since_handleParticipantsChangeis async and you’re calling it fromlisten(...)without awaiting, it’s easy to drop errors / create overlapping calls. You already importdart:async, so making it explicit helps.- _handleParticipantsChange( + unawaited(_handleParticipantsChange( state.callParticipants, (widget .pictureInPictureConfiguration ?.iOSPiPConfiguration .includeLocalParticipantVideo ?? widget.configuration?.includeLocalParticipantVideo ?? true) && widget.call.state.value.iOSMultitaskingCameraAccessEnabled, - ); + ));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart(4 hunks)packages/stream_video_flutter/lib/src/call_participants/call_participants_sorting_mixin.dart(1 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/call_content.dart(1 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart(2 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/picture_in_picture_configuration.dart(2 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_android_view.dart(1 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_ui_kit_view.dart(6 hunks)packages/stream_video_flutter/lib/src/livestream/livestream_content.dart(1 hunks)packages/stream_video_flutter/lib/stream_video_flutter.dart(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/stream_video_flutter/lib/src/livestream/livestream_content.dart
- packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_android_view.dart
⏰ 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). (8)
- GitHub Check: analyze
- GitHub Check: stream_video_push_notification
- GitHub Check: stream_video
- GitHub Check: stream_video_screen_sharing
- GitHub Check: build
- GitHub Check: stream_video_flutter
- GitHub Check: stream_video_noise_cancellation
- GitHub Check: analyze_legacy_version
🔇 Additional comments (11)
packages/stream_video_flutter/lib/stream_video_flutter.dart (1)
30-30: LGTM!The export is correctly positioned alphabetically and appropriately exposes the new mixin for consumers who need custom participant sorting behavior.
packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/picture_in_picture_configuration.dart (2)
12-12: Good use of enum for track priority.Using an enum instead of a boolean (as suggested in past review feedback) provides better clarity and extensibility for future priority options.
31-40: Clear and thorough documentation.The fallback behavior for camera priority is well-documented, making the feature's behavior predictable for consumers.
packages/stream_video_flutter/lib/src/call_screen/call_content/call_content.dart (1)
144-148: LGTM!The iOS PiP initialization correctly uses the consolidated
pictureInPictureConfigurationobject, aligning with the unified configuration approach across platforms.packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart (3)
77-101: Logic correctly implements track priority with fallback.The implementation properly handles:
- Screen share priority: shows screen share when available
- Camera priority: shows camera, but falls back to screen share when video is disabled
The conditional logic is sound and aligns with the documented behavior in
PictureInPictureConfiguration.
104-109: Good backward compatibility with deprecated parameters.The fallback chain correctly prefers the new
pictureInPictureConfigurationwhile maintaining support for deprecatedcustomBuilderparameter during the transition period.
44-45: No action required.The
participantFilterreturningnullis intentionally handled byCallParticipantsSortingMixinusing a null coalescing operator (participantFilter ?? (_) => true), which treatsnullas "include all participants." This is safe, correct, and the expected design.packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_ui_kit_view.dart (4)
41-63: Good API migration pattern (assert + deprecations), but document precedence when both configs are provided
Code clearly preferspictureInPictureConfigurationover deprecated fields; consider adding a short doc note in the constructor dartdoc about precedence when both are non-null.
91-98: Sort precedence looks correct
pictureInPictureConfiguration?.sort ?? participantSort ?? speakeris a sensible migration path and keeps old behavior available.
140-171: Config fallback wiring toiOSPiPConfigurationlooks consistent
ThepictureInPictureConfiguration?.iOSPiPConfiguration ?? configurationfallback reads clean and keeps deprecation compatibility.
281-303: Nice: screen-share tracks are now toggled alongside video tracks
This aligns the bandwidth-saving logic with the new PiP track-priority behavior.
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart
Outdated
Show resolved
Hide resolved
...m_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart
Show resolved
Hide resolved
...b/src/call_screen/call_content/picture_in_picture/stream_picture_in_picture_ui_kit_view.dart
Show resolved
Hide resolved
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart (1)
114-155: Fix subscription lifecycle: handle participants→null transition and cancel indisposeTwo issues around
_participantsSubscription:
No subscription when switching from custom
participantsback to call-driven stateIn
didUpdateWidget, when you go fromoldWidget.participants != nulltowidget.participants == nullandwidget.call == oldWidget.call, neither branch executes. That means:
- No subscription is created.
- The widget stops reacting to
callParticipantsupdates once the custom list is removed.You can fix this by treating “participants became null” similarly to the “call changed” case and (re)subscribing:
@override void didUpdateWidget(covariant StreamCallParticipants oldWidget) { super.didUpdateWidget(oldWidget); if (widget.participants != null) { _participantsSubscription?.cancel(); if (!const ListEquality<CallParticipantState>().equals( widget.participants!.toList(), oldWidget.participants?.toList(), )) { recalculateParticipants(widget.participants!); }
- } else if (widget.call != oldWidget.call) {
_participantsSubscription?.cancel();_participantsSubscription = widget.call.partialState((state) => state.callParticipants).listen(recalculateParticipants);
- } else {
final participantsBecameNull = oldWidget.participants != null;final callChanged = widget.call != oldWidget.call;if (participantsBecameNull || callChanged) {_participantsSubscription?.cancel();_participantsSubscription = widget.call.partialState((state) => state.callParticipants).listen(recalculateParticipants); }}
}If `partialState` does *not* synchronously emit the current value, you may also want to trigger an immediate `recalculateParticipants(widget.call.state.value.callParticipants)` in that branch.
No cleanup in
dispose
_participantsSubscriptionis canceled in somedidUpdateWidgetpaths but never indispose, so a lingering subscription could outlive the widget if nothing else triggers the cancellation.Add a
disposeoverride:@override void didUpdateWidget(covariant StreamCallParticipants oldWidget) { super.didUpdateWidget(oldWidget); ... }
- @OverRide
- void dispose() {
- _participantsSubscription?.cancel();
- super.dispose();
- }
Together these changes ensure the widget remains in sync when toggling between external and call-driven participants and avoids leaking subscriptions.
🧹 Nitpick comments (1)
packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart (1)
51-59: Consider handling configuration changes indidUpdateWidget.If the
callorpictureInPictureConfigurationchanges after initial build, the current implementation won't:
- Recreate the subscription for a different
call- Recalculate participants with the new sort order
+ @override + void didUpdateWidget(covariant AndroidPipOverlay oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.call != widget.call) { + _participantsSubscription?.cancel(); + _participantsSubscription = widget.call + .partialState((state) => state.callParticipants) + .listen(recalculateParticipants); + recalculateParticipants(widget.call.state.value.callParticipants); + } else if (oldWidget.pictureInPictureConfiguration?.sort != + widget.pictureInPictureConfiguration?.sort || + oldWidget.sort != widget.sort) { + recalculateParticipants(widget.call.state.value.callParticipants); + } + } + @override void dispose() {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart(2 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart(2 hunks)
⏰ 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). (9)
- GitHub Check: stream_video_push_notification
- GitHub Check: stream_video
- GitHub Check: stream_video_screen_sharing
- GitHub Check: stream_video_flutter
- GitHub Check: stream_video_noise_cancellation
- GitHub Check: build
- GitHub Check: analyze_legacy_version
- GitHub Check: analyze
- GitHub Check: iOS Build (Dogfooding)
🔇 Additional comments (4)
packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart (2)
78-85: Verify default behavior when no configuration is provided.When
pictureInPictureConfigurationisnull, the conditionpipTrackPriority != PipTrackPriority.cameraevaluates totrue(sincenull != PipTrackPriority.camera), meaning screen share is prioritized by default.Is this the intended default behavior for backward compatibility? Consider adding explicit handling:
+ // Default to screen share priority when not configured (backward compatibility) final shouldShowScreenShare = hasScreenShare && - (widget.pictureInPictureConfiguration?.pipTrackPriority != - PipTrackPriority.camera || + (widget.pictureInPictureConfiguration?.pipTrackPriority == + PipTrackPriority.screenShare || + widget.pictureInPictureConfiguration?.pipTrackPriority == null || !pipParticipant.isVideoEnabled);Alternatively, if camera should be the default, update accordingly.
105-115: LGTM! Proper fallback chain for custom builder.The resolution correctly prioritizes the new configuration's builder, falls back to the deprecated
customBuilder, and finally uses the computedpipBody. This maintains backward compatibility while supporting the new configuration approach.packages/stream_video_flutter/lib/src/call_participants/call_participants.dart (2)
112-121: Good use of mixin + clear wiring of filter/sort into the shared logic
CallParticipantsSortingMixinintegration and theparticipantFilter/participantSortgetters cleanly delegate configuration from the widget to the shared sorting/filtering logic. This keeps the state class thin and makes future reuse of the mixin straightforward.
159-172: Build logic cleanly delegates to screen‑share vs regular layouts using computed stateThe
buildmethod now branches onscreenShareParticipantand consistently feedssortedParticipantsinto bothScreenShareCallParticipantsContentandRegularCallParticipantsContent. This centralizes participant ordering/filtering in the mixin and keeps UI components focused on layout, which is a nice simplification.
...m_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart
Outdated
Show resolved
Hide resolved
…tStream/stream-video-flutter into feat/option-to-prioritize-camera-feed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart (1)
40-65: Consider handlingcallorsortchanges indidUpdateWidget.If the
callorpictureInPictureConfigurationprops can change during the widget's lifetime, the current implementation won't update the subscription or re-seed participants. For a PiP overlay that typically exists for one call session, this may be acceptable, but worth noting.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart(2 hunks)packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart(2 hunks)
⏰ 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). (8)
- GitHub Check: analyze_legacy_version
- GitHub Check: stream_video
- GitHub Check: stream_video_noise_cancellation
- GitHub Check: stream_video_flutter
- GitHub Check: stream_video_push_notification
- GitHub Check: analyze
- GitHub Check: build
- GitHub Check: iOS Build (Dogfooding)
🔇 Additional comments (6)
packages/stream_video_flutter/lib/src/call_participants/call_participants.dart (4)
112-120: Clean mixin integration.The state class properly integrates
CallParticipantsSortingMixinwith getter overrides that delegate to widget properties. This pattern cleanly separates sorting/filtering concerns.
122-134: Proper initial state seeding and subscription setup.The
initStatecorrectly callsrecalculateParticipantswith the initial state before subscribing to updates, avoiding the empty-state-on-first-build issue. The conditional subscription logic appropriately skips streaming when external participants are provided.
136-140: LGTM!Proper cleanup of the subscription in
dispose.
163-183: LGTM!The build method cleanly selects between screen-share and regular content based on the computed
screenShareParticipant, and consistently usessortedParticipantsfrom the mixin.packages/stream_video_flutter/lib/src/call_screen/call_content/picture_in_picture/android_pip_overlay.dart (2)
12-35: Good deprecation pattern with migration guidance.The deprecated annotations with clear migration messages help users transition to
PictureInPictureConfiguration. The dual deprecation (on parameter and field) ensures visibility in IDE warnings.
51-59: Initial state seeding addressed.The
initStatenow correctly callsrecalculateParticipantswith the initial participant state before subscribing, addressing the previously flagged issue.
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.