From 29f9f251d34df4efcaac3cf26e333dce0a048ac6 Mon Sep 17 00:00:00 2001
From: Nico Alt <nicoalt@posteo.org>
Date: Thu, 17 Dec 2020 18:07:21 +0100
Subject: [PATCH] Big final refactoring

---
 briar-gtk/briar_gtk/actions/window.py         |  10 +-
 .../briar_gtk/controllers/main_window.py      | 162 +++------------
 .../briar_gtk/controllers/notification.py     |  58 ++++++
 .../briar_gtk/controllers/private_chat.py     | 189 +++++++++++++++++-
 briar-gtk/briar_gtk/views/main_window.py      | 158 ++-------------
 briar-gtk/briar_gtk/views/private_chat.py     |   2 +
 briar-gtk/briar_gtk/window.py                 |   2 +-
 7 files changed, 291 insertions(+), 290 deletions(-)
 create mode 100644 briar-gtk/briar_gtk/controllers/notification.py

diff --git a/briar-gtk/briar_gtk/actions/window.py b/briar-gtk/briar_gtk/actions/window.py
index 93e017c..03fea0a 100644
--- a/briar-gtk/briar_gtk/actions/window.py
+++ b/briar-gtk/briar_gtk/actions/window.py
@@ -10,7 +10,7 @@ from gi.repository import GLib
 
 from briar_gtk.actions.actions import Actions
 from briar_gtk.actions.prefixes import WINDOW_PREFIX
-from briar_gtk.views.main_window import MainWindowView
+from briar_gtk.controllers.main_window import MainWindowController
 from briar_gtk.define import APP
 
 
@@ -64,16 +64,16 @@ class WindowActions(Actions):
 
     # pylint: disable=unused-argument
     def _back_to_sidebar(self, action, parameter):
-        if isinstance(self.widget.current_container, MainWindowView):
-            self.widget.current_container.show_sidebar()
+        if isinstance(self.widget.current_controller, MainWindowController):
+            self.widget.current_controller.close_private_chat()
 
     # pylint: disable=unused-argument
     def _delete_all_messages_dialog(self, action, parameter):
-        self.widget.current_container.open_delete_all_messages_dialog()
+        self.widget.current_controller.open_delete_all_messages_dialog()
 
     # pylint: disable=unused-argument
     def _delete_contact_dialog(self, action, parameter):
-        self.widget.current_container.open_delete_contact_dialog()
+        self.widget.current_controller.open_delete_contact_dialog()
 
     # pylint: disable=unused-argument
     def _change_alias_contact_dialog(self, action, parameter):
diff --git a/briar-gtk/briar_gtk/controllers/main_window.py b/briar-gtk/briar_gtk/controllers/main_window.py
index 83507cf..cf9243a 100644
--- a/briar-gtk/briar_gtk/controllers/main_window.py
+++ b/briar-gtk/briar_gtk/controllers/main_window.py
@@ -9,9 +9,11 @@ from briar_wrapper.models.contacts import Contacts
 
 from briar_gtk.containers.private_chat import PrivateChatContainer
 from briar_gtk.controllers.main_menu import MainMenuController
+from briar_gtk.controllers.notification import NotificationController
 from briar_gtk.controllers.private_chat import PrivateChatController
 from briar_gtk.controllers.sidebar import SidebarController
-from briar_gtk.define import APP
+from briar_gtk.define import APP, NOTIFICATION_CONTACT_ADDED
+from briar_gtk.define import NOTIFICATION_PRIVATE_MESSAGE
 from briar_gtk.views.main_menu import MainMenuView
 from briar_gtk.views.private_chat import PrivateChatView
 from briar_gtk.views.sidebar import SidebarView
@@ -27,7 +29,6 @@ class MainWindowController():
         self._signals = list()
 
         self._setup_children()
-        self._load_content()
         self._setup_destroy_listener()
 
     @staticmethod
@@ -36,126 +37,45 @@ class MainWindowController():
         about_dialog.show()
 
     def open_change_contact_alias_dialog(self):
-        if self._current_contact_id == 0:
-            raise Exception("Can't change contact alias with ID 0")
-
-        confirmation_dialog = EditDialog(
-            parent=APP().window,
-            flags=Gtk.DialogFlags.MODAL,
-            placeholder=self._get_contact_name(self._current_contact_id)
-        )
-
-        confirmation_dialog.set_title(_("Change contact name"))
-
-        response = confirmation_dialog.run()
-        user_alias = confirmation_dialog.get_entry().get_text()
-        confirmation_dialog.destroy()
-        if (response == Gtk.ResponseType.OK) and (user_alias != ''):
-            Contacts(APP().api).set_alias(self._current_contact_id, user_alias)
-            contact_name_label = self._builder.get_object("contact_name")
-            contact_name_label.set_text(user_alias)
-            self._sidebar_controller.refresh_contacts()
+        self._private_chat_controller.open_change_contact_alias_dialog()
+
+    def open_delete_all_messages_dialog(self):
+        self._private_chat_controller.open_delete_all_messages_dialog()
+
+    def open_delete_contact_dialog(self):
+        self._private_chat_controller.open_delete_contact_dialog()
+
+    def close_private_chat(self):
+        self._private_chat_controller.close_private_chat()
 
     def open_private_chat(self, contact_id):
-        contact_name = self._get_contact_name(contact_id)
-        self._prepare_chat_view(contact_name)
-        self._setup_private_chat_widget(contact_name, contact_id)
-        self._current_contact_id = contact_id
+        self._private_chat_controller.open_private_chat(contact_id)
 
     def _setup_children(self):
+        self._setup_notification_controller()
+        self._setup_sidebar_controller()
+        self._setup_private_chat_controller()
+        self._setup_main_menu_controller()
+
+    def _setup_notification_controller(self):
+        self._notification_controller = NotificationController()
+
+    def _setup_sidebar_controller(self):
         self._sidebar_view = SidebarView(self._builder)
         self._sidebar_controller = SidebarController(
             self._sidebar_view, APP().api)
 
+    def _setup_private_chat_controller(self):
         self._private_chat_view = PrivateChatView(self._builder)
         self._private_chat_controller = PrivateChatController(
-            self._private_chat_view, APP().api)
+            self._private_chat_view, self._sidebar_controller,
+            self._builder, APP().api)
 
+    def _setup_main_menu_controller(self):
         self._main_menu_view = MainMenuView()
         self._main_menu_controller = MainMenuController(
             self._main_menu_view, APP().api)
 
-    def _get_contact_name(self, contact_id):
-        name = ""
-        for contact in Contacts(APP().api).get():
-            if contact["contactId"] == contact_id:
-                name = contact["author"]["name"]
-                if "alias" in contact:
-                    name = contact["alias"]
-                break
-        return name
-
-    def _prepare_chat_view(self, contact_name):
-        main_content_stack = self._builder.get_object("main_content_stack")
-        chat_placeholder = main_content_stack.get_child_by_name(
-            "chat_placeholder")
-        if self._no_chat_opened():
-            chat_placeholder.hide()
-        else:
-            self._clear_history_container()
-
-        chat_view = main_content_stack.get_child_by_name("chat_view")
-        chat_view.show()
-        main_window_leaflet = self._builder.get_object("main_window_leaflet")
-        main_content_container = self._builder.get_object(
-            "main_content_container")
-        main_window_leaflet.set_visible_child(main_content_container)
-        contact_name_label = self._builder.get_object("contact_name")
-        contact_name_label.set_text(contact_name)
-        self._builder.get_object("chat_menu_button").show()
-
-    def _no_chat_opened(self):
-        main_content_stack = self._builder.get_object("main_content_stack")
-        chat_placeholder = main_content_stack.get_child_by_name(
-            "chat_placeholder")
-        return chat_placeholder.get_visible()
-
-    def _clear_history_container(self):
-        history_container = self._builder.get_object("history_container")
-        children = history_container.get_children()
-        for child in children:
-            child.destroy()
-        if hasattr(self, "_selected_contact"):
-            del self._selected_contact
-
-    # pylint: disable=no-member
-    def _load_content(self):
-        socket_listener = APP().api.socket_listener
-        self._setup_contact_added_listeners(socket_listener)
-        self._setup_message_received_listeners(socket_listener)
-
-    def _setup_contact_added_listeners(self, socket_listener):
-        signal_id = socket_listener.connect("ContactAddedEvent",
-                                            self._notify_contact_added)
-        self._signals.append(signal_id)
-
-    def _setup_message_received_listeners(self, socket_listener):
-        signal_id = socket_listener.connect("ConversationMessageReceivedEvent",
-                                            self._notify_message_received)
-        self._signals.append(signal_id)
-
-    # pylint: disable=unused-argument
-    def _notify_contact_added(self, message):
-        self._notify(
-            _("Contact added"),  # context: "Notification"
-            NOTIFICATION_CONTACT_ADDED
-        )
-
-    # pylint: disable=unused-argument
-    def _notify_message_received(self, message):
-        self._notify(
-            _("New private message"),  # context: "Notification"
-            NOTIFICATION_PRIVATE_MESSAGE
-        )
-
-    @staticmethod
-    def _notify(title, identifier):
-        if APP().window.is_active():
-            return
-        notification = Gio.Notification.new(title)
-        notification.set_priority(Gio.NotificationPriority.HIGH)
-        APP().send_notification(identifier, notification)
-
     def _setup_destroy_listener(self):
         self._main_window_view.connect("destroy", self._on_destroy)
 
@@ -165,32 +85,6 @@ class MainWindowController():
 
     def _disconnect_signals(self):
         self._sidebar_controller.disconnect_signals()
+        self._notification_controller.disconnect_signals()
         for signal in self._signals:
             APP().api.socket_listener.disconnect(signal)
-
-    def _setup_private_chat_widget(self, contact_name, contact_id):
-        self._current_private_chat_widget = PrivateChatContainer(
-            contact_name, contact_id)
-        history_container = self._builder.get_object("history_container")
-        history_container.add(self._current_private_chat_widget)
-        history_container.show_all()
-
-        self._disconnect_chat_entry_signals()
-        chat_entry = self._builder.get_object("chat_entry")
-        self._chat_entry_signal_id = chat_entry.connect(
-            "activate", self._on_chat_entry_activate
-        )
-        chat_entry.grab_focus()
-
-    def _disconnect_chat_entry_signals(self):
-        if not hasattr(self, "_chat_entry_signal_id"):
-            return
-        chat_entry = self._builder.get_object("chat_entry")
-        chat_entry.disconnect(self._chat_entry_signal_id)
-        del self._chat_entry_signal_id
-
-    def _on_chat_entry_activate(self, widget):
-        if len(widget.get_text()) == 0:
-            return
-        self._current_private_chat_widget.send_message(widget)
-        self._refresh_contacts()
diff --git a/briar-gtk/briar_gtk/controllers/notification.py b/briar-gtk/briar_gtk/controllers/notification.py
new file mode 100644
index 0000000..f169e90
--- /dev/null
+++ b/briar-gtk/briar_gtk/controllers/notification.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2020 Nico Alt
+# SPDX-License-Identifier: AGPL-3.0-only
+# License-Filename: LICENSE.md
+
+from gettext import gettext as _
+from gi.repository import Gio
+
+from briar_gtk.define import APP, NOTIFICATION_CONTACT_ADDED
+from briar_gtk.define import NOTIFICATION_PRIVATE_MESSAGE
+
+
+class NotificationController():
+
+    def __init__(self):
+        self._signals = list()
+
+        self._setup_listeners()
+
+    def disconnect_signals(self):
+        for signal in self._signals:
+            APP().api.socket_listener.disconnect(signal)
+
+    def _setup_listeners(self):
+        socket_listener = APP().api.socket_listener
+        self._setup_contact_added_listener(socket_listener)
+        self._setup_message_received_listener(socket_listener)
+
+    def _setup_contact_added_listener(self, socket_listener):
+        signal_id = socket_listener.connect("ContactAddedEvent",
+                                            self._notify_contact_added)
+        self._signals.append(signal_id)
+
+    def _setup_message_received_listener(self, socket_listener):
+        signal_id = socket_listener.connect("ConversationMessageReceivedEvent",
+                                            self._notify_message_received)
+        self._signals.append(signal_id)
+
+    # pylint: disable=unused-argument
+    def _notify_contact_added(self, message):
+        self._notify(
+            _("Contact added"),  # context: "Notification"
+            NOTIFICATION_CONTACT_ADDED
+        )
+
+    # pylint: disable=unused-argument
+    def _notify_message_received(self, message):
+        self._notify(
+            _("New private message"),  # context: "Notification"
+            NOTIFICATION_PRIVATE_MESSAGE
+        )
+
+    @staticmethod
+    def _notify(title, identifier):
+        if APP().window.is_active():
+            return
+        notification = Gio.Notification.new(title)
+        notification.set_priority(Gio.NotificationPriority.HIGH)
+        APP().send_notification(identifier, notification)
diff --git a/briar-gtk/briar_gtk/controllers/private_chat.py b/briar-gtk/briar_gtk/controllers/private_chat.py
index 0799e90..95b7e80 100644
--- a/briar-gtk/briar_gtk/controllers/private_chat.py
+++ b/briar-gtk/briar_gtk/controllers/private_chat.py
@@ -2,21 +2,202 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 # License-Filename: LICENSE.md
 
+from gettext import gettext as _
+from gi.repository import Gtk
+
+from briar_wrapper.models.contacts import Contacts
+from briar_wrapper.models.private_chat import PrivateChat
+
+from briar_gtk.containers.private_chat import PrivateChatContainer
 from briar_gtk.controllers.chat_menu import ChatMenuController
+from briar_gtk.define import APP
 from briar_gtk.views.chat_menu import ChatMenuView
+from briar_gtk.widgets.edit_dialog import EditDialog
 
 
 class PrivateChatController():
 
-    def __init__(self, private_chat_view, api):
+    _current_contact_id = 0
+
+    def __init__(self, private_chat_view, sidebar_controller, builder, api):
         self._private_chat_view = private_chat_view
+        self._sidebar_controller = sidebar_controller
+        self._builder = builder
         self._api = api
 
         self._chat_menu_view = ChatMenuView()
         self._chat_menu_controller = ChatMenuController(
             self._chat_menu_view, api)
 
-        self._load_content()
+    def close_private_chat(self):  # formerly `show_sidebar`
+        main_window_leaflet = self._builder.get_object("main_window_leaflet")
+        main_window_leaflet.set_visible_child(
+            self._builder.get_object("sidebar_box"))
+
+        main_content_stack = self._builder.get_object("main_content_stack")
+        chat_view = main_content_stack.get_child_by_name("chat_view")
+        chat_view.hide()
+
+        chat_placeholder = main_content_stack.get_child_by_name(
+            "chat_placeholder")
+        chat_placeholder.show()
+
+        self._clear_history_container()
+
+        contacts_list_box = self._builder.get_object("contacts_list_box")
+        contacts_list_box.unselect_all()
+
+        contact_name_label = self._builder.get_object("contact_name")
+        contact_name_label.set_text("")
+
+        self._current_contact_id = 0
+        self._builder.get_object("chat_menu_button").hide()
+
+    def open_change_contact_alias_dialog(self):
+        if self._current_contact_id == 0:
+            raise Exception("Can't change contact alias with ID 0")
+
+        confirmation_dialog = EditDialog(
+            parent=APP().window,
+            flags=Gtk.DialogFlags.MODAL,
+            placeholder=self._get_contact_name(self._current_contact_id)
+        )
+
+        confirmation_dialog.set_title(_("Change contact name"))
+
+        response = confirmation_dialog.run()
+        user_alias = confirmation_dialog.get_entry().get_text()
+        confirmation_dialog.destroy()
+        if (response == Gtk.ResponseType.OK) and (user_alias != ''):
+            Contacts(APP().api).set_alias(self._current_contact_id, user_alias)
+            contact_name_label = self._builder.get_object("contact_name")
+            contact_name_label.set_text(user_alias)
+            self._sidebar_controller.refresh_contacts()
+
+    def open_delete_all_messages_dialog(self):
+        if self._current_contact_id == 0:
+            raise Exception("Can't delete all messages with contact ID 0")
+
+        confirmation_dialog = Gtk.MessageDialog(
+            transient_for=APP().window,
+            flags=Gtk.DialogFlags.MODAL,
+            message_type=Gtk.MessageType.WARNING,
+            buttons=Gtk.ButtonsType.OK_CANCEL,
+            text=_("Confirm Message Deletion"),
+        )
+        confirmation_dialog.format_secondary_text(
+            _("Are you sure that you want to delete all messages?")
+        )
+
+        confirmation_dialog.connect("response", self._delete_all_messages)
+        confirmation_dialog.show_all()
+
+    def open_delete_contact_dialog(self):
+        if self._current_contact_id == 0:
+            raise Exception("Can't delete contact with ID 0")
+
+        confirmation_dialog = Gtk.MessageDialog(
+            transient_for=APP().window,
+            flags=Gtk.DialogFlags.MODAL,
+            message_type=Gtk.MessageType.WARNING,
+            buttons=Gtk.ButtonsType.OK_CANCEL,
+            text=_("Confirm Contact Deletion"),
+        )
+        confirmation_dialog.format_secondary_text(
+            _("Are you sure that you want to remove this contact and "
+              "all messages exchanged with this contact?")
+        )
+
+        confirmation_dialog.connect("response", self._delete_contact)
+        confirmation_dialog.show_all()
+
+    def open_private_chat(self, contact_id):
+        contact_name = self._get_contact_name(contact_id)
+        self._prepare_chat_view(contact_name)
+        self._setup_private_chat_widget(contact_name, contact_id)
+        self._current_contact_id = contact_id
+
+    def _get_contact_name(self, contact_id):
+        name = ""
+        for contact in Contacts(APP().api).get():
+            if contact["contactId"] == contact_id:
+                name = contact["author"]["name"]
+                if "alias" in contact:
+                    name = contact["alias"]
+                break
+        return name
+
+    def _delete_all_messages(self, widget, response_id):
+        if response_id == Gtk.ResponseType.OK:
+            private_chat = PrivateChat(APP().api, self._current_contact_id)
+            private_chat.delete_all_messages()
+            self._sidebar_controller.refresh_contacts()
+            self.close_private_chat()
+        widget.destroy()
+
+    def _delete_contact(self, widget, response_id):
+        if response_id == Gtk.ResponseType.OK:
+            Contacts(APP().api).delete(self._current_contact_id)
+            self._sidebar_controller.refresh_contacts()
+            self.close_private_chat()
+        widget.destroy()
+
+    def _prepare_chat_view(self, contact_name):
+        main_content_stack = self._builder.get_object("main_content_stack")
+        chat_placeholder = main_content_stack.get_child_by_name(
+            "chat_placeholder")
+        if self._no_chat_opened():
+            chat_placeholder.hide()
+        else:
+            self._clear_history_container()
+
+        chat_view = main_content_stack.get_child_by_name("chat_view")
+        chat_view.show()
+        main_window_leaflet = self._builder.get_object("main_window_leaflet")
+        main_content_container = self._builder.get_object(
+            "main_content_container")
+        main_window_leaflet.set_visible_child(main_content_container)
+        contact_name_label = self._builder.get_object("contact_name")
+        contact_name_label.set_text(contact_name)
+        self._builder.get_object("chat_menu_button").show()
+
+    def _no_chat_opened(self):
+        main_content_stack = self._builder.get_object("main_content_stack")
+        chat_placeholder = main_content_stack.get_child_by_name(
+            "chat_placeholder")
+        return chat_placeholder.get_visible()
+
+    def _clear_history_container(self):
+        history_container = self._builder.get_object("history_container")
+        children = history_container.get_children()
+        for child in children:
+            child.destroy()
+        if hasattr(self, "_selected_contact"):
+            del self._selected_contact
+
+    def _setup_private_chat_widget(self, contact_name, contact_id):
+        self._current_private_chat_widget = PrivateChatContainer(
+            contact_name, contact_id)
+        history_container = self._builder.get_object("history_container")
+        history_container.add(self._current_private_chat_widget)
+        history_container.show_all()
+
+        self._disconnect_chat_entry_signals()
+        chat_entry = self._builder.get_object("chat_entry")
+        self._chat_entry_signal_id = chat_entry.connect(
+            "activate", self._on_chat_entry_activate
+        )
+        chat_entry.grab_focus()
+
+    def _disconnect_chat_entry_signals(self):
+        if not hasattr(self, "_chat_entry_signal_id"):
+            return
+        chat_entry = self._builder.get_object("chat_entry")
+        chat_entry.disconnect(self._chat_entry_signal_id)
+        del self._chat_entry_signal_id
 
-    def _load_content(self):
-        pass
+    def _on_chat_entry_activate(self, widget):
+        if len(widget.get_text()) == 0:
+            return
+        self._current_private_chat_widget.send_message(widget)
+        self._sidebar_controller.refresh_contacts()
diff --git a/briar-gtk/briar_gtk/views/main_window.py b/briar-gtk/briar_gtk/views/main_window.py
index a574a6b..1481551 100644
--- a/briar-gtk/briar_gtk/views/main_window.py
+++ b/briar-gtk/briar_gtk/views/main_window.py
@@ -5,161 +5,27 @@
 # Initial version based on GNOME Fractal
 # https://gitlab.gnome.org/GNOME/fractal/-/tags/4.2.2
 
-from gettext import gettext as _
-from gi.repository import Gio, GLib, Gtk
+from gi.repository import Gtk
 
-from briar_wrapper.models.contacts import Contacts
-from briar_wrapper.models.private_chat import PrivateChat
-
-from briar_gtk.containers.private_chat import PrivateChatContainer
-from briar_gtk.controllers.main_menu import MainMenuController
-from briar_gtk.controllers.private_chat import PrivateChatController
-from briar_gtk.controllers.sidebar import SidebarController
-from briar_gtk.define import APP, NOTIFICATION_CONTACT_ADDED
-from briar_gtk.define import NOTIFICATION_PRIVATE_MESSAGE
-from briar_gtk.views.main_menu import MainMenuView
-from briar_gtk.views.private_chat import PrivateChatView
-from briar_gtk.views.sidebar import SidebarView
-from briar_gtk.widgets.contact_row import ContactRowWidget
+from briar_gtk.define import APP
 
 
 class MainWindowView(Gtk.Overlay):
 
-    _current_contact_id = 0
-    _current_private_chat_widget = None
-
-    def __init__(self, builder):
+    def __init__(self, builder, window):
         super().__init__()
-        self._builder = builder
-
-        self._setup_view()
-
-    @property
-    def main_window_leaflet(self):
-        return self._builder.get_object("main_window_leaflet")
-
-    @property
-    def contact_name_label(self):
-        return self._builder.get_object("contact_name")
-
-    @property
-    def contacts_list_box(self):
-        return self._builder.get_object("contacts_list_box")
-
-    @property
-    def main_content_stack(self):
-        return self._builder.get_object("main_content_stack")
-
-    @property
-    def main_content_container(self):
-        return self._builder.get_object("main_content_container")
-
-    @property
-    def chat_placeholder(self):
-        return self.main_content_stack.get_child_by_name("chat_placeholder")
-
-    @property
-    def chat_view(self):
-        return self.main_content_stack.get_child_by_name("chat_view")
-
-    @property
-    def history_container(self):
-        return self._builder.get_object("history_container")
-
-    @property
-    def chat_entry(self):
-        return self._builder.get_object("chat_entry")
+        self._setup_view(builder, window)
 
-    def show_sidebar(self):
-        self.main_window_leaflet.set_visible_child(
-            self._builder.get_object("sidebar_box"))
-        self.chat_view.hide()
-        self.chat_placeholder.show()
-        self._clear_history_container()
-        self.contacts_list_box.unselect_all()
-        self.contact_name_label.set_text("")
-        self._current_contact_id = 0
-        self._builder.get_object("chat_menu_button").hide()
+    def _setup_view(self, builder, window):
+        self._setup_main_window_stack(builder)
+        self._setup_headerbar_stack_holder(builder, window)
 
