Commit e3f1c364 authored by john's avatar john

Merge remote-tracking branch 'upstream/master'

parents 6c53e003 5f769ca3
This diff is collapsed.
......@@ -32,6 +32,10 @@
/* Secrets access */
"--talk-name=org.freedesktop.secrets",
/* GOA support */
"--talk-name=org.gnome.ControlCenter",
"--talk-name=org.gnome.OnlineAccounts",
/* Needed for dconf to work */
"--filesystem=xdg-run/dconf", "--filesystem=~/.config/dconf:ro",
"--talk-name=ca.desrt.dconf", "--env=DCONF_USER_CONFIG_DIR=.config/dconf",
......
This diff is collapsed.
This diff is collapsed.
......@@ -13,7 +13,7 @@ private errordomain AttachmentError {
// The actual widget for sending messages. Should be put in a ComposerContainer
[GtkTemplate (ui = "/org/gnome/Geary/composer-widget.ui")]
public class ComposerWidget : Gtk.EventBox {
public class ComposerWidget : Gtk.EventBox, Geary.BaseInterface {
public enum ComposeType {
......@@ -397,6 +397,7 @@ public class ComposerWidget : Gtk.EventBox {
ContactListStoreCache contact_list_store_cache,
ComposeType compose_type,
Configuration config) {
base_ref();
this.account = account;
this.contact_list_store_cache = contact_list_store_cache;
this.config = config;
......@@ -525,6 +526,10 @@ public class ComposerWidget : Gtk.EventBox {
load_entry_completions();
}
~ComposerWidget() {
base_unref();
}
public override void destroy() {
this.draft_timer.reset();
if (this.draft_manager_opening != null) {
......@@ -2005,22 +2010,13 @@ public class ComposerWidget : Gtk.EventBox {
}
private bool add_account_emails_to_from_list(Geary.Account other_account, bool set_active = false) {
Geary.RFC822.MailboxAddresses primary_address = new Geary.RFC822.MailboxAddresses.single(
other_account.information.primary_mailbox);
this.from_multiple.append_text(primary_address.to_full_display());
this.from_list.add(new FromAddressMap(other_account, primary_address));
if (!set_active && this.from.equal_to(primary_address)) {
this.from_multiple.set_active(this.from_list.size - 1);
set_active = true;
}
bool is_primary = true;
foreach (Geary.RFC822.MailboxAddress alternate_mailbox in
foreach (Geary.RFC822.MailboxAddress mailbox in
other_account.information.sender_mailboxes) {
Geary.RFC822.MailboxAddresses addresses =
new Geary.RFC822.MailboxAddresses.single(alternate_mailbox);
new Geary.RFC822.MailboxAddresses.single(mailbox);
string display = primary_address.to_full_display();
string display = mailbox.to_full_display();
if (!is_primary) {
// Displayed in the From dropdown to indicate an
// "alternate email address" for an account. The first
......@@ -2030,9 +2026,8 @@ public class ComposerWidget : Gtk.EventBox {
display = _("%1$s via %2$s").printf(
display, other_account.information.display_name
);
} else {
is_primary = false;
}
is_primary = false;
this.from_multiple.append_text(display);
this.from_list.add(new FromAddressMap(other_account, addresses));
......
......@@ -188,34 +188,35 @@ public class ConversationListStore : Gtk.ListStore {
emails.add_all(yield do_get_previews_async(needing_previews));
if (emails.size < 1)
return;
debug("Displaying %d previews for %s...", emails.size, conversation_monitor.base_folder.to_string());
foreach (Geary.Email email in emails) {
Geary.App.Conversation? conversation = conversation_monitor.get_by_email_identifier(email.id);
if (conversation != null)
// The conversation can be null if e.g. a search is
// changing quickly and the original has evaporated
// already.
if (conversation != null) {
set_preview_for_conversation(conversation, email);
else
debug("Couldn't find conversation for %s", email.id.to_string());
}
}
debug("Displayed %d previews for %s", emails.size, conversation_monitor.base_folder.to_string());
}
private async Gee.Collection<Geary.Email> do_get_previews_async(
Gee.Collection<Geary.EmailIdentifier> emails_needing_previews) {
Geary.Folder.ListFlags flags = (loading_local_only) ? Geary.Folder.ListFlags.LOCAL_ONLY
: Geary.Folder.ListFlags.NONE;
Gee.Collection<Geary.Email>? emails = null;
try {
debug("Loading %d previews...", emails_needing_previews.size);
emails = yield email_store.list_email_by_sparse_id_async(emails_needing_previews,
ConversationListStore.WITH_PREVIEW_FIELDS, flags, cancellable);
debug("Loaded %d previews...", emails_needing_previews.size);
} catch (Error err) {
// Ignore NOT_FOUND, as that's entirely possible when waiting for the remote to open
if (!(err is Geary.EngineError.NOT_FOUND))
debug("Unable to fetch preview: %s", err.message);
} catch (GLib.IOError.CANCELLED err) {
// All good
} catch (Geary.EngineError.NOT_FOUND err) {
// All good also, as that's entirely possible when waiting
// for the remote to open
} catch (GLib.Error err) {
warning("Unable to fetch preview: %s", err.message);
}
return emails ?? new Gee.ArrayList<Geary.Email>();
}
......
......@@ -553,6 +553,8 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
on_service_status_change
);
this.load_cancellable.cancelled.connect(on_load_cancelled);
this.body_loading_timeout = new Geary.TimeoutManager.milliseconds(
BODY_LOAD_TIMEOUT_MSEC, this.on_body_loading_timeout
);
......@@ -1027,6 +1029,10 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
this.primary_message.show_loading_pane();
}
private void on_load_cancelled() {
this.body_loading_timeout.reset();
}
private void on_flag_remote_images(ConversationMessage view) {
// XXX check we aren't already auto loading the image
mark_email(Geary.EmailFlags.LOAD_REMOTE_IMAGES, null);
......
......@@ -707,7 +707,9 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
ComposerRow row = new ComposerRow(embed);
row.enable_should_scroll();
row.should_scroll.connect(() => { scroll_to(row); });
// Use row param rather than row var from closure to avoid a
// circular ref.
row.should_scroll.connect((row) => { scroll_to(row); });
add(row);
embed.composer.draft_id_changed.connect((id) => { this.draft_id = id; });
......
......@@ -297,10 +297,6 @@ public class Geary.App.ConversationMonitor : BaseObject {
this.base_folder.account.email_removed.connect(on_account_email_removed);
this.base_folder.account.email_flags_changed.connect(on_account_email_flags_changed);
this.progress_monitor.start.connect(() => { debug("Monitor started"); });
this.progress_monitor.update.connect(() => { debug("Monitor progress"); });
this.progress_monitor.finish.connect(() => { debug("Monitor stopped"); });
this.queue = new ConversationOperationQueue(this.progress_monitor);
this.queue.operation_error.connect(on_operation_error);
this.queue.add(new FillWindowOperation(this));
......@@ -311,7 +307,9 @@ public class Geary.App.ConversationMonitor : BaseObject {
try {
yield stop_monitoring_internal(false, null);
} catch (Error stop_error) {
debug("Error cleaning up after folder open error: %s", err.message);
warning(
"Error cleaning up after folder open error: %s", err.message
);
}
throw err;
}
......@@ -520,21 +518,23 @@ public class Geary.App.ConversationMonitor : BaseObject {
yield folder.close_async(null);
opened = false;
} catch (Error err) {
debug("Error loading external emails: %s", err.message);
if (opened) {
// Always try to close the opened folder
try {
yield folder.close_async(null);
} catch (Error close_err) {
debug("Error closing folder %s: %s",
folder.to_string(), close_err.message);
warning("Error closing folder %s: %s",
folder.to_string(), close_err.message);
}
}
throw err;
}
if (emails != null && !emails.is_empty) {
debug("Fetched %d relevant emails locally", emails.size);
Logging.debug(
Logging.Flag.CONVERSATIONS,
"Fetched %d relevant emails locally", emails.size
);
yield process_email_async(emails, ProcessJobContext());
}
}
......@@ -573,8 +573,11 @@ public class Geary.App.ConversationMonitor : BaseObject {
this.operation_cancellable
);
if (count == 0) {
debug("Evaporating conversation %s because it has no emails in %s",
conversation.to_string(), this.base_folder.to_string());
Logging.debug(
Logging.Flag.CONVERSATIONS,
"Evaporating conversation %s because it has no emails in %s",
conversation.to_string(), this.base_folder.to_string()
);
this.conversations.remove_conversation(conversation);
evaporated.add(conversation);
}
......@@ -656,8 +659,8 @@ public class Geary.App.ConversationMonitor : BaseObject {
// Always close the folder to prevent open leaks
closing = yield this.base_folder.close_async(null);
} catch (Error err) {
debug("Unable to close monitored folder %s: %s",
this.base_folder.to_string(), err.message);
warning("Unable to close monitored folder %s: %s",
this.base_folder.to_string(), err.message);
close_err = err;
}
}
......@@ -727,10 +730,11 @@ public class Geary.App.ConversationMonitor : BaseObject {
out added, out appended, out removed_due_to_merge
);
}
} catch (Error err) {
debug("Unable to add emails to conversation: %s", err.message);
// fall-through
} catch (GLib.IOError.CANCELLED err) {
// All good
} catch (GLib.Error err) {
warning("Unable to add emails to conversation: %s", err.message);
// Fall-through anyway
}
if (removed_due_to_merge != null && removed_due_to_merge.size > 0) {
......@@ -862,10 +866,18 @@ public class Geary.App.ConversationMonitor : BaseObject {
Geary.EmailIdentifier? lowest = this.window_lowest;
if (lowest != null) {
if (lowest.natural_sort_comparator(id) < 0) {
debug("Unflagging email %s for deletion resurrects conversation", id.to_string());
Logging.debug(
Logging.Flag.CONVERSATIONS,
"Unflagging email %s for deletion resurrects conversation",
id.to_string()
);
inserted_ids.add(id);
} else {
debug("Not resurrecting undeleted email %s outside of window", id.to_string());
Logging.debug(
Logging.Flag.CONVERSATIONS,
"Not resurrecting undeleted email %s outside of window",
id.to_string()
);
}
}
}
......@@ -883,13 +895,15 @@ public class Geary.App.ConversationMonitor : BaseObject {
// Remove conversation if get_emails yields an empty collection -- this probably means
// the conversation was deleted.
if (conversation.get_emails(Geary.App.Conversation.Ordering.NONE).size == 0) {
debug("Flagging email %s for deletion evaporates conversation %s",
id.to_string(), conversation.to_string());
Logging.debug(
Logging.Flag.CONVERSATIONS,
"Flagging email %s for deletion evaporates conversation %s",
id.to_string(), conversation.to_string()
);
this.conversations.remove_conversation(conversation);
removed_conversations.add(conversation);
removed_ids.add(id);
}
}
}
// Notify about inserted messages
......@@ -909,7 +923,9 @@ public class Geary.App.ConversationMonitor : BaseObject {
}
private void on_operation_error(ConversationOperation op, Error err) {
debug("Error executing %s: %s", op.get_type().name(), err.message);
if (!(err is GLib.IOError.CANCELLED)) {
warning("Error executing %s: %s", op.get_type().name(), err.message);
}
notify_scan_error(err);
}
......
......@@ -961,7 +961,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
return;
} catch (Error err) {
ErrorContext context = new ErrorContext(err);
if (is_unrecoverable_failure(err)) {
if (!is_recoverable_failure(err)) {
debug("Unrecoverable failure opening remote, forcing closed: %s",
context.format_full_error());
yield force_close(
......
......@@ -42,7 +42,7 @@ private abstract class Geary.ImapEngine.ReplayOperation : Geary.BaseObject, Gee.
public enum OnError {
THROW,
RETRY,
IGNORE
IGNORE_REMOTE
}
public string name { get; set; }
......
......@@ -18,8 +18,8 @@ namespace Geary.ImapEngine {
* succeed if tried again unless some action is taken, such as
* authentication failures, protocol parsing errors, and so on.
*/
private static bool is_unrecoverable_failure(GLib.Error err) {
return !(
private static bool is_recoverable_failure(GLib.Error err) {
return (
err is EngineError.SERVER_UNAVAILABLE ||
err is IOError.BROKEN_PIPE ||
err is IOError.BUSY ||
......
......@@ -82,7 +82,7 @@ private abstract class Geary.ImapEngine.AbstractListEmail : Geary.ImapEngine.Sen
public AbstractListEmail(string name, MinimalFolder owner, Geary.Email.Field required_fields,
Folder.ListFlags flags, Cancellable? cancellable) {
base(name, OnError.IGNORE);
base(name, OnError.IGNORE_REMOTE);
this.owner = owner;
this.required_fields = required_fields;
......
......@@ -22,7 +22,7 @@ private class Geary.ImapEngine.ReplayAppend : Geary.ImapEngine.ReplayOperation {
Cancellable? cancellable) {
// IGNORE remote errors because the reconnect will re-normalize the folder, making this
// append moot
base ("Append", Scope.REMOTE_ONLY, OnError.IGNORE);
base ("Append", Scope.REMOTE_ONLY, OnError.IGNORE_REMOTE);
this.owner = owner;
this.remote_count = remote_count;
......
......@@ -17,7 +17,7 @@ private class Geary.ImapEngine.ReplayRemoval : Geary.ImapEngine.ReplayOperation
public ReplayRemoval(MinimalFolder owner, int remote_count, Imap.SequenceNumber position) {
// remote error will cause folder to reconnect and re-normalize, making this remove moot
base ("Removal", Scope.LOCAL_AND_REMOTE, OnError.IGNORE);
base ("Removal", Scope.LOCAL_AND_REMOTE, OnError.IGNORE_REMOTE);
this.owner = owner;
this.remote_count = remote_count;
......
......@@ -397,7 +397,7 @@ internal class Geary.Imap.ClientService : Geary.ClientService {
// honor Cancellable here, it's important to disconnect
// the client before dropping the ref
try {
yield new_session.disconnect_async();
yield new_session.disconnect_async(null);
} catch (Error disconnect_err) {
debug("[%s] Error disconnecting due to session initiation failure, ignored: %s",
new_session.to_string(), disconnect_err.message);
......@@ -436,7 +436,7 @@ internal class Geary.Imap.ClientService : Geary.ClientService {
// waiting for any since we don't want to delay closing the
// others.
foreach (ClientSession session in to_close) {
session.disconnect_async.begin();
session.disconnect_async.begin(null);
}
}
......@@ -452,7 +452,7 @@ internal class Geary.Imap.ClientService : Geary.ClientService {
// Don't wait for this to finish because we don't want to
// block claiming a new session, shutdown, etc.
session.disconnect_async.begin();
session.disconnect_async.begin(null);
}
private async bool remove_session_async(ClientSession session) throws Error {
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment