@@ -10,17 +10,25 @@ import 'participant_info.dart';
10
10
11
11
abstract class ParticipantWidget extends StatefulWidget {
12
12
// Convenience method to return relevant widget for participant
13
- static ParticipantWidget widgetFor (Participant participant) {
14
- if (participant is LocalParticipant ) {
15
- return LocalParticipantWidget (participant);
16
- } else if (participant is RemoteParticipant ) {
17
- return RemoteParticipantWidget (participant);
13
+ static ParticipantWidget widgetFor (ParticipantTrack participantTrack) {
14
+ if (participantTrack.participant is LocalParticipant ) {
15
+ return LocalParticipantWidget (
16
+ participantTrack.participant as LocalParticipant ,
17
+ participantTrack.videoTrack,
18
+ participantTrack.isScreenShare);
19
+ } else if (participantTrack.participant is RemoteParticipant ) {
20
+ return RemoteParticipantWidget (
21
+ participantTrack.participant as RemoteParticipant ,
22
+ participantTrack.videoTrack,
23
+ participantTrack.isScreenShare);
18
24
}
19
25
throw UnimplementedError ('Unknown participant type' );
20
26
}
21
27
22
28
// Must be implemented by child class
23
29
abstract final Participant participant;
30
+ abstract final VideoTrack ? videoTrack;
31
+ abstract final bool isScreenShare;
24
32
final VideoQuality quality;
25
33
26
34
const ParticipantWidget ({
@@ -32,9 +40,15 @@ abstract class ParticipantWidget extends StatefulWidget {
32
40
class LocalParticipantWidget extends ParticipantWidget {
33
41
@override
34
42
final LocalParticipant participant;
43
+ @override
44
+ final VideoTrack ? videoTrack;
45
+ @override
46
+ final bool isScreenShare;
35
47
36
48
const LocalParticipantWidget (
37
- this .participant, {
49
+ this .participant,
50
+ this .videoTrack,
51
+ this .isScreenShare, {
38
52
Key ? key,
39
53
}) : super (key: key);
40
54
@@ -45,9 +59,15 @@ class LocalParticipantWidget extends ParticipantWidget {
45
59
class RemoteParticipantWidget extends ParticipantWidget {
46
60
@override
47
61
final RemoteParticipant participant;
62
+ @override
63
+ final VideoTrack ? videoTrack;
64
+ @override
65
+ final bool isScreenShare;
48
66
49
67
const RemoteParticipantWidget (
50
- this .participant, {
68
+ this .participant,
69
+ this .videoTrack,
70
+ this .isScreenShare, {
51
71
Key ? key,
52
72
}) : super (key: key);
53
73
@@ -60,7 +80,7 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
60
80
//
61
81
bool _visible = true ;
62
82
VideoTrack ? get activeVideoTrack;
63
- TrackPublication ? get firstVideoPublication ;
83
+ TrackPublication ? get videoPublication ;
64
84
TrackPublication ? get firstAudioPublication;
65
85
66
86
@override
@@ -89,12 +109,12 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
89
109
void _onParticipantChanged () => setState (() {});
90
110
91
111
// Widgets to show above the info bar
92
- List <Widget > extraWidgets () => [];
112
+ List <Widget > extraWidgets (bool isScreenShare ) => [];
93
113
94
114
@override
95
115
Widget build (BuildContext ctx) => Container (
96
116
foregroundDecoration: BoxDecoration (
97
- border: widget.participant.isSpeaking
117
+ border: widget.participant.isSpeaking && ! widget.isScreenShare
98
118
? Border .all (
99
119
width: 5 ,
100
120
color: LKColors .lkBlue,
@@ -112,7 +132,7 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
112
132
child: activeVideoTrack != null
113
133
? VideoTrackRenderer (
114
134
activeVideoTrack! ,
115
- fit: RTCVideoViewObjectFit .RTCVideoViewObjectFitCover ,
135
+ fit: RTCVideoViewObjectFit .RTCVideoViewObjectFitContain ,
116
136
)
117
137
: const NoVideoWidget (),
118
138
),
@@ -124,14 +144,15 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
124
144
crossAxisAlignment: CrossAxisAlignment .stretch,
125
145
mainAxisSize: MainAxisSize .min,
126
146
children: [
127
- ...extraWidgets (),
147
+ ...extraWidgets (widget.isScreenShare ),
128
148
ParticipantInfoWidget (
129
149
title: widget.participant.name.isNotEmpty
130
150
? '${widget .participant .name } (${widget .participant .identity })'
131
151
: widget.participant.identity,
132
152
audioAvailable: firstAudioPublication? .muted == false &&
133
153
firstAudioPublication? .subscribed == true ,
134
154
connectionQuality: widget.participant.connectionQuality,
155
+ isScreenShare: widget.isScreenShare,
135
156
),
136
157
],
137
158
),
@@ -144,60 +165,48 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
144
165
class _LocalParticipantWidgetState
145
166
extends _ParticipantWidgetState <LocalParticipantWidget > {
146
167
@override
147
- LocalTrackPublication <LocalVideoTrack >? get firstVideoPublication =>
148
- widget.participant.videoTracks.firstOrNull;
168
+ LocalTrackPublication <LocalVideoTrack >? get videoPublication =>
169
+ widget.participant.videoTracks
170
+ .where ((element) => element.sid == widget.videoTrack? .sid)
171
+ .firstOrNull;
149
172
150
173
@override
151
174
LocalTrackPublication <LocalAudioTrack >? get firstAudioPublication =>
152
175
widget.participant.audioTracks.firstOrNull;
153
176
154
177
@override
155
- VideoTrack ? get activeVideoTrack {
156
- if (firstVideoPublication? .subscribed == true &&
157
- firstVideoPublication? .muted == false &&
158
- _visible) {
159
- return firstVideoPublication? .track;
160
- }
161
- return null ;
162
- }
178
+ VideoTrack ? get activeVideoTrack => widget.videoTrack;
163
179
}
164
180
165
181
class _RemoteParticipantWidgetState
166
182
extends _ParticipantWidgetState <RemoteParticipantWidget > {
167
183
@override
168
- RemoteTrackPublication <RemoteVideoTrack >? get firstVideoPublication =>
169
- widget.participant.videoTracks.firstOrNull;
184
+ RemoteTrackPublication <RemoteVideoTrack >? get videoPublication =>
185
+ widget.participant.videoTracks
186
+ .where ((element) => element.sid == widget.videoTrack? .sid)
187
+ .firstOrNull;
170
188
171
189
@override
172
190
RemoteTrackPublication <RemoteAudioTrack >? get firstAudioPublication =>
173
191
widget.participant.audioTracks.firstOrNull;
174
192
175
193
@override
176
- VideoTrack ? get activeVideoTrack {
177
- for (final trackPublication in widget.participant.videoTracks) {
178
- print (
179
- 'video track ${trackPublication .sid } subscribed ${trackPublication .subscribed } muted ${trackPublication .muted }' );
180
- if (trackPublication.subscribed && ! trackPublication.muted && _visible) {
181
- return trackPublication.track;
182
- }
183
- }
184
- return null ;
185
- }
194
+ VideoTrack ? get activeVideoTrack => widget.videoTrack;
186
195
187
196
@override
188
- List <Widget > extraWidgets () => [
197
+ List <Widget > extraWidgets (bool isScreenShare ) => [
189
198
Row (
190
199
mainAxisSize: MainAxisSize .max,
191
200
mainAxisAlignment: MainAxisAlignment .end,
192
201
children: [
193
202
// Menu for RemoteTrackPublication<RemoteVideoTrack>
194
- if (firstVideoPublication != null )
203
+ if (videoPublication != null )
195
204
RemoteTrackPublicationMenuWidget (
196
- pub: firstVideoPublication ! ,
197
- icon: EvaIcons .video,
205
+ pub: videoPublication ! ,
206
+ icon: isScreenShare ? EvaIcons .monitor : EvaIcons .video,
198
207
),
199
208
// Menu for RemoteTrackPublication<RemoteAudioTrack>
200
- if (firstAudioPublication != null )
209
+ if (firstAudioPublication != null && ! isScreenShare )
201
210
RemoteTrackPublicationMenuWidget (
202
211
pub: firstAudioPublication! ,
203
212
icon: EvaIcons .volumeUp,
0 commit comments