[recipes] Make gr_send_mail async



commit 575a579042a765e2be92db9099870eb49978a9af
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Mar 1 21:06:48 2017 -0500

    Make gr_send_mail async
    
    Implement the full async pattern for this API, and make the
    callers fall back to saving the file if sending email fails
    with an error.

 src/gr-mail.c            |   90 +++++++++++++++++++++++++++++++++++-----------
 src/gr-mail.h            |   14 +++++---
 src/gr-recipe-exporter.c |   53 +++++++++++++++++++++++++--
 src/gr-shopping-page.c   |   59 +++++++++++++++++++++++++++++-
 4 files changed, 186 insertions(+), 30 deletions(-)
---
diff --git a/src/gr-mail.c b/src/gr-mail.c
index 1e03035..fdfc282 100644
--- a/src/gr-mail.c
+++ b/src/gr-mail.c
@@ -25,10 +25,12 @@
 
 typedef struct {
         GtkWindow *window;
+        char *handle;
         char *address;
         char *subject;
         char *body;
         char **attachments;
+        GTask *task;
 } MailData;
 
 static void
@@ -36,41 +38,71 @@ mail_data_free (gpointer data)
 {
         MailData *md = data;
 
-        window_unexport_handle (md->window);
+        if (md->handle) {
+                window_unexport_handle (md->window);
+                g_free (md->handle);
+        }
         g_free (md->address);
         g_free (md->subject);
         g_free (md->body);
         g_strfreev (md->attachments);
+        g_object_unref (md->task);
         g_free (md);
 }
 
 static void
-send_mail_using_mailto (MailData *data)
+launch_uri_done (GObject      *source,
+                 GAsyncResult *result,
+                 gpointer      data)
+{
+        MailData *md = data;
+        GError *error = NULL;
+
+        if (!g_app_info_launch_default_for_uri_finish (result, &error))
+                g_task_return_error (md->task, error);
+        else
+                g_task_return_boolean (md->task, TRUE);
+
+        mail_data_free (data);
+}
+
+static void
+send_mail_using_mailto (MailData *md)
 {
         g_autoptr(GString) url = NULL;
         g_autofree char *encoded_subject = NULL;
         g_autofree char *encoded_body = NULL;
         int i;
+        GdkDisplay *display;
+        GAppLaunchContext *context;
 
-        encoded_subject = g_uri_escape_string (data->subject, NULL, FALSE);
-        encoded_body = g_uri_escape_string (data->body, NULL, FALSE);
+        encoded_subject = g_uri_escape_string (md->subject, NULL, FALSE);
+        encoded_body = g_uri_escape_string (md->body, NULL, FALSE);
 
         url = g_string_new ("mailto:";);
 
-        g_string_append_printf (url, "\"%s\"", data->address);
+        g_string_append_printf (url, "\"%s\"", md->address);
         g_string_append_printf (url, "?subject=%s", encoded_subject);
         g_string_append_printf (url, "&body=%s", encoded_body);
 
-        for (i = 0; data->attachments[i]; i++) {
+        for (i = 0; md->attachments[i]; i++) {
                 g_autofree char *path = NULL;
 
-                path = g_uri_escape_string (data->attachments[i], NULL, FALSE);
+                path = g_uri_escape_string (md->attachments[i], NULL, FALSE);
                 g_string_append_printf (url, "&attach=%s", path);
         }
 
-        gtk_show_uri_on_window (data->window, url->str, GDK_CURRENT_TIME, NULL);
+        display = gtk_widget_get_display (GTK_WIDGET (md->window));
+        context = G_APP_LAUNCH_CONTEXT (gdk_display_get_app_launch_context (display));
 
-        mail_data_free (data);
+        if (md->handle)
+                g_app_launch_context_setenv (context, "PARENT_WINDOW_ID", md->handle);
+
+        g_app_info_launch_default_for_uri_async (url->str,
+                                                 G_APP_LAUNCH_CONTEXT (context),
+                                                 NULL,
+                                                 launch_uri_done,
+                                                 md);
 }
 
 static GDBusProxy *
@@ -91,12 +123,12 @@ get_mail_portal_proxy (void)
 }
 
 static void
