[geary/mjog/493-undo-send: 15/20] Update composer draft lifecycle management
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/493-undo-send: 15/20] Update composer draft lifecycle management
- Date: Tue, 12 Nov 2019 21:43:07 +0000 (UTC)
commit c3446e73ec895f8c4616aad546836bcbdcf35f08
Author: Michael Gratton <mike vee net>
Date: Tue Nov 12 14:21:37 2019 +1100
Update composer draft lifecycle management
Make Geary.App.DraftManager's ::update and ::discard methods async and
drop the ::discard_on_close property. Update all Composer.Widget draft
methods to be aync, drop the `_async` prefix, take a cancellable arg and
throw their errors rather than logging them. Update call sites to take
this into account and report errors rather than logging them.
src/client/composer/composer-widget.vala | 154 +++++++++++++++++++------------
src/engine/app/app-draft-manager.vala | 47 ++--------
2 files changed, 104 insertions(+), 97 deletions(-)
---
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index d038c45f..93b6a799 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -556,7 +556,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
this.from = new Geary.RFC822.MailboxAddresses.single(account.information.primary_mailbox);
this.draft_timer = new Geary.TimeoutManager.seconds(
- 10, () => { this.save_draft.begin(); }
+ 10, on_draft_timeout
);
// Add actions once every element has been initialized and added
@@ -697,10 +697,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
);
try {
- yield open_draft_manager_async(
- is_draft ? referred.id : null,
- cancellable
- );
+ yield open_draft_manager(is_draft ? referred.id : null, cancellable);
} catch (Error e) {
debug("Could not open draft manager: %s", e.message);
}
@@ -827,7 +824,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
if (this.draft_manager != null) {
try {
- yield close_draft_manager_async(null);
+ yield close_draft_manager(null);
} catch (Error err) {
debug("Error closing draft manager on composer close");
}
@@ -867,7 +864,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
if (enabled) {
this.is_closing = false;
- this.open_draft_manager_async.begin(null, null);
+ this.open_draft_manager.begin(null, null);
} else {
if (this.container != null) {
this.container.close();
@@ -1447,33 +1444,32 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
private async void on_send_async() {
set_enabled(false);
- // Perform send.
try {
yield this.editor.clean_content();
yield this.application.controller.send_email(this);
- } catch (Error e) {
- GLib.message("Error sending email: %s", e.message);
- }
- Geary.Nonblocking.Semaphore? semaphore = discard_draft();
- if (semaphore != null) {
- try {
- yield semaphore.wait_async();
- } catch (Error err) {
- // ignored
+ if (this.draft_manager != null) {
+ yield discard_draft();
+ yield close_draft_manager(null);
}
- }
- if (this.container != null) {
- this.container.close();
+ if (this.container != null) {
+ this.container.close();
+ }
+ } catch (GLib.Error error) {
+ this.application.controller.report_problem(
+ new Geary.AccountProblemReport(
+ this.account.information, error
+ )
+ );
}
}
/**
* Creates and opens the composer's draft manager.
*/
- private async void open_draft_manager_async(Geary.EmailIdentifier? editing_draft_id,
- GLib.Cancellable? cancellable)
+ private async void open_draft_manager(Geary.EmailIdentifier? editing_draft_id,
+ GLib.Cancellable? cancellable)
throws GLib.Error {
if (!this.account.information.save_drafts) {
this.header.show_save_and_close = false;
@@ -1520,19 +1516,19 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
/**
* Closes current draft manager, if any, then opens a new one.
*/
- private async void reopen_draft_manager_async()
- throws Error {
+ private async void reopen_draft_manager(GLib.Cancellable? cancellable)
+ throws GLib.Error {
if (this.draft_manager != null) {
// Discard the draft, if any, since it may be on a
// different account
- discard_draft();
- this.draft_manager.discard_on_close = true;
- yield close_draft_manager_async(null);
+ yield discard_draft();
+ yield close_draft_manager(cancellable);
}
- yield open_draft_manager_async(null, null);
+ yield open_draft_manager(null, cancellable);
+ yield save_draft();
}
- private async void close_draft_manager_async(Cancellable? cancellable)
+ private async void close_draft_manager(GLib.Cancellable? cancellable)
throws GLib.Error {
this.draft_status_text = "";
@@ -1547,12 +1543,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
.disconnect(on_draft_id_changed);
old_manager.fatal.disconnect(on_draft_manager_fatal);
- // drop ref even if close failed
- try {
- yield old_manager.close_async(cancellable);
- } catch (Error err) {
- debug("Error closing draft manager: %s", err.message);
- }
+ yield old_manager.close_async(cancellable);
debug("Draft manager closed");
}
@@ -1594,51 +1585,62 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
}
// Note that drafts are NOT "linkified."
- private async void save_draft() {
+ private async void save_draft() throws GLib.Error {
+ debug("Saving draft");
+
// cancel timer in favor of just doing it now
this.draft_timer.reset();
if (this.draft_manager != null) {
- try {
- Geary.ComposedEmail draft = yield get_composed_email(null, true);
- this.draft_manager.update(
- yield draft.to_rfc822_message(null, null),
- this.draft_flags,
- null
- );
- } catch (Error err) {
- GLib.message("Unable to save draft: %s", err.message);
- }
+ Geary.ComposedEmail draft = yield get_composed_email(null, true);
+ yield this.draft_manager.update(
+ yield draft.to_rfc822_message(null, null),
+ this.draft_flags,
+ null,
+ null
+ );
}
}
- private Geary.Nonblocking.Semaphore? discard_draft() {
+ private async void discard_draft() throws GLib.Error {
+ debug("Discarding draft");
+
// cancel timer in favor of this operation
this.draft_timer.reset();
-
- try {
- if (this.draft_manager != null)
- return this.draft_manager.discard();
- } catch (Error err) {
- GLib.message("Unable to discard draft: %s", err.message);
- }
-
- return null;
+ yield this.draft_manager.discard(null);
}
private async void save_and_exit_async() {
this.is_closing = true;
set_enabled(false);
- yield save_draft();
+ try {
+ yield save_draft();
+ } catch (GLib.Error error) {
+ this.application.controller.report_problem(
+ new Geary.AccountProblemReport(
+ this.account.information, error
+ )
+ );
+ }
yield close();
}
private async void discard_and_exit_async() {
this.is_closing = true;
set_enabled(false);
+
if (this.draft_manager != null) {
- discard_draft();
- draft_manager.discard_on_close = true;
+ try {
+ yield discard_draft();
+ yield close_draft_manager(null);
+ } catch (GLib.Error error) {
+ this.application.controller.report_problem(
+ new Geary.AccountProblemReport(
+ this.account.information, error
+ )
+ );
+ }
+ }
}
yield close();
}
@@ -2297,7 +2299,22 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
this.account = selected.account;
this.update_signature.begin(null);
load_entry_completions();
- this.reopen_draft_manager_async.begin();
+
+ var current_account = this.account;
+ this.reopen_draft_manager.begin(
+ null,
+ (obj, res) => {
+ try {
+ this.reopen_draft_manager.end(res);
+ } catch (GLib.Error error) {
+ this.application.controller.report_problem(
+ new Geary.AccountProblemReport(
+ current_account.information, error
+ )
+ );
+ }
+ }
+ );
}
}
}
@@ -2618,6 +2635,23 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
discard_and_exit_async.begin();
}
+ private void on_draft_timeout() {
+ var current_account = this.account;
+ this.save_draft.begin(
+ (obj, res) => {
+ try {
+ this.save_draft.end(res);
+ } catch (GLib.Error error) {
+ this.application.controller.report_problem(
+ new Geary.AccountProblemReport(
+ current_account.information, error
+ )
+ );
+ }
+ }
+ );
+ }
+
private void on_account_available() {
update_from_field();
}
diff --git a/src/engine/app/app-draft-manager.vala b/src/engine/app/app-draft-manager.vala
index 112a17d0..23434b7b 100644
--- a/src/engine/app/app-draft-manager.vala
+++ b/src/engine/app/app-draft-manager.vala
@@ -31,7 +31,6 @@ public class Geary.App.DraftManager : BaseObject {
public const string PROP_CURRENT_DRAFT_ID = "current-draft-id";
public const string PROP_VERSIONS_SAVED = "versions-saved";
public const string PROP_VERSIONS_DROPPED = "versions-dropped";
- public const string PROP_DISCARD_ON_CLOSE = "discard-on-close";
/**
* Current saved state of the draft.
@@ -114,13 +113,6 @@ public class Geary.App.DraftManager : BaseObject {
*/
public int versions_dropped { get; private set; default = 0; }
- /**
- * When set, the draft will be discarded when {@link close_async} is called.
- *
- * In addition, when set all future {@link update}s will result in the draft being dropped.
- */
- public bool discard_on_close { get; set; default = false; }
-
private Account account;
private Folder? drafts_folder = null;
private FolderSupport.Create? create_support = null;
@@ -130,6 +122,7 @@ public class Geary.App.DraftManager : BaseObject {
private bool was_opened = false;
private Error? fatal_err = null;
+
/**
* Fired when a draft is successfully saved.
*/
@@ -272,13 +265,6 @@ public class Geary.App.DraftManager : BaseObject {
// don't flush a CLOSE down the pipe if failed, the operation loop is closed for business
if (fatal_err == null) {
- // if discarding on close, do so now
- if (discard_on_close) {
- // don't use discard(), which checks if open, but submit_push() directly,
- // which doesn't
- submit_push(null, null, null);
- }
-
// flush pending I/O
Nonblocking.Semaphore semaphore = new Nonblocking.Semaphore(cancellable);
mailbox.send(new Operation(OperationType.CLOSE, null, null, null, semaphore));
@@ -316,15 +302,13 @@ public class Geary.App.DraftManager : BaseObject {
*
* See {@link FolderSupport.Create.create_email_async} for more information on the flags and
* date_received arguments.
- *
- * @return A {@link Nonblocking.Semaphore} that is notified when the operation completes (with
- * or without error)
*/
- public Geary.Nonblocking.Semaphore? update(Geary.RFC822.Message draft, Geary.EmailFlags? flags,
- DateTime? date_received) throws Error {
+ public async void update(Geary.RFC822.Message draft,
+ Geary.EmailFlags? flags,
+ DateTime? date_received,
+ GLib.Cancellable? cancellable) throws GLib.Error {
check_open();
-
- return submit_push(draft, flags, date_received);
+ yield submit_push(draft, flags, date_received).wait_async(cancellable);
}
/**
@@ -335,27 +319,16 @@ public class Geary.App.DraftManager : BaseObject {
*
* Note: Replaced drafts are deleted, but on some services (i.e. Gmail) those deleted messages
* are actually moved to the Trash. This call does not currently solve that problem.
- *
- * @return A {@link Nonblocking.Semaphore} that is notified when the operation completes (with
- * or without error)
*/
- public Geary.Nonblocking.Semaphore? discard() throws Error {
+ public async void discard(GLib.Cancellable? cancellable)
+ throws GLib.Error {
check_open();
-
- return submit_push(null, null, null);
+ yield submit_push(null, null, null).wait_async(cancellable);
}
// Note that this call doesn't check_open(), important when used within close_async()
- private Nonblocking.Semaphore? submit_push(RFC822.Message? draft, EmailFlags? flags,
+ private Nonblocking.Semaphore submit_push(RFC822.Message? draft, EmailFlags? flags,
DateTime? date_received) {
- // no drafts are pushed when discarding on close
- if (draft != null && discard_on_close) {
- versions_dropped++;
- dropped(draft);
-
- return null;
- }
-
// clear out pending pushes (which can be updates or discards)
mailbox.revoke_matching((op) => {
// count and notify of dropped drafts
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]