part of '../../neon_spreed.dart'; class SpreedCallPage extends StatefulWidget { const SpreedCallPage({ required this.bloc, super.key, }); final SpreedCallBloc bloc; @override State createState() => _SpreedCallPageState(); } class _SpreedCallPageState extends State { @override void initState() { widget.bloc.errors.listen((final error) { if (!mounted) { return; } NeonError.showSnackbar(context, error); }); super.initState(); } @override Widget build(final BuildContext context) => StreamBuilder( stream: widget.bloc.audioEnabled, builder: (final context, final audioEnabledSnapshot) => StreamBuilder( stream: widget.bloc.videoEnabled, builder: (final context, final videoEnabledSnapshot) => StreamBuilder( stream: widget.bloc.screenEnabled, builder: (final context, final screenEnabledSnapshot) { final audioEnabled = audioEnabledSnapshot.data ?? false; final videoEnabled = videoEnabledSnapshot.data ?? false; final screenEnabled = screenEnabledSnapshot.data ?? false; return Scaffold( appBar: AppBar( automaticallyImplyLeading: false, actions: [ IconButton( icon: Icon( audioEnabled ? MdiIcons.microphone : MdiIcons.microphoneOff, color: !audioEnabled ? Colors.red : null, ), onPressed: () { widget.bloc.changeAudio(!audioEnabled); }, ), IconButton( icon: Icon( videoEnabled ? MdiIcons.video : MdiIcons.videoOff, color: !videoEnabled ? Colors.red : null, ), onPressed: () { widget.bloc.changeVideo(!videoEnabled); }, ), IconButton( icon: Icon( screenEnabled ? MdiIcons.monitorShare : MdiIcons.monitorOff, color: !screenEnabled ? Colors.red : null, ), onPressed: () async { if (!screenEnabled) { final result = await showDialog( context: context, builder: (final context) => const SpreedSelectScreenDialog(), ); if (result == null) { return; } } widget.bloc.changeScreen(!screenEnabled); }, ), SpreedCallButton( type: SpreedCallButtonType.leaveCall, onPressed: () { Navigator.of(context).pop(); }, ), ] .intersperse( const SizedBox( width: 20, ), ) .toList(), ), body: StreamBuilder( stream: widget.bloc.remoteParticipants, builder: (final context, final remoteParticipantsSnapshot) { if (remoteParticipantsSnapshot.data == null) { return Center( child: LayoutBuilder( builder: (final context, final constraints) => SizedBox( width: constraints.maxWidth / 2, child: const NeonLinearProgressIndicator(), ), ), ); } final participants = [ ...remoteParticipantsSnapshot.requireData, widget.bloc.localParticipant, ]; return Center( child: LayoutBuilder( builder: (final context, final constraints) { final viewSize = calculateViewSize(participants.length, constraints.biggest); return Wrap( alignment: WrapAlignment.center, children: [ for (final participant in participants) ...[ Container( constraints: BoxConstraints( maxWidth: viewSize.width, maxHeight: viewSize.height, ), child: SpreedCallParticipantView( participant: participant, localAudioEnabled: audioEnabled, localVideoEnabled: videoEnabled, localScreenEnabled: screenEnabled, ), ), ], ], ); }, ), ); }, ), ); }, ), ), ); }