[fractal] login: Show network state



commit 44c96d3d4c1a1cd5eeec37b0b7302c08f93ac647
Author: Julian Sparber <julian sparber net>
Date:   Mon Jul 25 23:44:41 2022 +0200

    login: Show network state
    
    This only disables navigation when no network is available, since the
    homeserver may be on a local network.

 data/resources/ui/greeter.ui | 21 +++++++++++++++++-
 data/resources/ui/login.ui   | 19 ++++++++++++++++
 po/POTFILES.in               |  1 +
 src/greeter.rs               | 45 +++++++++++++++++++++++++++++++++++--
 src/login/mod.rs             | 53 +++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 133 insertions(+), 6 deletions(-)
---
diff --git a/data/resources/ui/greeter.ui b/data/resources/ui/greeter.ui
index b36ba6dba..2a85b249e 100644
--- a/data/resources/ui/greeter.ui
+++ b/data/resources/ui/greeter.ui
@@ -29,7 +29,7 @@
               <object class="GtkBox">
                 <property name="orientation">vertical</property>
                 <child>
-                  <object class="GtkInfoBar">
+                  <object class="GtkInfoBar" id="development_info_bar">
                     <property name="message-type">warning</property>
                     <child>
                       <object class="AdwClamp">
@@ -47,6 +47,24 @@
                     </child>
                   </object>
                 </child>
+                <child>
+                  <object class="GtkInfoBar" id="offline_info_bar">
+                    <property name="message-type">warning</property>
+                    <child>
+                      <object class="AdwClamp">
+                        <property name="maximum-size">440</property>
+                        <property name="tightening-threshold">340</property>
+                        <property name="hexpand">true</property>
+                        <child>
+                          <object class="GtkLabel" id="offline_info_bar_label">
+                            <property name="justify">center</property>
+                            <property name="wrap">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
                 <child>
                   <object class="AdwClamp">
                     <property name="maximum-size">440</property>
@@ -136,3 +154,4 @@
     </child>
   </template>
 </interface>
+
diff --git a/data/resources/ui/login.ui b/data/resources/ui/login.ui
index 79b29620c..8b0d3e84e 100644
--- a/data/resources/ui/login.ui
+++ b/data/resources/ui/login.ui
@@ -28,6 +28,24 @@
             </child>
           </object>
         </child>
+        <child>
+          <object class="GtkInfoBar" id="offline_info_bar">
+            <property name="message-type">warning</property>
+            <child>
+              <object class="AdwClamp">
+                <property name="maximum-size">440</property>
+                <property name="tightening-threshold">340</property>
+                <property name="hexpand">true</property>
+                <child>
+                  <object class="GtkLabel" id="offline_info_bar_label">
+                    <property name="justify">center</property>
+                    <property name="wrap">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
         <child>
           <object class="GtkStack" id="main_stack">
             <property name="transition-type">crossfade</property>
@@ -229,3 +247,4 @@
     </child>
   </template>
 </interface>
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 65c52c28c..6c9b4d2c0 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -45,6 +45,7 @@ src/components/editable_avatar.rs
 src/components/location_viewer.rs
 src/components/media_content_viewer.rs
 src/error_page.rs
+src/greeter.rs
 src/login/mod.rs
 src/secret.rs
 src/session/account_settings/devices_page/device_list.rs
diff --git a/src/greeter.rs b/src/greeter.rs
index 0eb5745d4..8517e320d 100644
--- a/src/greeter.rs
+++ b/src/greeter.rs
@@ -1,5 +1,7 @@
 use adw::subclass::prelude::BinImpl;
-use gtk::{self, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
+use gtk::{self, gio, glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
+
+use crate::gettext;
 
 mod imp {
     use glib::subclass::InitializingObject;
@@ -13,6 +15,12 @@ mod imp {
         pub back_button: TemplateChild<gtk::Button>,
         #[template_child]
         pub login_button: TemplateChild<gtk::Button>,
+        #[template_child]
+        pub development_info_bar: TemplateChild<gtk::InfoBar>,
+        #[template_child]
+        pub offline_info_bar: TemplateChild<gtk::InfoBar>,
+        #[template_child]
+        pub offline_info_bar_label: TemplateChild<gtk::Label>,
     }
 
     #[glib::object_subclass]
@@ -31,7 +39,18 @@ mod imp {
         }
     }
 
-    impl ObjectImpl for Greeter {}
+    impl ObjectImpl for Greeter {
+        fn constructed(&self, obj: &Self::Type) {
+            self.parent_constructed(obj);
+
+            let monitor = gio::NetworkMonitor::default();
+            monitor.connect_network_changed(clone!(@weak obj => move |_, _| {
+                obj.update_network_state();
+            }));
+
+            obj.update_network_state();
+        }
+    }
 
     impl WidgetImpl for Greeter {}
 
@@ -51,6 +70,28 @@ impl Greeter {
     pub fn default_widget(&self) -> gtk::Widget {
         self.imp().login_button.get().upcast()
     }
+
+    fn update_network_state(&self) {
+        let priv_ = self.imp();
+        let monitor = gio::NetworkMonitor::default();
+
+        if !monitor.is_network_available() {
+            priv_.development_info_bar.set_revealed(false);
+            priv_
+                .offline_info_bar_label
+                .set_label(&gettext("No network connection"));
+            priv_.offline_info_bar.set_revealed(true);
+        } else if monitor.connectivity() < gio::NetworkConnectivity::Full {
+            priv_.development_info_bar.set_revealed(false);
+            priv_
+                .offline_info_bar_label
+                .set_label(&gettext("No Internet connection"));
+            priv_.offline_info_bar.set_revealed(true);
+        } else {
+            priv_.development_info_bar.set_revealed(true);
+            priv_.offline_info_bar.set_revealed(false);
+        }
+    }
 }
 
 impl Default for Greeter {
diff --git a/src/login/mod.rs b/src/login/mod.rs
index d093e26ee..65ea55645 100644
--- a/src/login/mod.rs
+++ b/src/login/mod.rs
@@ -1,6 +1,6 @@
 use adw::{prelude::*, subclass::prelude::BinImpl};
 use gettextrs::gettext;
-use gtk::{self, glib, glib::clone, subclass::prelude::*, CompositeTemplate};
+use gtk::{self, gio, glib, glib::clone, subclass::prelude::*, CompositeTemplate};
 use log::{debug, warn};
 use matrix_sdk::{
     config::RequestConfig,
@@ -63,6 +63,10 @@ mod imp {
         pub sso_box: TemplateChild<gtk::Box>,
         #[template_child]
         pub more_sso_option: TemplateChild<gtk::Button>,
+        #[template_child]
+        pub offline_info_bar: TemplateChild<gtk::InfoBar>,
+        #[template_child]
+        pub offline_info_bar_label: TemplateChild<gtk::Label>,
         pub prepared_source_id: RefCell<Option<SignalHandlerId>>,
         pub logged_out_source_id: RefCell<Option<SignalHandlerId>>,
         pub ready_source_id: RefCell<Option<SignalHandlerId>>,
@@ -159,6 +163,13 @@ mod imp {
 
             self.parent_constructed(obj);
 
+            let monitor = gio::NetworkMonitor::default();
+            monitor.connect_network_changed(clone!(@weak obj => move |_, _| {
+                obj.update_network_state();
+            }));
+
+            obj.update_network_state();
+
             self.main_stack
                 .connect_visible_child_notify(clone!(@weak obj => move |_|
                     obj.update_next_action();
@@ -279,13 +290,21 @@ impl Login {
                 } else {
                     build_homeserver_url(homeserver.as_str()).is_ok()
                 };
-                self.action_set_enabled("login.next", enabled);
+                self.action_set_enabled(
+                    "login.next",
+                    enabled && gio::NetworkMonitor::default().is_network_available(),
+                );
                 priv_.next_button.set_visible(true);
             }
             "password" => {
                 let username_length = priv_.username_entry.text().len();
                 let password_length = priv_.password_entry.text().len();
-                self.action_set_enabled("login.next", username_length != 0 && password_length != 0);
+                self.action_set_enabled(
+                    "login.next",
+                    username_length != 0
+                        && password_length != 0
+                        && gio::NetworkMonitor::default().is_network_available(),
+                );
                 priv_.next_button.set_visible(true);
             }
             _ => {
@@ -633,6 +652,34 @@ impl Login {
             .and_then(|root| root.downcast().ok())
             .expect("Login needs to have a parent window")
     }
+
+    fn update_network_state(&self) {
+        let priv_ = self.imp();
+        let monitor = gio::NetworkMonitor::default();
+
+        if !monitor.is_network_available() {
+            priv_
+                .offline_info_bar_label
+                .set_label(&gettext("No network connection"));
+            priv_.offline_info_bar.set_revealed(true);
+            self.update_next_action();
+            priv_.sso_box.set_sensitive(false);
+            priv_.more_sso_option.set_sensitive(false);
+        } else if monitor.connectivity() < gio::NetworkConnectivity::Full {
+            priv_
+                .offline_info_bar_label
+                .set_label(&gettext("No Internet connection"));
+            priv_.offline_info_bar.set_revealed(true);
+            self.update_next_action();
+            priv_.sso_box.set_sensitive(true);
+            priv_.more_sso_option.set_sensitive(true);
+        } else {
+            priv_.offline_info_bar.set_revealed(false);
+            self.update_next_action();
+            priv_.sso_box.set_sensitive(true);
+            priv_.more_sso_option.set_sensitive(true);
+        }
+    }
 }
 
 impl Default for Login {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]