Skip to content
Snippets Groups Projects
Commit 889edc8f authored by vjrj's avatar vjrj
Browse files

New export options

parent 6b96702f
No related branches found
No related tags found
No related merge requests found
......@@ -196,10 +196,6 @@
"payment_waiting_internet_desc_beta": "Retry your payment when internet is back",
"your_name_here": "Name this card",
"copied_to_clipboard": "Copied to clipboard",
"share_export_title": "Share your wallet",
"share_export_desc": "Your wallet has been exported locally. Would you like to additionally share it with yourself via email/chat/etc. for safekeeping?",
"share_export_subject": "My Ğ1nkgo Wallet",
"share_export_button": "SHARE",
"pay_with_nfc_tooltip": "To receive a payment, simply bring this device close to the other wallet with NFC activated.",
"import_wallet_from_clipboard": "Import Wallet from Clipboard",
"import_wallet_from_clipboard_desc": "Please paste a previously exported wallet text to import it",
......@@ -207,12 +203,14 @@
"paste": "PASTE",
"import": "IMPORT",
"select_import_method": "Select Import Method",
"select_import_method_desc": "Please choose where to import the wallet from",
"file_import": "Import from File",
"export": "EXPORT",
"clipboard_export": "Export to Clipboard",
"select_export_method": "Select Export Method",
"select_export_method_desc": "Please choose where to export the wallet",
"file_export": "Export to File",
"clipboard_export": "Export to Clipboard"
"clipboard_export": "Export to Clipboard",
"share_export": "Share via email/chat/etc.",
"wallet_copied": "Walled copied to clipboard",
"link_export": "Export to Link",
"share_export_subject": "Ğ1nkgo Wallet Export"
}
......@@ -198,10 +198,6 @@
"payment_waiting_internet_desc_beta": "Reintenta el pago cuando vuelvas a tener conexión",
"your_name_here": "Da un nombre a esta tarjeta",
"copied_to_clipboard": "Copiado al portapapeles",
"share_export_title": "Comporte tu monedero",
"share_export_desc": "Tu monedero ha sido exportado localmente. ¿Te gustaría compartirlo adicionalmente contigo mismo vía email/chat/etc. para su resguardo?",
"share_export_subject": "Mi monedero Ğ1nkgo",
"share_export_button": "COMPARTIR",
"pay_with_nfc_tooltip": "Para recibir un pago, simplemente acerca este dispositivo al otro monedero con NFC activado.",
"import_wallet_from_clipboard": "Importar monedero desde el portapapeles",
"import_wallet_from_clipboard_desc": "Por favor, pega aquí el textod del backup previo de tu monedero",
......@@ -209,13 +205,15 @@
"paste": "PEGAR",
"import": "IMPORTAR",
"select_import_method": "Selecciona el método de importación",
"select_import_method_desc": "Por favor, selecciona el método de importación de tu monedero",
"file_import": "Importar desde archivo",
"clipboard_import": "Importar desde portapapeles",
"export": "EXPORTAR",
"clipboard_export": "Exportar al portapapeles",
"select_export_method": "Selecciona el método de exportación",
"select_export_method_desc": "Por favor, selecciona el método de exportación de tu monedero",
"file_export": "Exportar a archivo",
"clipboard_export": "Exportar al portapapeles"
"file_export": "Exportar a un archivo",
"clipboard_export": "Exportar al portapapeles",
"share_export": "Exportar vía email/chat/etc.",
"wallet_copied": "Monedero copiado al portapapeles",
"link_export": "Exportar vía enlace",
"share_export_subject": "Ğ1nkgo Wallet Export"
}
......@@ -9,7 +9,6 @@ import '../../data/models/app_state.dart';
import '../../data/models/bottom_nav_cubit.dart';
import '../../data/models/theme_cubit.dart';
import '../../shared_prefs.dart';
import '../notification_controller.dart';
import '../tutorial.dart';
import '../tutorial_keys.dart';
import '../ui_helpers.dart';
......@@ -82,7 +81,7 @@ class _FifthScreenState extends State<FifthScreen> {
),
onChanged: (Locale? newLocale) {
context.setLocale(newLocale!);
NotificationController.locale = newLocale;
// NotificationController.locale = newLocale;
},
items: const <DropdownMenuItem<Locale>>[
DropdownMenuItem<Locale>(
......@@ -180,12 +179,7 @@ class _FifthScreenState extends State<FifthScreen> {
title: 'export_key',
icon: Icons.download,
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const ExportDialog();
},
);
_showSelectExportMethodDialog();
}),
GridItem(
title: 'import_key',
......@@ -260,6 +254,24 @@ class _FifthScreenState extends State<FifthScreen> {
);
}
}
Future<void> _showSelectExportMethodDialog() async {
final ExportType? method = await showDialog<ExportType>(
context: context,
builder: (BuildContext context) => const SelectExportMethodDialog(),
);
if (method != null) {
if (!mounted) {
return;
}
showDialog(
context: context,
builder: (BuildContext context) {
return ExportDialog(type: method);
},
);
}
}
}
class SelectImportMethodDialog extends StatelessWidget {
......@@ -269,15 +281,43 @@ class SelectImportMethodDialog extends StatelessWidget {
Widget build(BuildContext context) {
return AlertDialog(
title: Text(tr('select_import_method')),
content: Text(tr('select_import_method_desc')),
// content: Text(tr('select_import_method_desc')),
actions: <Widget>[
TextButton(
child: Text(tr('file_import')),
TextButton.icon(
icon: const Icon(Icons.file_present),
label: Text(tr('file_import')),
onPressed: () => Navigator.of(context).pop('file')),
TextButton(
child: Text(tr('clipboard_import')),
TextButton.icon(
icon: const Icon(Icons.content_paste),
label: Text(tr('clipboard_import')),
onPressed: () => Navigator.of(context).pop('clipboard')),
],
);
}
}
class SelectExportMethodDialog extends StatelessWidget {
const SelectExportMethodDialog({super.key});
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(tr('select_export_method')),
// content: Text(tr('select_export_method_desc')),
actions: <Widget>[
TextButton.icon(
icon: const Icon(Icons.file_present),
label: Text(tr('file_export')),
onPressed: () => Navigator.of(context).pop(ExportType.file)),
TextButton.icon(
icon: const Icon(Icons.content_paste),
label: Text(tr('clipboard_export')),
onPressed: () => Navigator.of(context).pop(ExportType.clipboard)),
TextButton.icon(
icon: const Icon(Icons.share),
label: Text(tr('share_export')),
onPressed: () => Navigator.of(context).pop(ExportType.share)),
],
);
}
}
......@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:clipboard/clipboard.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:file_saver/file_saver.dart';
import 'package:flutter/foundation.dart';
......@@ -19,8 +20,12 @@ import '../../logger.dart';
import '../../ui_helpers.dart';
import 'pattern_util.dart';
enum ExportType { clipboard, file, share }
class ExportDialog extends StatefulWidget {
const ExportDialog({super.key});
const ExportDialog({super.key, required this.type});
final ExportType type;
@override
State<ExportDialog> createState() => _ExportDialogState();
......@@ -66,7 +71,7 @@ class _ExportDialogState extends State<ExportDialog> {
if (isConfirm) {
if (listEquals<int>(input, pattern)) {
Navigator.of(context).pop();
_export(pattern!.join(), context);
_export(pattern!.join(), context, widget.type);
} else {
context.replaceSnackbar(
content: Text(
......@@ -93,70 +98,67 @@ class _ExportDialogState extends State<ExportDialog> {
);
}
Future<void> _export(String password, BuildContext context) async {
Future<void> _export(String password, BuildContext context,
ExportType type) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String jsonString = jsonEncode(prefs
.getKeys()
.fold<Map<String, dynamic>>(
<String, dynamic>{},
<String, dynamic>{},
(Map<String, dynamic> map, String key) =>
<String, dynamic>{...map, key: prefs.get(key)}));
<String, dynamic>{...map, key: prefs.get(key)}));
final Map<String, String> jsonData =
encryptJsonForExport(jsonString, password);
encryptJsonForExport(jsonString, password);
final String fileJson = jsonEncode(jsonData);
final List<int> bytes = utf8.encode(fileJson);
if (kIsWeb) {
webDownload(bytes);
} else {
saveFile(bytes);
}
if (!mounted) {
return;
switch (type) {
case ExportType.clipboard:
FlutterClipboard.copy(fileJson)
.then((dynamic value) =>
context.replaceSnackbar(
content: Text(
tr('wallet_copied'),
style: const TextStyle(color: Colors.red),
),
));
break;
case ExportType.file:
if (kIsWeb) {
webDownload(bytes);
} else {
saveFile(bytes);
}
if (!mounted) {
return;
}
context.replaceSnackbar(
content: Text(
tr('wallet_exported'),
style: const TextStyle(color: Colors.red),
),
);
break;
case ExportType.share:
if (!mounted) {
return;
}
shareExport(context, fileJson);
break;
}
context.replaceSnackbar(
content: Text(
tr('wallet_exported'),
style: const TextStyle(color: Colors.red),
),
);
confirmAndShare(context, fileJson);
}
void confirmAndShare(BuildContext context, String fileJson) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(tr('share_export_title')),
content: Text(tr('share_export_desc')),
actions: <Widget>[
TextButton(
child: Text(tr('cancel')),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text(tr('share_export_button')),
onPressed: () {
if (kIsWeb) {
/* final String url =
'mailto:?subject=${Uri.encodeComponent('My wallet')}&body=${Uri.encodeComponent(fileJson)}';
html.window.open(url, '_blank'); */
Share.share(fileJson, subject: tr('share_export_subject'));
} else {
Share.share(fileJson, subject: tr('share_export_subject'));
}
Navigator.of(context).pop();
},
),
],
);
},
);
Future<void> shareExport(BuildContext context, String fileJson) {
if (kIsWeb) {
final Uri uri = Uri.parse(html.window.location.href);
final String fileJsonUrlComponent = Uri.encodeComponent(fileJson);
final Uri finalUri = uri.replace(path: '/import/$fileJsonUrlComponent');
// TODO Allow to import this link
return Share.share(inDevelopment ? finalUri.toString() : fileJson,
subject: tr('share_export_subject'));
} else {
return Share.share(fileJson, subject: tr('share_export_subject'));
}
}
void webDownload(List<int> bytes) {
......@@ -165,14 +167,15 @@ class _ExportDialogState extends State<ExportDialog> {
final html.AnchorElement anchor = html.AnchorElement(href: url);
anchor.download =
'ginkgo-wallet-${simplifyPubKey(SharedPreferencesHelper().getPubKey())}.json';
'ginkgo-wallet-${simplifyPubKey(
SharedPreferencesHelper().getPubKey())}.json';
anchor.click();
}
Future<void> saveFile(List<int> bytes) async {
try {
final Directory? externalDirectory =
await getAppSpecificExternalFilesDirectory(); // ensureDownloadsDirectoryExists();
await getAppSpecificExternalFilesDirectory(); // ensureDownloadsDirectoryExists();
if (externalDirectory == null) {
logger('Downloads directory not found');
return;
......@@ -203,7 +206,8 @@ class _ExportDialogState extends State<ExportDialog> {
String walletFileName() {
final String fileName =
'ginkgo-wallet-${simplifyPubKey(SharedPreferencesHelper().getPubKey())}.json';
'ginkgo-wallet-${simplifyPubKey(
SharedPreferencesHelper().getPubKey())}.json';
return fileName;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment