// Version: 1.0.0 | Created: 2026-04-05 // Parses a Jitsi meeting link into room name and optional JWT. /// Parsed Jitsi meeting link. class JitsiLink { const JitsiLink({required this.roomName, this.jwt}); final String roomName; final String? jwt; /// Parses a Jitsi link in common formats: /// - `https://conf.m8chat.au/RoomName` /// - `https://conf.m8chat.au/RoomName?jwt=abc123` /// - `conf.m8chat.au/RoomName?jwt=abc123` /// - `RoomName` (bare room name) static JitsiLink? tryParse(String input) { final trimmed = input.trim(); if (trimmed.isEmpty) return null; // Try as a URL first. var uriString = trimmed; if (!uriString.contains('://') && uriString.contains('/')) { uriString = 'https://$uriString'; } final uri = Uri.tryParse(uriString); if (uri != null && uri.pathSegments.isNotEmpty && uri.host.isNotEmpty) { final roomName = uri.pathSegments .where((s) => s.isNotEmpty) .join('/'); if (roomName.isEmpty) return null; final jwt = uri.queryParameters['jwt']; return JitsiLink(roomName: roomName, jwt: jwt); } // Bare room name — no slashes, no protocol. if (!trimmed.contains('/') && !trimmed.contains(' ')) { return JitsiLink(roomName: trimmed); } return null; } }