[geary/mjog/email-templates: 1/7] Geary.App.DraftManaager: Update API to something more RAII-like
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/email-templates: 1/7] Geary.App.DraftManaager: Update API to something more RAII-like
- Date: Tue, 21 Apr 2020 13:37:11 +0000 (UTC)
commit 085ed9a6a33dfa0d4919d155ed7f564bf4ed9859
Author: Michael Gratton <mike vee net>
Date: Mon Apr 20 23:46:02 2020 +1000
Geary.App.DraftManaager: Update API to something more RAII-like
Replace open method with an async ctor, so we can make a few properties
non-null by default, and callers need to call one less call. Make
destination folder configurable, and require email flags passed in
via the ctor, not every time when saving.
src/client/composer/composer-widget.vala | 36 ++++++----
src/engine/app/app-draft-manager.vala | 109 ++++++++++++++-----------------
2 files changed, 71 insertions(+), 74 deletions(-)
---
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index e10d2272..9c013a6b 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -468,7 +468,6 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
private Geary.App.DraftManager? draft_manager = null;
private GLib.Cancellable? draft_manager_opening = null;
- private Geary.EmailFlags draft_flags = new Geary.EmailFlags.with(Geary.EmailFlags.DRAFT);
private Geary.TimeoutManager draft_timer;
private bool is_draft_saved = false;
private string draft_status_text {
@@ -1632,11 +1631,31 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
);
this.draft_manager_opening = internal_cancellable;
- Geary.App.DraftManager new_manager = new Geary.App.DraftManager(
- this.sender_context.account
+ Geary.Folder? target = yield this.sender_context.account.get_required_special_folder_async(
+ DRAFTS, internal_cancellable
);
+
+ Geary.EmailFlags? flags = (
+ target.used_as == DRAFTS
+ ? new Geary.EmailFlags.with(Geary.EmailFlags.DRAFT)
+ : new Geary.EmailFlags()
+ );
+
try {
- yield new_manager.open_async(editing_draft_id, internal_cancellable);
+ var new_manager = yield new Geary.App.DraftManager(
+ this.sender_context.account,
+ target,
+ flags,
+ editing_draft_id,
+ internal_cancellable
+ );
+ new_manager.notify[Geary.App.DraftManager.PROP_DRAFT_STATE]
+ .connect(on_draft_state_changed);
+ new_manager.notify[Geary.App.DraftManager.PROP_CURRENT_DRAFT_ID]
+ .connect(on_draft_id_changed);
+ new_manager.fatal
+ .connect(on_draft_manager_fatal);
+ this.draft_manager = new_manager;
debug("Draft manager opened");
} catch (GLib.Error err) {
this.header.show_save_and_close = false;
@@ -1645,14 +1664,6 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
this.draft_manager_opening = null;
}
- new_manager.notify[Geary.App.DraftManager.PROP_DRAFT_STATE]
- .connect(on_draft_state_changed);
- new_manager.notify[Geary.App.DraftManager.PROP_CURRENT_DRAFT_ID]
- .connect(on_draft_id_changed);
- new_manager.fatal.connect(on_draft_manager_fatal);
-
- this.draft_manager = new_manager;
-
update_draft_state();
this.header.show_save_and_close = true;
}
@@ -1743,7 +1754,6 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
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
);
diff --git a/src/engine/app/app-draft-manager.vala b/src/engine/app/app-draft-manager.vala
index bcaf26c9..8e9863af 100644
--- a/src/engine/app/app-draft-manager.vala
+++ b/src/engine/app/app-draft-manager.vala
@@ -1,28 +1,29 @@
-/* Copyright 2016 Software Freedom Conservancy Inc.
+/*
+ * Copyright 2016 © Software Freedom Conservancy Inc.
+ * Copyright 2020 © Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
- * Manage saving, replacing, and deleting the various versions of a draft message while the user is
- * editing it.
+ * Manage saving, replacing, and deleting an email being edited.
*
- * Each composer should create a single DraftManager object for the lifetime of the compose
- * session. The DraftManager interface offers "fire-and-forget" nonblocking (but not
- * asynchronous) methods for the composer to schedule remote operations without worrying about
- * synchronization, operation ordering, error-handling, and so forth.
+ * Each composer should create a single DraftManager object for the
+ * lifetime of the compose session. The DraftManager interface offers
+ * "fire-and-forget" nonblocking methods for the composer to schedule
+ * remote operations without worrying about synchronization, operation
+ * ordering, error-handling, and so forth.
*
- * If successive drafts are submitted for storage, drafts waiting in the queue (i.e. not yet sent
- * to the server) are dropped without further consideration. This prevents needless I/O with the
- * server saving drafts that are only to be replaced by later versions.
+ * If successive drafts are submitted for storage, drafts waiting in
+ * the queue (i.e. not yet sent to the server) are dropped without
+ * further consideration. This prevents needless I/O with the server
+ * saving drafts that are only to be replaced by later versions.
*
- * Important: This object should be used ''per'' composed email and not to manage multiple emails
- * being composed to the same {@link Account}. DraftManager's internal state is solely for managing
- * the lifecycle of a single email being composed by the user.
- *
- * The only async calls for DraftManager is {@link open_async} and {@link close_async}, which give
- * it a chance to initialize and tear-down in an orderly manner.
+ * Important: This object should be used ''per'' composed email and
+ * not to manage multiple emails being composed to the same {@link
+ * Account}. DraftManager's internal state is solely for managing the
+ * lifecycle of a single email being composed by the user.
*/
public class Geary.App.DraftManager : BaseObject {
@@ -81,10 +82,10 @@ public class Geary.App.DraftManager : BaseObject {
/**
* Indicates the {@link DraftManager} is open and ready for service.
*
- * Although this property can be monitored, the object is considered "open" when
- * {@link open_async} completes, not when this property changes to true.
+ * The object is considered "open" from when it has been
+ * constructed until {@link close_async} is called.
*/
- public bool is_open { get; private set; default = false; }
+ public bool is_open { get; private set; default = true; }
/**
* The current saved state of the draft.
@@ -99,7 +100,7 @@ public class Geary.App.DraftManager : BaseObject {
/**
* The version number of the most recently saved draft.
*
- * Even if an initial draft is supplied (with {@link open_async}, this always starts at zero.
+ * Even if an initial draft is supplied, this always starts at zero.
* It merely represents the number of times a draft was successfully saved.
*
* A {@link discard} operation will reset this counter to zero.
@@ -114,12 +115,12 @@ public class Geary.App.DraftManager : BaseObject {
public int versions_dropped { get; private set; default = 0; }
private Account account;
- private Folder? drafts_folder = null;
- private FolderSupport.Create? create_support = null;
- private FolderSupport.Remove? remove_support = null;
+ private Geary.EmailFlags flags = null;
+ private Folder drafts_folder;
+ private FolderSupport.Create create_support;
+ private FolderSupport.Remove remove_support;
private Nonblocking.Queue<Operation?> mailbox =
new Nonblocking.Queue<Operation?>.fifo();
- private bool was_opened = false;
private Error? fatal_err = null;
@@ -163,10 +164,6 @@ public class Geary.App.DraftManager : BaseObject {
debug("%s: Irrecoverable failure: %s", to_string(), err.message);
}
- public DraftManager(Geary.Account account) {
- this.account = account;
- }
-
protected virtual void notify_stored(Geary.RFC822.Message draft) {
versions_saved++;
stored(draft);
@@ -192,32 +189,33 @@ public class Geary.App.DraftManager : BaseObject {
*
* @see is_open
*/
- public async void open_async(Geary.EmailIdentifier? initial_draft_id, Cancellable? cancellable = null)
- throws Error {
- if (is_open)
- throw new EngineError.ALREADY_OPEN("%s is already open", to_string());
- else if (was_opened)
- throw new EngineError.UNSUPPORTED("%s cannot be re-opened", to_string());
-
- was_opened = true;
+ public async DraftManager(Account account,
+ Folder save_to,
+ EmailFlags flags,
+ EmailIdentifier? initial_draft_id,
+ GLib.Cancellable? cancellable = null)
+ throws GLib.Error {
+ this.account = account;
+ this.drafts_folder = save_to;
+ this.flags = flags;
- current_draft_id = initial_draft_id;
- if (current_draft_id != null)
+ this.current_draft_id = initial_draft_id;
+ if (this.current_draft_id != null) {
draft_state = DraftState.STORED;
-
- drafts_folder = account.get_special_folder(DRAFTS);
- if (drafts_folder == null)
- throw new EngineError.NOT_FOUND("%s: No drafts folder found", to_string());
+ }
// if drafts folder doesn't support create and remove, call it quits
- create_support = drafts_folder as Geary.FolderSupport.Create;
- remove_support = drafts_folder as Geary.FolderSupport.Remove;
- if (create_support == null || remove_support == null) {
- throw new EngineError.UNSUPPORTED("%s: Drafts folder %s does not support create and remove",
- to_string(), drafts_folder.to_string());
+ if (!(save_to is FolderSupport.Create &&
+ save_to is FolderSupport.Remove)) {
+ throw new EngineError.UNSUPPORTED(
+ "%s: Drafts folder %s does not support create and remove",
+ to_string(), drafts_folder.to_string()
+ );
}
+ this.create_support = (FolderSupport.Create) save_to;
+ this.remove_support = (FolderSupport.Remove) save_to;
- drafts_folder.closed.connect(on_folder_closed);
+ this.drafts_folder.closed.connect(on_folder_closed);
yield drafts_folder.open_async(Folder.OpenFlags.NO_DELAY, cancellable);
@@ -236,9 +234,6 @@ public class Geary.App.DraftManager : BaseObject {
// start the operation message loop, which ensures commands are handled in orderly fashion
operation_loop_async.begin();
-
- // done
- is_open = true;
}
private void on_folder_closed(Folder.CloseReason reason) {
@@ -253,7 +248,6 @@ public class Geary.App.DraftManager : BaseObject {
*
* Once closed, the object cannot be opened again. Create a new object in that case.
*
- * @see open_async
* @see is_open
*/
public async void close_async(Cancellable? cancellable = null) throws Error {
@@ -283,13 +277,7 @@ public class Geary.App.DraftManager : BaseObject {
// Disconnect before closing, as signal handler is for unexpected closes
drafts_folder.closed.disconnect(on_folder_closed);
- try {
- yield drafts_folder.close_async(cancellable);
- } finally {
- drafts_folder = null;
- create_support = null;
- remove_support = null;
- }
+ yield drafts_folder.close_async(cancellable);
}
private void check_open() throws EngineError {
@@ -304,7 +292,6 @@ public class Geary.App.DraftManager : BaseObject {
* date_received arguments.
*/
public async void update(Geary.RFC822.Message draft,
- Geary.EmailFlags? flags,
DateTime? date_received,
GLib.Cancellable? cancellable) throws GLib.Error {
check_open();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]