diff --git a/src/engine/api/geary-account.vala b/src/engine/api/geary-account.vala index d381208a..f54b3cbe 100644 --- a/src/engine/api/geary-account.vala +++ b/src/engine/api/geary-account.vala @@ -27,32 +27,73 @@ public abstract class Geary.Account : BaseObject { internal const uint AUTH_ATTEMPTS_MAX = 3; - /** + /** + * Denotes the account's current status. + * + * @see Account.current_status + * @see ClientService.current_status + */ + [Flags] + public enum Status { + + /** + * The account is currently online and operating normally. + * + * This flags will be set when the account's {@link incoming} + * service's {@link ClientService.current_status} is {@link + * ClientService.Status.CONNECTED}. + */ + ONLINE, + + /** + * One or of the account's services is degraded. + * + * This flag will be set when one or both of its services has + * encountered a problem. Consult the {@link + * ClientService.current_status} to determine which and the + * exact problem. + */ + SERVICE_PROBLEM; + + + /** Determines if the {@link ONLINE} flag is set. */ + public bool is_online() { + return (this & ONLINE) == ONLINE; + } + + /** Determines if the {@link SERVICE_PROBLEM} flag is set. */ + public bool has_service_problem() { + return (this & SERVICE_PROBLEM) == SERVICE_PROBLEM; + } + + } + + + /** * The account's current configuration. */ public AccountInformation information { get; protected set; } /** - * Determines if this account appears to be online. + * The account's current status. * - * This property is true if the account is to the best of the - * engine's knowledge is online, i.e. it is enabled, has been able - * to connect to the remote incoming mail server, and so on. Some - * network problems are not immediately obvious however, and so at - * times the value of this property may be inaccurate. At best it - * should be treated as a heuristic. + * This property's value is set based on the {@link + * ClientService.current_status} of the account's {@link incoming} + * and {@link outgoing} services. if + * + * @see ClientService.current_status */ - public abstract bool is_online { get; protected set; } + public Status current_status { get; protected set; default = 0; } /** * The service manager for the incoming email service. */ - public abstract ClientService incoming { get; } + public ClientService incoming { get; private set; } /** * The service manager for the outgoing email service. */ - public abstract ClientService outgoing { get; } + public ClientService outgoing { get; private set; } public Geary.ProgressMonitor search_upgrade_monitor { get; protected set; } public Geary.ProgressMonitor db_upgrade_monitor { get; protected set; } @@ -174,11 +215,22 @@ public abstract class Geary.Account : BaseObject { Gee.Map map); - protected Account(AccountInformation information) { + protected Account(AccountInformation information, + ClientService incoming, + ClientService outgoing) { this.information = information; + this.incoming = incoming; + this.outgoing = outgoing; this.id = "%s[%s]".printf( information.id, information.service_provider.to_value() ); + + incoming.notify["current-status"].connect( + on_service_status_notify + ); + outgoing.notify["current-status"].connect( + on_service_status_notify + ); } /** @@ -478,4 +530,17 @@ public abstract class Geary.Account : BaseObject { ); } + private void on_service_status_notify() { + Status new_status = 0; + if (incoming.current_status != UNKNOWN && + incoming.current_status != UNREACHABLE) { + new_status |= ONLINE; + } + if (incoming.current_status.is_error() || + outgoing.current_status.is_error()) { + new_status |= SERVICE_PROBLEM; + } + this.current_status = new_status; + } + } diff --git a/src/engine/api/geary-client-service.vala b/src/engine/api/geary-client-service.vala index 8cd879b3..1c72df46 100644 --- a/src/engine/api/geary-client-service.vala +++ b/src/engine/api/geary-client-service.vala @@ -25,6 +25,7 @@ public abstract class Geary.ClientService : BaseObject { * Denotes the service's current status. * * @see ClientService.current_status + * @see Account.current_status */ public enum Status { @@ -109,6 +110,18 @@ public abstract class Geary.ClientService : BaseObject { ); } + /** + * Determines the current status is an error condition. + * + * Returns true if not offline or connected. + */ + public bool is_error() { + return ( + this != OFFLINE && + this != CONNECTED + ); + } + public string to_value() { return ObjectUtils.to_enum_nick(typeof(Status), this); } @@ -144,6 +157,8 @@ public abstract class Geary.ClientService : BaseObject { * (e.g. online/offline state may not be fully known, and hence * the value of this property reflects the engine's current * understanding of the service's status, not necessarily reality. + * + * @see Account.current_status */ public Status current_status { get; protected set; default = OFFLINE; } diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala b/src/engine/imap-engine/imap-engine-generic-account.vala index 97dbdc27..123e0ca1 100644 --- a/src/engine/imap-engine/imap-engine-generic-account.vala +++ b/src/engine/imap-engine/imap-engine-generic-account.vala @@ -25,14 +25,6 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { Geary.SpecialFolderType.ARCHIVE, }; - public override bool is_online { get; protected set; default = false; } - - /** Returns the IMAP client service. */ - public override ClientService incoming { get { return this.imap; } } - - /** Returns the SMTP client service. */ - public override ClientService outgoing { get { return this.smtp; } } - /** Service for incoming IMAP connections. */ public Imap.ClientService imap { get; private set; } @@ -64,26 +56,32 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { ImapDB.Account local, Endpoint incoming_remote, Endpoint outgoing_remote) { - base(config); + Imap.ClientService imap = new Imap.ClientService( + config, + config.incoming, + incoming_remote + ); + Smtp.ClientService smtp = new Smtp.ClientService( + config, + config.outgoing, + outgoing_remote + ); + + base(config, imap, smtp); + this.local = local; this.local.contacts_loaded.connect(() => { contacts_loaded(); }); - this.imap = new Imap.ClientService( - config, config.incoming, incoming_remote - ); - this.imap.min_pool_size = IMAP_MIN_POOL_SIZE; - this.imap.notify["current-status"].connect( + imap.min_pool_size = IMAP_MIN_POOL_SIZE; + imap.notify["current-status"].connect( on_imap_status_notify ); + this.imap = imap; - this.smtp = new Smtp.ClientService( - config, - config.outgoing, - outgoing_remote, - new Outbox.Folder(this, this.local) - ); - this.smtp.email_sent.connect(on_email_sent); - this.smtp.report_problem.connect(notify_report_problem); + smtp.outbox = new Outbox.Folder(this, local); + smtp.email_sent.connect(on_email_sent); + smtp.report_problem.connect(notify_report_problem); + this.smtp = smtp; this.sync = new AccountSynchronizer(this); @@ -994,11 +992,9 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { private void on_imap_status_notify() { if (this.open) { if (this.imap.current_status == CONNECTED) { - this.is_online = true; this.remote_ready_lock.blind_notify(); update_remote_folders(); } else { - this.is_online = false; this.remote_ready_lock.reset(); this.refresh_folder_timer.reset(); } diff --git a/src/engine/smtp/smtp-client-service.vala b/src/engine/smtp/smtp-client-service.vala index a6027a24..58b93634 100644 --- a/src/engine/smtp/smtp-client-service.vala +++ b/src/engine/smtp/smtp-client-service.vala @@ -23,7 +23,7 @@ internal class Geary.Smtp.ClientService : Geary.ClientService { /** Folder used for storing and retrieving queued mail. */ - public Outbox.Folder outbox { get; private set; } + public Outbox.Folder? outbox { get; internal set; default = null; } /** Progress monitor indicating when email is being sent. */ public ProgressMonitor sending_monitor { @@ -47,10 +47,8 @@ internal class Geary.Smtp.ClientService : Geary.ClientService { public ClientService(AccountInformation account, ServiceInformation service, - Endpoint remote, - Outbox.Folder outbox) { + Endpoint remote) { base(account, service, remote); - this.outbox = outbox; } /** diff --git a/test/engine/api/geary-account-mock.vala b/test/engine/api/geary-account-mock.vala index b9274e9e..6b2b76df 100644 --- a/test/engine/api/geary-account-mock.vala +++ b/test/engine/api/geary-account-mock.vala @@ -19,7 +19,7 @@ public class Geary.MockAccount : Account, MockObject { public class MockContactStore : ContactStore { internal MockContactStore() { - + } public override async void @@ -60,34 +60,23 @@ public class Geary.MockAccount : Account, MockObject { } - public override bool is_online { get; protected set; default = false; } - - public override ClientService incoming { - get { return this.incoming; } - } - private ClientService _incoming; - - public override ClientService outgoing { - get { return this._outgoing; } - } - private ClientService _outgoing; - protected Gee.Queue expected { get; set; default = new Gee.LinkedList(); } public MockAccount(AccountInformation config) { - base(config); - this._incoming = new MockClientService( - config, - config.incoming, - new Endpoint(config.incoming.host, config.incoming.port, 0, 0) - ); - this._outgoing = new MockClientService( - config, - config.outgoing, - new Endpoint(config.outgoing.host, config.outgoing.port, 0, 0) + base(config, + new MockClientService( + config, + config.incoming, + new Endpoint(config.incoming.host, config.incoming.port, 0, 0) + ), + new MockClientService( + config, + config.outgoing, + new Endpoint(config.outgoing.host, config.outgoing.port, 0, 0) + ) ); }