From fe7bd794d1802da0c7462f9829e1aa362724ca31 Mon Sep 17 00:00:00 2001
From: lovetox <philipp@hoerist.com>
Date: Mon, 26 Apr 2021 11:44:08 +0200
Subject: [PATCH] Add GroupchatState widget

---
 gajim/data/gui/groupchat_control.ui |  88 +------------------
 gajim/data/gui/groupchat_state.ui   | 128 ++++++++++++++++++++++++++++
 gajim/groupchat_control.py          |  35 +++++---
 gajim/gtk/groupchat_state.py        |  63 ++++++++++++++
 4 files changed, 215 insertions(+), 99 deletions(-)
 create mode 100644 gajim/data/gui/groupchat_state.ui
 create mode 100644 gajim/gtk/groupchat_state.py

diff --git a/gajim/data/gui/groupchat_control.ui b/gajim/data/gui/groupchat_control.ui
index 479993d310..7a3c2a14f6 100644
--- a/gajim/data/gui/groupchat_control.ui
+++ b/gajim/data/gui/groupchat_control.ui
@@ -624,93 +624,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkBox">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <!-- n-columns=3 n-rows=3 -->
-                  <object class="GtkGrid">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <property name="halign">center</property>
-                    <property name="valign">center</property>
-                    <property name="hexpand">True</property>
-                    <property name="vexpand">True</property>
-                    <property name="row-spacing">6</property>
-                    <child>
-                      <object class="GtkSpinner" id="progress_spinner">
-                        <property name="width-request">40</property>
-                        <property name="height-request">40</property>
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="left-attach">0</property>
-                        <property name="top-attach">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can-focus">False</property>
-                        <property name="label" translatable="yes">Joining…</property>
-                        <style>
-                          <class name="bold16"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="left-attach">0</property>
-                        <property name="top-attach">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="abort_button">
-                        <property name="label" translatable="yes">_Abort</property>
-                        <property name="visible">True</property>
-                        <property name="can-focus">True</property>
-                        <property name="receives-default">True</property>
-                        <property name="use-underline">True</property>
-                        <signal name="clicked" handler="_on_abort_button_clicked" swapped="no"/>
-                        <style>
-                          <class name="margin-top12"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="left-attach">0</property>
-                        <property name="top-attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="name">progress</property>
-                <property name="position">1</property>
-              </packing>
+              <placeholder/>
             </child>
             <child>
               <object class="GtkBox">
diff --git a/gajim/data/gui/groupchat_state.ui b/gajim/data/gui/groupchat_state.ui
new file mode 100644
index 0000000000..15afd4e486
--- /dev/null
+++ b/gajim/data/gui/groupchat_state.ui
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface>
+  <requires lib="gtk+" version="3.24"/>
+  <object class="GtkStack" id="groupchat_state">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes">Not joined</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton">
+            <property name="label" translatable="yes">Join Now</property>
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="receives-default">True</property>
+            <signal name="clicked" handler="_on_join_clicked" swapped="no"/>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="name">not-joined</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <child>
+          <object class="GtkSpinner">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="active">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes">Joining</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton">
+            <property name="label" translatable="yes">Abort</property>
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="receives-default">True</property>
+            <signal name="clicked" handler="_on_abort_clicked" swapped="no"/>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="name">joining</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <child>
+          <object class="GtkSpinner">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes">Fetching</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="name">fetching</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/gajim/groupchat_control.py b/gajim/groupchat_control.py
index 2d531d18fb..4b69b23454 100644
--- a/gajim/groupchat_control.py
+++ b/gajim/groupchat_control.py
@@ -49,7 +49,6 @@
 from gajim.common.helpers import event_filter
 from gajim.common.helpers import to_user_string
 from gajim.common.const import AvatarSize
-from gajim.common.const import SimpleClientState
 
 from gajim.common.i18n import _
 from gajim.common.const import MUCJoinedState
@@ -71,6 +70,7 @@
 from gajim.gui.groupchat_invite import GroupChatInvite
 from gajim.gui.groupchat_settings import GroupChatSettings
 from gajim.gui.groupchat_roster import GroupchatRoster
+from gajim.gui.groupchat_state import GroupchatState
 from gajim.gui.util import NickCompletionGenerator
 from gajim.gui.util import get_app_window
 from gajim.gui.util import open_window
@@ -158,7 +158,7 @@ def __init__(self, parent_win, jid, muc_data, acct):
 
         # Banner
         self.hide_roster_button = Gtk.Button.new_from_icon_name(
-            'go-next-symbolic', Gtk.IconSize.MENU)
+            'go-previous-symbolic', Gtk.IconSize.MENU)
         self.hide_roster_button.set_valign(Gtk.Align.CENTER)
         self.hide_roster_button.connect('clicked',
                                         lambda *args: self.show_roster())
@@ -211,6 +211,13 @@ def __init__(self, parent_win, jid, muc_data, acct):
 
         self._set_control_inactive()
 
+        self._groupchat_state = GroupchatState()
+        self._groupchat_state.connect('join-clicked',
+                                      self._on_groupchat_state_join_clicked)
+        self._groupchat_state.connect('abort-clicked',
+                                      self._on_groupchat_state_abort_clicked)
+        self.xml.conv_view_overlay.add_overlay(self._groupchat_state)
+
         # Stack
         self.xml.stack.show_all()
         self.xml.stack.set_visible_child_name('groupchat')
