36 lines
1.2 KiB
Dart
36 lines
1.2 KiB
Dart
import 'dart:developer';
|
|
|
|
import 'package:flutter_linkify/flutter_linkify.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
/// Single entry point for opening links that come from outside the app (chat
|
|
/// messages, ticker content, emergency notices).
|
|
class UrlOpener {
|
|
/// Schemes we hand to the platform. Message content is user supplied, so
|
|
/// anything that could address another app directly stays out.
|
|
static const _allowedSchemes = {'http', 'https', 'mailto', 'tel'};
|
|
|
|
static Future<void> onOpen(LinkableElement link) => openUrl(link.url);
|
|
|
|
static Future<void> openUrl(String url) async {
|
|
final uri = Uri.tryParse(url);
|
|
if (uri == null || !_allowedSchemes.contains(uri.scheme.toLowerCase())) {
|
|
return;
|
|
}
|
|
|
|
// externalApplication first: it hands the link to the app that owns it
|
|
// (YouTube, Maps, the mail client) instead of iOS' in-app Safari sheet,
|
|
// which throws a PlatformException whenever its load fails.
|
|
for (final mode in const [
|
|
LaunchMode.externalApplication,
|
|
LaunchMode.platformDefault,
|
|
]) {
|
|
try {
|
|
if (await launchUrl(uri, mode: mode)) return;
|
|
} catch (e) {
|
|
log('launching $uri as $mode failed: $e');
|
|
}
|
|
}
|
|
}
|
|
}
|