A framework for building convergent cross-platform Nextcloud clients using Flutter.
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.

146 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,
),
),
],
],
);
},
),
);
},
),
);
},
),
),
);
}