diff --git a/data/resources/ui/greeter.ui b/data/resources/ui/greeter.ui index b36ba6db..2a85b249 100644 --- a/data/resources/ui/greeter.ui +++ b/data/resources/ui/greeter.ui @@ -29,7 +29,7 @@ vertical - + warning @@ -47,6 +47,24 @@ + + + warning + + + 440 + 340 + true + + + center + True + + + + + + 440 @@ -136,3 +154,4 @@ + diff --git a/data/resources/ui/login.ui b/data/resources/ui/login.ui index 79b29620..8b0d3e84 100644 --- a/data/resources/ui/login.ui +++ b/data/resources/ui/login.ui @@ -28,6 +28,24 @@ + + + warning + + + 440 + 340 + true + + + center + True + + + + + + crossfade @@ -229,3 +247,4 @@ + diff --git a/po/POTFILES.in b/po/POTFILES.in index 65c52c28..6c9b4d2c 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 0eb5745d..8517e320 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, #[template_child] pub login_button: TemplateChild, + #[template_child] + pub development_info_bar: TemplateChild, + #[template_child] + pub offline_info_bar: TemplateChild, + #[template_child] + pub offline_info_bar_label: TemplateChild, } #[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 d093e26e..65ea5564 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, #[template_child] pub more_sso_option: TemplateChild, + #[template_child] + pub offline_info_bar: TemplateChild, + #[template_child] + pub offline_info_bar_label: TemplateChild, pub prepared_source_id: RefCell>, pub logged_out_source_id: RefCell>, pub ready_source_id: RefCell>, @@ -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 {