-callback (GObject      *source,
-          GAsyncResult *result,
-          gpointer      data)
+compose_mail_done (GObject      *source,
+                   GAsyncResult *result,
+                   gpointer      data)
 {
         g_autoptr(GVariant) reply = NULL;
-        g_autoptr(GError) error = NULL;
+        GError *error = NULL;
         MailData *md = data;
 
         reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
@@ -106,9 +138,11 @@ callback (GObject      *source,
                 send_mail_using_mailto (md);
                 return;
         }
-        else if (error) {
-                g_message ("Sending mail using Email portal failed: %s", error->message);
-        }
+
+        if (error)
+                g_task_return_error (md->task, error);
+        else
+                g_task_return_boolean (md->task, TRUE);
 
         mail_data_free (md);
 }
@@ -122,6 +156,8 @@ window_handle_exported (GtkWindow  *window,
         GVariantBuilder opt_builder;
         GDBusProxy *proxy;
 
+        md->handle = g_strdup (handle_str);
+
         proxy = get_mail_portal_proxy ();
 
         if (proxy == NULL) {
@@ -134,7 +170,8 @@ window_handle_exported (GtkWindow  *window,
         g_variant_builder_add (&opt_builder, "{sv}", "address", g_variant_new_string (md->address));
         g_variant_builder_add (&opt_builder, "{sv}", "subject", g_variant_new_string (md->subject));
         g_variant_builder_add (&opt_builder, "{sv}", "body", g_variant_new_string (md->body));
-        g_variant_builder_add (&opt_builder, "{sv}", "attachments", g_variant_new_strv ((const char * const 
*)md->attachments, -1));
+        if (md->attachments)
+                g_variant_builder_add (&opt_builder, "{sv}", "attachments", g_variant_new_strv ((const char 
* const *)md->attachments, -1));
 
         g_dbus_proxy_call (proxy,
                            "ComposeEmail",
@@ -144,7 +181,7 @@ window_handle_exported (GtkWindow  *window,
                            G_DBUS_CALL_FLAGS_NONE,
                            G_MAXINT,
                            NULL,
-                           callback,
+                           compose_mail_done,
                            data);
 }
 
@@ -153,16 +190,27 @@ gr_send_mail (GtkWindow   *window,
               const char  *address,
               const char  *subject,
               const char  *body,
-              const char **attachments)
+              const char **attachments,
+              GAsyncReadyCallback   callback,
+              gpointer              user_data)
 {
         MailData *data;
+        const char *empty_strv[1] = { NULL };
 
-        data = g_new (MailData, 1);
+        data = g_new0 (MailData, 1);
         data->window = window;
         data->address = g_strdup (address ? address : "");
         data->subject = g_strdup (subject ? subject : "");
         data->body = g_strdup (body ? body : "");
-        data->attachments = g_strdupv ((char **)attachments);
+        data->attachments = g_strdupv (attachments ? (char **)attachments : (char **)empty_strv);
+        data->task = g_task_new (NULL, NULL, callback, user_data);
 
         window_export_handle (window, window_handle_exported, data);
 }
+
+gboolean
+gr_send_mail_finish (GAsyncResult  *result,
+                     GError       **error)
+{
+        return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/src/gr-mail.h b/src/gr-mail.h
index 623fd37..0950226 100644
--- a/src/gr-mail.h
+++ b/src/gr-mail.h
@@ -24,10 +24,14 @@
 
 G_BEGIN_DECLS
 
-void gr_send_mail (GtkWindow *window,
-                   const char  *address,
-                   const char  *subject,
-                   const char  *body,
-                   const char **attachments);
+void gr_send_mail (GtkWindow            *window,
+                   const char           *address,
+                   const char           *subject,
+                   const char           *body,
+                   const char          **attachments,
+                   GAsyncReadyCallback   callback,
+                   gpointer              user_data);
+gboolean gr_send_mail_finish (GAsyncResult  *result,
+                              GError       **error);
 
 G_END_DECLS
diff --git a/src/gr-recipe-exporter.c b/src/gr-recipe-exporter.c
index 123e7f2..f6d6ff8 100644
--- a/src/gr-recipe-exporter.c
+++ b/src/gr-recipe-exporter.c
@@ -119,6 +119,53 @@ cleanup_export (GrRecipeExporter *exporter)
 }
 
 #ifdef ENABLE_AUTOAR
+
+static void
+file_chooser_response (GtkNativeDialog  *self,
+                       int               response_id,
+                       GrRecipeExporter *exporter)
+{
+        if (response_id == GTK_RESPONSE_ACCEPT) {
+                g_autoptr(GFile) file = NULL;
+
+                file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (self));
+                g_file_copy_async (exporter->dest, file, 0, 0, NULL, NULL, NULL, NULL, NULL);
+        }
+
+        gtk_native_dialog_destroy (self);
+
+        cleanup_export (exporter);
+}
+
+static void
+mail_done (GObject      *source,
+           GAsyncResult *result,
+           gpointer      data)
+{
+        GrRecipeExporter *exporter = data;
+        g_autoptr(GError) error = NULL;
+
+        if (!gr_send_mail_finish (result, &error)) {
+                GObject *file_chooser;
+
+                g_message ("Sending mail failed: %s", error->message);
+
+                file_chooser = (GObject *)gtk_file_chooser_native_new (_("Save the exported recipe"),
+                                                                       GTK_WINDOW (exporter->window),
+                                                                       GTK_FILE_CHOOSER_ACTION_SAVE,
+                                                                       _("Save"),
+                                                                       _("Canel"));
+                gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (file_chooser), TRUE);
+
+                g_signal_connect (file_chooser, "response", G_CALLBACK (file_chooser_response), exporter);
+
+                gtk_native_dialog_show (GTK_NATIVE_DIALOG (file_chooser));
+                return;
+        }
+
+        cleanup_export (exporter);
+}
+
 static void
 completed_cb (AutoarCompressor *compressor,
               GrRecipeExporter *exporter)
