addVideosGrid function
- AddVideosGridOptions options
Adds video and audio streams of participants to the main and alternate grids based on specified options.
This function manages the layout and styling of participant video, audio, and mini-cards in the main and alternate grids, with customizations based on event type, background, and layout settings. It dynamically updates the UI by adding or removing components in real-time, handling both the main and alternate grids.
- The function creates
VideoCard
widgets for participants with active video streams andAudioCard
widgets for participants with audio streams but without video. - For participants who don’t have active audio or video, a
MiniCard
is generated, displaying participant initials.
This function is typically called when the user joins or leaves the room, changes display settings, or new streams become available.
Parameters:
options
:AddVideosGridOptions
containing layout details like the number of rows and columns, lists of main and alternate grid streams, flags for removing alternate grids, and other stream-related parameters.
Example:
await addVideosGrid(AddVideosGridOptions(
mainGridStreams: [/* main stream participants */],
altGridStreams: [/* alternate stream participants */],
numRows: 2,
numCols: 2,
actualRows: 2,
lastRowCols: 1,
removeAltGrid: true,
parameters: gridParams,
));
Implementation
Future<void> addVideosGrid(AddVideosGridOptions options) async {
try {
// Retrieve updated parameters
AddVideosGridParameters parameters =
options.parameters.getUpdatedAllParams();
// Extract all necessary properties from parameters
final eventType = parameters.eventType;
final updateAddAltGrid = parameters.updateAddAltGrid;
List<Participant> refParticipants = List.from(parameters.refParticipants);
final islevel = parameters.islevel;
final videoAlreadyOn = parameters.videoAlreadyOn;
final localStreamVideo = parameters.localStreamVideo;
final keepBackground = parameters.keepBackground;
final virtualStream = parameters.virtualStream;
final forceFullDisplay = parameters.forceFullDisplay;
final member = parameters.member;
List<List<Widget>> otherGridStreams =
List.from(parameters.otherGridStreams);
final updateOtherGridStreams = parameters.updateOtherGridStreams;
final updateMiniCardsGrid = parameters.updateMiniCardsGrid;
// Extract custom component builders
final customVideoCard = parameters.customVideoCard;
final customAudioCard = parameters.customAudioCard;
final customMiniCard = parameters.customMiniCard;
// Initialize new components
List<List<Widget>> newComponents = [[], []];
Stream participant;
String remoteProducerId = "";
// Update number to add based on mainGridStreams length
int numToAdd = options.mainGridStreams.length;
if (options.removeAltGrid) {
updateAddAltGrid(false);
}
// Add participants to the main grid
for (int i = 0; i < numToAdd; i++) {
participant = options.mainGridStreams[i];
remoteProducerId = participant.producerId;
bool pseudoName = remoteProducerId.isEmpty;
if (pseudoName) {
remoteProducerId = participant.name ?? '';
if (participant.audioID != null && participant.audioID!.isNotEmpty) {
final actualParticipant = refParticipants.firstWhere(
(obj) => obj.audioID == participant.audioID,
orElse: () =>
Participant(id: '', name: '', videoID: '', audioID: ''),
);
// Use custom AudioCard builder if available
if (customAudioCard != null) {
newComponents[0].add(customAudioCard(
name: participant.name ?? "",
barColor: true, // This maps to the red color
textColor: Colors.white,
imageSource: "", // You may need to add actual image source
roundedImage: 1.0,
imageStyle: Colors.transparent,
parameters: parameters,
));
} else {
newComponents[0].add(AudioCard(
options: AudioCardOptions(
name: participant.name ?? "",
barColor: Colors.red,
textColor: Colors.white,
customStyle: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: eventType != EventType.broadcast
? Colors.black
: Colors.transparent,
width: eventType != EventType.broadcast ? 2.0 : 0.0,
),
),
controlsPosition: 'topLeft',
infoPosition: 'topRight',
roundedImage: true,
parameters: parameters,
backgroundColor: Colors.transparent,
showControls: eventType != EventType.chat,
participant: actualParticipant,
)));
}
} else {
// Use custom MiniCard builder if available
if (customMiniCard != null) {
newComponents[0].add(customMiniCard(
initials: participant.name ?? "",
fontSize: "20",
customStyle: false,
name: participant.name ?? "",
showVideoIcon: false,
showAudioIcon: false,
imageSource: "",
roundedImage: 1.0,
imageStyle: Colors.transparent,
parameters: parameters,
));
} else {
newComponents[0].add(
MiniCard(
options: MiniCardOptions(
initials: participant.name ?? "",
fontSize: 20,
customStyle: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: eventType != EventType.broadcast
? Colors.black
: Colors.transparent,
width: eventType != EventType.broadcast ? 2.0 : 0.0,
),
),
)),
);
}
}
} else {
if (remoteProducerId == 'youyou' || remoteProducerId == 'youyouyou') {
String name = 'You';
if (islevel == '2' && eventType != EventType.chat) {
name = 'You (Host)';
}
if (!videoAlreadyOn) {
// Use custom MiniCard builder if available
if (customMiniCard != null) {
newComponents[0].add(customMiniCard(
initials: name,
fontSize: "20",
customStyle: false,
name: name,
showVideoIcon: false,
showAudioIcon: false,
imageSource: "",
roundedImage: 1.0,
imageStyle: Colors.transparent,
parameters: parameters,
));
} else {
newComponents[0].add(
MiniCard(
options: MiniCardOptions(
initials: name,
fontSize: 20,
customStyle: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: eventType != EventType.broadcast
? Colors.black
: Colors.transparent,
width: eventType != EventType.broadcast ? 2.0 : 0.0,
),
),
)),
);
}
} else {
participant = Stream(
id: 'youyouyou',
stream: keepBackground && virtualStream != null
? virtualStream
: localStreamVideo,
name: 'youyouyou',
producerId: 'youyouyou',
);
final actualParticipant = refParticipants.firstWhere(
(obj) => obj.name == member,
orElse: () =>
Participant(id: '', name: '', videoID: '', audioID: ''),
);
// Use custom VideoCard builder if available
if (customVideoCard != null) {
newComponents[0].add(customVideoCard(
participant: actualParticipant,
stream: participant,
width: 100.0, // You may need to calculate actual width
height: 100.0, // You may need to calculate actual height
imageSize: null,
doMirror: "true",
showControls: false,
showInfo: false,
name: participant.name ?? '',
backgroundColor: Colors.transparent,
onVideoPress: null,
parameters: parameters,
));
} else {
newComponents[0].add(
VideoCard(
options: VideoCardOptions(
videoStream: participant.stream,
remoteProducerId: participant.stream?.id ?? '',
eventType: eventType,
forceFullDisplay:
eventType == EventType.webinar ? false : forceFullDisplay,
participant: actualParticipant,
backgroundColor: Colors.transparent,
showControls: false,
showInfo: false,
name: participant.name ?? '',
doMirror: true,
parameters: parameters,
)),
);
}
}
} else {
Participant? participant_ = refParticipants.firstWhere(
(obj) => obj.videoID == remoteProducerId,
orElse: () =>
Participant(id: '', name: '', videoID: '', audioID: ''),
);
if (participant_.name.isNotEmpty) {
// Use custom VideoCard builder if available
if (customVideoCard != null) {
newComponents[0].add(customVideoCard(
participant: participant_,
stream: participant,
width: 100.0, // You may need to calculate actual width
height: 100.0, // You may need to calculate actual height
imageSize: null,
doMirror: "false",
showControls: eventType != EventType.chat,
showInfo: true,
name: participant_.name,
backgroundColor: Colors.transparent,
onVideoPress: null,
parameters: parameters,
));
} else {
newComponents[0].add(VideoCard(
options: VideoCardOptions(
videoStream: participant.stream,
remoteProducerId: remoteProducerId,
eventType: eventType,
forceFullDisplay: forceFullDisplay,
participant: participant_,
backgroundColor: Colors.transparent,
showControls: eventType != EventType.chat,
showInfo: true,
name: participant_.name,
doMirror: false,
parameters: parameters,
),
));
}
}
}
}
// Update grids at the end of the loop
if (i == numToAdd - 1) {
otherGridStreams[0] = List<Widget>.from(newComponents[0]);
final optionsUpdate = UpdateMiniCardsGridOptions(
rows: options.numRows,
cols: options.numCols,
defal: true,
actualRows: options.actualRows,
parameters: parameters);
await updateMiniCardsGrid(
optionsUpdate,
);
updateOtherGridStreams(otherGridStreams);
await updateMiniCardsGrid(
optionsUpdate,
);
}
}
// Handle the alternate grid streams
if (!options.removeAltGrid) {
for (int i = 0; i < options.altGridStreams.length; i++) {
participant = options.altGridStreams[i];
remoteProducerId = participant.producerId;
bool pseudoName = remoteProducerId.isEmpty;
if (pseudoName) {
remoteProducerId = participant.name ?? '';
if (participant.audioID != null && participant.audioID!.isNotEmpty) {
final actualParticipant = refParticipants.firstWhere(
(obj) => obj.audioID == participant.audioID,
orElse: () =>
Participant(id: '', name: '', videoID: '', audioID: ''),
);
// Use custom AudioCard builder if available
if (customAudioCard != null) {
newComponents[1].add(customAudioCard(
name: participant.name ?? "",
barColor: true, // This maps to the red color
textColor: Colors.white,
imageSource: "", // You may need to add actual image source
roundedImage: 1.0,
imageStyle: Colors.transparent,
parameters: parameters,
));
} else {
newComponents[1].add(
AudioCard(
options: AudioCardOptions(
name: participant.name ?? "",
barColor: Colors.red,
textColor: Colors.white,
customStyle: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: eventType != EventType.broadcast
? Colors.black
: Colors.transparent,
width: eventType != EventType.broadcast ? 2.0 : 0.0,
),
),
controlsPosition: 'topLeft',
infoPosition: 'topRight',
roundedImage: true,
parameters: parameters,
backgroundColor: Colors.transparent,
showControls: eventType != EventType.chat,
participant: actualParticipant,
)),
);
}
} else {
// Use custom MiniCard builder if available
if (customMiniCard != null) {
newComponents[1].add(customMiniCard(
initials: participant.name ?? "",
fontSize: "20",
customStyle: false,
name: participant.name ?? "",
showVideoIcon: false,
showAudioIcon: false,
imageSource: "",
roundedImage: 1.0,
imageStyle: Colors.transparent,
parameters: parameters,
));
} else {
newComponents[1].add(
MiniCard(
options: MiniCardOptions(
initials: participant.name ?? "",
fontSize: 20,
customStyle: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: eventType != EventType.broadcast
? Colors.black
: Colors.transparent,
width: eventType != EventType.broadcast ? 2.0 : 0.0,
),
),
)),
);
}
}
} else {
Participant? participant_ = refParticipants.firstWhere(
(obj) => obj.videoID == remoteProducerId,
orElse: () =>
Participant(id: '', name: '', videoID: '', audioID: ''),
);
if (participant_.name.isNotEmpty) {
// Use custom VideoCard builder if available
if (customVideoCard != null) {
newComponents[1].add(customVideoCard(
participant: participant_,
stream: participant,
width: 100.0, // You may need to calculate actual width
height: 100.0, // You may need to calculate actual height
imageSize: null,
doMirror: "false",
showControls: eventType != EventType.chat,
showInfo: true,
name: participant_.name,
backgroundColor: Colors.transparent,
onVideoPress: null,
parameters: parameters,
));
} else {
newComponents[1].add(
VideoCard(
options: VideoCardOptions(
videoStream: participant.stream,
remoteProducerId: remoteProducerId,
eventType: eventType,
forceFullDisplay: forceFullDisplay,
participant: participant_,
backgroundColor: Colors.transparent,
showControls: eventType != EventType.chat,
showInfo: true,
name: participant_.name,
doMirror: false,
parameters: parameters,
)),
);
}
}
}
// Update alternate grid at the end of the loop
if (i == options.altGridStreams.length - 1) {
otherGridStreams[1] = List<Widget>.from(newComponents[1]);
final optionsUpdate = UpdateMiniCardsGridOptions(
rows: options.numRows,
cols: options.numCols,
defal: false,
actualRows: options.actualRows,
parameters: parameters);
await updateMiniCardsGrid(
optionsUpdate,
);
updateOtherGridStreams(otherGridStreams);
await updateMiniCardsGrid(
optionsUpdate,
);
}
}
} else {
// Remove alternate grid
parameters.updateAddAltGrid(false);
otherGridStreams[1] = <Widget>[]; // Clear the alternate grid
final optionsUpdate = UpdateMiniCardsGridOptions(
rows: 0,
cols: 0,
defal: false,
actualRows: options.actualRows,
parameters: parameters);
await updateMiniCardsGrid(
optionsUpdate,
);
updateOtherGridStreams(otherGridStreams);
await updateMiniCardsGrid(
optionsUpdate,
);
}
} catch (error) {
if (kDebugMode) {
print('Error in addVideosGrid: $error');
}
}
}