fix: calls — correct MSC4143 JWT flow + message order
Calls: - JWT fetch now uses correct MSC4143 flow: get OpenID token from Synapse, then POST to /_matrix/livekit/jwt/sfu/get (was using GET with Bearer token to wrong path — returned 301→404) - Error messages now visible for 3 seconds before popping screen (was flashing away instantly — user couldn't see failure reason) - Voice vs video calls differentiated via ?video=0/1 query param - Debug logging added to JWT flow for troubleshooting Messages: - Chat timeline now shows newest at bottom (standard behaviour). Was reversed twice: SDK returns newest-first, code reversed to oldest-first, then ListView(reverse:true) put oldest at bottom. Removed the extra .reversed — newest-first + reverse:true = correct. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Version: 1.2.0 | Created: 2026-04-01 | Updated: 2026-04-02
|
||||
// Version: 1.2.1 | Created: 2026-04-01 | Updated: 2026-04-03
|
||||
// Full call screen with LiveKit video/audio.
|
||||
// - Remote video: full screen background
|
||||
// - Local video: picture-in-picture overlay (bottom right)
|
||||
@@ -16,9 +16,14 @@ import '../domain/call_state.dart';
|
||||
import 'call_controller.dart';
|
||||
|
||||
class CallScreen extends ConsumerStatefulWidget {
|
||||
const CallScreen({super.key, required this.roomId});
|
||||
const CallScreen({
|
||||
super.key,
|
||||
required this.roomId,
|
||||
this.isVideo = true,
|
||||
});
|
||||
|
||||
final String roomId;
|
||||
final bool isVideo;
|
||||
|
||||
@override
|
||||
ConsumerState<CallScreen> createState() => _CallScreenState();
|
||||
@@ -28,12 +33,11 @@ class _CallScreenState extends ConsumerState<CallScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Start the call as soon as the screen opens.
|
||||
// Using addPostFrameCallback so the provider is ready.
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
ref
|
||||
.read(callControllerProvider.notifier)
|
||||
.joinCall(Uri.decodeComponent(widget.roomId), withVideo: true);
|
||||
ref.read(callControllerProvider.notifier).joinCall(
|
||||
Uri.decodeComponent(widget.roomId),
|
||||
withVideo: widget.isVideo,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,10 +45,25 @@ class _CallScreenState extends ConsumerState<CallScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
final callState = ref.watch(callControllerProvider);
|
||||
|
||||
// Pop back automatically when call ends.
|
||||
// On call ended: show error reason for 3 seconds before popping,
|
||||
// so the user can see WHY the call failed.
|
||||
ref.listen<CallState>(callControllerProvider, (_, next) {
|
||||
if (next is CallEnded && context.canPop()) {
|
||||
context.pop();
|
||||
if (next is CallEnded && mounted) {
|
||||
final reason = next.reason;
|
||||
if (reason != null && reason.isNotEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(reason),
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
);
|
||||
}
|
||||
// Delay pop so the user sees the error.
|
||||
final nav = GoRouter.of(context);
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
if (mounted) nav.pop();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user