-    def open_delete_all_messages_dialog(self):
-        if self._current_contact_id == 0:
-            raise Exception("Can't delete all messages with contact ID 0")
-
-        confirmation_dialog = Gtk.MessageDialog(
-            transient_for=APP().window,
-            flags=Gtk.DialogFlags.MODAL,
-            message_type=Gtk.MessageType.WARNING,
-            buttons=Gtk.ButtonsType.OK_CANCEL,
-            text=_("Confirm Message Deletion"),
-        )
-        confirmation_dialog.format_secondary_text(
-            _("Are you sure that you want to delete all messages?")
-        )
-
-        confirmation_dialog.connect("response", self._delete_all_messages)
-        confirmation_dialog.show_all()
-
-    def open_delete_contact_dialog(self):
-        if self._current_contact_id == 0:
-            raise Exception("Can't delete contact with ID 0")
-
-        confirmation_dialog = Gtk.MessageDialog(
-            transient_for=APP().window,
-            flags=Gtk.DialogFlags.MODAL,
-            message_type=Gtk.MessageType.WARNING,
-            buttons=Gtk.ButtonsType.OK_CANCEL,
-            text=_("Confirm Contact Deletion"),
-        )
-        confirmation_dialog.format_secondary_text(
-            _("Are you sure that you want to remove this contact and "
-              "all messages exchanged with this contact?")
-        )
-
-        confirmation_dialog.connect("response", self._delete_contact)
-        confirmation_dialog.show_all()
-
-    def _delete_all_messages(self, widget, response_id):
-        if response_id == Gtk.ResponseType.OK:
-            private_chat = PrivateChat(APP().api, self._current_contact_id)
-            private_chat.delete_all_messages()
-            self._refresh_contacts()
-            self.show_sidebar()
-        widget.destroy()
-
-    def _delete_contact(self, widget, response_id):
-        if response_id == Gtk.ResponseType.OK:
-            Contacts(APP().api).delete(self._current_contact_id)
-            self._refresh_contacts()
-            self.show_sidebar()
-        widget.destroy()
-
-    def _disconnect_chat_entry_signals(self):
-        if not hasattr(self, "_chat_entry_signal_id"):
-            return
-        self.chat_entry.disconnect(self._chat_entry_signal_id)
-        del self._chat_entry_signal_id
-
-    def _clear_history_container(self):
-        children = self.history_container.get_children()
-        for child in children:
-            child.destroy()
-        if hasattr(self, "_selected_contact"):
-            del self._selected_contact
-
-    def _setup_view(self):
-        self._setup_main_window_stack()
-        self._setup_headerbar_stack_holder()
-
-    def _setup_main_window_stack(self):
-        main_window_stack = self._builder.get_object("main_window_stack")
+    def _setup_main_window_stack(self, builder):
+        main_window_stack = builder.get_object("main_window_stack")
         main_window_stack.show_all()
         self.add(main_window_stack)
 
-    def _setup_headerbar_stack_holder(self):
-        headerbar_stack_holder = self._builder.get_object(
-            "headerbar_stack_holder")
+    def _setup_headerbar_stack_holder(self, builder, window):
+        headerbar_stack_holder = builder.get_object("headerbar_stack_holder")
         headerbar_stack_holder.show_all()
-        APP().window.set_titlebar(headerbar_stack_holder)
-
-    def _refresh_contacts(self):
-        self._sidebar_controller.refresh_contacts()
+        window.set_titlebar(headerbar_stack_holder)
diff --git a/briar-gtk/briar_gtk/views/private_chat.py b/briar-gtk/briar_gtk/views/private_chat.py
index 61c55c8..515cd01 100644
--- a/briar-gtk/briar_gtk/views/private_chat.py
+++ b/briar-gtk/briar_gtk/views/private_chat.py
@@ -11,6 +11,8 @@ from briar_gtk.define import RESOURCES_DIR
 
 class PrivateChatView():
 
+    _current_private_chat_widget = None
+
     def __init__(self, builder):
         self._builder = builder
         self._setup_view()
diff --git a/briar-gtk/briar_gtk/window.py b/briar-gtk/briar_gtk/window.py
index c12de54..5c85ce3 100644
--- a/briar-gtk/briar_gtk/window.py
+++ b/briar-gtk/briar_gtk/window.py
@@ -103,7 +103,7 @@ class Window(Gtk.ApplicationWindow):
 
     def _setup_main_container(self):
         builder = self._setup_builder()
-        main_window_view = MainWindowView(builder)
+        main_window_view = MainWindowView(builder, self)
         main_window_controller = MainWindowController(
             main_window_view, builder)
         self._setup_container(main_window_view)
-- 
GitLab