@@ -250,9 +257,13 @@ def _connect_contact_signals(self):
 
     def _on_muc_state_changed(self, _contact, _signal_name):
         state = self.contact.state
+        if state == MUCJoinedState.JOINING:
+            self._groupchat_state.set_joining()
+
         if state == MUCJoinedState.JOINED:
             self._set_control_active()
             self.show_roster()
+            self._groupchat_state.set_joined()
 
         elif state == MUCJoinedState.NOT_JOINED:
             self._set_control_inactive()
@@ -1688,9 +1699,7 @@ def _on_ban_participant_clicked(self, _button):
     def _on_page_change(self, stack, _param):
         page_name = stack.get_visible_child_name()
         if page_name == 'groupchat':
-            self.xml.progress_spinner.stop()
-        elif page_name == 'progress':
-            self.xml.progress_spinner.start()
+            pass
         elif page_name == 'muc-info':
             self.xml.info_close_button.grab_default()
         elif page_name == 'password':
@@ -1781,7 +1790,7 @@ def _on_password_set_clicked(self, _button):
         password = self.xml.password_entry.get_text()
         self._muc_data.password = password
         self._client.get_module('MUC').join(self._muc_data)
-        self._show_page('progress')
+        self._show_page('groupchat')
 
     def _on_password_changed(self, entry, _param):
         self.xml.password_set_button.set_sensitive(bool(entry.get_text()))
@@ -1829,7 +1838,7 @@ def _on_captcha_set_clicked(self, _button):
         form_node = self._captcha_request.get_submit_form()
         self._client.get_module('MUC').send_captcha(self.room_jid, form_node)
         self._remove_captcha_request()
-        self._show_page('progress')
+        self._show_page('groupchat')
 
     def _on_captcha_cancel_clicked(self, _button=None):
         self._client.get_module('MUC').cancel_captcha(self.room_jid)
@@ -1838,7 +1847,7 @@ def _on_captcha_cancel_clicked(self, _button=None):
 
     def _on_captcha_try_again_clicked(self, _button=None):
         self._client.get_module('MUC').join(self._muc_data)
-        self._show_page('progress')
+        self._show_page('groupchat')
 
     def _on_remove_bookmark_button_clicked(self, _button=None):
         self._client.get_module('Bookmarks').remove(self.room_jid)
@@ -1846,7 +1855,7 @@ def _on_remove_bookmark_button_clicked(self, _button=None):
 
     def _on_retry_join_clicked(self, _button=None):
         self._client.get_module('MUC').join(self._muc_data)
-        self._show_page('progress')
+        self._show_page('groupchat')
 
     def _on_page_cancel_clicked(self, _button=None):
         self._show_page('groupchat')
@@ -1854,6 +1863,8 @@ def _on_page_cancel_clicked(self, _button=None):
     def _on_page_close_clicked(self, _button=None):
         self._close_control()
 
-    def _on_abort_button_clicked(self, _button):
-        self.parent_win.window.lookup_action(
-            'disconnect-%s' % self.control_id).activate()
+    def _on_groupchat_state_abort_clicked(self, _button):
+        app.window.lookup_action('disconnect-%s' % self.control_id).activate()
+
+    def _on_groupchat_state_join_clicked(self, groupchat_state):
+        pass
diff --git a/gajim/gtk/groupchat_state.py b/gajim/gtk/groupchat_state.py
new file mode 100644
index 0000000000..4635d7eb4c
--- /dev/null
+++ b/gajim/gtk/groupchat_state.py
@@ -0,0 +1,63 @@
+# This file is part of Gajim.
+#
+# Gajim is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; version 3 only.
+#
+# Gajim is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
+
+
+from gi.repository import Gtk
+from gi.repository import GObject
+
+from gajim.gui.util import get_builder
+
+
+class GroupchatState(Gtk.Box):
+
+    __gsignals__ = {
+        'join-clicked': (
+            GObject.SignalFlags.RUN_FIRST,
+            None,
+            ()),
+        'abort-clicked': (
+            GObject.SignalFlags.RUN_FIRST,
+            None,
+            ()),
+    }
+
+    def __init__(self):
+        Gtk.Box.__init__(self)
+
+        self.set_halign(Gtk.Align.CENTER)
+        self.set_valign(Gtk.Align.END)
+
+        self._ui = get_builder('groupchat_state.ui')
+        self._ui.connect_signals(self)
+        self.add(self._ui.groupchat_state)
+        self.show_all()
+
+    def set_joining(self):
+        self._ui.groupchat_state.set_visible_child_name('joining')
+
+    def set_joined(self):
+        self.hide()
+
+    def set_not_joined(self):
+        self._ui.groupchat_state.set_visible_child_name('not-joining')
+        self.show()
+
+    def set_fetching(self):
+        self._ui.groupchat_state.set_visible_child_name('fetching')
+
+    def _on_join_clicked(self, _button):
+        self.emit('join-clicked')
+
+    def _on_abort_clicked(self, _button):
+        self.emit('abort-clicked')
-- 
GitLab