enum SfuConnectionQuality {
unspecified,
poor,
good,
excellent,
}Connection Unstable
When a participant's network connection becomes unstable, you can provide visual feedback in two ways: warning users when their connection quality degrades, and showing a reconnecting indicator when the connection drops entirely.
Poor Connection Quality Warning
As described in the Network Quality Indicator guide, each participant's connection quality is available through the connectionQuality property on CallParticipantState.
The connection quality can have the following values:
To warn the local participant when their connection is poor, you can build a custom participant widget that overlays a notification banner:
class ConnectionAwareParticipant extends StatelessWidget {
const ConnectionAwareParticipant({
super.key,
required this.call,
required this.participant,
});
final Call call;
final CallParticipantState participant;
@override
Widget build(BuildContext context) {
return Stack(
children: [
StreamCallParticipant(
call: call,
participant: participant,
),
if (participant.isLocal &&
participant.connectionQuality == SfuConnectionQuality.poor)
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
color: Colors.orange.shade400.withValues(alpha: .85),
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.signal_wifi_bad, color: Colors.white, size: 16),
SizedBox(width: 8),
Text(
'Your connection is unstable',
style: TextStyle(color: Colors.white, fontSize: 12),
),
],
),
),
),
],
);
}
}Then pass it to StreamCallParticipants via the callParticipantBuilder:
StreamCallContent(
call: call,
callParticipantsWidgetBuilder: (context, call) {
return StreamCallParticipants(
call: call,
callParticipantBuilder: (context, call, participant) {
return ConnectionAwareParticipant(
call: call,
participant: participant,
);
},
);
},
)Best Practices
- Only show the warning for
SfuConnectionQuality.poorto avoid notification fatigue. - Consider showing the banner only for the local participant — they can act on their own connection issues, while other participants' quality indicators are already visible through the network quality indicator.
Reconnection State
When the connection drops entirely, the SDK automatically attempts to reconnect. The reconnection state is available through CallState.status. It transitions to CallStatusReconnecting during reconnection attempts.
You can check for this state using call.state:
final status = call.state.value.status;
if (status.isReconnecting) {
// Connection dropped, SDK is reconnecting
}Listening to Reconnection State
To reactively rebuild your UI when the reconnection state changes, use the partialState stream or the PartialCallStateBuilder widget:
PartialCallStateBuilder<CallStatus>(
call: call,
selector: (state) => state.status,
builder: (context, status) {
if (status.isReconnecting) {
return const Center(child: Text('Reconnecting...'));
}
return const SizedBox.shrink();
},
)Displaying a Reconnecting Overlay
For a better user experience, you can display a full-screen overlay during reconnection. StreamCallContent supports this through the callNotConnectedBuilder and callFastReconnectingOverlayBuilder parameters.
Customizing the Not-Connected View
When the connection is fully lost (non-fast reconnect), StreamCallContent shows a fallback view. You can customize it with callNotConnectedBuilder:
StreamCallContent(
call: call,
callNotConnectedBuilder: (context, properties) {
if (properties.isReconnecting) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const CircularProgressIndicator(color: Colors.white),
const SizedBox(height: 16),
Text(
'Reconnecting to call...',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(color: Colors.white),
),
],
),
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
)Customizing the Fast-Reconnect Overlay
During a fast reconnect (a brief interruption where participants remain visible), a small indicator is shown. You can customize it with callFastReconnectingOverlayBuilder:
StreamCallContent(
call: call,
callFastReconnectingOverlayBuilder: (context, properties) {
return Positioned(
top: 16,
left: 0,
right: 0,
child: Center(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.orange.shade800,
borderRadius: BorderRadius.circular(20),
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.white,
),
),
SizedBox(width: 8),
Text(
'Reconnecting...',
style: TextStyle(color: Colors.white, fontSize: 13),
),
],
),
),
),
);
},
)Built-in Support
The SDK's StreamCallContent automatically handles both reconnection states out of the box:
- During a full reconnect, it displays a centered "Reconnecting" label.
- During a fast reconnect, it shows a small
CircularProgressIndicatorin the top-left corner while keeping participants visible.
If you're using the default StreamCallContent, reconnection feedback is handled automatically without any additional configuration.