Appbar in call

This commit is contained in:
LittleSheep 2024-06-02 15:08:11 +08:00
parent 8271852867
commit bece579f9d
2 changed files with 103 additions and 62 deletions

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -5,6 +6,7 @@ import 'package:get/get.dart';
import 'package:solian/providers/content/call.dart'; import 'package:solian/providers/content/call.dart';
import 'package:solian/widgets/chat/call/call_controls.dart'; import 'package:solian/widgets/chat/call/call_controls.dart';
import 'package:solian/widgets/chat/call/call_participant.dart'; import 'package:solian/widgets/chat/call/call_participant.dart';
import 'package:solian/widgets/prev_page.dart';
class CallScreen extends StatefulWidget { class CallScreen extends StatefulWidget {
const CallScreen({super.key}); const CallScreen({super.key});
@ -14,6 +16,24 @@ class CallScreen extends StatefulWidget {
} }
class _CallScreenState extends State<CallScreen> { class _CallScreenState extends State<CallScreen> {
String parseDuration() {
final ChatCallProvider provider = Get.find();
if (provider.current.value == null) return '00:00:00';
Duration duration =
DateTime.now().difference(provider.current.value!.createdAt);
String twoDigits(int n) => n.toString().padLeft(2, '0');
String formattedTime = "${twoDigits(duration.inHours)}:"
"${twoDigits(duration.inMinutes.remainder(60))}:"
"${twoDigits(duration.inSeconds.remainder(60))}";
Timer.periodic(const Duration(seconds: 1), (_) {
setState(() {});
});
return formattedTime;
}
@override @override
void initState() { void initState() {
Get.find<ChatCallProvider>().setupRoom(); Get.find<ChatCallProvider>().setupRoom();
@ -26,73 +46,92 @@ class _CallScreenState extends State<CallScreen> {
return Material( return Material(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
child: SafeArea( child: Scaffold(
top: false, appBar: AppBar(
child: Obx( title: RichText(
() => Stack( textAlign: TextAlign.center,
children: [ text: TextSpan(children: [
Column( TextSpan(
children: [ text: 'call'.tr,
Expanded( style: Theme.of(context).textTheme.titleLarge,
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( const TextSpan(text: "\n"),
left: 0, TextSpan(
right: 0, text: parseDuration(),
top: 0, style: Theme.of(context).textTheme.bodySmall,
child: SizedBox( ),
height: 128, ]),
child: ListView.builder( ),
scrollDirection: Axis.horizontal, leading: const PrevPageButton(),
itemCount: math.max(0, provider.participantTracks.length), ),
itemBuilder: (BuildContext context, int index) { body: SafeArea(
final track = provider.participantTracks[index]; child: Obx(
if (track.participant.sid == () => Stack(
provider.focusTrack.value?.participant.sid) { children: [
return Container(); 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( return Padding(
padding: const EdgeInsets.only(top: 8, left: 8), padding: const EdgeInsets.only(top: 8, left: 8),
child: ClipRRect( child: ClipRRect(
borderRadius: borderRadius:
const BorderRadius.all(Radius.circular(8)), const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget( child: InteractiveParticipantWidget(
isFixed: true, isFixed: true,
width: 120, width: 120,
height: 120, height: 120,
color: Theme.of(context).cardColor, color: Theme.of(context).cardColor,
participant: track, participant: track,
onTap: () { onTap: () {
if (track.participant.sid != if (track.participant.sid !=
provider.focusTrack.value?.participant.sid) { provider
provider.changeFocusTrack(track); .focusTrack.value?.participant.sid) {
} provider.changeFocusTrack(track);
}, }
},
),
), ),
), );
); },
}, ),
), ),
), ),
), ],
], ),
), ),
), ),
), ),

View File

@ -153,6 +153,7 @@ class SolianMessages extends Translations {
'messageDeletionConfirm': 'Confirm message deletion', 'messageDeletionConfirm': 'Confirm message deletion',
'messageDeletionConfirmCaption': 'messageDeletionConfirmCaption':
'Are your sure to delete message @id? This action cannot be undone!', 'Are your sure to delete message @id? This action cannot be undone!',
'call': 'Call',
'callOngoing': 'A call is ongoing...', 'callOngoing': 'A call is ongoing...',
'callJoin': 'Join', 'callJoin': 'Join',
'callResume': 'Resume', 'callResume': 'Resume',
@ -322,6 +323,7 @@ class SolianMessages extends Translations {
'messageActionList': '消息的操作', 'messageActionList': '消息的操作',
'messageDeletionConfirm': '确认删除消息', 'messageDeletionConfirm': '确认删除消息',
'messageDeletionConfirmCaption': '你确定要删除消息 @id 吗?该操作不可撤销。', 'messageDeletionConfirmCaption': '你确定要删除消息 @id 吗?该操作不可撤销。',
'call': '通话',
'callOngoing': '一则通话正在进行中…', 'callOngoing': '一则通话正在进行中…',
'callJoin': '加入', 'callJoin': '加入',
'callResume': '恢复', 'callResume': '恢复',