@@ -168,9 +215,9 @@ completed_cb (AutoarCompressor *compressor,
         attachments[0] = path;
         attachments[1] = NULL;
 
-        gr_send_mail (GTK_WINDOW (exporter->window), address, subject, body, attachments);
-
-        cleanup_export (exporter);
+        gr_send_mail (GTK_WINDOW (exporter->window),
+                      address, subject, body, attachments,
+                      mail_done, exporter);
 }
 
 static void
diff --git a/src/gr-shopping-page.c b/src/gr-shopping-page.c
index d4ffce2..b4d99f1 100644
--- a/src/gr-shopping-page.c
+++ b/src/gr-shopping-page.c
@@ -674,6 +674,61 @@ print_list (GrShoppingPage *page)
         g_list_free_full (items, item_free);
 }
 
+
+static void
+file_chooser_response (GtkNativeDialog  *self,
+                       int               response_id,
+                       GrShoppingPage   *page)
+{
+        if (response_id == GTK_RESPONSE_ACCEPT) {
+                GList *recipes, *items;
+                g_autoptr(GFile) file = NULL;
+                g_autofree char *text = NULL;
+
+                recipes = get_recipes (page);
+                items = get_ingredients (page);
+
+                text = gr_shopping_list_format (recipes, items);
+
+                g_list_free_full (recipes, g_object_unref);
+                g_list_free_full (items, item_free);
+
+                file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (self));
+                g_file_replace_contents (file, text, -1, NULL, FALSE, 0, NULL, NULL, NULL);
+        }
+
+        gtk_native_dialog_destroy (self);
+}
+
+static void
+mail_done (GObject      *source,
+           GAsyncResult *result,
+           gpointer      data)
+{
+        GrShoppingPage *page = data;
+        g_autoptr(GError) error = NULL;
+
+        if (!gr_send_mail_finish (result, &error)) {
+                GObject *file_chooser;
+                GtkWidget *window;
+
+                g_message ("Sending mail failed: %s", error->message);
+
+                window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
+                file_chooser = (GObject *)gtk_file_chooser_native_new (_("Save the shopping list"),
+                                                                       GTK_WINDOW (window),
+                                                                       GTK_FILE_CHOOSER_ACTION_SAVE,
+                                                                       _("Save"),
+                                                                       _("Canel"));
+                gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (file_chooser), TRUE);
+
+                g_signal_connect (file_chooser, "response", G_CALLBACK (file_chooser_response), page);
+
+                gtk_native_dialog_show (GTK_NATIVE_DIALOG (file_chooser));
+                return;
+        }
+}
+
 static void
 share_list (GrShoppingPage *page)
 {
@@ -688,7 +743,9 @@ share_list (GrShoppingPage *page)
 
         window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
 
-        gr_send_mail (GTK_WINDOW (window), NULL, _("Shopping List"), text, NULL);
+        gr_send_mail (GTK_WINDOW (window),
+                      NULL, _("Shopping List"), text, NULL,
+                      mail_done, page);
 
         g_list_free_full (recipes, g_object_unref);
         g_list_free_full (items, item_free);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]