From cb95454334bb565da4628e915df2cde47db178fc Mon Sep 17 00:00:00 2001
From: Nico Alt <nicoalt@posteo.org>
Date: Sat, 7 Dec 2019 02:11:11 +0100
Subject: [PATCH] Implement remote contact adding

---
 data/ui/add_contact.ui                  | 118 ++++++++++++++++++++++++
 data/ui/app.briar.gtk.gresource.xml     |   1 +
 data/ui/toolbar_start.ui                |  17 ++++
 po/briar-gtk.pot                        |  53 +++++++----
 po/de.po                                |  53 +++++++----
 po/es.po                                |  53 +++++++----
 src/briar/gtk/containers/add_contact.py |  43 +++++++++
 src/briar/gtk/toolbar.py                |  10 ++
 src/briar/gtk/window.py                 |  16 ++++
 9 files changed, 304 insertions(+), 60 deletions(-)
 create mode 100644 data/ui/add_contact.ui
 create mode 100644 src/briar/gtk/containers/add_contact.py

diff --git a/data/ui/add_contact.ui b/data/ui/add_contact.ui
new file mode 100644
index 0000000..e5899ff
--- /dev/null
+++ b/data/ui/add_contact.ui
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkGrid" id="add_contact">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="halign">center</property>
+    <property name="valign">center</property>
+    <property name="margin_left">18</property>
+    <property name="margin_right">18</property>
+    <property name="margin_top">18</property>
+    <property name="margin_bottom">18</property>
+    <child>
+      <object class="GtkGrid" id="link_grid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="row_spacing">6</property>
+        <property name="column_spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="own_link_label">
+            <property name="visible">True</property>
+            <property name="halign">center</property>
+            <property name="label" translatable="yes">Give this link to the contact you want to add</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="own_link_entry">
+            <property name="visible">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="their_link_label">
+            <property name="visible">True</property>
+            <property name="halign">center</property>
+            <property name="label" translatable="yes">Enter the link from your contact here</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="their_link_entry">
+            <property name="visible">True</property>
+            <property name="placeholder_text" translatable="yes" context="link exchange: their link input field">Contact's link</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="link_continue">
+            <property name="visible">True</property>
+            <property name="halign">center</property>
+            <property name="label" translatable="yes" context="link exchange: button – initiate pairing">Continue</property>
+            <signal name="clicked" handler="on_link_button_clicked"/>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">4</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkGrid" id="alias_grid">
+        <property name="visible">False</property>
+        <property name="can_focus">False</property>
+        <property name="row_spacing">6</property>
+        <property name="column_spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="alias_label">
+            <property name="visible">True</property>
+            <property name="halign">center</property>
+            <property name="label" translatable="yes">Give your contact a nickname. Only you can see it.</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="alias_entry">
+            <property name="visible">True</property>
+            <property name="placeholder_text" translatable="yes" context="remote contact adding: alias input field">Enter a nickname</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="add_contact_button">
+            <property name="visible">True</property>
+            <property name="halign">center</property>
+            <property name="label" translatable="yes" context="remote contact adding: button">Add Contact</property>
+            <signal name="clicked" handler="on_add_contact_button_clicked"/>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">3</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
+
+
diff --git a/data/ui/app.briar.gtk.gresource.xml b/data/ui/app.briar.gtk.gresource.xml
index e5baeff..b1c063e 100644
--- a/data/ui/app.briar.gtk.gresource.xml
+++ b/data/ui/app.briar.gtk.gresource.xml
@@ -2,6 +2,7 @@
 <gresources>
   <gresource prefix="/app/briar/gtk">
     <file compressed="true">ui/application.css</file>
+    <file compressed="true" preprocess="xml-stripblanks">ui/add_contact.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/chat.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/login.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/main.ui</file>
diff --git a/data/ui/toolbar_start.ui b/data/ui/toolbar_start.ui
index c4994a4..5722aa2 100644
--- a/data/ui/toolbar_start.ui
+++ b/data/ui/toolbar_start.ui
@@ -8,6 +8,11 @@
     <property name="can_focus">False</property>
     <property name="icon_name">go-previous-symbolic</property>
   </object>
+  <object class="GtkImage" id="add_contact_image">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">list-add-symbolic</property>
+  </object>
   <object class="GtkBox" id="toolbar_start">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -24,6 +29,18 @@
         <property name="position">0</property>
       </packing>
     </child>
+    <child>
+      <object class="GtkButton" id="add_contact_button">
+        <property name="visible">False</property>
+        <property name="valign">center</property>
+        <property name="image">add_contact_image</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
   </object>
 </interface>
 
diff --git a/po/briar-gtk.pot b/po/briar-gtk.pot
index 66d90b7..1bbfa79 100644
--- a/po/briar-gtk.pot
+++ b/po/briar-gtk.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-06-06 10:35+0200\n"
+"POT-Creation-Date: 2019-12-07 01:31+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,15 +17,43 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../data/ui/chat.ui:29
-msgctxt "chat page: input field"
-msgid "Type Message"
+#: ../data/ui/add_contact.ui:23
+msgid "Give this link to the contact you want to add"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:43
+msgid "Enter the link from your contact here"
 msgstr ""
 
-#: ../data/ui/login.ui:23 ../data/ui/setup.ui:64
+#: ../data/ui/add_contact.ui:63
+msgctxt "link exchange page: button – initiate pairing"
+msgid "Continue"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:83 ../data/ui/login.ui:23 ../data/ui/setup.ui:64
 msgid "Password"
 msgstr ""
 
+#: ../data/ui/add_contact.ui:94 ../data/ui/setup.ui:75
+msgctxt "registration page: password input field"
+msgid "Choose your password"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:105 ../data/ui/setup.ui:86
+msgctxt "registration page: password input field"
+msgid "Confirm your password"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:116 ../data/ui/setup.ui:97
+msgctxt "registration page: button"
+msgid "Create Account"
+msgstr ""
+
+#: ../data/ui/chat.ui:29
+msgctxt "chat page: input field"
+msgid "Type Message"
+msgstr ""
+
 #: ../data/ui/login.ui:44
 msgctxt "login page: button"
 msgid "Sign in"
@@ -44,18 +72,3 @@ msgstr ""
 msgctxt "registration page: button – from username to passwords"
 msgid "Next"
 msgstr ""
-
-#: ../data/ui/setup.ui:75
-msgctxt "registration page: password input field"
-msgid "Choose your password"
-msgstr ""
-
-#: ../data/ui/setup.ui:86
-msgctxt "registration page: password input field"
-msgid "Confirm your password"
-msgstr ""
-
-#: ../data/ui/setup.ui:97
-msgctxt "registration page: button"
-msgid "Create Account"
-msgstr ""
diff --git a/po/de.po b/po/de.po
index 8a1c23e..6d69430 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,21 +1,49 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-06-06 10:35+0200\n"
+"POT-Creation-Date: 2019-12-07 01:31+0100\n"
 "Language: de\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
+#: ../data/ui/add_contact.ui:23
+msgid "Give this link to the contact you want to add"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:43
+msgid "Enter the link from your contact here"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:63
+msgctxt "link exchange page: button – initiate pairing"
+msgid "Continue"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:83 ../data/ui/login.ui:23 ../data/ui/setup.ui:64
+msgid "Password"
+msgstr "Passwort"
+
+#: ../data/ui/add_contact.ui:94 ../data/ui/setup.ui:75
+msgctxt "registration page: password input field"
+msgid "Choose your password"
+msgstr "Wähle Dein Passwort"
+
+#: ../data/ui/add_contact.ui:105 ../data/ui/setup.ui:86
+msgctxt "registration page: password input field"
+msgid "Confirm your password"
+msgstr "Bestätige Dein Passwort"
+
+#: ../data/ui/add_contact.ui:116 ../data/ui/setup.ui:97
+msgctxt "registration page: button"
+msgid "Create Account"
+msgstr "Account erstellen"
+
 #: ../data/ui/chat.ui:29
 msgctxt "chat page: input field"
 msgid "Type Message"
 msgstr "Nachricht eingeben"
 
