From 87b45991bba1cb3ad3a1e34a1b1ea2481b18f8ee Mon Sep 17 00:00:00 2001
From: vjrj <vjrj@comunes.org>
Date: Sat, 15 Jul 2023 09:19:57 +0200
Subject: [PATCH] Add contacts

---
 assets/translations/en.json                   |   2 +
 assets/translations/es.json                   |   2 +
 lib/ui/screens/third_screen.dart              | 101 +++++++++++-------
 .../first_screen/contact_fav_icon.dart        |   4 +-
 .../fourth_screen/transaction_item.dart       |   4 +-
 ...t_dialog.dart => contact_form_dialog.dart} |  68 ++++++++----
 .../widgets/third_screen/contacts_page.dart   |   4 +-
 7 files changed, 120 insertions(+), 65 deletions(-)
 rename lib/ui/widgets/third_screen/{contact_edit_dialog.dart => contact_form_dialog.dart} (53%)

diff --git a/assets/translations/en.json b/assets/translations/en.json
index 469230db..b5a73561 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -111,9 +111,11 @@
   "share_your_key": "Share your public key",
   "share_this_key": "Share",
   "form_save": "SAVE",
+  "form_contact_title_add": "Add a contact",
   "form_contact_title": "Edit contact",
   "form_contact_name": "Name",
   "form_contact_name_validation": "Please enter a name",
+  "form_contact_name_validation_pub_key": "Please enter a valid public key",
   "form_contact_notes": "Notes",
   "long_press_to_edit": "Slide to select this contact. Tap and hold to edit",
   "form_contact_pub_key": "Public key",
diff --git a/assets/translations/es.json b/assets/translations/es.json
index aa83be37..1e2e1f3f 100644
--- a/assets/translations/es.json
+++ b/assets/translations/es.json
@@ -112,8 +112,10 @@
   "share_this_key": "Comparte",
   "form_save": "GUARDAR",
   "form_contact_title": "Editar contacto",
+  "form_contact_title_add": "Añade un contacto",
   "form_contact_name": "Nombre",
   "form_contact_name_validation": "Por favor, ingresa un nombre",
+  "form_contact_name_validation_pub_key": "Por favor, ingresa una clave pública valida",
   "form_contact_notes": "Notas",
   "long_press_to_edit": "Desliza para seleccionar este contacto. Mantén pulsado para editar",
   "form_contact_pub_key": "Clave pública",
diff --git a/lib/ui/screens/third_screen.dart b/lib/ui/screens/third_screen.dart
index bb287ffe..eba4e21a 100644
--- a/lib/ui/screens/third_screen.dart
+++ b/lib/ui/screens/third_screen.dart
@@ -11,6 +11,7 @@ import '../qr_manager.dart';
 import '../tutorial.dart';
 import '../tutorial_keys.dart';
 import '../widgets/card_drawer.dart';
+import '../widgets/third_screen/contact_form_dialog.dart';
 import '../widgets/third_screen/contacts_page.dart';
 import '../widgets/third_screen/third_tutorial.dart';
 
@@ -36,47 +37,75 @@ class _ThirdScreenState extends State<ThirdScreen> {
   @override
   Widget build(BuildContext context) {
     return Scaffold(
-      appBar: AppBar(title: Text(tr('bottom_nav_trd')), actions: <Widget>[
-        IconButton(
-            key: contactsQrKey,
-            icon: const Icon(Icons.qr_code),
-            onPressed: () async {
-              final String? pubKey = await QrManager.qrScan(context);
-              if (pubKey != null && validateKey(pubKey)) {
-                final Contact contact =
-                    await ContactsCache().getContact(pubKey);
-                if (!mounted) {
-                  return;
-                }
-                if (!context.read<ContactsCubit>().isContact(pubKey)) {
-                  context.read<ContactsCubit>().addContact(contact);
-                  ScaffoldMessenger.of(context).showSnackBar(
-                    SnackBar(
-                      content: Text(tr('contact_added')),
-                    ),
-                  );
+        appBar: AppBar(title: Text(tr('bottom_nav_trd')), actions: <Widget>[
+          IconButton(
+              key: contactsQrKey,
+              icon: const Icon(Icons.qr_code),
+              onPressed: () async {
+                final String? pubKey = await QrManager.qrScan(context);
+                if (pubKey != null && validateKey(pubKey)) {
+                  final Contact contact =
+                      await ContactsCache().getContact(pubKey);
+                  if (!mounted) {
+                    return;
+                  }
+                  if (!context.read<ContactsCubit>().isContact(pubKey)) {
+                    context.read<ContactsCubit>().addContact(contact);
+                    ScaffoldMessenger.of(context).showSnackBar(
+                      SnackBar(
+                        content: Text(tr('contact_added')),
+                      ),
+                    );
+                  } else {
+                    ScaffoldMessenger.of(context).showSnackBar(
+                      SnackBar(
+                        content: Text(tr('contact_already_exists')),
+                      ),
+                    );
+                  }
                 } else {
+                  if (!mounted) {
+                    return;
+                  }
                   ScaffoldMessenger.of(context).showSnackBar(
                     SnackBar(
-                      content: Text(tr('contact_already_exists')),
+                      content: Text(tr('wrong_public_key')),
                     ),
                   );
                 }
-              } else {
-                if (!mounted) {
-                  return;
-                }
-                ScaffoldMessenger.of(context).showSnackBar(
-                  SnackBar(
-                    content: Text(tr('wrong_public_key')),
-                  ),
-                );
-              }
-            }),
-        const SizedBox(width: 5),
-      ]),
-      drawer: const CardDrawer(),
-      body: const ContactsPage(),
-    );
+              }),
+          const SizedBox(width: 5),
+        ]),
+        drawer: const CardDrawer(),
+        body: const ContactsPage(),
+        floatingActionButton: FloatingActionButton(
+          onPressed: () async {
+            showDialog(
+                context: context,
+                builder: (BuildContext context) {
+                  return ContactFormDialog(
+                      contact: const Contact(
+                        name: '',
+                        pubKey: '',
+                      ),
+                      isNew: true,
+                      onSave: (Contact c) {
+                        context.read<ContactsCubit>().addContact(c);
+                        ContactsCache().saveContact(c);
+                        ScaffoldMessenger.of(context).showSnackBar(
+                          SnackBar(
+                            content: Text(tr('contact_added')),
+                          ),
+                        );
+                      });
+                });
+          },
+          shape: const RoundedRectangleBorder(
+            borderRadius: BorderRadius.all(
+              Radius.circular(50.0),
+            ),
+          ),
+          child: const Icon(Icons.add),
+        ));
   }
 }
diff --git a/lib/ui/widgets/first_screen/contact_fav_icon.dart b/lib/ui/widgets/first_screen/contact_fav_icon.dart
index ae89622e..05d9e584 100644
--- a/lib/ui/widgets/first_screen/contact_fav_icon.dart
+++ b/lib/ui/widgets/first_screen/contact_fav_icon.dart
@@ -5,7 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import '../../../data/models/contact.dart';
 import '../../../data/models/contact_cubit.dart';
 import '../../contacts_cache.dart';
