Closes #7374 Ensure draft is deleted on send
This commit is contained in:
parent
735b093b0d
commit
afe33527ef
5 changed files with 103 additions and 21 deletions
|
|
@ -203,6 +203,7 @@ engine/imap-engine/other/imap-engine-other-account.vala
|
|||
engine/imap-engine/other/imap-engine-other-folder.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-copy-email.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-create-email.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-expunge-email.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-fetch-email.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-list-email-by-id.vala
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ public class ComposerWindow : Gtk.Window {
|
|||
private Geary.EmailIdentifier? draft_id = null;
|
||||
private uint draft_save_timeout_id = 0;
|
||||
private Cancellable cancellable_drafts = new Cancellable();
|
||||
private Cancellable cancellable_save_draft = new Cancellable();
|
||||
|
||||
private WebKit.WebView editor;
|
||||
// We need to keep a reference to the edit-fixer in composer-window, so it doesn't get
|
||||
|
|
@ -764,6 +765,8 @@ public class ComposerWindow : Gtk.Window {
|
|||
|
||||
// Used internally by on_send()
|
||||
private async void on_send_async() {
|
||||
cancellable_save_draft.cancel();
|
||||
|
||||
linkify_document(editor.get_dom_document());
|
||||
|
||||
// Perform send.
|
||||
|
|
@ -804,12 +807,12 @@ public class ComposerWindow : Gtk.Window {
|
|||
// Save to the draft folder, if available.
|
||||
// Note that drafts are NOT "linkified."
|
||||
private bool save_draft() {
|
||||
save_async.begin();
|
||||
save_async.begin(cancellable_save_draft);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async void save_async() {
|
||||
private async void save_async(Cancellable? cancellable) {
|
||||
if (drafts_folder == null)
|
||||
return;
|
||||
|
||||
|
|
@ -818,7 +821,7 @@ public class ComposerWindow : Gtk.Window {
|
|||
|
||||
try {
|
||||
draft_id = yield drafts_folder.create_email_async(new Geary.RFC822.Message.from_composed_email(
|
||||
get_composed_email()), new Geary.EmailFlags(), null, draft_id, null);
|
||||
get_composed_email()), new Geary.EmailFlags(), null, draft_id, cancellable);
|
||||
|
||||
draft_save_label.label = DRAFT_SAVED_TEXT;
|
||||
} catch (Error e) {
|
||||
|
|
@ -852,7 +855,7 @@ public class ComposerWindow : Gtk.Window {
|
|||
make_gui_insensitive();
|
||||
|
||||
// Do the save.
|
||||
yield save_async();
|
||||
yield save_async(null);
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1156,30 +1156,32 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
|
|||
if (id != null)
|
||||
check_id("create_email_async", id);
|
||||
|
||||
// TODO: Move this into a ReplayQueue operation
|
||||
yield wait_for_open_async(cancellable);
|
||||
|
||||
// use IMAP APPEND command on remote folders, which doesn't require opening a folder
|
||||
Geary.EmailIdentifier? ret = yield remote_folder.create_email_async(rfc822, flags,
|
||||
date_received, cancellable);
|
||||
if (ret != null) {
|
||||
// TODO: need to prevent gaps that may occur here
|
||||
Geary.Email created = new Geary.Email(ret);
|
||||
Gee.Map<Geary.Email, bool> results = yield local_folder.create_or_merge_email_async(
|
||||
new Collection.SingleItem<Geary.Email>(created), cancellable);
|
||||
if (results.size > 0)
|
||||
ret = Collection.get_first<Geary.Email>(results.keys).id;
|
||||
Error? cancel_error = null;
|
||||
Geary.EmailIdentifier? ret = null;
|
||||
try {
|
||||
CreateEmail create = new CreateEmail(this, rfc822, flags, date_received, cancellable);
|
||||
replay_queue.schedule(create);
|
||||
yield create.wait_for_ready_async(cancellable);
|
||||
|
||||
ret = create.created_id;
|
||||
} catch (Error e) {
|
||||
if (e is IOError.CANCELLED)
|
||||
cancel_error = e;
|
||||
else
|
||||
ret = null;
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Remove old message.
|
||||
if (id != null) {
|
||||
Geary.FolderSupport.Remove? remove_folder = this as Geary.FolderSupport.Remove;
|
||||
if (remove_folder != null)
|
||||
yield remove_folder.remove_single_email_async(id, cancellable);
|
||||
yield remove_folder.remove_single_email_async(id, null);
|
||||
}
|
||||
|
||||
// If the user cancelled the operation, throw the error here.
|
||||
if (cancel_error != null)
|
||||
throw cancel_error;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
/* Copyright 2013 Yorba Foundation
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
private class Geary.ImapEngine.CreateEmail : Geary.ImapEngine.SendReplayOperation {
|
||||
public Geary.EmailIdentifier? created_id { get; private set; default = null; }
|
||||
|
||||
private GenericFolder engine;
|
||||
private RFC822.Message rfc822;
|
||||
private Geary.EmailFlags? flags;
|
||||
private DateTime? date_received;
|
||||
private Cancellable? cancellable;
|
||||
|
||||
public CreateEmail(GenericFolder engine, RFC822.Message rfc822, Geary.EmailFlags? flags,
|
||||
DateTime? date_received, Cancellable? cancellable) {
|
||||
base.only_remote("CreateEmail");
|
||||
|
||||
this.engine = engine;
|
||||
|
||||
this.rfc822 = rfc822;
|
||||
this.flags = flags;
|
||||
this.date_received = date_received;
|
||||
this.cancellable = cancellable;
|
||||
}
|
||||
|
||||
public override async ReplayOperation.Status replay_local_async() throws Error {
|
||||
return ReplayOperation.Status.CONTINUE;
|
||||
}
|
||||
|
||||
public override void notify_remote_removed_ids(Gee.Collection<ImapDB.EmailIdentifier> ids) {
|
||||
}
|
||||
|
||||
public override async void backout_local_async() throws Error {
|
||||
}
|
||||
|
||||
public override string describe_state() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public override async ReplayOperation.Status replay_remote_async() throws Error {
|
||||
// Deal with cancellable manually since create_email_async cannot be cancelled.
|
||||
if (cancellable.is_cancelled())
|
||||
throw new IOError.CANCELLED("CreateEmail op cancelled immediately");
|
||||
|
||||
// use IMAP APPEND command on remote folders, which doesn't require opening a folder
|
||||
created_id = yield engine.remote_folder.create_email_async(rfc822, flags, date_received);
|
||||
|
||||
if (created_id == null)
|
||||
return ReplayOperation.Status.FAILED;
|
||||
|
||||
// If the user cancelled the operation, we need to wipe the new message to keep this
|
||||
// operation atomic.
|
||||
if (cancellable.is_cancelled()) {
|
||||
yield engine.remote_folder.remove_email_async(
|
||||
new Imap.MessageSet.uid(((ImapDB.EmailIdentifier) created_id).uid), null);
|
||||
|
||||
throw new IOError.CANCELLED("CreateEmail op cancelled after create");
|
||||
}
|
||||
|
||||
// TODO: need to prevent gaps that may occur here
|
||||
Geary.Email created = new Geary.Email(created_id);
|
||||
Gee.Map<Geary.Email, bool> results = yield engine.local_folder.create_or_merge_email_async(
|
||||
new Collection.SingleItem<Geary.Email>(created), cancellable);
|
||||
if (results.size > 0)
|
||||
created_id = Collection.get_first<Geary.Email>(results.keys).id;
|
||||
else
|
||||
created_id = null;
|
||||
|
||||
return ReplayOperation.Status.COMPLETED;
|
||||
}
|
||||
}
|
||||
|
|
@ -862,8 +862,11 @@ private class Geary.Imap.Folder : BaseObject {
|
|||
}
|
||||
|
||||
// Returns a no-message-id ImapDB.EmailIdentifier with the UID stored in it.
|
||||
// This method does not take a cancellable; there is currently no way to tell if an email was
|
||||
// created or not if exec_commands_async() is cancelled during the append. For atomicity's sake,
|
||||
// callers need to remove the returned email ID if a cancel occurred.
|
||||
public async Geary.EmailIdentifier? create_email_async(RFC822.Message message, Geary.EmailFlags? flags,
|
||||
DateTime? date_received, Cancellable? cancellable) throws Error {
|
||||
DateTime? date_received) throws Error {
|
||||
check_open();
|
||||
|
||||
MessageFlags? msg_flags = null;
|
||||
|
|
@ -880,7 +883,7 @@ private class Geary.Imap.Folder : BaseObject {
|
|||
msg_flags, internaldate, message.get_network_buffer(false));
|
||||
|
||||
Gee.Map<Command, StatusResponse> responses = yield exec_commands_async(
|
||||
new Collection.SingleItem<AppendCommand>(cmd), null, null, cancellable);
|
||||
new Collection.SingleItem<AppendCommand>(cmd), null, null, null);
|
||||
|
||||
// Grab the response and parse out the UID, if available.
|
||||
StatusResponse response = responses.get(cmd);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue