Solian/lib/screens/chat/call.dart

186 lines
5.5 KiB
Dart
Raw Normal View History

2024-04-26 17:36:54 +00:00
import 'package:flutter/material.dart';
2024-04-27 05:12:26 +00:00
import 'package:livekit_client/livekit_client.dart';
2024-04-26 17:36:54 +00:00
import 'package:provider/provider.dart';
import 'package:solian/models/call.dart';
2024-04-30 12:31:54 +00:00
import 'package:solian/providers/chat.dart';
2024-04-28 11:36:06 +00:00
import 'package:solian/widgets/chat/call/controls.dart';
2024-04-27 05:12:26 +00:00
import 'package:solian/widgets/chat/call/participant.dart';
import 'package:solian/widgets/chat/call/participant_menu.dart';
2024-04-26 17:36:54 +00:00
import 'package:solian/widgets/indent_wrapper.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
2024-04-27 05:12:26 +00:00
import 'dart:math' as math;
2024-04-26 17:36:54 +00:00
class ChatCall extends StatefulWidget {
final Call call;
const ChatCall({super.key, required this.call});
@override
State<ChatCall> createState() => _ChatCallState();
}
class _ChatCallState extends State<ChatCall> {
2024-04-30 12:31:54 +00:00
bool _isHandled = false;
2024-04-27 05:12:26 +00:00
2024-04-30 12:31:54 +00:00
late ChatProvider _chat;
2024-04-28 13:49:03 +00:00
2024-04-30 12:31:54 +00:00
ChatCallInstance get _call => _chat.call!;
2024-04-27 05:12:26 +00:00
2024-04-30 12:31:54 +00:00
@override
void initState() {
super.initState();
2024-04-27 16:21:16 +00:00
2024-04-30 12:31:54 +00:00
WidgetsBinding.instance.addPostFrameCallback((_) {
_chat.setShown(true);
2024-04-27 05:12:26 +00:00
});
}
2024-04-30 12:31:54 +00:00
@override
Widget build(BuildContext context) {
_chat = context.watch<ChatProvider>();
if (!_isHandled) {
_isHandled = true;
if (_chat.handleCall(widget.call, widget.call.channel)) {
_chat.call?.init();
2024-04-27 05:12:26 +00:00
}
}
2024-04-30 12:31:54 +00:00
Widget content;
if (_chat.call == null) {
content = const Center(
child: CircularProgressIndicator(),
);
2024-04-27 05:12:26 +00:00
} else {
2024-04-30 12:31:54 +00:00
content = FutureBuilder(
future: _call.exchangeToken(context),
2024-04-26 17:36:54 +00:00
builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.data == null) {
return const Center(child: CircularProgressIndicator());
}
2024-04-27 05:12:26 +00:00
return Stack(
children: [
Column(
children: [
Expanded(
2024-04-27 16:07:32 +00:00
child: Container(
color: Theme.of(context).colorScheme.surfaceVariant,
2024-04-30 12:31:54 +00:00
child: _call.focusTrack != null
? InteractiveParticipantWidget(
2024-04-30 12:31:54 +00:00
isFixed: false,
participant: _call.focusTrack!,
onTap: () {},
)
2024-04-27 16:07:32 +00:00
: Container(),
),
2024-04-27 05:12:26 +00:00
),
2024-04-30 12:31:54 +00:00
if (_call.room.localParticipant != null)
ControlsWidget(
_call.room,
_call.room.localParticipant!,
),
2024-04-27 05:12:26 +00:00
],
),
Positioned(
left: 0,
right: 0,
top: 0,
child: SizedBox(
height: 128,
2024-04-27 05:12:26 +00:00
child: ListView.builder(
scrollDirection: Axis.horizontal,
2024-04-30 12:31:54 +00:00
itemCount: math.max(0, _call.participantTracks.length),
itemBuilder: (BuildContext context, int index) {
2024-04-30 12:31:54 +00:00
final track = _call.participantTracks[index];
2024-05-01 09:37:34 +00:00
if (track.participant.sid ==
_call.focusTrack?.participant.sid) {
return Container();
}
return Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: ClipRRect(
2024-05-01 09:37:34 +00:00
borderRadius:
const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget(
2024-04-30 12:31:54 +00:00
isFixed: true,
width: 120,
height: 120,
color: Theme.of(context).cardColor,
participant: track,
onTap: () {
2024-05-01 09:37:34 +00:00
if (track.participant.sid !=
_call.focusTrack?.participant.sid) {
2024-04-30 12:31:54 +00:00
_call.changeFocusTrack(track);
}
},
),
2024-04-27 16:21:16 +00:00
),
);
},
2024-04-27 05:12:26 +00:00
),
),
),
],
);
2024-04-26 17:36:54 +00:00
},
2024-04-30 12:31:54 +00:00
);
}
return IndentWrapper(
title: AppLocalizations.of(context)!.chatCall,
hideDrawer: true,
child: content,
2024-04-26 17:36:54 +00:00
);
}
2024-04-27 05:12:26 +00:00
@override
void deactivate() {
2024-04-30 12:31:54 +00:00
WidgetsBinding.instance.addPostFrameCallback((_) => _chat.setShown(false));
2024-04-27 05:12:26 +00:00
super.deactivate();
}
2024-04-26 17:36:54 +00:00
}
class InteractiveParticipantWidget extends StatelessWidget {
final double? width;
final double? height;
final Color? color;
2024-04-30 12:37:08 +00:00
final bool isFixed;
final ParticipantTrack participant;
final Function() onTap;
const InteractiveParticipantWidget({
super.key,
this.width,
this.height,
this.color,
2024-04-29 12:22:06 +00:00
this.isFixed = false,
required this.participant,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return InkWell(
child: Container(
width: width,
height: height,
color: color,
2024-04-30 12:37:08 +00:00
child: ParticipantWidget.widgetFor(participant, isFixed: isFixed),
),
onTap: () => onTap(),
onLongPress: () {
if (participant.participant is LocalParticipant) return;
showModalBottomSheet(
context: context,
builder: (context) => ParticipantMenu(
participant: participant.participant as RemoteParticipant,
videoTrack: participant.videoTrack,
isScreenShare: participant.isScreenShare,
),
);
},
);
}
}