fix: Jitsi meeting join rendered blank page — call JitsiMeetExternalAPI with 'new'

- Bind JitsiMeetExternalAPI as extension type external constructor;
  the old external function binding invoked the ES6 class without 'new'
  and threw at runtime (silently, in release builds)
- joinMeeting: wait up to 5s for platform-view container div (post-frame
  race), build options via setProperty (jsify cannot carry DOM nodes),
  return success bool, log failures to browser console
- jitsi_screen: show 'Could not start the meeting' UI instead of blank
- v1.6.2+10, deployed to app2.m8chat.au

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 07:05:32 +10:00
parent 3568b17f0f
commit 923c0ad878
5 changed files with 115 additions and 45 deletions

View File

@@ -1,4 +1,4 @@
// Version: 1.2.0 | Created: 2026-04-05 | Updated: 2026-04-10
// Version: 1.3.0 | Created: 2026-04-05 | Updated: 2026-07-04
// Full-screen Jitsi meeting embedded via HtmlElementView (web platform view).
import 'package:flutter/material.dart';
@@ -21,6 +21,7 @@ class _JitsiScreenState extends State<JitsiScreen> {
late final JitsiLink? _link;
bool _meetingStarted = false;
bool _meetingEnded = false;
bool _meetingFailed = false;
@override
void initState() {
@@ -42,8 +43,9 @@ class _JitsiScreenState extends State<JitsiScreen> {
_meetingStarted = true;
// Post-frame so the HtmlElementView div is mounted in the DOM.
WidgetsBinding.instance.addPostFrameCallback((_) {
JitsiWebService.instance.joinMeeting(
// joinMeeting itself waits for the container div to appear.
WidgetsBinding.instance.addPostFrameCallback((_) async {
final ok = await JitsiWebService.instance.joinMeeting(
roomName: _link.roomName,
jwt: _link.jwt,
onReadyToClose: () {
@@ -52,6 +54,9 @@ class _JitsiScreenState extends State<JitsiScreen> {
}
},
);
if (!ok && mounted) {
setState(() => _meetingFailed = true);
}
});
}
@@ -111,6 +116,34 @@ class _JitsiScreenState extends State<JitsiScreen> {
);
}
if (_meetingFailed) {
return Scaffold(
appBar: AppBar(title: const Text('Conference')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.videocam_off_outlined, size: 48),
const SizedBox(height: 16),
const Text(
'Could not start the meeting. '
'Check your connection and try again.',
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () => context.go('/rooms'),
child: const Text('Back'),
),
],
),
),
),
);
}
// Render the Jitsi iframe and kick off the meeting once mounted.
_startMeeting();