[geary/wip/17-noisy-problem-reports: 5/12] Add initial support for showing/hiding account status as it changes



commit e7c6da94966bf4cf93c9e05eb1026eaebc945200
Author: Michael Gratton <mike vee net>
Date:   Sun Dec 30 22:40:04 2018 +1100

    Add initial support for showing/hiding account status as it changes
    
    Add infobars for offline, service problems, auth & cert problems. Show
    offline and service problem infobars as needed.

 src/client/application/geary-controller.vala |  68 +++++-
 src/client/components/main-window.vala       |  54 ++++-
 ui/main-window.ui                            | 349 ++++++++++++++++++++++++++-
 3 files changed, 453 insertions(+), 18 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index dda59ec8..3eb6a3d9 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -88,6 +88,29 @@ public class GearyController : Geary.BaseObject {
             this.store = new Geary.App.EmailStore(account);
         }
 
+        public Geary.Account.Status get_effective_status() {
+            Geary.Account.Status current = this.account.current_status;
+            Geary.Account.Status effective = 0;
+            if (current.is_online()) {
+                effective |= ONLINE;
+            }
+            if (current.has_service_problem()) {
+                // Only retain this flag if the problem isn't auth or
+                // cert related, that is handled elsewhere.
+                Geary.ClientService.Status incoming =
+                    account.incoming.current_status;
+                Geary.ClientService.Status outgoing =
+                    account.outgoing.current_status;
+                if (incoming != AUTHENTICATION_FAILED &&
+                    incoming != TLS_VALIDATION_FAILED &&
+                    outgoing != AUTHENTICATION_FAILED &&
+                    outgoing != TLS_VALIDATION_FAILED) {
+                    effective |= SERVICE_PROBLEM;
+                }
+            }
+            return effective;
+        }
+
     }
 
 
@@ -601,6 +624,9 @@ public class GearyController : Geary.BaseObject {
     }
 
     private void open_account(Geary.Account account) {
+        account.notify["current-status"].connect(
+            on_account_status_notify
+        );
         account.report_problem.connect(on_report_problem);
         connect_account_async.begin(account, cancellable_open_account);
 
@@ -608,16 +634,18 @@ public class GearyController : Geary.BaseObject {
         account.contacts_loaded.connect(list_store.set_sort_function);
     }
 
-    private async void close_account(Geary.AccountInformation info) {
-        AccountContext? context = this.accounts.get(info);
+    private async void close_account(Geary.AccountInformation config) {
+        AccountContext? context = this.accounts.get(config);
         if (context != null) {
-            Geary.ContactStore contact_store = context.account.get_contact_store();
-            ContactListStore list_store = this.contact_list_store_cache.get(contact_store);
+            Geary.Account account = context.account;
+            Geary.ContactStore contact_store = account.get_contact_store();
+            ContactListStore list_store =
+                this.contact_list_store_cache.get(contact_store);
 
-            context.account.contacts_loaded.disconnect(list_store.set_sort_function);
+            account.contacts_loaded.disconnect(list_store.set_sort_function);
             this.contact_list_store_cache.unset(contact_store);
 
-            if (this.current_account == context.account) {
+            if (this.current_account == account) {
                 this.current_account = null;
 
                 previous_non_search_folder = null;
@@ -626,9 +654,12 @@ public class GearyController : Geary.BaseObject {
                 cancel_folder();
             }
 
-            // Stop showing errors when closing the account - the user
-            // doesn't care
-            context.account.report_problem.disconnect(on_report_problem);
+            // Stop updating status and showing errors when closing
+            // the account - the user doesn't care any more
+            account.report_problem.disconnect(on_report_problem);
+            account.notify["current-status"].disconnect(
+                on_account_status_notify
+            );
 
             yield disconnect_account_async(context);
         }
@@ -858,6 +889,21 @@ public class GearyController : Geary.BaseObject {
         }
     }
 
+    private void update_account_status() {
+        Geary.Account.Status effective_status =
+            this.accounts.values.fold<Geary.Account.Status>(
+                (ctx, status) => ctx.get_effective_status() | status,
+                0
+            );
+
+        foreach (Gtk.Window window in this.application.get_windows()) {
+            MainWindow? main = window as MainWindow;
+            if (main != null) {
+                main.update_account_status(effective_status);
+            }
+        }
+    }
+
     private void on_retry_problem(MainWindowInfoBar info_bar) {
         Geary.ServiceProblemReport? service_report =
             info_bar.report as Geary.ServiceProblemReport;
@@ -952,6 +998,10 @@ public class GearyController : Geary.BaseObject {
         report_problem(problem);
     }
 
+    private void on_account_status_notify() {
+        update_account_status();
+    }
+
     private void on_account_email_removed(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> ids) {
         if (folder.special_folder_type == Geary.SpecialFolderType.OUTBOX) {
             main_window.status_bar.deactivate_message(StatusBar.Message.OUTBOX_SEND_FAILURE);
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index dceb3f2a..25e83078 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -59,6 +59,19 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
     [GtkChild]
     private Gtk.Grid info_bar_container;
 
+    [GtkChild]
+    private Gtk.InfoBar offline_infobar;
+
+    [GtkChild]
+    private Gtk.InfoBar service_problem_infobar;
+
+    [GtkChild]
+    private Gtk.InfoBar auth_problem_infobar;
+
+    [GtkChild]
+    private Gtk.InfoBar cert_problem_infobar;
+
+
     /** Fired when the shift key is pressed or released. */
     public signal void on_shift_key(bool pressed);
 
@@ -87,6 +100,23 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
         base_unref();
     }
 
+    /** Updates the window's account status info bars. */
+    public void update_account_status(Geary.Account.Status status) {
+        // Only ever show one at a time. Offline is primary since
+        // nothing else can happen when offline. Service problems are
+        // secondary since auth and cert problems can't be resolved
+        // when the service isn't talking to the server. Auth and cert
+        // problems are enabled elsewhere, since the controller might
+        // be already prompting the user about it.
+        this.offline_infobar.set_visible(!status.is_online());
+        this.service_problem_infobar.set_visible(
+            status.is_online() && status.has_service_problem()
+        );
+        this.auth_problem_infobar.hide();
+        this.cert_problem_infobar.hide();
+        update_infobar_frame();
+    }
+
     public void show_infobar(MainWindowInfoBar info_bar) {
         this.info_bar_container.add(info_bar);
         this.info_bar_frame.show();
@@ -443,6 +473,18 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
             this.main_toolbar.folder = this.current_folder.get_display_name();
     }
 
+    private void update_infobar_frame() {
+        // Ensure the info bar frame is shown only when it has visible
+        // children
+        bool show_frame = false;
+        info_bar_container.foreach((child) => {
+                if (child.visible) {
+                    show_frame = true;
+                }
+            });
+        this.info_bar_frame.set_visible(show_frame);
+    }
+
     private inline void check_shift_event(Gdk.EventKey event) {
         // FIXME: it's possible the user will press two shift keys.  We want
         // the shift key to report as released when they release ALL of them.
@@ -474,13 +516,15 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
         return Gdk.EVENT_STOP;
     }
 
+    [GtkCallback]
+    private void on_offline_infobar_response() {
+        this.offline_infobar.hide();
+        update_infobar_frame();
+    }
+
     [GtkCallback]
     private void on_info_bar_container_remove() {
-        // Ensure the info bar frame is hidden when the last info bar
-        // is removed from the container.
-        if (this.info_bar_container.get_children().length() == 0) {
-            this.info_bar_frame.hide();
-        }
+        update_infobar_frame();
     }
 
 }
diff --git a/ui/main-window.ui b/ui/main-window.ui
index 367e7566..811b886f 100644
--- a/ui/main-window.ui
+++ b/ui/main-window.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.0 -->
+<!-- Generated with glade 3.22.1 -->
 <interface>
   <requires lib="gtk+" version="3.20"/>
   <template class="MainWindow" parent="GtkApplicationWindow">
@@ -9,6 +9,9 @@
     <property name="show_menubar">False</property>
     <signal name="delete-event" handler="on_delete_event" swapped="no"/>
     <signal name="focus-in-event" handler="on_focus_event" swapped="no"/>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
     <child>
       <object class="GtkOverlay" id="overlay">
         <property name="visible">True</property>
@@ -143,6 +146,347 @@
                     <property name="can_focus">False</property>
                     <property name="orientation">vertical</property>
                     <signal name="remove" handler="on_info_bar_container_remove" swapped="no"/>
+                    <child>
+                      <object class="GtkInfoBar" id="offline_infobar">
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="show_close_button">True</property>
+                        <signal name="response" handler="on_offline_infobar_response" swapped="no"/>
+                        <child internal-child="action_area">
+                          <object class="GtkButtonBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <property name="layout_style">end</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child internal-child="content_area">
+                          <object class="GtkBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">16</property>
+                            <child>
+                              <object class="GtkGrid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="offline_title">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Infobar title when 
one or more accounts are offline">Working offline</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="offline_description">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="tooltip_text" translatable="yes" comments="Label and 
tooltip for offline infobar">Your computer does not appear to be connected to the Internet.
+You will not be able to send or receive email until it is re-connected.</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Label and tooltip 
for offline infobar">You will not be able to send or receive email until re-connected.</property>
+                                    <property name="wrap">True</property>
+                                    <property name="ellipsize">end</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <style>
+                              <class name="sigh"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkInfoBar" id="service_problem_infobar">
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="message_type">error</property>
+                        <child internal-child="action_area">
+                          <object class="GtkButtonBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <property name="layout_style">end</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child internal-child="content_area">
+                          <object class="GtkBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">16</property>
+                            <child>
+                              <object class="GtkGrid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="service_problem_title">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Infobar title when 
one or more accounts have encounted an error">Account problem</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="service_problem_description">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="tooltip_text" translatable="yes" comments="Label and 
tooltip for account service problem infobar">Geary encountered a problem connecting to an account.
+Please check your Internet connection, the server configuration and try again.</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Label and tooltip 
for account service problem infobar">Geary encountered a problem connecting to an account.</property>
+                                    <property name="wrap">True</property>
+                                    <property name="ellipsize">end</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <style>
+                              <class name="sigh"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkInfoBar" id="auth_problem_infobar">
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="message_type">error</property>
+                        <child internal-child="action_area">
+                          <object class="GtkButtonBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <property name="layout_style">end</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child internal-child="content_area">
+                          <object class="GtkBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">16</property>
+                            <child>
+                              <object class="GtkGrid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="auth_problem_title">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Infobar title when 
one or more accounts have a login error">Login problem</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="auth_problem_description">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="tooltip_text" translatable="yes" comments="Label and 
tooltip for authentication problem infobar">An account has reported an incorrect login or password.
+Please check your login name and try again.</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Label and tooltip 
for authentication problem infobar">An account has reported an incorrect login or password.</property>
+                                    <property name="wrap">True</property>
+                                    <property name="ellipsize">end</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <style>
+                              <class name="sigh"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkInfoBar" id="cert_problem_infobar">
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="message_type">warning</property>
+                        <child internal-child="action_area">
+                          <object class="GtkButtonBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <property name="layout_style">end</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child internal-child="content_area">
+                          <object class="GtkBox">
+                            <property name="can_focus">False</property>
+                            <property name="spacing">16</property>
+                            <child>
+                              <object class="GtkGrid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="cert_problem_title">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Infobar title when 
one or more accounts have a TLS cert validation error">Security problem</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="cert_problem_description">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="tooltip_text" translatable="yes" comments="Label and 
tooltip for TLS cert validation error infobar">An account has reported an untrusted server.
+Please check the server configuration and try again.</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes" comments="Label and tooltip 
for TLS cert validation error infobar">An account has reported an untrusted server.</property>
+                                    <property name="wrap">True</property>
+                                    <property name="ellipsize">end</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <style>
+                              <class name="sigh"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">3</property>
+                      </packing>
+                    </child>
                   </object>
                 </child>
                 <child type="label_item">
@@ -165,8 +509,5 @@
         </child>
       </object>
     </child>
-    <child type="titlebar">
-      <placeholder/>
-    </child>
   </template>
 </interface>


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