Application.Controller: Allow creating composers with alt save folders

Allow a non-draft folder to be specified as the location to save
email being composed.
This commit is contained in:
Michael Gratton 2020-04-20 23:47:38 +10:00 committed by Michael James Gratton
parent 085ed9a6a3
commit 14f3dd0c36
2 changed files with 97 additions and 83 deletions

View file

@ -325,7 +325,8 @@ internal class Application.Controller : Geary.BaseObject {
/**
* Opens a composer for writing a new, blank message.
*/
public async void compose_new_email(Geary.RFC822.MailboxAddress? to = null) {
public async Composer.Widget? compose_new_email(Geary.RFC822.MailboxAddress? to = null,
Geary.Folder? save_to = null) {
// If there's already an empty composer open, just use that
MainWindow main = this.application.get_active_main_window();
Composer.Widget existing = main.conversation_viewer.current_composer;
@ -334,17 +335,19 @@ internal class Application.Controller : Geary.BaseObject {
existing.is_blank) {
existing.present();
existing.set_focus();
return;
return existing;
}
var context = this.accounts.get(
this.application.get_active_main_window().selected_account.information
);
Composer.Widget? composer = null;
if (context != null) {
var composer = new Composer.Widget(
composer = new Composer.Widget(
this.application,
context,
this.accounts.values.read_only_view
this.accounts.values.read_only_view,
save_to
);
register_composer(composer);
show_composer(composer);
@ -354,6 +357,85 @@ internal class Application.Controller : Geary.BaseObject {
report_problem(new Geary.ProblemReport(err));
}
}
return composer;
}
/**
* Opens new composer with an existing message as context.
*
* If the given type is {@link Composer.Widget.ContextType.EDIT},
* the context is loaded to be edited (e.g. for drafts, templates,
* sending again. Otherwise the context is treated as the email to
* be replied to, etc.
*/
public async Composer.Widget? compose_with_context_email(Composer.Widget.ContextType type,
Geary.Email context,
string? quote,
Geary.Folder? save_to = null) {
MainWindow show_on = this.application.get_active_main_window();
if (type == EDIT) {
// Check all known composers since the context may be open
// an existing composer already.
foreach (Composer.Widget composer in this.composer_widgets) {
if (composer.current_mode != NONE &&
composer.current_mode != CLOSED &&
composer.saved_id != null &&
composer.saved_id.equal_to(context.id)) {
composer.present();
composer.set_focus();
return composer;
}
}
} else {
// See whether there is already an inline message in the
// current window that is either a reply/forward for that
// message, or there is a quote to insert into it.
foreach (Composer.Widget existing in this.composer_widgets) {
if (existing.get_toplevel() == show_on &&
(existing.current_mode == INLINE ||
existing.current_mode == INLINE_COMPACT) &&
(context.id in existing.get_referred_ids() ||
quote != null)) {
try {
existing.append_to_email(context, quote, type);
existing.present();
return existing;
} catch (Geary.EngineError error) {
report_problem(new Geary.ProblemReport(error));
}
}
}
// Can't re-use an existing composer, so need to create a
// new one. Replies must open inline in the main window,
// so we need to ensure there are no composers open there
// first.
if (!show_on.close_composer(true)) {
return null;
}
}
var account = this.accounts.get(
this.application.get_active_main_window().selected_account.information
);
Composer.Widget? composer = null;
if (account != null) {
composer = new Composer.Widget(
this.application,
account,
this.accounts.values.read_only_view,
save_to
);
register_composer(composer);
show_composer(composer);
try {
yield composer.load_context(type, context, quote);
} catch (GLib.Error err) {
report_problem(new Geary.ProblemReport(err));
}
}
return composer;
}
/**
@ -384,80 +466,6 @@ internal class Application.Controller : Geary.BaseObject {
}
}
/**
* Opens new composer with an existing message as context.
*
* If the given type is {@link Composer.Widget.ContextType.EDIT},
* the context is loaded to be edited (e.g. for drafts, templates,
* sending again. Otherwise the context is treated as the email to
* be replied to, etc.
*/
public async void compose_with_context_email(Composer.Widget.ContextType type,
Geary.Email context,
string? quote) {
MainWindow show_on = this.application.get_active_main_window();
if (type == EDIT) {
// Check all known composers since the context may be open
// an existing composer already.
foreach (Composer.Widget composer in this.composer_widgets) {
if (composer.current_mode != NONE &&
composer.current_mode != CLOSED &&
composer.saved_id != null &&
composer.saved_id.equal_to(context.id)) {
composer.present();
composer.set_focus();
return;
}
}
} else {
// See whether there is already an inline message in the
// current window that is either a reply/forward for that
// message, or there is a quote to insert into it.
foreach (Composer.Widget existing in this.composer_widgets) {
if (existing.get_toplevel() == show_on &&
(existing.current_mode == INLINE ||
existing.current_mode == INLINE_COMPACT) &&
(context.id in existing.get_referred_ids() ||
quote != null)) {
try {
existing.append_to_email(context, quote, type);
existing.present();
return;
} catch (Geary.EngineError error) {
report_problem(new Geary.ProblemReport(error));
}
}
}
// Can't re-use an existing composer, so need to create a
// new one. Replies must open inline in the main window,
// so we need to ensure there are no composers open there
// first.
if (!show_on.close_composer(true)) {
return;
}
}
var account = this.accounts.get(
this.application.get_active_main_window().selected_account.information
);
if (account != null) {
var composer = new Composer.Widget(
this.application,
account,
this.accounts.values.read_only_view
);
register_composer(composer);
show_composer(composer);
try {
yield composer.load_context(type, context, quote);
} catch (GLib.Error err) {
report_problem(new Geary.ProblemReport(err));
}
}
}
/** Displays a problem report when an error has been encountered. */
public void report_problem(Geary.ProblemReport report) {
debug("Problem reported: %s", report.to_string());

View file

@ -29,7 +29,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
/// Translators: Title for an empty composer window
private const string DEFAULT_TITLE = _("New Message");
/**
* Determines the type of the context email passed to the composer
*
@ -466,6 +466,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
private Gee.Map<string,Geary.Memory.Buffer> inline_files = new Gee.HashMap<string,Geary.Memory.Buffer>();
private Gee.Map<string,Geary.Memory.Buffer> cid_files = new Gee.HashMap<string,Geary.Memory.Buffer>();
private Geary.Folder? save_to;
private Geary.App.DraftManager? draft_manager = null;
private GLib.Cancellable? draft_manager_opening = null;
private Geary.TimeoutManager draft_timer;
@ -503,12 +504,14 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
public Widget(Application.Client application,
Application.AccountContext initial_account,
Gee.Collection<Application.AccountContext> all_accounts) {
Gee.Collection<Application.AccountContext> all_accounts,
Geary.Folder? save_to = null) {
components_reflow_box_get_type();
base_ref();
this.application = application;
this.sender_context = initial_account;
this.accounts = all_accounts;
this.save_to = save_to;
this.header = new Headerbar(application.config);
this.header.expand_composer.connect(on_expand_compact_headers);
@ -1631,9 +1634,12 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
);
this.draft_manager_opening = internal_cancellable;
Geary.Folder? target = yield this.sender_context.account.get_required_special_folder_async(
DRAFTS, internal_cancellable
);
Geary.Folder? target = this.save_to;
if (target == null) {
this.sender_context.account.get_required_special_folder_async(
DRAFTS, internal_cancellable
);
}
Geary.EmailFlags? flags = (
target.used_as == DRAFTS