-import '../third_screen/contact_edit_dialog.dart';
+import '../third_screen/contact_form_dialog.dart';
 
 class ContactFavIcon extends StatelessWidget {
   const ContactFavIcon({
@@ -37,7 +37,7 @@ class ContactFavIcon extends StatelessWidget {
               showDialog(
                 context: context,
                 builder: (BuildContext context) {
-                  return ContactEditDialog(
+                  return ContactFormDialog(
                       contact: contact,
                       onSave: (Contact c) {
                         context.read<ContactsCubit>().updateContact(c);
diff --git a/lib/ui/widgets/fourth_screen/transaction_item.dart b/lib/ui/widgets/fourth_screen/transaction_item.dart
index 1d14392c..ba661873 100644
--- a/lib/ui/widgets/fourth_screen/transaction_item.dart
+++ b/lib/ui/widgets/fourth_screen/transaction_item.dart
@@ -16,7 +16,7 @@ import '../../../shared_prefs.dart';
 import '../../contacts_cache.dart';
 import '../../pay_helper.dart';
 import '../../ui_helpers.dart';
-import '../third_screen/contact_edit_dialog.dart';
+import '../third_screen/contact_form_dialog.dart';
 
 class TransactionListItem extends StatelessWidget {
   const TransactionListItem(
@@ -176,7 +176,7 @@ class TransactionListItem extends StatelessWidget {
                   showDialog(
                     context: context,
                     builder: (BuildContext context) {
-                      return ContactEditDialog(
+                      return ContactFormDialog(
                           contact: newContact,
                           onSave: (Contact c) {
                             context.read<ContactsCubit>().updateContact(c);
diff --git a/lib/ui/widgets/third_screen/contact_edit_dialog.dart b/lib/ui/widgets/third_screen/contact_form_dialog.dart
similarity index 53%
rename from lib/ui/widgets/third_screen/contact_edit_dialog.dart
rename to lib/ui/widgets/third_screen/contact_form_dialog.dart
index 4d14dc63..67659d74 100644
--- a/lib/ui/widgets/third_screen/contact_edit_dialog.dart
+++ b/lib/ui/widgets/third_screen/contact_form_dialog.dart
@@ -5,18 +5,23 @@ import '../../../data/models/contact.dart';
 import '../../../g1/g1_helper.dart';
 import '../../ui_helpers.dart';
 
-class ContactEditDialog extends StatefulWidget {
-  const ContactEditDialog(
-      {super.key, required this.contact, required this.onSave});
+class ContactFormDialog extends StatefulWidget {
+  const ContactFormDialog({
+    super.key,
+    required this.contact,
+    required this.onSave,
+    this.isNew = false,
+  });
 
   final Contact contact;
   final Function(Contact) onSave;
+  final bool isNew;
 
   @override
-  State<ContactEditDialog> createState() => _ContactEditDialogState();
+  State<ContactFormDialog> createState() => _ContactFormDialogState();
 }
 
-class _ContactEditDialogState extends State<ContactEditDialog> {
+class _ContactFormDialogState extends State<ContactFormDialog> {
   final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
   late Contact _updatedContact;
 
@@ -29,36 +34,53 @@ class _ContactEditDialogState extends State<ContactEditDialog> {
   @override
   Widget build(BuildContext context) {
     return AlertDialog(
-      title: Text(tr('form_contact_title')),
+      title: Text(
+          tr(widget.isNew ? 'form_contact_title_add' : 'form_contact_title')),
       content: Form(
         key: _formKey,
         child: Column(
           mainAxisSize: MainAxisSize.min,
           children: <Widget>[
-            Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
-              Flexible(
-                  child: TextFormField(
-                // maxLines: 2,
-                initialValue: humanizePubKey(_updatedContact.pubKey),
+            if (!widget.isNew)
+              Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
+                Flexible(
+                    child: TextFormField(
+                  // maxLines: 2,
+                  initialValue: humanizePubKey(_updatedContact.pubKey),
+                  decoration: InputDecoration(
+                    labelText: tr('form_contact_pub_key'),
+                  ),
+                  enabled: false,
+                )),
+                GestureDetector(
+                  onTap: () {
+                    showQrDialog(
+                        context: context,
+                        publicKey: getFullPubKey(_updatedContact.pubKey),
+                        noTitle: true,
+                        feedbackText: 'some_key_copied_to_clipboard');
+                  },
+                  child: const Icon(Icons.qr_code, size: 50),
+                ),
+              ]),
+            if (widget.isNew)
+              TextFormField(
+                validator: (String? value) {
+                  if (value == null || value.isEmpty || !validateKey(value)) {
+                    return tr('form_contact_name_validation_pub_key');
+                  }
+                  return null;
+                },
                 decoration: InputDecoration(
                   labelText: tr('form_contact_pub_key'),
                 ),
-                enabled: false,
-              )),
-              GestureDetector(
-                onTap: () {
-                  showQrDialog(
-                      context: context,
-                      publicKey: getFullPubKey(_updatedContact.pubKey),
-                      noTitle: true,
-                      feedbackText: 'some_key_copied_to_clipboard');
+                onChanged: (String? value) {
+                  _updatedContact = _updatedContact.copyWith(pubKey: value);
                 },
-                child: const Icon(Icons.qr_code, size: 50),
               ),
-            ]),
             TextFormField(
               initialValue: _updatedContact.name,
-              decoration: const InputDecoration(labelText: 'Name'),
+              decoration: InputDecoration(labelText: tr('form_contact_name')),
               validator: (String? value) {
                 if (value == null || value.isEmpty) {
                   return tr('form_contact_name_validation');
diff --git a/lib/ui/widgets/third_screen/contacts_page.dart b/lib/ui/widgets/third_screen/contacts_page.dart
index d2002e5b..994356e1 100644
--- a/lib/ui/widgets/third_screen/contacts_page.dart
+++ b/lib/ui/widgets/third_screen/contacts_page.dart
@@ -12,7 +12,7 @@ import '../../../g1/g1_helper.dart';
 import '../../contacts_cache.dart';
 import '../../ui_helpers.dart';
 import '../bottom_widget.dart';
-import 'contact_edit_dialog.dart';
+import 'contact_form_dialog.dart';
 
 class ContactsPage extends StatefulWidget {
   const ContactsPage({super.key});
@@ -134,7 +134,7 @@ class _ContactsPageState extends State<ContactsPage> {
                         showDialog(
                           context: context,
                           builder: (BuildContext context) {
-                            return ContactEditDialog(
+                            return ContactFormDialog(
                                 contact: contact,
                                 onSave: (Contact c) {
                                   context
-- 
GitLab