[geary/mjog/email-templates: 6/7] Plugins: Add EmailTemplate plugin
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/email-templates: 6/7] Plugins: Add EmailTemplate plugin
- Date: Tue, 21 Apr 2020 13:37:36 +0000 (UTC)
commit 47d4056010303024ee2be1ed07da7f63bbb86737
Author: Michael Gratton <mike vee net>
Date: Mon Apr 20 23:51:55 2020 +1000
Plugins: Add EmailTemplate plugin
.../email-templates.plugin.desktop.in | 4 +
.../plugin/email-templates/email-templates.vala | 332 +++++++++++++++++++++
src/client/plugin/email-templates/meson.build | 26 ++
src/client/plugin/meson.build | 1 +
4 files changed, 363 insertions(+)
---
diff --git a/src/client/plugin/email-templates/email-templates.plugin.desktop.in
b/src/client/plugin/email-templates/email-templates.plugin.desktop.in
new file mode 100644
index 00000000..650e3c50
--- /dev/null
+++ b/src/client/plugin/email-templates/email-templates.plugin.desktop.in
@@ -0,0 +1,4 @@
+[Plugin]
+Module=email-templates
+Name=Email Templates
+Description=Create reusable templates for sending email
diff --git a/src/client/plugin/email-templates/email-templates.vala
b/src/client/plugin/email-templates/email-templates.vala
new file mode 100644
index 00000000..5882e515
--- /dev/null
+++ b/src/client/plugin/email-templates/email-templates.vala
@@ -0,0 +1,332 @@
+/*
+ * 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.
+ */
+
+[ModuleInit]
+public void peas_register_types(TypeModule module) {
+ Peas.ObjectModule obj = module as Peas.ObjectModule;
+ obj.register_extension_type(
+ typeof(Plugin.PluginBase),
+ typeof(Plugin.EmailTemplates)
+ );
+}
+
+/**
+ * Manages UI for special folders.
+ */
+public class Plugin.EmailTemplates :
+ PluginBase, FolderExtension, EmailExtension {
+
+
+ // Translators: Templates folder name alternatives. Separate names
+ // using a vertical bar and put the most common localized name to
+ // the front for the default. English names do not need to be
+ // included.
+ private const string LOC_NAMES = _(
+ "Templates | Template Mail | Template Email | Template E-Mail"
+ );
+ // This must be identical to he above except without translation
+ private const string UNLOC_NAMES = (
+ "Templates | Template Mail | Template Email | Template E-Mail"
+ );
+
+
+ private const string ACTION_NEW = "new-template";
+ private const string ACTION_EDIT = "edit-template";
+ private const string ACTION_SEND = "send-template";
+
+ private const int INFO_BAR_PRIORITY = 0;
+
+
+ public FolderContext folders {
+ get; set construct;
+ }
+
+ public EmailContext email {
+ get; set construct;
+ }
+
+
+ private FolderStore? folder_store = null;
+ private EmailStore? email_store = null;
+
+ private GLib.SimpleAction? new_action = null;
+ private GLib.SimpleAction? edit_action = null;
+ private GLib.SimpleAction? send_action = null;
+
+ private Gee.Map<Folder,InfoBar> info_bars =
+ new Gee.HashMap<Folder,InfoBar>();
+
+ private Gee.List<string> folder_names = new Gee.ArrayList<string>();
+
+ private GLib.Cancellable cancellable = new GLib.Cancellable();
+
+
+ public override async void activate() throws GLib.Error {
+ Geary.iterate_array(UNLOC_NAMES.split("|")).map<string>(
+ (name) => name.strip()
+ ).add_all_to(this.folder_names);
+ Geary.iterate_array(LOC_NAMES.split("|")).map<string>(
+ (name) => name.strip()
+ ).add_all_to(this.folder_names);
+
+ this.folder_store = yield this.folders.get_folder_store();
+ this.folder_store.folders_available.connect(on_folders_available);
+ this.folder_store.folders_unavailable.connect(on_folders_unavailable);
+ this.folder_store.folders_type_changed.connect(on_folders_type_changed);
+ this.folder_store.folder_selected.connect(on_folder_selected);
+
+ this.email_store = yield this.email.get_email_store();
+ this.email_store.email_displayed.connect(on_email_displayed);
+
+ this.new_action = new GLib.SimpleAction(
+ ACTION_NEW, this.folder_store.folder_variant_type
+ );
+ this.new_action.activate.connect(on_new_activated);
+ this.plugin_application.register_action(this.new_action);
+
+ this.edit_action = new GLib.SimpleAction(
+ ACTION_EDIT, this.email_store.email_identifier_variant_type
+ );
+ this.edit_action.activate.connect(on_edit_activated);
+ this.plugin_application.register_action(this.edit_action);
+
+ this.send_action = new GLib.SimpleAction(
+ ACTION_SEND, this.email_store.email_identifier_variant_type
+ );
+ this.send_action.activate.connect(on_send_activated);
+ this.plugin_application.register_action(this.send_action);
+
+ foreach (var folder in this.folder_store.get_folders()) {
+ if (folder.display_name in this.folder_names) {
+ register_folder(folder);
+ }
+ }
+ }
+
+ public override async void deactivate(bool is_shutdown) throws GLib.Error {
+ // Take a copy of the keys so the collection doesn't asplode
+ // as it is being modified.
+ foreach (var folder in this.info_bars.keys.to_array()) {
+ unregister_folder(folder);
+ }
+ this.info_bars.clear();
+ this.folder_names.clear();
+
+ this.plugin_application.deregister_action(this.new_action);
+ this.new_action = null;
+
+ this.plugin_application.deregister_action(this.edit_action);
+ this.edit_action = null;
+
+ this.plugin_application.deregister_action(this.send_action);
+ this.send_action = null;
+
+ this.folder_store.folders_available.disconnect(on_folders_available);
+ this.folder_store.folders_unavailable.disconnect(on_folders_unavailable);
+ this.folder_store.folders_type_changed.disconnect(on_folders_type_changed);
+ this.folder_store.folder_selected.disconnect(on_folder_selected);
+ this.folder_store = null;
+
+ this.email_store.email_displayed.disconnect(on_email_displayed);
+ this.email_store = null;
+
+ this.cancellable.cancel();
+ }
+
+ private async void edit_email(Folder? target, EmailIdentifier? id, bool send) {
+ var account = (target != null) ? target.account : id.account;
+ try {
+ var composer = this.plugin_application.new_composer(account);
+ if (!send) {
+ var folder = target;
+ if (folder == null && id != null) {
+ var containing = yield this.folder_store.list_containing_folders(
+ id, this.cancellable
+ );
+ folder = containing.first_match(
+ (f) => this.info_bars.has_key(f)
+ );
+ }
+ composer.save_to_folder(folder);
+ composer.can_send = false;
+ }
+
+ if (id != null) {
+ yield composer.edit_email(id);
+ }
+ composer.show();
+ } catch (GLib.Error err) {
+ warning("Unable to construct composer: %s", err.message);
+ }
+ }
+
+ private void register_folder(Folder target) {
+ try {
+ this.folders.register_folder_used_as(
+ target,
+ // Translators: The name of the folder used to
+ // store email templates
+ _("Templates"),
+ "folder-templates-symbolic"
+ );
+ this.info_bars.set(
+ target,
+ new_templates_folder_info_bar(target)
+ );
+ } catch (GLib.Error err) {
+ warning(
+ "Failed to register %s as templates folder: %s",
+ target.persistent_id,
+ err.message
+ );
+ }
+ }
+
+ private void unregister_folder(Folder target) {
+ var info_bar = this.info_bars.get(target);
+ if (info_bar != null) {
+ try {
+ this.folders.unregister_folder_used_as(target);
+ } catch (GLib.Error err) {
+ warning(
+ "Failed to unregister %s as templates folder: %s",
+ target.persistent_id,
+ err.message
+ );
+ }
+ this.folders.remove_folder_info_bar(target, info_bar);
+ this.info_bars.unset(target);
+ }
+ }
+
+ private void update_folder(Folder target) {
+ var info_bar = this.info_bars.get(target);
+ if (info_bar != null) {
+ this.folders.add_folder_info_bar(
+ target, info_bar, INFO_BAR_PRIORITY
+ );
+ }
+ }
+
+ private async void update_email(Email target) {
+ var containing = Gee.Collection.empty<Folder>();
+ try {
+ containing = yield this.folder_store.list_containing_folders(
+ target.identifier, this.cancellable
+ );
+ } catch (GLib.Error err) {
+ warning("Could not load folders for email: %s", err.message);
+ }
+ if (containing.any_match((f) => this.info_bars.has_key(f))) {
+ this.email.add_email_info_bar(
+ target.identifier,
+ new_template_email_info_bar(target.identifier),
+ INFO_BAR_PRIORITY
+ );
+ }
+ }
+
+ private InfoBar new_templates_folder_info_bar(Folder target) {
+ var bar = this.info_bars.get(target);
+ if (bar == null) {
+ bar = new InfoBar(target.display_name);
+ bar.primary_button = new Button(
+ // Translators: Info bar button label for creating a
+ // new email template
+ _("New"),
+ this.new_action,
+ target.to_variant()
+ );
+ this.info_bars.set(target, bar);
+ }
+ return bar;
+ }
+
+ private InfoBar new_template_email_info_bar(EmailIdentifier target) {
+ // Translators: Infobar status label for an email template
+ var bar = new InfoBar(_("Message template"));
+ bar.primary_button = new Button(
+ // Translators: Info bar button label for sending an
+ // email template
+ _("Send"),
+ this.send_action,
+ target.to_variant()
+ );
+ bar.secondary_buttons.add(
+ new Button(
+ // Translators: Info bar button label for editing an
+ // existing email template
+ _("Edit"),
+ this.edit_action,
+ target.to_variant()
+ )
+ );
+ return bar;
+ }
+
+ private void on_folders_available(Gee.Collection<Folder> available) {
+ foreach (var folder in available) {
+ if (folder.display_name in this.folder_names) {
+ register_folder(folder);
+ }
+ }
+ }
+
+ private void on_folders_unavailable(Gee.Collection<Folder> unavailable) {
+ foreach (var folder in unavailable) {
+ unregister_folder(folder);
+ }
+ }
+
+ private void on_folders_type_changed(Gee.Collection<Folder> changed) {
+ foreach (var folder in changed) {
+ unregister_folder(folder);
+ if (folder.display_name in this.folder_names) {
+ register_folder(folder);
+ }
+ update_folder(folder);
+ }
+ }
+
+ private void on_folder_selected(Folder selected) {
+ update_folder(selected);
+ }
+
+ private void on_new_activated(GLib.Action action, GLib.Variant? target) {
+ if (this.folder_store != null && target != null) {
+ Folder? folder = this.folder_store.get_folder_from_variant(target);
+ if (folder != null) {
+ this.edit_email.begin(folder, null, false);
+ }
+ }
+ }
+
+ private void on_edit_activated(GLib.Action action, GLib.Variant? target) {
+ if (this.email_store != null && target != null) {
+ EmailIdentifier? id =
+ this.email_store.get_email_identifier_from_variant(target);
+ if (id != null) {
+ this.edit_email.begin(null, id, false);
+ }
+ }
+ }
+
+ private void on_send_activated(GLib.Action action, GLib.Variant? target) {
+ if (this.email_store != null && target != null) {
+ EmailIdentifier? id =
+ this.email_store.get_email_identifier_from_variant(target);
+ if (id != null) {
+ this.edit_email.begin(null, id, true);
+ }
+ }
+ }
+
+ private void on_email_displayed(Email email) {
+ this.update_email.begin(email);
+ }
+
+}
diff --git a/src/client/plugin/email-templates/meson.build b/src/client/plugin/email-templates/meson.build
new file mode 100644
index 00000000..56ef251f
--- /dev/null
+++ b/src/client/plugin/email-templates/meson.build
@@ -0,0 +1,26 @@
+
+plugin_name = 'email-templates'
+
+plugin_src = files(plugin_name + '.vala')
+plugin_data = plugin_name + plugin_data_suffix
+plugin_dest = plugins_dir / plugin_name
+
+shared_module(
+ plugin_name,
+ sources: plugin_src,
+ dependencies: plugin_dependencies,
+ include_directories: config_h_dir,
+ vala_args: geary_vala_args,
+ c_args: plugin_c_args,
+ install: true,
+ install_dir: plugin_dest
+)
+
+i18n.merge_file(
+ input: files(plugin_data + plugin_data_src_suffix),
+ output: plugin_data,
+ type: 'desktop',
+ po_dir: po_dir,
+ install: true,
+ install_dir: plugin_dest
+)
diff --git a/src/client/plugin/meson.build b/src/client/plugin/meson.build
index 33c5ece4..6197a5f0 100644
--- a/src/client/plugin/meson.build
+++ b/src/client/plugin/meson.build
@@ -28,6 +28,7 @@ plugin_data_src_suffix = '.desktop.in'
plugin_data_suffix = '.plugin'
subdir('desktop-notifications')
+subdir('email-templates')
subdir('folder-highlight')
subdir('messaging-menu')
subdir('notification-badge')
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]