diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 134556de..7b36b909 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -11,6 +11,13 @@ "type": "text", "placeholders": {} }, + "cantOpenUri": "Can't open the URI {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, "chats": "Chats", "@chats": { "type": "text", diff --git a/lib/utils/url_launcher.dart b/lib/utils/url_launcher.dart index 305cdbc9..7e282380 100644 --- a/lib/utils/url_launcher.dart +++ b/lib/utils/url_launcher.dart @@ -7,6 +7,8 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:vrouter/vrouter.dart'; +import 'package:punycode/punycode.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class UrlLauncher { final String url; @@ -19,7 +21,34 @@ class UrlLauncher { url.toLowerCase().startsWith(AppConfig.schemePrefix)) { return openMatrixToUrl(); } - launch(url); + final uri = Uri.tryParse(url); + if (uri == null) { + // we can't open this thing + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(L10n.of(context).cantOpenUri(url)))); + return; + } + if (!{'https', 'http'}.contains(uri.scheme)) { + // just launch non-https / non-http uris directly + launch(url); + return; + } + if (uri.host == null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(L10n.of(context).cantOpenUri(url)))); + return; + } + // okay, we have either an http or an https URI. + // As some platforms have issues with opening unicode URLs, we are going to help + // them out by punycode-encoding them for them ourself. + final newHost = uri.host.split('.').map((hostPartEncoded) { + final hostPart = Uri.decodeComponent(hostPartEncoded); + final hostPartPunycode = punycodeEncode(hostPart); + return hostPartPunycode != hostPart + '-' + ? 'xn--$hostPartPunycode' + : hostPart; + }).join('.'); + launch(uri.replace(host: newHost).toString()); } void openMatrixToUrl() async { diff --git a/pubspec.lock b/pubspec.lock index b8f387e0..788352a6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -670,12 +670,12 @@ packages: source: hosted version: "0.3.5" matrix_link_text: - dependency: transitive + dependency: "direct main" description: name: matrix_link_text url: "https://pub.dartlang.org" source: hosted - version: "0.4.1" + version: "0.4.2" meta: dependency: transitive description: @@ -930,6 +930,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + punycode: + dependency: "direct main" + description: + name: punycode + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" quiver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index cf586e4d..bbbd8ddf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: localstorage: ^4.0.0+1 lottie: ^1.1.0 matrix: ^0.1.11 + matrix_link_text: ^0.4.2 native_imaging: git: https://gitlab.com/famedly/libraries/native_imaging.git open_noti_settings: ^0.2.0 @@ -55,6 +56,7 @@ dependencies: permission_handler: ^8.1.4+2 pin_code_text_field: ^1.8.0 provider: ^5.0.0 + punycode: ^1.0.0 receive_sharing_intent: ^1.4.5 record: ^3.0.0 scroll_to_index: ^2.0.0