Provide common account and service status tracking via Account
Similarly to ClientService, add a `current_status` property that denotes the account's operational state, so that clients can just set a notify on that to be informed of all account status changes. Keep the property updated by watching for changes to the client service's status property.
This commit is contained in:
parent
a637a6b63a
commit
20447c814f
5 changed files with 126 additions and 63 deletions
|
|
@ -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<Geary.EmailIdentifier, Geary.EmailFlags> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Status>(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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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<ExpectedCall> expected {
|
||||
get; set; default = new Gee.LinkedList<ExpectedCall>();
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue