Reactions during Live Stream - Flutter
To enhance interaction between viewers and speakers during a livestream, a creative approach is to display viewers' reactions to everyone. This can be achieved by creating a lively atmosphere with flying emojis, similar to the experience seen in livestreams on platforms like Instagram.
This guide explains how to implement this engaging feature using the VideoSDK PubSub mechanism.
Step 1: Creating a button to send reaction
To implement this functionality, start by creating a button that sends reactions to all users. When this button is clicked, publish a message with the emoji name to all participants using the VideoSDK PubSub mechanism.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ReactionSender extends StatelessWidget {
final Room room;
const ReactionSender({required this.room});
void sendReaction(BuildContext context, String reaction) {
// Show local emoji immediately
showEmoji(context, reaction);
// Send reaction to others
room.pubSub.publish(
"REACTION",
reaction,
const PubSubPublishOptions(persist: false),
);
}
void showEmoji(BuildContext context, String reaction) {
final overlay = Overlay.of(context);
final emojiEntry = OverlayEntry(
builder: (context) => FlyingEmojiWidget(emoji: reaction),
);
overlay.insert(emojiEntry);
Future.delayed(const Duration(seconds: 3), () => emojiEntry.remove());
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => sendReaction(context, "😍"),
child: const Text("Send Reaction"),
);
}
}
class FlyingEmojiWidget extends StatefulWidget {
final String emoji;
const FlyingEmojiWidget({required this.emoji});
@override
State<FlyingEmojiWidget> createState() => _FlyingEmojiWidgetState();
}
class _FlyingEmojiWidgetState extends State<FlyingEmojiWidget>
with SingleTickerProviderStateMixin {
late final AnimationController _controller;
late final Animation<Offset> _animation;
final Random random = Random();
@override
void initState() {
super.initState();
final dx = random.nextDouble() * 2 - 1; // random horizontal direction
final startOffset = Offset(dx, 1.2); // start off bottom
final endOffset = Offset(dx, -0.2); // move to top
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 3000),
);
_animation = Tween<Offset>(
begin: startOffset,
end: endOffset,
).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut));
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Positioned.fill(
child: SlideTransition(
position: _animation,
child: Align(
alignment: Alignment.center,
child: Text(widget.emoji, style: const TextStyle(fontSize: 40)),
),
),
);
}
}
Step 2: Displaying the Reactions to all the users
FlyingEmojiWidget
will be utilized to display the reactions on the screen. Listen to the browser event sent on the button click to show the flying emoji and display all reactions sent by other participants
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ReactionListener extends StatefulWidget {
final Room room;
const ReactionListener({required this.room});
@override
State<ReactionListener> createState() => _ReactionListenerState();
}
class _ReactionListenerState extends State<ReactionListener> {
@override
void initState() {
super.initState();
widget.room.pubSub.subscribe("REACTION", handleReaction);
}
@override
void dispose() {
widget.room.pubSub.unsubscribe("REACTION", handleReaction);
super.dispose();
}
void handleReaction(PubSubMessage message) {
final reaction = message.message;
showEmoji(context, reaction);
}
void showEmoji(BuildContext context, String emoji) {
final overlay = Overlay.of(context);
final emojiEntry = OverlayEntry(
builder: (context) => FlyingEmojiWidget(emoji: emoji),
);
overlay.insert(emojiEntry);
Future.delayed(const Duration(seconds: 3), () => emojiEntry.remove());
}
@override
Widget build(BuildContext context) {
return const SizedBox();
}
}
API Reference
The API references for all the methods and events utilized in this guide are provided below.
Got a Question? Ask us on discord