import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:encrypt/encrypt.dart' as encrypt; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:universal_html/html.dart' as html; /* This is a work in progress to export/import keys with some password */ class ExportImportPage extends StatefulWidget { const ExportImportPage({super.key}); @override State<ExportImportPage> createState() => _ExportImportPageState(); } class _ExportImportPageState extends State<ExportImportPage> { final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final TextEditingController _passwordController = TextEditingController(); String _statusMessage = ''; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Exportar/Importar Preferencias Compartidas'), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ TextFormField( controller: _passwordController, decoration: const InputDecoration( labelText: 'Contraseña de patrón', ), obscureText: true, validator: (String? value) { if (value != null && value.isEmpty) { return 'Por favor, introduce una contraseña de patrón'; } return null; }, ), const SizedBox(height: 16.0), ElevatedButton( onPressed: _exportarPreferenciasCompartidas, child: const Text('Exportar Preferencias Compartidas'), ), const SizedBox(height: 16.0), ElevatedButton( onPressed: _importarPreferenciasCompartidas, child: const Text('Importar Preferencias Compartidas'), ), ], ), ), const SizedBox(height: 16.0), Text(_statusMessage), ], ), ), ); } Future<void> _exportarPreferenciasCompartidas() async { if (_formKey.currentState != null && !_formKey.currentState!.validate()) { return; } final String password = _passwordController.text; final SharedPreferences prefs = await SharedPreferences.getInstance(); final String jsonString = jsonEncode(prefs .getKeys() .fold<Map<String, dynamic>>( <String, dynamic>{}, (Map<String, dynamic> map, String key) => <String, dynamic>{...map, key: prefs.get(key)})); final Uint8List plainText = Uint8List.fromList(utf8.encode(jsonString)); final encrypt.Key key = encrypt.Key.fromUtf8(password.padRight(32)); final encrypt.IV iv = encrypt.IV.fromLength(16); final encrypt.Encrypter encrypter = encrypt.Encrypter(encrypt.AES(key)); final encrypt.Encrypted encrypted = encrypter.encryptBytes(plainText, iv: iv); Directory? appDir = await getDownloadsDirectory(); appDir = appDir ?? await getApplicationDocumentsDirectory(); final File file = File('${appDir.path}/shared_preferences.bin.txt'); await file.writeAsBytes(encrypted.bytes); setState(() { _statusMessage = 'Preferencias Compartidas exportadas con éxito'; }); } Future<void> _importarPreferenciasCompartidas() async { final Completer<void> completer = Completer<void>(); // Crear un elemento <input type="file"> para seleccionar archivos final html.InputElement input = html.InputElement()..type = 'file'; input.multiple = false; input.accept = '.txt'; // Opcional: limitar a tipos de archivo específicos input.click(); // Esperar hasta que se seleccionen los archivos input.onChange.listen((html.Event event) async { if (input.files != null && input.files!.isEmpty) { completer.complete(); return; } final html.File file = input.files!.first; final html.FileReader reader = html.FileReader(); // Leer el archivo seleccionado como texto reader.readAsText(file); await reader.onLoadEnd.first; // Restablecer las preferencias compartidas desde el archivo cargado try { final String jsonString = reader.result as String; final jsonMap = jsonDecode(jsonString); final SharedPreferences prefs = await SharedPreferences.getInstance(); // TODO(vjrj): jsonMap.forEach((key, value) => prefs.set(key, value)); setState(() { _statusMessage = 'Preferencias Compartidas importadas con éxito'; }); } catch (e) { setState(() { _statusMessage = 'Error al importar las Preferencias Compartidas'; }); } completer.complete(); }); return completer.future; } }