I#1373 - itip-view: Offer to show other parts from multipart/alternative ][

Change how the alternative HTML is present to the user, to avoid
hiding meeting details when the sender-provided description
does not contain it.

Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1373
This commit is contained in:
Milan Crha
2022-03-01 15:59:15 +01:00
parent 7a29a79831
commit aa788e3866
5 changed files with 228 additions and 68 deletions

View File

@ -11,9 +11,9 @@
<_description>Whether to preset option to preserve existing reminder by default</_description>
</key>
<key name="show-message-description" type="b">
<default>true</default>
<default>false</default>
<_summary>Show invitation description provided by the sender</_summary>
<_description>Set to true to show invitation description as provided by the sender, if such is available; otherwise generate the invitation description from the iCalendar component</_description>
<_description>Set to true to show invitation description as provided by the sender, if such is available</_description>
</key>
</schema>
</schemalist>

View File

@ -48,6 +48,29 @@ static const gchar *formatter_mime_types[] = {
NULL
};
static gboolean
emfe_itip_get_use_alternative_html (const gchar *uri)
{
SoupURI *soup_uri;
gboolean res = FALSE;
if (!uri)
return FALSE;
soup_uri = soup_uri_new (uri);
if (soup_uri) {
GHashTable *query;
query = soup_form_decode (soup_uri->query);
res = query && g_strcmp0 (g_hash_table_lookup (query, "e-itip-view-alternative-html"), "1") == 0;
if (query)
g_hash_table_destroy (query);
soup_uri_free (soup_uri);
}
return res;
}
static gboolean
emfe_itip_format (EMailFormatterExtension *extension,
EMailFormatter *formatter,
@ -58,12 +81,18 @@ emfe_itip_format (EMailFormatterExtension *extension,
{
GString *buffer;
EMailPartItip *itip_part;
gboolean use_alternative_html;
/* This can be called with attachment parts too, thus
return silently in that case */
if (!E_IS_MAIL_PART_ITIP (part))
return FALSE;
use_alternative_html = emfe_itip_get_use_alternative_html (context->uri);
if (use_alternative_html && context->mode != E_MAIL_FORMATTER_MODE_RAW)
return TRUE;
itip_part = (EMailPartItip *) part;
if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
@ -83,6 +112,17 @@ emfe_itip_format (EMailFormatterExtension *extension,
itip_view_write_for_printing (itip_view, buffer);
} else if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
if (use_alternative_html) {
if (itip_part->alternative_html) {
g_output_stream_write_all (stream,
itip_part->alternative_html,
strlen (itip_part->alternative_html),
NULL, cancellable, NULL);
}
return TRUE;
}
buffer = g_string_sized_new (2048);
itip_view_write (itip_part, formatter, buffer);
@ -114,6 +154,7 @@ emfe_itip_format (EMailFormatterExtension *extension,
itip_part->folder = folder ? g_object_ref (folder) : NULL;
itip_part->message = g_object_ref (message);
itip_part->message_uid = g_strdup (message_uid);
g_clear_pointer (&itip_part->alternative_html, g_free);
g_clear_object (&old_folder);
g_clear_object (&old_message);

View File

@ -42,11 +42,9 @@ mail_part_itip_dispose (GObject *object)
g_cancellable_cancel (part->cancellable);
g_free (part->message_uid);
part->message_uid = NULL;
g_free (part->vcalendar);
part->vcalendar = NULL;
g_clear_pointer (&part->message_uid, g_free);
g_clear_pointer (&part->vcalendar, g_free);
g_clear_pointer (&part->alternative_html, g_free);
g_clear_object (&part->folder);
g_clear_object (&part->message);
@ -69,6 +67,54 @@ mail_part_itip_finalize (GObject *object)
G_OBJECT_CLASS (e_mail_part_itip_parent_class)->finalize (object);
}
static void
itip_view_alternative_html_clicked_cb (EWebView *web_view,
const gchar *iframe_id,
const gchar *element_id,
const gchar *element_class,
const gchar *element_value,
const GtkAllocation *element_position,
gpointer user_data)
{
EMailPart *mail_part = user_data;
gchar tmp[128];
g_return_if_fail (E_IS_MAIL_PART_ITIP (mail_part));
if (!element_id || !element_value)
return;
g_return_if_fail (g_snprintf (tmp, sizeof (tmp), "%p:", mail_part) < sizeof (tmp));
if (g_str_has_prefix (element_id, tmp)) {
gchar spn[128];
g_return_if_fail (g_snprintf (spn, sizeof (spn), "%s-spn", element_value) < sizeof (spn));
g_return_if_fail (g_snprintf (tmp, sizeof (tmp), "%s-img", element_value) < sizeof (tmp));
e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (web_view), e_web_view_get_cancellable (web_view),
"var elem = Evo.FindElement(%s, %s);\n"
"if (elem) {\n"
" elem.hidden = !elem.hidden;\n"
"}\n"
"elem = Evo.FindElement(%s, %s);\n"
"if (elem) {\n"
" var tmp = elem.src;\n"
" elem.src = elem.getAttribute(\"othersrc\");\n"
" elem.setAttribute(\"othersrc\", tmp);\n"
"}\n"
"elem = Evo.FindElement(%s, %s);\n"
"if (elem) {\n"
" var tmp = elem.innerText;\n"
" elem.innerText = elem.getAttribute(\"othertext\");\n"
" elem.setAttribute(\"othertext\", tmp);\n"
"}\n",
iframe_id, element_value,
iframe_id, tmp,
iframe_id, spn);
}
}
static void
mail_part_itip_content_loaded (EMailPart *part,
EWebView *web_view,
@ -116,6 +162,8 @@ mail_part_itip_content_loaded (EMailPart *part,
pitip->priv->views = g_slist_prepend (pitip->priv->views, itip_view);
}
e_web_view_register_element_clicked (web_view, "itip-view-alternative-html", itip_view_alternative_html_clicked_cb, pitip);
}
static void

View File

@ -59,6 +59,7 @@ struct _EMailPartItip {
gchar *message_uid;
CamelMimePart *itip_mime_part;
gchar *vcalendar;
gchar *alternative_html;
/* cancelled when freeing the puri */
GCancellable *cancellable;

View File

@ -38,6 +38,7 @@
#include <mail/em-config.h>
#include <mail/em-utils.h>
#include <em-format/e-mail-formatter-utils.h>
#include <em-format/e-mail-part-utils.h>
#include "itip-view.h"
#include "e-mail-part-itip.h"
@ -1859,85 +1860,156 @@ itip_view_write (gpointer itip_part_ptr,
EMailFormatter *formatter,
GString *buffer)
{
EMailPartItip *itip_part = itip_part_ptr;
gint icon_width, icon_height;
GSettings *settings;
gchar *header;
gchar *alternative_html;
header = e_mail_formatter_get_html_header (formatter);
g_string_append (buffer, header);
g_free (header);
settings = e_util_ref_settings ("org.gnome.evolution.plugin.itip");
g_clear_pointer (&itip_part->alternative_html, g_free);
if (g_settings_get_boolean (settings, "show-message-description"))
alternative_html = itip_view_dup_alternative_html (itip_part_ptr);
else
alternative_html = NULL;
itip_part->alternative_html = itip_view_dup_alternative_html (itip_part_ptr);
g_clear_object (&settings);
if (!alternative_html) {
if (!gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, &icon_width, &icon_height)) {
icon_width = 16;
icon_height = 16;
}
g_string_append_printf (
buffer,
"<img src=\"gtk-stock://%s?size=%d\" class=\"itip icon\" width=\"%dpx\" height=\"%dpx\"/>\n",
MEETING_ICON, GTK_ICON_SIZE_BUTTON, icon_width, icon_height);
g_string_append (
buffer,
"<div class=\"itip content\" id=\"" DIV_ITIP_CONTENT "\">\n");
/* The first section listing the sender */
/* FIXME What to do if the send and organizer do not match */
g_string_append (
buffer,
"<div id=\"" TEXT_ROW_SENDER "\" class=\"itip sender\"></div>\n");
g_string_append (buffer, "<hr>\n");
/* Elementary event information */
g_string_append (
buffer,
"<table class=\"itip table\" border=\"0\" "
"cellspacing=\"5\" cellpadding=\"0\">\n");
append_text_table_row (buffer, TABLE_ROW_SUMMARY, NULL, NULL);
append_text_table_row (buffer, TABLE_ROW_LOCATION, _("Location:"), NULL);
append_text_table_row (buffer, TABLE_ROW_URL, _("URL:"), NULL);
append_text_table_row (buffer, TABLE_ROW_START_DATE, _("Start time:"), NULL);
append_text_table_row (buffer, TABLE_ROW_END_DATE, _("End time:"), NULL);
append_text_table_row (buffer, TABLE_ROW_DUE_DATE, _("Due date:"), NULL);
append_text_table_row (buffer, TABLE_ROW_ESTIMATED_DURATION, _("Estimated duration:"), NULL);
append_text_table_row (buffer, TABLE_ROW_STATUS, _("Status:"), NULL);
append_text_table_row (buffer, TABLE_ROW_COMMENT, _("Comment:"), NULL);
append_text_table_row (buffer, TABLE_ROW_CATEGORIES, _("Categories:"), NULL);
append_text_table_row (buffer, TABLE_ROW_ATTENDEES, _("Attendees:"), NULL);
g_string_append (buffer, "</table>\n");
if (!gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, &icon_width, &icon_height)) {
icon_width = 16;
icon_height = 16;
}
g_string_append_printf (
buffer,
"<img src=\"gtk-stock://%s?size=%d\" class=\"itip icon\" width=\"%dpx\" height=\"%dpx\"/>\n",
MEETING_ICON, GTK_ICON_SIZE_BUTTON, icon_width, icon_height);
g_string_append (
buffer,
"<div class=\"itip content\" id=\"" DIV_ITIP_CONTENT "\">\n");
/* The first section listing the sender */
/* FIXME What to do if the send and organizer do not match */
g_string_append (
buffer,
"<div id=\"" TEXT_ROW_SENDER "\" class=\"itip sender\"></div>\n");
g_string_append (buffer, "<hr>\n");
/* Elementary event information */
g_string_append (
buffer,
"<table class=\"itip table\" border=\"0\" "
"cellspacing=\"5\" cellpadding=\"0\">\n");
append_text_table_row (buffer, TABLE_ROW_SUMMARY, NULL, NULL);
append_text_table_row (buffer, TABLE_ROW_LOCATION, _("Location:"), NULL);
append_text_table_row (buffer, TABLE_ROW_URL, _("URL:"), NULL);
append_text_table_row (buffer, TABLE_ROW_START_DATE, _("Start time:"), NULL);
append_text_table_row (buffer, TABLE_ROW_END_DATE, _("End time:"), NULL);
append_text_table_row (buffer, TABLE_ROW_DUE_DATE, _("Due date:"), NULL);
append_text_table_row (buffer, TABLE_ROW_ESTIMATED_DURATION, _("Estimated duration:"), NULL);
append_text_table_row (buffer, TABLE_ROW_STATUS, _("Status:"), NULL);
append_text_table_row (buffer, TABLE_ROW_COMMENT, _("Comment:"), NULL);
append_text_table_row (buffer, TABLE_ROW_CATEGORIES, _("Categories:"), NULL);
append_text_table_row (buffer, TABLE_ROW_ATTENDEES, _("Attendees:"), NULL);
g_string_append (buffer, "</table>\n");
/* Upper Info items */
g_string_append (
buffer,
"<table class=\"itip info\" id=\"" TABLE_UPPER_ITIP_INFO "\" border=\"0\" "
"cellspacing=\"5\" cellpadding=\"0\">");
if (alternative_html) {
g_string_append (buffer, alternative_html);
} else {
/* Description */
g_string_append (
buffer,
"<div id=\"" TABLE_ROW_DESCRIPTION "\" class=\"itip description\" hidden=\"\"></div>\n");
}
/* Description */
g_string_append (
buffer,
"<div id=\"" TABLE_ROW_DESCRIPTION "\" class=\"itip description\" hidden=\"\"></div>\n");
g_string_append (buffer, "<hr>\n");
if (itip_part->alternative_html) {
EMailPart *part = E_MAIL_PART (itip_part);
GSettings *settings;
const gchar *default_charset, *charset;
const gchar *text, *other_text;
const gchar *img, *other_img;
gboolean expand;
gchar *uri;
settings = e_util_ref_settings ("org.gnome.evolution.plugin.itip");
expand = g_settings_get_boolean (settings, "show-message-description");
g_clear_object (&settings);
text = _("Show description provided by the sender");
other_text = _("Hide description provided by the sender");
img = "pan-end-symbolic";
other_img = "pan-down-symbolic";
if (expand) {
#define SWAP(a,b) { const gchar *tmp = a; a = b; b = tmp; }
SWAP (text, other_text);
SWAP (img, other_img);
#undef SWAP
}
if (!gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height)) {
icon_width = 16;
icon_height = 16;
}
e_util_markup_append_escaped (buffer,
"<span class=\"itip-view-alternative-html\" id=\"%p:spn\" value=\"itip-view-alternative-html-%p\" style=\"vertical-align:bottom;\">"
"<img id=\"itip-view-alternative-html-%p-img\" style=\"vertical-align:middle;\" width=\"%dpx\" height=\"%dpx\""
" src=\"gtk-stock://%s?size=%d\" othersrc=\"gtk-stock://%s?size=%d\" style=\"vertical-align:center;\">&nbsp;"
"<span id=\"itip-view-alternative-html-%p-spn\" othertext=\"%s\" style=\"vertical-align:center;\">%s</span></span><br>",
itip_part, itip_part, itip_part, icon_width, icon_height,
img, GTK_ICON_SIZE_MENU,
other_img, GTK_ICON_SIZE_MENU,
itip_part,
other_text, text);
default_charset = e_mail_formatter_get_default_charset (formatter);
charset = e_mail_formatter_get_charset (formatter);
if (!default_charset)
default_charset = "";
if (!charset)
charset = "";
uri = e_mail_part_build_uri (
itip_part->folder, itip_part->message_uid,
"part_id", G_TYPE_STRING, e_mail_part_get_id (part),
"mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW,
"formatter_default_charset", G_TYPE_STRING, default_charset,
"formatter_charset", G_TYPE_STRING, charset,
"e-itip-view-alternative-html", G_TYPE_STRING, "1",
NULL);
settings = e_util_ref_settings ("org.gnome.evolution.mail");
g_string_append_printf (
buffer,
"<div class=\"part-container-nostyle\" id=\"itip-view-alternative-html-%p\"%s>"
"<iframe width=\"100%%\" height=\"10\" "
" frameborder=\"0\" src=\"%s\" "
" id=\"%s.iframe\" name=\"%s\" "
" class=\"-e-mail-formatter-frame-color\" "
" %s>"
"</iframe>"
"</div>",
itip_part,
expand ? "" : " hidden",
uri,
e_mail_part_get_id (part),
e_mail_part_get_id (part),
g_settings_get_boolean (settings, "preview-unset-html-colors") ? "x-e-unset-colors=\"1\"" : "style=\"background-color: #ffffff;\"");
g_clear_object (&settings);
g_free (uri);
g_string_append (buffer, "<hr>\n");
}
/* Lower Info items */
g_string_append (
buffer,
@ -1991,8 +2063,6 @@ itip_view_write (gpointer itip_part_ptr,
g_string_append (buffer, "<div class=\"itip error\" id=\"" DIV_ITIP_ERROR "\"></div>");
g_string_append (buffer, "</body></html>");
g_free (alternative_html);
}
void