Call in same screen on large screen

This commit is contained in:
2024-08-20 01:10:15 +08:00
parent c82c48dfec
commit 253cd1ecbd
10 changed files with 265 additions and 189 deletions

View File

@@ -9,14 +9,20 @@ import 'package:solian/models/call.dart';
import 'package:solian/models/channel.dart';
import 'package:solian/platform.dart';
import 'package:solian/providers/call.dart';
import 'package:solian/theme.dart';
import 'package:solian/widgets/chat/call/call_prejoin.dart';
class ChannelCallIndicator extends StatelessWidget {
final Channel channel;
final Call ongoingCall;
final Function onJoin;
const ChannelCallIndicator(
{super.key, required this.channel, required this.ongoingCall});
const ChannelCallIndicator({
super.key,
required this.channel,
required this.ongoingCall,
required this.onJoin,
});
void _showCallPrejoin(BuildContext context) {
showModalBottomSheet(
@@ -40,48 +46,72 @@ class ChannelCallIndicator extends StatelessWidget {
dividerColor: Colors.transparent,
content: Row(
children: [
if (ongoingCall.participants.isEmpty) Text('callOngoingEmpty'.tr),
if (ongoingCall.participants.isNotEmpty)
Text('callOngoingParticipants'.trParams({
'count': ongoingCall.participants.length.toString(),
})),
Obx(() {
if (call.isInitialized.value) {
return Text('callOngoingJoined'.trParams({
'duration': call.lastDuration.value,
}));
} else if (ongoingCall.participants.isEmpty) {
return Text('callOngoingEmpty'.tr);
} else {
return Text('callOngoingParticipants'.trParams({
'count': ongoingCall.participants.length.toString(),
}));
}
}),
const SizedBox(width: 6),
if (ongoingCall.participants.isNotEmpty)
Container(
height: 28,
constraints: const BoxConstraints(maxWidth: 120),
child: AvatarStack(
Obx(() {
if (call.isInitialized.value) {
return const SizedBox();
}
if (ongoingCall.participants.isNotEmpty) {
return Container(
height: 28,
borderWidth: 0,
avatars: ongoingCall.participants.map((x) {
final userinfo = Account.fromJson(jsonDecode(x['metadata']));
return PlatformInfo.canCacheImage
? CachedNetworkImageProvider(userinfo.avatar)
as ImageProvider
: NetworkImage(userinfo.avatar) as ImageProvider;
}).toList(),
),
),
constraints: const BoxConstraints(maxWidth: 120),
child: AvatarStack(
height: 28,
borderWidth: 0,
avatars: ongoingCall.participants.map((x) {
final userinfo =
Account.fromJson(jsonDecode(x['metadata']));
return PlatformInfo.canCacheImage
? CachedNetworkImageProvider(userinfo.avatar)
as ImageProvider
: NetworkImage(userinfo.avatar) as ImageProvider;
}).toList(),
),
);
}
return const SizedBox();
})
],
),
actions: [
Obx(() {
if (call.current.value == null) {
if (call.isBusy.value) {
return const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(strokeWidth: 3),
).paddingAll(16);
} else if (call.current.value == null) {
return TextButton(
onPressed: () => _showCallPrejoin(context),
child: Text('callJoin'.tr),
);
} else if (call.channel.value?.id == channel.id) {
} else if (call.channel.value?.id == channel.id &&
!SolianTheme.isLargeScreen(context)) {
return TextButton(
onPressed: () => call.gotoScreen(context),
onPressed: () => onJoin(),
child: Text('callResume'.tr),
);
} else {
} else if (!SolianTheme.isLargeScreen(context)) {
return TextButton(
onPressed: null,
child: Text('callJoin'.tr),
);
}
return const SizedBox();
})
],
);

View File

@@ -88,10 +88,12 @@ class _ControlsWidgetState extends State<ControlsWidget> {
void _disconnect() async {
if (await showDisconnectDialog() != true) return;
final ChatCallProvider provider = Get.find();
if (provider.current.value != null) {
provider.disposeRoom();
Navigator.pop(context);
final ChatCallProvider call = Get.find();
if (call.current.value != null) {
call.disposeRoom();
if (Navigator.canPop(context)) {
Navigator.pop(context);
}
}
}
@@ -209,8 +211,7 @@ class _ControlsWidgetState extends State<ControlsWidget> {
runSpacing: 5,
children: [
IconButton(
icon: Transform.flip(
flipX: true, child: const Icon(Icons.exit_to_app)),
icon: const Icon(Icons.exit_to_app),
color: Theme.of(context).colorScheme.onSurface,
onPressed: _disconnect,
),

View File

@@ -25,22 +25,23 @@ class ChatCallPrejoinPopup extends StatefulWidget {
class _ChatCallPrejoinPopupState extends State<ChatCallPrejoinPopup> {
bool _isBusy = false;
void performJoin() async {
void _performJoin() async {
final AuthProvider auth = Get.find();
final ChatCallProvider provider = Get.find();
final ChatCallProvider call = Get.find();
if (auth.isAuthorized.isFalse) return;
setState(() => _isBusy = true);
provider.setCall(widget.ongoingCall, widget.channel);
call.setCall(widget.ongoingCall, widget.channel);
call.isBusy.value = true;
try {
final resp = await provider.getRoomToken();
final resp = await call.getRoomToken();
final token = resp.$1;
final endpoint = resp.$2;
provider.initRoom();
provider.setupRoomListeners(
call.initRoom();
call.setupRoomListeners(
onDisconnected: (reason) {
context.showSnackbar(
'callDisconnected'.trParams({'reason': reason.toString()}),
@@ -48,11 +49,9 @@ class _ChatCallPrejoinPopupState extends State<ChatCallPrejoinPopup> {
},
);
provider.joinRoom(endpoint, token);
call.joinRoom(endpoint, token);
provider.gotoScreen(context).then((_) {
Navigator.pop(context);
});
Navigator.pop(context);
} catch (e) {
context.showErrorDialog(e);
}
@@ -62,9 +61,9 @@ class _ChatCallPrejoinPopupState extends State<ChatCallPrejoinPopup> {
@override
void initState() {
final ChatCallProvider provider = Get.find();
provider.checkPermissions().then((_) {
provider.initHardware();
final ChatCallProvider call = Get.find();
call.checkPermissions().then((_) {
call.initHardware();
});
super.initState();
@@ -169,7 +168,7 @@ class _ChatCallPrejoinPopupState extends State<ChatCallPrejoinPopup> {
backgroundColor:
Theme.of(context).colorScheme.primaryContainer,
),
onPressed: _isBusy ? null : performJoin,
onPressed: _isBusy ? null : _performJoin,
child: Text('callJoin'.tr),
),
],

View File

@@ -7,10 +7,10 @@ class ChatCallCurrentIndicator extends StatelessWidget {
@override
Widget build(BuildContext context) {
final ChatCallProvider provider = Get.find();
final ChatCallProvider call = Get.find();
return Obx(() {
if (provider.current.value == null || provider.channel.value == null) {
if (call.current.value == null || call.channel.value == null) {
return const SizedBox();
}
@@ -18,11 +18,8 @@ class ChatCallCurrentIndicator extends StatelessWidget {
tileColor: Theme.of(context).colorScheme.surfaceContainerHigh,
contentPadding: const EdgeInsets.symmetric(horizontal: 32),
leading: const Icon(Icons.call),
title: Text(provider.channel.value!.name),
title: Text(call.channel.value!.name),
subtitle: Text('callAlreadyOngoing'.tr),
onTap: () {
provider.gotoScreen(context);
},
);
});
}

View File

@@ -296,8 +296,8 @@ class ChatEvent extends StatelessWidget {
),
],
).paddingSymmetric(horizontal: 12),
_buildLinkExpansion().paddingOnly(left: 52),
_buildAttachment(context).paddingOnly(left: 56),
_buildLinkExpansion().paddingOnly(left: 52, right: 8),
_buildAttachment(context).paddingOnly(left: 56, right: 8),
],
);
}