Invite Guest on Stage - Flutter
In this guide, we will see how you can request a viewer to join your livestream by using the changeMode()
.
Before going forward in this guide, do make sure all the attendees join the meeting with mode as VIEWER
and the host joins with mode as CONFERENCE
Let's first have a look at how we will be using the PubSub
mechanism to acheive the requesting and switching of the participant's mode.
Step 1: Loading Viewer List
The host will see a list of participants who have joined as VIEWER
along with a button that, when selected, will invite that user to join the livestream.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class SpeakerScreen extends StatefulWidget {
...
}
class _SpeakerScreenState extends State<SpeakerScreen> {
late Room room;
Map<String, Participant> _attendees = {};
@override
void initState() {
...
updateAttendees();
setupRoomEventListener();
}
@override
Widget build(BuildContext context) {
return Column(
children:[
//button which will show viewers list
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: ListView.builder(
itemCount: viewers.values.length,
itemBuilder: (builderContext, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Text(viewers.values
.elementAt(index)
.displayName)),
ElevatedButton(
onPressed: () {
},
child: Text("Invite on Stage")),
],
),
);
}),
));
},
child: const Text("Invite Viewer on Stage"),
),
...
]
);
}
void updateAttendees(){
Map<String, Participant> attendees = {};
if(room.localParticipant.mode == Mode.VIEWER);
attendees.putIfAbsent(
room.localParticipant.id, () => room.localParticipant);
room.participants.values.forEach((participant) {
if (participant.mode == Mode.VIEWER) {
attendees.putIfAbsent(participant.id, () => participant);
}
});
setState(()=>_attendees = attendees);
}
void setupRoomEventListener() {
room.on(Events.roomJoined, () {
updateAttendees();
});
room.on(Events.participantModeChanged, (Map<String, dynamic> data){
updateAttendees()
});
room.on(Events.participantJoined, (Participant participant) {
updateAttendees();
});
room.on(Events.participantLeft, (String participantId) {
updateAttendees();
});
}
}
Step 2: Requesting a Viewer to Join Livestream
We have a Viewer list ready. Now, let us handle the click event for the Join Livestream button.
We will be using CHANGE_MODE_$participantId
as the topic for PubSub.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class SpeakerScreen extends StatefulWidget {
...
}
class _SpeakerScreenState extends State<SpeakerScreen> {
late Room room;
Map<String, Participant> _attendees = {};
@override
void initState() {
...
}
@override
Widget build(BuildContext context) {
return Column(
children:[
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: ListView.builder(
itemCount: viewers.values.length,
itemBuilder: (builderContext, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Text(viewers.values
.elementAt(index)
.displayName)),
ElevatedButton(
onPressed: () {
//Publish the message on CHANGE_MODE_$participantId to join
widget.room.pubSub.publish(
"CHANGE_MODE_${viewers.values.elementAt(index).id}",
"VIEWER");
},
child: Text("Invite on Stage")),
],
),
);
}),
));
},
child: const Text("Invite Viewer on Stage"),
),
...
]
);
}
void updateAttendees(){
...
}
void setupRoomEventListener() {
...
}
}
Step 3: Showing Viewer Request Dialog
After implementing the Host requesting viewer to join the livestream, let's display the viewer's request dialogue and switch the VIEWER
mode to CONFERENCE
.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:videosdk/videosdk.dart';
import './livestream_player.dart';
class ILSViewerView extends StatefulWidget {
final Room room;
...
}
class _ILSViewerViewState extends State<ILSViewerView> {
@override
void initState() {
super.initState();
//subscribe to the change mode reequest topic
widget.room.pubSub.subscribe(
"CHANGE_MODE_${widget.room.localParticipant.id}",
changeModeRequestHandler);
}
//show dialog to accept or reject when change mode requested by speaker
void changeModeRequestHandler(PubSubMessage message) {
if (mounted) {
showDialog(
context: this.context,
builder: (context) {
return AlertDialog(
actions: [
ElevatedButton(
onPressed: () {
widget.room.changeMode(Mode.CONFERENCE);
Navigator.of(context).pop();
},
child: const Text("Accept"),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("Reject"),
)
],
content:
Text("${message.senderName} requestd you to join livestream"),
);
});
}
}
@override
Widget build(BuildContext context) {
return YourViewerWidget;
}
@override
void dispose() {
widget.room.pubSub.unsubscribe(
"CHANGE_MODE_${widget.room.localParticipant.id}",
changeModeRequestHandler);
super.dispose();
}
}
Step 4: Pin the participant
We need to pin the participant so that he/she can appears on the livestream. To achieve this, we will listen to the callback on the participantModeChanged
of Room
object. Here, we are already calling the updateAttendees()
which we will update to pin only the CONFERENCE
mode participants.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class SpeakerScreen extends StatefulWidget {
...
}
class _SpeakerScreenState extends State<SpeakerScreen> {
late Room room;
Map<String, Participant> _attendees = {};
@override
void initState() {
...
}
@override
Widget build(BuildContext context) {
return Column(
children:[
...
]
);
}
void updateAttendees(){
Map<String, Participant> attendees = {};
//we will pin localparticiant if mode is CONFERENCE
if(room.localParticipant.mode == Mode.VIEWER);{
attendees.putIfAbsent(
room.localParticipant.id, () => room.localParticipant);
room.localParticipant.unpin();
}else{
room.localParticipant.pin();
}
room.participants.values.forEach((participant) {
if (participant.mode == Mode.VIEWER) {
attendees.putIfAbsent(participant.id, () => participant);
participant.unpin();
}
});
setState(()=>_attendees = attendees);
}
}
API Reference
The API references for all the methods utilized in this guide are provided below.
Got a Question? Ask us on discord