From 78c5cf3f04b64e1e8e086df4f34cea4002d87908 Mon Sep 17 00:00:00 2001 From: Hugo Delaunay Date: Sun, 12 Jan 2025 21:55:18 +0100 Subject: [PATCH] fix: Better handling of HTTPS links in the app settings. --- android/app/src/main/AndroidManifest.xml | 7 ++++ lib/pages/settings/entries/github.dart | 39 ++++++++---------- lib/pages/settings/entries/translate.dart | 25 ++++------- .../settings/entries/uri_settings_entry.dart | 41 +++++++++++++++++++ lib/pages/settings/page.dart | 4 +- 5 files changed, 77 insertions(+), 39 deletions(-) create mode 100644 lib/pages/settings/entries/uri_settings_entry.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index efba8a4b..3cd230e9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -58,4 +58,11 @@ android:name="flutter_deeplinking_enabled" android:value="false" /> + + + + + + + diff --git a/lib/pages/settings/entries/github.dart b/lib/pages/settings/entries/github.dart index de595054..f419381d 100644 --- a/lib/pages/settings/entries/github.dart +++ b/lib/pages/settings/entries/github.dart @@ -1,31 +1,28 @@ import 'package:flutter/material.dart'; import 'package:open_authenticator/app.dart'; import 'package:open_authenticator/i18n/translations.g.dart'; -import 'package:url_launcher/url_launcher.dart'; +import 'package:open_authenticator/pages/settings/entries/uri_settings_entry.dart'; /// Takes the user to Github to report bugs, suggest new features, ... -class GithubSettingsEntryWidget extends StatelessWidget { +class GithubSettingsEntryWidget extends UriSettingsEntry { /// Creates a new Github settings entry widget instance. - const GithubSettingsEntryWidget({ + GithubSettingsEntryWidget({ super.key, - }); + }) : super( + icon: Icons.bug_report, + title: translations.settings.about.github.title, + subtitle: translations.settings.about.github.subtitle, + uri: Uri.parse(App.githubRepositoryUrl), + ); @override - Widget build(BuildContext context) => ListTile( - leading: const Icon(Icons.bug_report), - title: Text(translations.settings.about.github.title), - subtitle: Text(translations.settings.about.github.subtitle), - onTap: () async { - Uri uri = Uri.parse(App.githubRepositoryUrl); - Uri withFragment = Uri( - scheme: uri.scheme, - host: uri.host, - path: uri.path, - fragment: 'report-bugs-or-suggest-new-features', - ); - if (await canLaunchUrl(withFragment)) { - launchUrl(withFragment); - } - }, - ); + Uri get uri { + Uri uri = super.uri; + return Uri( + scheme: uri.scheme, + host: uri.host, + path: uri.path, + fragment: 'report-bugs-or-suggest-new-features', + ); + } } diff --git a/lib/pages/settings/entries/translate.dart b/lib/pages/settings/entries/translate.dart index c46b1b6d..edabd511 100644 --- a/lib/pages/settings/entries/translate.dart +++ b/lib/pages/settings/entries/translate.dart @@ -1,25 +1,18 @@ import 'package:flutter/material.dart'; import 'package:open_authenticator/app.dart'; import 'package:open_authenticator/i18n/translations.g.dart'; +import 'package:open_authenticator/pages/settings/entries/uri_settings_entry.dart'; import 'package:url_launcher/url_launcher.dart'; /// Takes the user to the app translation page. -class TranslateSettingsEntryWidget extends StatelessWidget { +class TranslateSettingsEntryWidget extends UriSettingsEntry { /// Creates a new translate settings entry widget instance. - const TranslateSettingsEntryWidget({ + TranslateSettingsEntryWidget({ super.key, - }); - - @override - Widget build(BuildContext context) => ListTile( - leading: const Icon(Icons.translate), - title: Text(translations.settings.about.translate.title), - subtitle: Text(translations.settings.about.translate.subtitle(appName: App.appName)), - onTap: () async { - Uri uri = Uri.parse(App.appTranslationUrl); - if (await canLaunchUrl(uri)) { - launchUrl(uri); - } - }, - ); + }) : super( + icon: Icons.translate, + title: translations.settings.about.translate.title, + subtitle: translations.settings.about.translate.subtitle(appName: App.appName), + uri: Uri.parse(App.appTranslationUrl), + ); } diff --git a/lib/pages/settings/entries/uri_settings_entry.dart b/lib/pages/settings/entries/uri_settings_entry.dart new file mode 100644 index 00000000..959ed97b --- /dev/null +++ b/lib/pages/settings/entries/uri_settings_entry.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; + +/// A settings entry that allows to open a specific URI. +class UriSettingsEntry extends StatelessWidget { + /// The entry widget title. + final String title; + + /// The entry widget subtitle. + final String? subtitle; + + /// The icon. + final IconData? icon; + + /// The URI to open. + final Uri uri; + + /// Creates a new URI settings entry instance. + const UriSettingsEntry({ + super.key, + required this.title, + this.subtitle, + this.icon, + required this.uri, + }); + + @override + Widget build(BuildContext context) => FutureBuilder( + future: canLaunchUrl(uri), + builder: (context, snapshot) => createListTile(context, snapshot.data), + ); + + Widget createListTile(BuildContext context, bool? canLaunchUri) => canLaunchUri == null || canLaunchUri == true + ? ListTile( + leading: const Icon(Icons.translate), + title: Text(title), + subtitle: subtitle == null ? null : Text(subtitle!), + onTap: canLaunchUri == true ? (() async => await launchUrl(uri)) : null, + ) + : SizedBox.shrink(); +} diff --git a/lib/pages/settings/page.dart b/lib/pages/settings/page.dart index 6321a570..0cd7ccd3 100644 --- a/lib/pages/settings/page.dart +++ b/lib/pages/settings/page.dart @@ -69,8 +69,8 @@ class SettingsPage extends ConsumerWidget { const BackupNowSettingsEntryWidget(), const ManageBackupSettingsEntryWidget(), _SettingsPageSectionTitle(title: translations.settings.about.title), - const TranslateSettingsEntryWidget(), - const GithubSettingsEntryWidget(), + TranslateSettingsEntryWidget(), + GithubSettingsEntryWidget(), const AboutSettingsEntryWidget(), _SettingsPageSectionTitle(title: translations.settings.dangerZone.title), const DeleteAccountSettingsEntryWidget(),