fluffychat/lib/pages/dialer/group_call_view.dart
2022-06-28 16:20:06 +05:30

167 lines
5.2 KiB
Dart

import 'package:fluffychat/utils/voip/group_call_state.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:matrix/matrix.dart';
class GroupCallView extends StatefulWidget {
final GroupCallSessionState call;
const GroupCallView({
Key? key,
required this.call,
}) : super(key: key);
@override
State<GroupCallView> createState() => _GroupCallViewState();
}
class _GroupCallViewState extends State<GroupCallView> {
WrappedMediaStream? get primaryStream => widget.call.primaryStream;
List<WrappedMediaStream> get screenSharingStreams =>
widget.call.screenSharingStreams;
List<WrappedMediaStream> get userMediaStreams => widget.call.userMediaStreams;
WrappedMediaStream? get primaryScreenShare =>
widget.call.screenSharingStreams.first;
void updateStreams() {
Logs().i('Group calls, updating streams');
widget.call.groupCall.onStreamAdd.stream.listen((event) {
if (event.purpose == SDPStreamMetadataPurpose.Usermedia) {
if (userMediaStreams.indexWhere((element) => element == event) == -1) {
setState(() {
userMediaStreams.add(event);
});
}
} else if (event.purpose == SDPStreamMetadataPurpose.Screenshare) {
if (screenSharingStreams.indexWhere((element) => element == event) ==
-1) {
setState(() {
screenSharingStreams.add(event);
});
}
}
});
widget.call.groupCall.onStreamRemoved.stream.listen((event) {
if (event.purpose == SDPStreamMetadataPurpose.Usermedia) {
userMediaStreams
.removeWhere((element) => element.stream!.id == event.stream!.id);
setState(() {
userMediaStreams.remove(event);
});
} else if (event.purpose == SDPStreamMetadataPurpose.Screenshare) {
screenSharingStreams
.removeWhere((element) => element.stream!.id == event.stream!.id);
setState(() {
screenSharingStreams.remove(event);
});
}
});
}
@override
void initState() {
updateStreams();
super.initState();
}
@override
Widget build(BuildContext context) {
Logs().e('Group call state: ' + widget.call.groupCall.state);
Logs().e('Group call state: ' +
widget.call.groupCall.participants.length.toString());
if (screenSharingStreams.isNotEmpty) {
return Center(
child: ListView(
children: [
RTCVideoView(
primaryScreenShare!.renderer as RTCVideoRenderer,
mirror: primaryScreenShare!.isLocal(),
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
),
const SizedBox(
height: 100,
),
CallGrid(
call: widget.call,
screenSharing: true,
userMediaStreams: userMediaStreams,
),
],
),
);
} else {
// No one is screen sharing, show avatars and user streams here
return Center(
child: CallGrid(
call: widget.call,
screenSharing: false,
userMediaStreams: userMediaStreams,
),
);
}
}
}
class CallGrid extends StatefulWidget {
final GroupCallSessionState call;
final bool screenSharing;
final List<WrappedMediaStream> userMediaStreams;
const CallGrid(
{Key? key,
required this.call,
required this.screenSharing,
required this.userMediaStreams})
: super(key: key);
@override
State<CallGrid> createState() => _CallGridState();
}
class _CallGridState extends State<CallGrid> {
@override
Widget build(BuildContext context) {
final client = Matrix.of(context).client;
return GridView.builder(
itemCount: widget.call.groupCall.participants.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: widget.screenSharing ? 4 : 2),
itemBuilder: (context, index) {
final participant = widget.call.groupCall.participants[index];
Logs().e('Group calls participants - ' +
participant.displayName.toString());
if (widget.userMediaStreams
.map((stream) => stream.userId)
.contains(participant.id)) {
return Container(
color: Colors.amber,
child: RTCVideoView(
widget.userMediaStreams
.firstWhere((element) => element.userId == participant.id)
.renderer as RTCVideoRenderer,
mirror: false,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
),
);
} else {
return Center(
child: Container(
height: 200,
width: 200,
color: Colors.red,
child: Avatar(
mxContent: participant.avatarUrl,
name: participant.displayName,
size: 24,
client: client,
),
),
);
}
});
}
}