diff --git a/chameleonultragui/lib/gui/component/hex_editor.dart b/chameleonultragui/lib/gui/component/hex_editor.dart deleted file mode 100644 index 827c24e4..00000000 --- a/chameleonultragui/lib/gui/component/hex_editor.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:chameleonultragui/helpers/general.dart'; -import 'dart:typed_data'; - -// Localizations -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -class HexEdit extends StatefulWidget { - final List data; - - const HexEdit({Key? key, required this.data}) : super(key: key); - - @override - HexEditState createState() => HexEditState(); -} - -class HexEditState extends State { - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var localizations = AppLocalizations.of(context)!; - - List sectors = []; - - for (var i = 0, x = 0; i < widget.data.length; i += 4, x++) { - if (widget.data[i].isNotEmpty) { - String data = ''; - for (var j = 0; j < 4; j++) { - data += '\n ${bytesToHex(widget.data[i + j])}'; - } - - sectors.add( - TextField( - maxLines: null, - controller: TextEditingController(text: data.toUpperCase()), - decoration: InputDecoration( - labelText: '${localizations.sector} $x', - hintText: localizations.enter_data), - ), - ); - } - } - - return AlertDialog( - title: Text(localizations.edit_data), - content: SizedBox( - width: MediaQuery.of(context).size.width / 4, - height: MediaQuery.of(context).size.height, - child: ListView( - children: sectors, - ), - ), - actions: const [], - ); - } -} diff --git a/chameleonultragui/lib/gui/menu/card_edit.dart b/chameleonultragui/lib/gui/menu/card_edit.dart index 7167b5eb..15a7e03c 100644 --- a/chameleonultragui/lib/gui/menu/card_edit.dart +++ b/chameleonultragui/lib/gui/menu/card_edit.dart @@ -6,6 +6,7 @@ import 'package:chameleonultragui/bridge/chameleon.dart'; import 'package:provider/provider.dart'; import 'package:chameleonultragui/main.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; +import 'package:chameleonultragui/gui/menu/hex_edit.dart'; // Localizations import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -259,6 +260,28 @@ class CardEditMenuState extends State { ), ), actions: [ + Visibility( + visible: chameleonTagToFrequency(selectedType) != TagFrequency.lf, + child: TextButton( + onPressed: () async { + final data = await showDialog( + context: context, + builder: (BuildContext context) { + return HexEditMenu( + tagSave: widget.tagSave, + ); + }, + ); + + if (data != null) { + setState(() { + widget.tagSave.data = data; + }); + } + }, + child: Text(localizations.edit_hex) + ), + ), TextButton( onPressed: () { Navigator.pop(context); diff --git a/chameleonultragui/lib/gui/menu/hex_edit.dart b/chameleonultragui/lib/gui/menu/hex_edit.dart new file mode 100644 index 00000000..06c0751d --- /dev/null +++ b/chameleonultragui/lib/gui/menu/hex_edit.dart @@ -0,0 +1,154 @@ +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:chameleonultragui/helpers/general.dart'; +import 'package:chameleonultragui/sharedprefsprovider.dart'; +import'package:rich_text_controller/rich_text_controller.dart'; +//import 'package:provider/provider.dart'; +//import 'package:chameleonultragui/main.dart'; + +// Localizations +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class HexEditMenu extends StatefulWidget { + final CardSave tagSave; + + const HexEditMenu({Key? key, required this.tagSave}) + : super(key: key); + + @override + HexEditMenuState createState() => HexEditMenuState(); +} + +class HexEditMenuState extends State { + @override + void initState() { + super.initState(); + } + + final List _controllers = []; + + List cardSaveToBlockView(CardSave card) { + List sectors = []; + List blocks = []; + List data = card.data; + + // one block consists of 16 bytes + // Split the data into blocks + // 4 blocks per sector + for (var i = 0; i < data.length; i += 4) { + try { + if (data[i].isEmpty) { + blocks.add(""); + } else { + blocks.add("${bytesToHexSpace(data[i])}\n${bytesToHexSpace(data[i + 1])}\n${bytesToHexSpace(data[i + 2])}\n${bytesToHexSpace(data[i + 3])}"); + } + } on RangeError { + // If the data is not divisible by 4, add the remaining byte(s) + blocks.add(bytesToHexSpace(data[i])); + } + + // Create a new TextEditingController for each sector + _controllers.add( + RichTextController( + text: blocks.last, + //patternMatchMap: { + //RegExp(r''): const TextStyle(color: Colors.green), + //RegExp(r'((?:\s[0-9A-F]{2}){4})(?=.{18}$)'): const TextStyle(color: Colors.red), + //RegExp(r'((?:[0-9A-F]{2}(?:\ |\n|\))?){6})$'): const TextStyle(color: Colors.blue), + //}, + stringMatchMap: { + blocks.last.substring(blocks.last.length- 18, blocks.last.length): const TextStyle(color: Colors.blue), + blocks.last.substring(blocks.last.length - 29, blocks.last.length - 21): const TextStyle(color: Colors.red), + blocks.last.substring(blocks.last.length - 48, blocks.last.length - 30): const TextStyle(color: Colors.green), + " ": const TextStyle(color: Colors.blue), // This is a hack to properly display all colors, its a bug in the library + }, // This function has also some edgecase where stuff gets colored incorrectly, needs to be fixed some day when regex lookahead is fixed... //TODO: Fix when library got patched + onMatch: (List matches) {}, + ), + ); + } + + for (var i = 0; i < blocks.length; i++) { + sectors.add(const SizedBox(height: 10)); + sectors.add( + TextField( + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: 'Sector $i', + ), + controller: _controllers[i], + keyboardType: TextInputType.multiline, + maxLines: null, + onChanged: (value) async {}, + ), + ); + } + + return sectors; + } + + List extractDataFromTextFields() { + List data = []; + + for (var i = 0; i < _controllers.length; i++) { + String text = _controllers[i].text; + List lines = text.split('\n'); + for (var line in lines) { + data.add(hexToBytesSpace(line.toUpperCase())); + } + } + + return data; + } + + @override + Widget build(BuildContext context) { + //var appState = context.watch(); + var localizations = AppLocalizations.of(context)!; + + return AlertDialog( + title: Text(localizations.edit_hex), + content: SingleChildScrollView( + child: Column( + children: [ + FittedBox( + fit: BoxFit.fitWidth, + child: Row( + children: [ + const Icon(Icons.square, color: Colors.green,), + Text(localizations.key_a), + const SizedBox(width: 10,), + const Icon(Icons.square, color: Colors.red,), + Text(localizations.acs), + const SizedBox(width: 10,), + const Icon(Icons.square, color: Colors.blue,), + Text(localizations.key_b), + ], + ), + ), + const SizedBox(height: 10,), + ...cardSaveToBlockView(widget.tagSave), + ], + ) + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text(localizations.cancel), + ), + TextButton( + onPressed: () { + List data = extractDataFromTextFields(); + widget.tagSave.data = data; + + // Return data back to widget that called this dialog + Navigator.pop(context, data); + }, + child: Text(localizations.save), + ), + ], + ); + } +} diff --git a/chameleonultragui/lib/l10n/app_en.arb b/chameleonultragui/lib/l10n/app_en.arb index 6c2ce195..e9271291 100644 --- a/chameleonultragui/lib/l10n/app_en.arb +++ b/chameleonultragui/lib/l10n/app_en.arb @@ -227,5 +227,9 @@ "must_be_valid_hex": "Must be valid HEX", "export_to_dictionary": "Export found keys", "enter_name_of_card": "Enter name of card", - "enter_name_of_dictionary": "Enter name of dictionary" + "enter_name_of_dictionary": "Enter name of dictionary", + "edit_hex": "Edit HEX", + "key_a": "Key A", + "key_b": "Key B", + "acs": "ACS" } \ No newline at end of file diff --git a/chameleonultragui/pubspec.lock b/chameleonultragui/pubspec.lock index ebf34eee..1e3b049d 100644 --- a/chameleonultragui/pubspec.lock +++ b/chameleonultragui/pubspec.lock @@ -557,6 +557,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.0" + rich_text_controller: + dependency: "direct main" + description: + name: rich_text_controller + sha256: "2697b0313c03429ac4d924e14f16e07d16e31a234d31c46bcce9f8f8e713f05f" + url: "https://pub.dev" + source: hosted + version: "1.4.2" shared_preferences: dependency: "direct main" description: diff --git a/chameleonultragui/pubspec.yaml b/chameleonultragui/pubspec.yaml index b24f954d..907fddc6 100644 --- a/chameleonultragui/pubspec.yaml +++ b/chameleonultragui/pubspec.yaml @@ -65,6 +65,7 @@ dependencies: sdk: flutter intl: any wakelock_plus: ^1.1.1 + rich_text_controller: ^1.4.2 dev_dependencies: flutter_test: