diff --git a/app/lib/main.dart b/app/lib/main.dart index 319c926..7f067bd 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -14,8 +14,15 @@ import 'package:oauth2/oauth2.dart' as oauth2; import 'package:url_launcher/url_launcher.dart'; +import 'package:provider/provider.dart'; + void main() { - runApp(const MyApp()); + runApp( + ChangeNotifierProvider( + create: (context) => SSHKeyList(), + child: const MyApp(), + ), + ); } Future getOAuth2Client() async { @@ -335,7 +342,19 @@ class _MyHomePageState extends State { children: [ TextButton(onPressed: doOAuth, child: Text("Oauth2 Login")), Text('Current output:'), + Consumer( + builder: (BuildContext context, SSHKeyList sshKeyList, Widget? child) { + return Text( + sshKeyList.keysToKeep.isEmpty + ? 'No keys selected to keep.' + : 'Keys selected to keep: ${sshKeyList.keysToKeep.join(', ')}', + ); + }, + ), Text(outputText, style: Theme.of(context).textTheme.headlineMedium), + // Generated code for this Text Widget... + KeepOrDeleteKey(sshKey: "ssh-ed22519 abs csas blabla"), + KeepOrDeleteKey(sshKey: "ssh-ed22519 abs "), ], ), ); @@ -413,3 +432,134 @@ class _MyHomePageState extends State { ); } } + +class SSHKeyList extends ChangeNotifier { + final List _allKeys = []; + final List _keysToKeep = []; + + List get allKeys => _allKeys; + List get keysToKeep => _keysToKeep; + + void keepKey(String key) { + if (_keysToKeep.contains(key)) { + // If the key is already in the list, do nothing + return; + } + _keysToKeep.add(key); + notifyListeners(); + } + + void selectKeyForDeletion(String key) { + _keysToKeep.remove(key); + notifyListeners(); + } + + bool isKeySelectedToKeep(String key) { + return _keysToKeep.contains(key); + } + + void clearKeys() { + _keysToKeep.clear(); + notifyListeners(); + } +} + +class KeepOrDeleteKey extends StatefulWidget { + final String sshKey; + + const KeepOrDeleteKey({super.key, required this.sshKey}); + + @override + State createState() => _KeepOrDeleteKeyState(); +} + +class _KeepOrDeleteKeyState extends State { + bool _selectedForDeletion = false; + + bool get selectedForDeletion => _selectedForDeletion; + + @override + Widget build(BuildContext context) { + final key = widget.sshKey; + final isKeySelectedToKeep = context.select( + (keylist) => keylist.isKeySelectedToKeep(key), + ); + + final buttonStyleKeepActive = ButtonStyle( + backgroundColor: MaterialStateProperty.all(Colors.blue), + foregroundColor: MaterialStateProperty.all(Colors.white), + ); + + final buttonStyleDeleteActive = ButtonStyle( + backgroundColor: MaterialStateProperty.all(Colors.red), + foregroundColor: MaterialStateProperty.all(Colors.white), + ); + + ButtonStyle? buttonStyleKeep; + ButtonStyle? buttonStyleDelete = buttonStyleDeleteActive; + + if (isKeySelectedToKeep) { + buttonStyleKeep = buttonStyleKeepActive; + buttonStyleDelete = null; + } + + var title = "Unnamed Key"; + final sshKeySplit = widget.sshKey.split(' '); + if (sshKeySplit.length >= 3) { + final potentialTitle = sshKeySplit.sublist(2).join(' '); + if (potentialTitle != "") { + title = potentialTitle; + } + } + + return Card( + margin: EdgeInsets.fromLTRB(20, 20, 20, 0), + child: Column( + children: [ + Padding( + padding: EdgeInsets.all(20), + child: Text(title, style: TextStyle(fontSize: 25)), + ), + Padding( + padding: EdgeInsets.fromLTRB(20, 0, 20, 20), + child: Text(widget.sshKey, style: TextStyle(fontSize: 15)), + ), + Padding( + padding: EdgeInsets.fromLTRB(20, 0, 20, 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + TextButton( + onPressed: () { + setState(() { + _selectedForDeletion = true; + Provider.of( + context, + listen: false, + ).selectKeyForDeletion(widget.sshKey); + }); + }, + style: buttonStyleDelete, + child: Text('Select for Deletion'), + ), + TextButton( + onPressed: () { + setState(() { + _selectedForDeletion = false; + Provider.of( + context, + listen: false, + ).keepKey(widget.sshKey); + }); + }, + style: buttonStyleKeep, + child: Text('Keep Key'), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/app/pubspec.lock b/app/pubspec.lock index 20c902b..2cc7b39 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -256,6 +256,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" oauth2: dependency: "direct main" description: @@ -352,6 +360,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.9.1" + provider: + dependency: "direct main" + description: + name: provider + sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + url: "https://pub.dev" + source: hosted + version: "6.1.5" sky_engine: dependency: transitive description: flutter diff --git a/app/pubspec.yaml b/app/pubspec.yaml index c3bf81e..825618e 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -40,6 +40,7 @@ dependencies: oauth2: ^2.0.3 webview_flutter: ^4.13.0 url_launcher: ^6.3.1 + provider: ^6.1.5 dev_dependencies: flutter_test: