diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 2770c0a1..306f0f99 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -655,6 +655,7 @@ "s_no_export": null, "s_export": null, "l_export_configuration_file": null, + "l_exported_can_be_uploaded_at": null, "@_otp_slot_actions": {}, "s_delete_slot": null, diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3ec2509c..45c35790 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -655,6 +655,7 @@ "s_no_export": "No export", "s_export": "Export", "l_export_configuration_file": "Export configuration to file", + "l_exported_can_be_uploaded_at": "Exported credentials can be uploaded at", "@_otp_slot_actions": {}, "s_delete_slot": "Delete credential", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 2dd6c2f9..6b018d7c 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -655,6 +655,7 @@ "s_no_export": null, "s_export": null, "l_export_configuration_file": null, + "l_exported_can_be_uploaded_at": null, "@_otp_slot_actions": {}, "s_delete_slot": null, diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index 1a33771f..6163f33a 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -655,6 +655,7 @@ "s_no_export": null, "s_export": null, "l_export_configuration_file": null, + "l_exported_can_be_uploaded_at": null, "@_otp_slot_actions": {}, "s_delete_slot": null, diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 17c522c8..5d9d6f80 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -655,6 +655,7 @@ "s_no_export": "Brak eksportu", "s_export": "Eksportuj", "l_export_configuration_file": "Eksportuj konfigurację do pliku", + "l_exported_can_be_uploaded_at": null, "@_otp_slot_actions": {}, "s_delete_slot": "Usuń poświadczenie", diff --git a/lib/otp/views/configure_yubiotp_dialog.dart b/lib/otp/views/configure_yubiotp_dialog.dart index 81643834..5ffbfcb9 100644 --- a/lib/otp/views/configure_yubiotp_dialog.dart +++ b/lib/otp/views/configure_yubiotp_dialog.dart @@ -18,11 +18,13 @@ import 'dart:io'; import 'dart:math'; import 'package:file_picker/file_picker.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logging/logging.dart'; import 'package:material_symbols_icons/symbols.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../../app/logging.dart'; import '../../app/message.dart'; @@ -365,6 +367,17 @@ class _ConfigureYubiOtpDialogState }, ), ], + ), + RichText( + text: TextSpan( + text: l10n.l_exported_can_be_uploaded_at, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant), + children: [ + const TextSpan(text: ' '), + _createUploadOtpLink(context) + ], + ), ) ] .map((e) => Padding( @@ -376,4 +389,21 @@ class _ConfigureYubiOtpDialogState ), ); } + + TextSpan _createUploadOtpLink(BuildContext context) { + final theme = Theme.of(context); + final uploadOtpUri = Uri.parse('https://upload.yubico.com'); + return TextSpan( + text: uploadOtpUri.host, + style: + theme.textTheme.bodySmall?.copyWith(color: theme.colorScheme.primary), + recognizer: TapGestureRecognizer() + ..onTap = () async { + await launchUrl(uploadOtpUri, mode: LaunchMode.externalApplication); + }, + children: const [ + TextSpan(text: ' ') // without this the recognizer takes over whole row + ], + ); + } }