mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-04-20 08:57:51 +02:00
167 lines
5.2 KiB
Dart
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,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
});
|
|
}
|
|
}
|