import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:uuid/uuid.dart'; import 'package:dialer/services/cryptography/asymmetric_crypto_service.dart'; class ManageKeysPage extends StatefulWidget { @override _ManageKeysPageState createState() => _ManageKeysPageState(); } class _ManageKeysPageState extends State { List> _keys = []; bool _isLoading = true; @override void initState() { super.initState(); _fetchKeys(); } Future _fetchKeys() async { final AsymmetricCryptoService cryptoService = Provider.of(context, listen: false); try { final keys = await cryptoService.getAllKeys(); setState(() { _keys = keys; _isLoading = false; }); } catch (e) { // Handle error, e.g., show a snackbar setState(() { _isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error fetching keys: $e')), ); } } Future _createKey() async { final AsymmetricCryptoService cryptoService = Provider.of(context, listen: false); String? label = await _showCreateKeyDialog(); if (label == null) return; // User cancelled try { await cryptoService.generateKeyPair(label: label); await _fetchKeys(); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Key "$label" created successfully.')), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error creating key: $e')), ); } } Future _showCreateKeyDialog() async { String label = ''; return showDialog( context: context, builder: (context) { return AlertDialog( title: Text('Create New Key'), content: TextField( onChanged: (value) { label = value; }, decoration: InputDecoration(hintText: "Enter key label"), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(null), child: Text('Cancel'), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(label.trim().isEmpty ? 'Key ${Uuid().v4()}' : label.trim()), child: Text('Create'), ), ], ); }, ); } Future _deleteKey(String alias, String label) async { final AsymmetricCryptoService cryptoService = Provider.of(context, listen: false); bool confirm = await _showDeleteConfirmationDialog(label); if (!confirm) return; try { await cryptoService.deleteKeyPair(alias); await _fetchKeys(); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Key "$label" deleted successfully.')), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error deleting key: $e')), ); } } Future _showDeleteConfirmationDialog(String label) async { return await showDialog( context: context, builder: (context) => AlertDialog( title: Text('Delete Key'), content: Text('Are you sure you want to delete the key "$label"? This action cannot be undone.'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: Text('Cancel'), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), style: ElevatedButton.styleFrom(foregroundColor: Colors.red), child: Text('Delete'), ), ], ), ) ?? false; } Future _viewPublicKey(String alias, String label) async { final AsymmetricCryptoService cryptoService = Provider.of(context, listen: false); try { final String publicKey = await cryptoService.getPublicKey(alias); await showDialog( context: context, builder: (context) => AlertDialog( title: Text('Public Key for "$label"'), content: SelectableText(publicKey), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text('Close'), ), // Optionally, add a button to copy the key to clipboard ], ), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error retrieving public key: $e')), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Manage Keys'), actions: [ IconButton( icon: Icon(Icons.add), onPressed: _createKey, tooltip: 'Create New Key', ), ], ), body: _isLoading ? Center(child: CircularProgressIndicator()) : _keys.isEmpty ? Center(child: Text('No keys found.')) : ListView.builder( itemCount: _keys.length, itemBuilder: (context, index) { final key = _keys[index]; return ListTile( title: Text(key['label']), subtitle: Text('Created at: ${key['created_at']}'), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: Icon(Icons.edit), onPressed: () => _editKeyLabel(key['alias'], key['label']), tooltip: 'Edit Label', ), IconButton( icon: Icon(Icons.visibility), onPressed: () => _viewPublicKey(key['alias'], key['label']), tooltip: 'View Public Key', ), IconButton( icon: Icon(Icons.delete, color: Colors.red), onPressed: () => _deleteKey(key['alias'], key['label']), tooltip: 'Delete Key', ), ], ), ); }, )); } /// Updates the label of a key. Future _editKeyLabel(String alias, String currentLabel) async { final AsymmetricCryptoService cryptoService = Provider.of(context, listen: false); String? newLabel = await _showEditLabelDialog(currentLabel); if (newLabel == null) return; // User cancelled try { await cryptoService.updateKeyLabel(alias, newLabel); await _fetchKeys(); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Key label updated to "$newLabel".')), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error updating key label: $e')), ); } } Future _showEditLabelDialog(String currentLabel) async { String label = currentLabel; return showDialog( context: context, builder: (context) { return AlertDialog( title: Text('Edit Key Label'), content: TextField( onChanged: (value) { label = value; }, decoration: InputDecoration(hintText: "Enter new key label"), controller: TextEditingController(text: currentLabel), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(null), child: Text('Cancel'), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(label.trim().isEmpty ? currentLabel : label.trim()), child: Text('Save'), ), ], ); }, ); } }