Full functional call

This commit is contained in:
2024-06-01 20:18:25 +08:00
parent 508cba8ed3
commit 5c625fc15a
19 changed files with 1934 additions and 19 deletions

View File

@ -0,0 +1,101 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/providers/content/call.dart';
import 'package:solian/widgets/chat/call/call_controls.dart';
import 'package:solian/widgets/chat/call/call_participant.dart';
class CallScreen extends StatefulWidget {
const CallScreen({super.key});
@override
State<CallScreen> createState() => _CallScreenState();
}
class _CallScreenState extends State<CallScreen> {
@override
void initState() {
Get.find<ChatCallProvider>().setupRoom();
super.initState();
}
@override
Widget build(BuildContext context) {
final ChatCallProvider provider = Get.find();
return Material(
color: Theme.of(context).colorScheme.surface,
child: SafeArea(
top: false,
child: Obx(
() => Stack(
children: [
Column(
children: [
Expanded(
child: Container(
color: Theme.of(context).colorScheme.surfaceContainer,
child: provider.focusTrack.value != null
? InteractiveParticipantWidget(
isFixed: false,
participant: provider.focusTrack.value!,
onTap: () {},
)
: const SizedBox(),
),
),
if (provider.room.localParticipant != null)
ControlsWidget(
provider.room,
provider.room.localParticipant!,
),
],
),
Positioned(
left: 0,
right: 0,
top: 0,
child: SizedBox(
height: 128,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: math.max(0, provider.participantTracks.length),
itemBuilder: (BuildContext context, int index) {
final track = provider.participantTracks[index];
if (track.participant.sid ==
provider.focusTrack.value?.participant.sid) {
return Container();
}
return Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: ClipRRect(
borderRadius:
const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget(
isFixed: true,
width: 120,
height: 120,
color: Theme.of(context).cardColor,
participant: track,
onTap: () {
if (track.participant.sid !=
provider.focusTrack.value?.participant.sid) {
provider.changeFocusTrack(track);
}
},
),
),
);
},
),
),
),
],
),
),
),
);
}
}

View File

@ -11,10 +11,12 @@ import 'package:solian/models/packet.dart';
import 'package:solian/models/pagination.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/providers/chat.dart';
import 'package:solian/providers/content/call.dart';
import 'package:solian/providers/content/channel.dart';
import 'package:solian/router.dart';
import 'package:solian/services.dart';
import 'package:solian/theme.dart';
import 'package:solian/widgets/chat/call/call_prejoin.dart';
import 'package:solian/widgets/chat/call/chat_call_action.dart';
import 'package:solian/widgets/chat/chat_message.dart';
import 'package:solian/widgets/chat/chat_message_action.dart';
@ -177,6 +179,17 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
return a.createdAt.difference(b.createdAt).inMinutes <= 3;
}
void showCallPrejoin() {
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) => ChatCallPrejoinPopup(
ongoingCall: _ongoingCall!,
channel: _channel!,
),
);
}
Message? _messageToReplying;
Message? _messageToEditing;
@ -238,7 +251,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
@override
Widget build(BuildContext context) {
if (_isBusy) {
if (_isBusy || _channel == null) {
return const Center(
child: CircularProgressIndicator(),
);
@ -257,6 +270,8 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
);
}
final ChatCallProvider call = Get.find();
return Scaffold(
appBar: AppBar(
title: Text(title),
@ -335,18 +350,37 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
),
),
if (_ongoingCall != null)
MaterialBanner(
padding: const EdgeInsets.only(left: 10, right: 20),
leading: const Icon(Icons.call_received),
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
dividerColor: const Color.fromARGB(1, 0, 0, 0),
content: Text('callOngoing'.tr),
actions: [
TextButton(
child: Text('callJoin'.tr),
onPressed: () {},
),
],
Positioned(
top: 0,
left: 0,
right: 0,
child: MaterialBanner(
padding: const EdgeInsets.only(left: 16, top: 4, bottom: 4),
leading: const Icon(Icons.call_received),
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
dividerColor: Colors.transparent,
content: Text('callOngoing'.tr),
actions: [
Obx(() {
if (call.current.value == null) {
return TextButton(
onPressed: showCallPrejoin,
child: Text('callJoin'.tr),
);
} else if (call.channel.value?.id == _channel?.id) {
return TextButton(
onPressed: () => call.gotoScreen(context),
child: Text('callResume'.tr),
);
} else {
return TextButton(
onPressed: null,
child: Text('callJoin'.tr),
);
}
})
],
),
),
],
),