-#: ../data/ui/login.ui:23 ../data/ui/setup.ui:64
-msgid "Password"
-msgstr "Passwort"
-
 #: ../data/ui/login.ui:44
 msgctxt "login page: button"
 msgid "Sign in"
@@ -34,18 +62,3 @@ msgstr "Wähle Deinen Benutzernamen"
 msgctxt "registration page: button – from username to passwords"
 msgid "Next"
 msgstr "Weiter"
-
-#: ../data/ui/setup.ui:75
-msgctxt "registration page: password input field"
-msgid "Choose your password"
-msgstr "Wähle Dein Passwort"
-
-#: ../data/ui/setup.ui:86
-msgctxt "registration page: password input field"
-msgid "Confirm your password"
-msgstr "Bestätige Dein Passwort"
-
-#: ../data/ui/setup.ui:97
-msgctxt "registration page: button"
-msgid "Create Account"
-msgstr "Account erstellen"
diff --git a/po/es.po b/po/es.po
index f213f71..80f9fe8 100644
--- a/po/es.po
+++ b/po/es.po
@@ -1,21 +1,49 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-06-06 10:35+0200\n"
+"POT-Creation-Date: 2019-12-07 01:31+0100\n"
 "Language: es\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../data/ui/chat.ui:29
-msgctxt "chat page: input field"
-msgid "Type Message"
+#: ../data/ui/add_contact.ui:23
+msgid "Give this link to the contact you want to add"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:43
+msgid "Enter the link from your contact here"
 msgstr ""
 
-#: ../data/ui/login.ui:23 ../data/ui/setup.ui:64
+#: ../data/ui/add_contact.ui:63
+msgctxt "link exchange page: button – initiate pairing"
+msgid "Continue"
+msgstr ""
+
+#: ../data/ui/add_contact.ui:83 ../data/ui/login.ui:23 ../data/ui/setup.ui:64
 msgid "Password"
 msgstr "Contraseña"
 
+#: ../data/ui/add_contact.ui:94 ../data/ui/setup.ui:75
+msgctxt "registration page: password input field"
+msgid "Choose your password"
+msgstr "Elegir tu contraseña"
+
+#: ../data/ui/add_contact.ui:105 ../data/ui/setup.ui:86
+msgctxt "registration page: password input field"
+msgid "Confirm your password"
+msgstr "Confirmar tu contraseña"
+
+#: ../data/ui/add_contact.ui:116 ../data/ui/setup.ui:97
+msgctxt "registration page: button"
+msgid "Create Account"
+msgstr "Crear cuenta"
+
+#: ../data/ui/chat.ui:29
+msgctxt "chat page: input field"
+msgid "Type Message"
+msgstr ""
+
 #: ../data/ui/login.ui:44
 msgctxt "login page: button"
 msgid "Sign in"
@@ -34,18 +62,3 @@ msgstr "Elegir tu nombre"
 msgctxt "registration page: button – from username to passwords"
 msgid "Next"
 msgstr "Seguir"
