diff --git a/briar-gtk/briar_gtk/controllers/main_window.py b/briar-gtk/briar_gtk/controllers/main_window.py
index 9a67c227a277fd2423a91bfbe475413897d6a8e4..772ec56ade58c4a4f53eb3834342b5a4d6fe606c 100644
--- a/briar-gtk/briar_gtk/controllers/main_window.py
+++ b/briar-gtk/briar_gtk/controllers/main_window.py
@@ -27,24 +27,36 @@ class MainWindowController:
         about_dialog.show()
 
     def open_change_contact_alias_dialog(self):
-        self._private_chat_controller.open_change_contact_alias_dialog()
+        if self._private_chat_controller is not None:
+            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()
+        if self._private_chat_controller is not None:
+            self._private_chat_controller.open_delete_all_messages_dialog()
 
     def open_delete_contact_dialog(self):
-        self._private_chat_controller.open_delete_contact_dialog()
+        if self._private_chat_controller is not None:
+            self._private_chat_controller.open_delete_contact_dialog()
 
     def close_private_chat(self):
-        self._private_chat_controller.close_private_chat()
+        if self._private_chat_controller is not None:
+            self._private_chat_controller.close_private_chat()
+            self._private_chat_controller = None
 
     def open_private_chat(self, contact_id):
-        self._private_chat_controller.open_private_chat(contact_id)
+        if self._private_chat_controller is not None:
+            raise Exception("Private Chat is already open")
+        private_chat_view = PrivateChatView(self._builder)
+        self._private_chat_controller = PrivateChatController(
+            contact_id, private_chat_view, self._sidebar_controller,
+            self._builder, APP().api)
 
     def _setup_children(self):
         self._setup_notification_handler()
         self._setup_sidebar_controller()
-        self._setup_private_chat_controller()
+        self._private_chat_controller = None
+        contact_name_label = self._builder.get_object("contact_name")
+        contact_name_label.set_text("")
 
     def _setup_notification_handler(self):
         self._notification_handler = NotificationHandler()
@@ -54,12 +66,6 @@ class MainWindowController:
         self._sidebar_controller = SidebarController(
             sidebar_view, APP().api)
 
-    def _setup_private_chat_controller(self):
-        private_chat_view = PrivateChatView(self._builder)
-        self._private_chat_controller = PrivateChatController(
-            private_chat_view, self._sidebar_controller,
-            self._builder, APP().api)
-
     def _setup_destroy_listener(self):
         self._main_window_view.connect("destroy", self._on_destroy)
 
diff --git a/briar-gtk/briar_gtk/controllers/private_chat.py b/briar-gtk/briar_gtk/controllers/private_chat.py
index 45bf8f7a40eca26de3a6843d1fe4a3f98f3c0e25..45e98a726f466e9e32f7f8d6700611684612a7e7 100644
--- a/briar-gtk/briar_gtk/controllers/private_chat.py
+++ b/briar-gtk/briar_gtk/controllers/private_chat.py
@@ -8,7 +8,6 @@ from gi.repository import Gtk
 from briar_wrapper.models.contacts import Contacts
 from briar_wrapper.models.private_chat import PrivateChat
 
-from briar_gtk.private_chat_container import PrivateChatContainer
 from briar_gtk.define import APP
 from briar_gtk.widgets.edit_dialog import EditDialog
 
@@ -16,11 +15,12 @@ from briar_gtk.widgets.edit_dialog import EditDialog
 class PrivateChatController:
     _current_contact_id = 0
 
-    def __init__(self, private_chat_view, sidebar_controller, builder, api):
+    def __init__(self, contact_id, 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.open_private_chat(contact_id)
 
     def close_private_chat(self):  # formerly `show_sidebar`
         main_window_leaflet = self._builder.get_object("main_window_leaflet")
@@ -105,9 +105,10 @@ class PrivateChatController:
         confirmation_dialog.show_all()
 
     def open_private_chat(self, contact_id):
+        print(f"Contact id: {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._setup_private_chat_widget(contact_id)
         self._current_contact_id = contact_id
 
     @staticmethod
@@ -167,11 +168,11 @@ class PrivateChatController:
         for child in children:
             child.destroy()
 
-    def _setup_private_chat_widget(self, contact_name, contact_id):
-        self._current_private_chat_widget = PrivateChatContainer(
-            contact_name, contact_id)
+    def _setup_private_chat_widget(self, contact_id):
+        self._private_chat_view.setup_view(contact_id)
+        self._private_chat_view.load_content()
         history_container = self._builder.get_object("history_container")
-        history_container.add(self._current_private_chat_widget)
+        history_container.add(self._private_chat_view)
         history_container.show_all()
 
         self._disconnect_chat_entry_signals()
@@ -191,5 +192,5 @@ class PrivateChatController:
     def _on_chat_entry_activate(self, widget):
         if len(widget.get_text()) == 0:
             return
-        self._current_private_chat_widget.send_message(widget)
+        self._private_chat_view.send_message(widget)
         self._sidebar_controller.refresh_contacts()
diff --git a/briar-gtk/briar_gtk/private_chat_container.py b/briar-gtk/briar_gtk/private_chat_container.py
deleted file mode 100644
index 7a2d76893db414249429511cf1fb115ea120d3a4..0000000000000000000000000000000000000000
--- a/briar-gtk/briar_gtk/private_chat_container.py
+++ /dev/null
@@ -1,160 +0,0 @@
-# Copyright (c) 2019 Nico Alt
-# SPDX-License-Identifier: AGPL-3.0-only
-# License-Filename: LICENSE.md
-#
-# Initial version based on GNOME Fractal
-# https://gitlab.gnome.org/GNOME/fractal/-/tags/4.2.2
-import os
-import time
-
-from gi.repository import GLib, Gtk, Handy
-
-from briar_wrapper.models.private_chat import PrivateChat
-
-from briar_gtk.define import APP, RESOURCES_DIR
-from briar_gtk.widgets.private_message import PrivateMessageWidget
-
-
-class PrivateChatContainer(Gtk.Overlay):
-
-    CONTAINER_UI = "private_chat.ui"
-
-    def __init__(self, contact_name, contact_id):
-        super().__init__()
-        self.builder = Gtk.Builder()
-
-        self._signals = list()
-        self._contact_name = contact_name
-        self._contact_id = contact_id
-        self._previous_message = dict()
-
-        self._setup_view()
-        self._load_content()
-
-    def send_message(self, widget):
-        message = widget.get_text()
-        private_chat = PrivateChat(APP().api, self._contact_id)
-        private_chat.send(message)
-
-        self._add_message(
-            {
-                "text": message,
-                "local": True,
-                "sent": False,
-                "seen": False,
-
-                # TODO: Remove once web events updating is implemented
-                "no_stored_indicator": True,
-
-                "timestamp": int(round(time.time() * 1000))
-            })
-        widget.set_text("")
-        GLib.idle_add(self._scroll_to_bottom)
-
-    def _setup_view(self):
-        self._add_from_resource(self.CONTAINER_UI)
-
-        self._messages_box = Gtk.ListBox()
-        self._messages_box.get_style_context().add_class("messages-history")
-        self._messages_box.show()
-
-        clamp = Handy.Clamp.new()
-        clamp.set_maximum_size(800)
-        clamp.set_tightening_threshold(600)
-        clamp.set_hexpand(True)
-        clamp.set_vexpand(True)
-        clamp.add(self._messages_box)
-        clamp.show()
-
-        messages_column = self.builder.get_object("messages_column")
-        messages_column.get_style_context().add_class("messages-box")
-        messages_column.add(clamp)
-        messages_column.show()
-
-        messages_scroll = self.builder.get_object("messages_scroll")
-        self._draw_signal_id = messages_scroll.connect(
-            "draw", self._on_message_scroll_draw
-        )
-        self.add(messages_scroll)
-
-        self.builder.connect_signals(self)
-        self._setup_destroy_listener()
-
-    def _add_from_resource(self, ui_filename):
-        self.builder.add_from_resource(
-            os.path.join(RESOURCES_DIR, ui_filename)
-        )
-
-    def _setup_destroy_listener(self):
-        self.connect("destroy", self._on_destroy)
-
-    # pylint: disable=unused-argument
-    def _on_destroy(self, widget):
-        self._disconnect_signals()
-
-    def _disconnect_signals(self):
-        for signal in self._signals:
-            APP().api.socket_listener.disconnect(signal)
-
-    def _load_content(self):
-        private_chat = PrivateChat(APP().api, self._contact_id)
-        messages_list = private_chat.get()
-        self._messages_count = len(messages_list)
-        for message in messages_list:
-            # Abusing idle_add function here because otherwise the message box
-            # is too small and scrolling cuts out messages
-            GLib.idle_add(self._add_message, message)
-            if message.get("read", True) is False:
-                GLib.idle_add(private_chat.mark_read, message["id"])
-        socket_listener = APP().api.socket_listener
-        signal_id = socket_listener.connect("ConversationMessageReceivedEvent",
-                                            self._add_message_async)
-        self._signals.append(signal_id)
-
-    def _add_message(self, message):
-        if self._is_not_message(message):
-            return
-        message_widget = PrivateMessageWidget(
-            self._contact_name,
-            message,
-            self._previous_message
-        )
-        self._previous_message = message
-        self._messages_box.add(message_widget)
-
-    @staticmethod
-    def _is_not_message(message):
-        return "text" not in message
-
-    def _add_message_async(self, message):
-        if message["data"]["contactId"] != self._contact_id:
-            return
-        GLib.idle_add(self._add_message_and_scroll, message["data"])
-        if message["data"].get("read", True) is False:
-            private_chat = PrivateChat(APP().api, self._contact_id)
-            GLib.idle_add(private_chat.mark_read, message["data"]["id"])
-
-    def _add_message_and_scroll(self, message):
-        self._add_message(message)
-        GLib.idle_add(self._scroll_to_bottom)
-
-    # pylint: disable=unused-argument
-    def _on_message_scroll_draw(self, widget, cairo_context):
-        self._scroll_to_bottom()
-        if self._draw_signal_is_not_needed():
-            widget.disconnect(self._draw_signal_id)
-
-    def _scroll_to_bottom(self):
-        messages_scroll = self.builder.get_object("messages_scroll")
-        adjustment = messages_scroll.get_vadjustment()
-        adjustment.set_value(
-            adjustment.get_upper() - adjustment.get_page_size()
-        )
-
-    def _draw_signal_is_not_needed(self):
-        if self._messages_count == 0:
-            return True
-
-        messages_scroll = self.builder.get_object("messages_scroll")
-        adjustment = messages_scroll.get_vadjustment()
-        return adjustment.get_value() != 0
diff --git a/briar-gtk/briar_gtk/views/private_chat.py b/briar-gtk/briar_gtk/views/private_chat.py
index 2acb4f561e3f1a42fa929fded8fa79df1fcddc41..73ffea7dffb45249d4b424946967ea8b1af5f7b2 100644
--- a/briar-gtk/briar_gtk/views/private_chat.py
+++ b/briar-gtk/briar_gtk/views/private_chat.py
@@ -1,14 +1,158 @@
-# Copyright (c) 2020 Nico Alt
+# Copyright (c) 2019-2020 Nico Alt
 # SPDX-License-Identifier: AGPL-3.0-only
 # License-Filename: LICENSE.md
+#
+# Initial version based on GNOME Fractal
+# https://gitlab.gnome.org/GNOME/fractal/-/tags/4.2.2
+import os
+import time
 
+from gi.repository import GLib, Gtk, Handy
 
-class PrivateChatView:
+from briar_wrapper.models.private_chat import PrivateChat
+
+from briar_gtk.define import APP, RESOURCES_DIR
+from briar_gtk.widgets.private_message import PrivateMessageWidget
+
+
+class PrivateChatView(Gtk.Overlay):
+
+    CONTAINER_UI = "private_chat.ui"
 
     def __init__(self, builder):
-        self._builder = builder
-        self._setup_view()
+        super().__init__()
+        self.builder = builder
+
+        self._signals = list()
+        self._contact_name = ""
+        self._contact_id = -1
+        self._previous_message = dict()
+
+    def send_message(self, widget):
+        message = widget.get_text()
+        private_chat = PrivateChat(APP().api, self._contact_id)
+        private_chat.send(message)
+
+        self._add_message(
+            {
+                "text": message,
+                "local": True,
+                "sent": False,
+                "seen": False,
+
+                # TODO: Remove once web events updating is implemented
+                "no_stored_indicator": True,
+
+                "timestamp": int(round(time.time() * 1000))
+            })
+        widget.set_text("")
+        GLib.idle_add(self._scroll_to_bottom)
+
+    def setup_view(self, contact_id):
+        self._contact_id = contact_id
+        self._add_from_resource(self.CONTAINER_UI)
+
+        self._messages_box = Gtk.ListBox()
+        self._messages_box.get_style_context().add_class("messages-history")
+        self._messages_box.show()
+
+        clamp = Handy.Clamp.new()
+        clamp.set_maximum_size(800)
+        clamp.set_tightening_threshold(600)
+        clamp.set_hexpand(True)
+        clamp.set_vexpand(True)
+        clamp.add(self._messages_box)
+        clamp.show()
+
+        messages_column = self.builder.get_object("messages_column")
+        messages_column.get_style_context().add_class("messages-box")
+        messages_column.add(clamp)
+        messages_column.show()
+
+        messages_scroll = self.builder.get_object("messages_scroll")
+        self._draw_signal_id = messages_scroll.connect(
+            "draw", self._on_message_scroll_draw
+        )
+        self.add(messages_scroll)
+
+        self.builder.connect_signals(self)
+        self._setup_destroy_listener()
+
+    def _add_from_resource(self, ui_filename):
+        self.builder.add_from_resource(
+            os.path.join(RESOURCES_DIR, ui_filename)
+        )
+
+    def _setup_destroy_listener(self):
+        self.connect("destroy", self._on_destroy)
+
+    # pylint: disable=unused-argument
+    def _on_destroy(self, widget):
+        self._disconnect_signals()
+
+    def _disconnect_signals(self):
+        for signal in self._signals:
+            APP().api.socket_listener.disconnect(signal)
+
+    def load_content(self):
+        private_chat = PrivateChat(APP().api, self._contact_id)
+        messages_list = private_chat.get()
+        self._messages_count = len(messages_list)
+        for message in messages_list:
+            # Abusing idle_add function here because otherwise the message box
+            # is too small and scrolling cuts out messages
+            GLib.idle_add(self._add_message, message)
+            if message.get("read", True) is False:
+                GLib.idle_add(private_chat.mark_read, message["id"])
+        socket_listener = APP().api.socket_listener
+        signal_id = socket_listener.connect("ConversationMessageReceivedEvent",
+                                            self._add_message_async)
+        self._signals.append(signal_id)
+
+    def _add_message(self, message):
+        if self._is_not_message(message):
+            return
+        message_widget = PrivateMessageWidget(
+            self._contact_name,
+            message,
+            self._previous_message
+        )
+        self._previous_message = message
+        self._messages_box.add(message_widget)
+
+    @staticmethod
+    def _is_not_message(message):
+        return "text" not in message
+
+    def _add_message_async(self, message):
+        if message["data"]["contactId"] != self._contact_id:
+            return
+        GLib.idle_add(self._add_message_and_scroll, message["data"])
+        if message["data"].get("read", True) is False:
+            private_chat = PrivateChat(APP().api, self._contact_id)
+            GLib.idle_add(private_chat.mark_read, message["data"]["id"])
+
+    def _add_message_and_scroll(self, message):
+        self._add_message(message)
+        GLib.idle_add(self._scroll_to_bottom)
+
+    # pylint: disable=unused-argument
+    def _on_message_scroll_draw(self, widget, cairo_context):
+        self._scroll_to_bottom()
+        if self._draw_signal_is_not_needed():
+            widget.disconnect(self._draw_signal_id)
+
+    def _scroll_to_bottom(self):
+        messages_scroll = self.builder.get_object("messages_scroll")
+        adjustment = messages_scroll.get_vadjustment()
+        adjustment.set_value(
+            adjustment.get_upper() - adjustment.get_page_size()
+        )
+
+    def _draw_signal_is_not_needed(self):
+        if self._messages_count == 0:
+            return True
 
-    def _setup_view(self):
-        contact_name_label = self._builder.get_object("contact_name")
-        contact_name_label.set_text("")
+        messages_scroll = self.builder.get_object("messages_scroll")
+        adjustment = messages_scroll.get_vadjustment()
+        return adjustment.get_value() != 0