Modernize the Flutter example app - #1066
Conversation
…tter-example-app # Conflicts: # example/lib/pages/connect.dart
| if (!hasVideoPublication) { | ||
| userMediaTracks.add(ParticipantTrack(participant: participant)); | ||
| } |
There was a problem hiding this comment.
🟡 Participants who share their screen with the camera off disappear from the participant view
A participant tile is only added when the participant has no video publications at all (if (!hasVideoPublication) at example/lib/pages/room.dart:313-315), so someone whose only video is a screen share gets no personal tile, meaning they vanish from the participant view while sharing.
Impact: While a camera-off user shares their screen, other people can no longer see that user's tile (name, speaking indicator, avatar) in the room.
Why the screen-share-only case falls through the audio-only fallback
The loop sets hasVideoPublication = true for every video publication, including screen shares. A screen-share publication therefore suppresses the fallback that was added to show audio-only participants, and the screen-share entry itself is pushed into screenTracks rather than a user-media tile. The same pattern is duplicated for the local participant at example/lib/pages/room.dart:352-354. A fix would track camera (non-screen-share) publications separately from screen-share publications, e.g. only skip the fallback when a non-screen-share video publication was seen.
Prompt for agents
In example/lib/pages/room.dart, _sortParticipants() adds a fallback user-media tile only when a participant has zero video publications (hasVideoPublication). Because screen-share publications also set that flag, a participant whose only video publication is a screen share gets no personal tile at all (their screen share appears, but they themselves disappear from the grid). The same logic is duplicated for the local participant later in the same function. Consider tracking camera/user-media publications separately from screen-share publications so the fallback tile is added whenever there is no non-screen-share video publication.
Was this helpful? React with 👍 or 👎 to provide feedback.
| 33CC10EB2044A3C60003C045 /* Resources */, | ||
| 33CC110E2044A8840003C045 /* Bundle Framework */, | ||
| 3399D490228B24CF009A79C7 /* ShellScript */, | ||
| 514FABDBA3BE0B4C6B1D1F14 /* [CP] Embed Pods Frameworks */, |
There was a problem hiding this comment.
🟡 macOS example app may fail to launch because the step that bundles its CocoaPods frameworks was deleted
The build step that copies the CocoaPods dynamic frameworks into the macOS example app bundle was removed from the app target ([CP] Embed Pods Frameworks deleted at example/macos/Runner.xcodeproj/project.pbxproj:192), so the app links against libraries that are no longer packaged with it.
Impact: Building and running the macOS example from the committed Xcode project can crash at launch with a missing-library error until CocoaPods regenerates the step.
Why the phase is required for this target
example/macos/Podfile declares use_frameworks!, so pods (including the WebRTC xcframework pulled in by flutter_webrtc) are built as dynamic frameworks and must be embedded by the [CP] Embed Pods Frameworks script phase. Both the phase reference in the Runner target's buildPhases and the PBXShellScriptBuildPhase definition itself were deleted, while Pods_Runner.framework remains linked in the Frameworks phase. The iOS project still contains the equivalent phase (example/ios/Runner.xcodeproj/project.pbxproj:210). Running pod install will re-add it, which is likely why the removal was not noticed, but it should be restored so the checked-in project builds standalone.
Was this helpful? React with 👍 or 👎 to provide feedback.
| url: _uriCtrl.text.trim(), | ||
| token: _tokenCtrl.text.trim(), | ||
| e2ee: _e2ee, | ||
| e2eeKey: _sharedKeyCtrl.text, | ||
| simulcast: _simulcast, | ||
| adaptiveStream: _adaptiveStream, | ||
| dynacast: _dynacast, | ||
| autoSubscribe: _autoSubscribe, | ||
| multiCodec: _multiCodec, | ||
| preferredCodec: _preferredCodec, | ||
| updatedAt: DateTime.now(), | ||
| ); | ||
| if (entry.url.isEmpty && entry.token.isEmpty) return; | ||
|
|
||
| final next = [ | ||
| entry, | ||
| ..._history.where( | ||
| (item) => item.url != entry.url || item.token != entry.token, | ||
| ), | ||
| ].take(5).toList(); | ||
|
|
||
| setState(() { |
There was a problem hiding this comment.
🟨 Room access tokens and E2EE keys are persisted in plaintext connection history
The new "recent connections" feature serializes the full JWT access token and the E2EE shared key into JSON and stores it in SharedPreferences (_saveCurrentConnectionToHistory at example/lib/pages/connect.dart:203-224, written via _writeHistory at example/lib/pages/connect.dart:136-142). SharedPreferences is unencrypted on disk (plist / XML / localStorage on web), so on web builds or rooted/backed-up devices any other script or process with access to the app storage can read live room credentials and the media encryption key.
Was this helpful? React with 👍 or 👎 to provide feedback.
No description provided.