-
-#: ../data/ui/setup.ui:75
-msgctxt "registration page: password input field"
-msgid "Choose your password"
-msgstr "Elegir tu contraseña"
-
-#: ../data/ui/setup.ui:86
-msgctxt "registration page: password input field"
-msgid "Confirm your password"
-msgstr "Confirmar tu contraseña"
-
-#: ../data/ui/setup.ui:97
-msgctxt "registration page: button"
-msgid "Create Account"
-msgstr "Crear cuenta"
diff --git a/src/briar/gtk/containers/add_contact.py b/src/briar/gtk/containers/add_contact.py
new file mode 100644
index 0000000..59e8476
--- /dev/null
+++ b/src/briar/gtk/containers/add_contact.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2019 Nico Alt
+# SPDX-License-Identifier: AGPL-3.0-only
+# License-Filename: LICENSE.md
+
+from gi.repository import GLib, Gtk
+
+from briar.api.models.contacts import Contacts
+from briar.gtk.container import Container
+from briar.gtk.define import APP
+
+
+class AddContactContainer(Container):
+
+    CONTAINER_UI = "/app/briar/gtk/ui/add_contact.ui"
+
+    def __init__(self):
+        super().__init__()
+        self._api = APP().api
+        self._setup_view()
+        self._load_content()
+
+    def _setup_view(self):
+        self.builder.add_from_resource(self.CONTAINER_UI)
+        self.add(self.builder.get_object("add_contact"))
+        self.builder.connect_signals(self)
+
+    def _load_content(self):
+        contacts = Contacts(self._api)
+        own_link = contacts.get_link()
+        self.builder.get_object("own_link_entry").set_text(own_link)
+
+    # pylint: disable=unused-argument
+    def on_link_button_clicked(self, button):
+        self.builder.get_object("link_grid").set_visible(False)
+        self.builder.get_object("alias_grid").set_visible(True)
+
+    # pylint: disable=unused-argument
+    def on_add_contact_button_clicked(self, button):
+        their_link = self.builder.get_object("their_link_entry").get_text()
+        alias = self.builder.get_object("alias_entry").get_text()
+        contacts = Contacts(self._api)
+        contacts.add_pending(their_link, alias)
+        GLib.idle_add(APP().window._back_to_main, None)
diff --git a/src/briar/gtk/toolbar.py b/src/briar/gtk/toolbar.py
index f65c147..64784d8 100644
--- a/src/briar/gtk/toolbar.py
+++ b/src/briar/gtk/toolbar.py
@@ -20,6 +20,16 @@ class Toolbar(Gtk.HeaderBar):
         self._setup_builder()
         self._setup_toolbar()
 
+    def show_add_contact_button(self, show, callback=None):
+        add_contact_button = self._builder.get_object("add_contact_button")
+        if not show:
+            add_contact_button.hide()
+            return
+        if callback is None:
+            raise Exception("Callback needed when showing add contact button")
+        add_contact_button.show()
+        add_contact_button.connect("clicked", callback)
+
     def show_back_button(self, show, callback=None):
         back_button = self._builder.get_object("back_button")
         if not show:
diff --git a/src/briar/gtk/window.py b/src/briar/gtk/window.py
index 13cc9ee..121b1f3 100644
--- a/src/briar/gtk/window.py
+++ b/src/briar/gtk/window.py
@@ -4,6 +4,7 @@
 
 from gi.repository import Gtk
 
+from briar.gtk.containers.add_contact import AddContactContainer
 from briar.gtk.containers.chat import ChatContainer
 from briar.gtk.containers.main import MainContainer
 from briar.gtk.containers.startup import StartupContainer
@@ -73,6 +74,20 @@ class Window(Gtk.ApplicationWindow):
         self._container = MainContainer()
         self._container.show()
         self._grid.add(self._container)
+        self._toolbar.show_add_contact_button(True, self.show_add_contact)
+
+    # pylint: disable=unused-argument
+    def show_add_contact(self, widget):
+        self._grid.destroy()
+        self._setup_grid()
+        self._setup_add_contact()
+
+    def _setup_add_contact(self):
+        self._container = AddContactContainer()
+        self._container.show()
+        self._grid.add(self._container)
+        self._toolbar.show_back_button(True, self._back_to_main)
+        self._toolbar.show_add_contact_button(False)
 
     def open_private_chat(self, contact_id):
         self._grid.destroy()
@@ -84,6 +99,7 @@ class Window(Gtk.ApplicationWindow):
         self._container.show()
         self._grid.add(self._container)
         self._toolbar.show_back_button(True, self._back_to_main)
+        self._toolbar.show_add_contact_button(False)
 
     # pylint: disable=unused-argument
     def _back_to_main(self, widget):
-- 
GitLab