You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
5.5 KiB
145 lines
5.5 KiB
part of '../../neon_spreed.dart'; |
|
|
|
class SpreedCallPage extends StatefulWidget { |
|
const SpreedCallPage({ |
|
required this.bloc, |
|
super.key, |
|
}); |
|
|
|
final SpreedCallBloc bloc; |
|
|
|
@override |
|
State<SpreedCallPage> createState() => _SpreedCallPageState(); |
|
} |
|
|
|
class _SpreedCallPageState extends State<SpreedCallPage> { |
|
@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: <Widget>[ |
|
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<DesktopCapturerSource>( |
|
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, |
|
), |
|
), |
|
], |
|
], |
|
); |
|
}, |
|
), |
|
); |
|
}, |
|
), |
|
); |
|
}, |
|
), |
|
), |
|
); |
|
}
|
|
|