ews-I#295 - itip-formatter: Import of forwarded meeting as bare event

This part adds an "Import as Event" button to the meeting request
window when the selected calendar claims it can add only meetings
organized by the calendar owner, which will remove the organizer
and all the attendees before the import.

Related to https://gitlab.gnome.org/GNOME/evolution-ews/-/issues/295
This commit is contained in:
Milan Crha
2025-01-29 12:25:40 +01:00
parent 3816f5dc44
commit f4dffb28cf
7 changed files with 115 additions and 29 deletions

View File

@ -1529,7 +1529,8 @@ var EvoItip = {
CHECKBOX_INHERIT_ALARM : "checkbox_inherit_alarm",
CHECKBOX_UPDATE : "checkbox_update",
CHECKBOX_FREE_TIME : "checkbox_free_time",
TABLE_ROW_BUTTONS : "table_row_buttons"
TABLE_ROW_BUTTONS : "table_row_buttons",
BUTTON_IMPORT_BARE : "button_import_bare"
};
EvoItip.alarmCheckClickedCb = function(check1)
@ -1842,6 +1843,10 @@ EvoItip.SetButtonsDisabled = function(iframe_id, disabled)
if (elem)
elem.disabled = disabled;
elem = doc.getElementById(EvoItip.BUTTON_IMPORT_BARE);
if (elem)
elem.disabled = disabled;
elem = doc.getElementById(EvoItip.TABLE_ROW_BUTTONS);
if (!elem)
return;

View File

@ -221,13 +221,13 @@ th.rtl {
font-weight: bold;
}
#table_row_buttons button {
#table_row_buttons button, .table_row_buttons button {
line-height: 28px;
min-width: 150px;
white-space: nowrap;
}
#table_row_buttons img {
#table_row_buttons img, .table_row_buttons img {
padding-right: 5px;
vertical-align: middle;
}

View File

@ -548,8 +548,8 @@ mail_display_iframes_height_update_cb (gpointer user_data)
return G_SOURCE_REMOVE;
}
static void
mail_display_schedule_iframes_height_update (EMailDisplay *mail_display)
void
e_mail_display_schedule_iframes_height_update (EMailDisplay *mail_display)
{
if (mail_display_can_use_frame_flattening ())
return;
@ -1473,7 +1473,7 @@ mail_display_content_loaded_cb (EWebView *web_view,
}
}
mail_display_schedule_iframes_height_update (mail_display);
e_mail_display_schedule_iframes_height_update (mail_display);
}
static void
@ -1792,7 +1792,7 @@ mail_display_schedule_iframes_height_update_cb (WebKitUserContentManager *manage
g_return_if_fail (mail_display != NULL);
mail_display_schedule_iframes_height_update (mail_display);
e_mail_display_schedule_iframes_height_update (mail_display);
}
static gboolean
@ -3068,7 +3068,7 @@ e_mail_display_init (EMailDisplay *display)
g_signal_connect (
display, "resource-loaded",
G_CALLBACK (mail_display_schedule_iframes_height_update), NULL);
G_CALLBACK (e_mail_display_schedule_iframes_height_update), NULL);
g_signal_connect_after (
display, "drag-data-get",

View File

@ -118,6 +118,8 @@ gboolean e_mail_display_process_magic_spacebar
gboolean towards_bottom);
gboolean e_mail_display_get_skip_insecure_parts
(EMailDisplay *mail_display);
void e_mail_display_schedule_iframes_height_update
(EMailDisplay *mail_display);
G_END_DECLS

View File

@ -63,6 +63,8 @@
#define BUTTON_UPDATE_ATTENDEE_STATUS "button_update_attendee_status"
#define BUTTON_SAVE "button_save"
#define BUTTON_IMPORT "button_import"
#define BUTTON_IMPORT_BARE "button_import_bare"
#define BUTTON_IMPORT_BARE_HINT "button_import_bare_hint"
#define TABLE_UPPER_ITIP_INFO "table_upper_itip_info"
#define TABLE_LOWER_ITIP_INFO "table_lower_itip_info"

View File

@ -37,6 +37,7 @@
#include <mail/em-config.h>
#include <mail/em-utils.h>
#include <mail/e-mail-display.h>
#include <em-format/e-mail-formatter-utils.h>
#include <em-format/e-mail-part-utils.h>
@ -1265,7 +1266,14 @@ buttons_table_write_button (GString *buffer,
const gchar *icon,
ItipViewResponse response)
{
gchar *access_key, *html_label;
gchar *access_key, *html_label, *hint = NULL;
const gchar *colspan = "";
if (response == ITIP_VIEW_RESPONSE_IMPORT_BARE) {
hint = g_markup_printf_escaped (" <span id='" BUTTON_IMPORT_BARE_HINT "' style='font-size:smaller;' hidden>%s</span>",
_("Imported event will have removed the organizer and all the attendees."));
colspan = " colspan='11'";
}
html_label = e_mail_formatter_parse_html_mnemonics (label, &access_key);
@ -1279,23 +1287,23 @@ buttons_table_write_button (GString *buffer,
g_string_append_printf (
buffer,
"<td><button class=\"itip-button\" type=\"button\" name=\"%s\" value=\"%p:%d\" id=\"%s\" accesskey=\"%s\" hidden disabled>"
"<td%s><button class=\"itip-button\" type=\"button\" name=\"%s\" value=\"%p:%d\" id=\"%s\" accesskey=\"%s\" hidden disabled>"
"<div><img src=\"gtk-stock://%s?size=%d\" width=\"%dpx\" height=\"%dpx\"> <span>%s</span></div>"
"</button></td>\n",
name, itip_part_ptr, response, name, access_key ? access_key : "" , icon,
GTK_ICON_SIZE_BUTTON, icon_width, icon_height, html_label);
"</button>%s</td>\n",
colspan, name, itip_part_ptr, response, name, access_key ? access_key : "" , icon,
GTK_ICON_SIZE_BUTTON, icon_width, icon_height, html_label, hint ? hint : "");
} else {
g_string_append_printf (
buffer,
"<td><button class=\"itip-button\" type=\"button\" name=\"%s\" value=\"%p:%d\" id=\"%s\" accesskey=\"%s\" hidden disabled>"
"<td%s><button class=\"itip-button\" type=\"button\" name=\"%s\" value=\"%p:%d\" id=\"%s\" accesskey=\"%s\" hidden disabled>"
"<div><span>%s</span></div>"
"</button></td>\n",
name, itip_part_ptr, response, name, access_key ? access_key : "" , html_label);
"</button>%s</td>\n",
colspan, name, itip_part_ptr, response, name, access_key ? access_key : "" , html_label, hint ? hint : "");
}
g_free (html_label);
g_free (access_key);
g_free (hint);
}
static void
@ -1344,6 +1352,11 @@ append_buttons_table (GString *buffer,
buffer, itip_part_ptr, BUTTON_IMPORT, _("Im_port"),
NULL, ITIP_VIEW_RESPONSE_IMPORT);
g_string_append (buffer, "</tr><tr class='" TABLE_ROW_BUTTONS "'>");
buttons_table_write_button (
buffer, itip_part_ptr, BUTTON_IMPORT_BARE, _("Im_port as Event"),
NULL, ITIP_VIEW_RESPONSE_IMPORT_BARE);
g_string_append (buffer, "</tr></table>");
}
@ -2392,6 +2405,57 @@ itip_view_new (const gchar *part_id,
return view;
}
static void
itip_view_update_import_bare_options (ItipView *self)
{
ICalProperty *prop;
gchar *cal_email = NULL;
gboolean show = FALSE;
if ((self->priv->method != I_CAL_METHOD_PUBLISH && self->priv->method != I_CAL_METHOD_REQUEST) ||
!self->priv->current_client ||
!self->priv->ical_comp ||
!e_client_check_capability (E_CLIENT (self->priv->current_client), E_CAL_STATIC_CAPABILITY_USER_IS_ORGANIZER_ONLY) ||
!e_cal_util_component_has_attendee (self->priv->ical_comp) ||
!e_cal_util_component_has_organizer (self->priv->ical_comp) ||
i_cal_component_isa (self->priv->ical_comp) != I_CAL_VEVENT_COMPONENT ||
!e_client_get_backend_property_sync (E_CLIENT (self->priv->current_client), E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, &cal_email, self->priv->cancellable, NULL)) {
hide_element (self, BUTTON_IMPORT_BARE, TRUE);
hide_element (self, BUTTON_IMPORT_BARE_HINT, TRUE);
enable_button (self, BUTTON_IMPORT_BARE, FALSE);
enable_button (self, BUTTON_IMPORT_BARE_HINT, FALSE);
return;
}
prop = i_cal_component_get_first_property (self->priv->ical_comp, I_CAL_ORGANIZER_PROPERTY);
if (prop) {
const gchar *orgnzr_email;
orgnzr_email = i_cal_property_get_organizer (prop);
show = orgnzr_email && cal_email && !e_cal_util_email_addresses_equal (orgnzr_email, cal_email);
g_clear_object (&prop);
}
hide_element (self, BUTTON_IMPORT_BARE, !show);
hide_element (self, BUTTON_IMPORT_BARE_HINT, !show);
enable_button (self, BUTTON_IMPORT_BARE, show);
enable_button (self, BUTTON_IMPORT_BARE_HINT, show);
g_free (cal_email);
if (show) {
EWebView *web_view;
web_view = itip_view_ref_web_view (self);
if (E_IS_MAIL_DISPLAY (web_view))
e_mail_display_schedule_iframes_height_update (E_MAIL_DISPLAY (web_view));
g_clear_object (&web_view);
}
}
void
itip_view_set_mode (ItipView *view,
ItipViewMode mode)
@ -2424,6 +2488,8 @@ itip_view_set_mode (ItipView *view,
if (view->priv->needs_decline)
show_button (view, BUTTON_DECLINE);
show_button (view, BUTTON_ACCEPT);
itip_view_update_import_bare_options (view);
} else {
show_button (view, BUTTON_IMPORT);
}
@ -4185,6 +4251,7 @@ itip_view_cal_opened_cb (GObject *source_object,
view->priv->current_client = E_CAL_CLIENT (g_object_ref (client));
itip_view_update_import_bare_options (view);
set_buttons_sensitive (view);
exit:
@ -4426,7 +4493,7 @@ find_cal_update_ui (FormatItipFindData *fd,
itip_view_set_show_keep_alarm_check (view, fd->keep_alarm_check);
view->priv->current_client = cal_client;
itip_view_update_import_bare_options (view);
/* Provide extra info, since its not in the component */
/* FIXME Check sequence number of meeting? */
@ -5464,6 +5531,7 @@ receive_objects_ready_cb (GObject *ecalclient,
}
break;
case ITIP_VIEW_RESPONSE_IMPORT:
case ITIP_VIEW_RESPONSE_IMPORT_BARE:
switch (e_cal_client_get_source_type (client)) {
case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
default:
@ -5704,7 +5772,8 @@ update_item (ItipView *view,
}
static void
import_item (ItipView *view)
import_item (ItipView *view,
gboolean bare_import)
{
ICalComponent *main_comp_clone;
ICalComponent *subcomp;
@ -5723,14 +5792,20 @@ import_item (ItipView *view)
if ((child_kind == I_CAL_VEVENT_COMPONENT ||
child_kind == I_CAL_VJOURNAL_COMPONENT ||
child_kind == I_CAL_VTODO_COMPONENT) &&
e_cal_util_component_has_property (subcomp, I_CAL_ATTACH_PROPERTY)) {
ECalComponent *comp;
child_kind == I_CAL_VTODO_COMPONENT)) {
if (bare_import) {
e_cal_util_component_remove_property_by_kind (subcomp, I_CAL_ORGANIZER_PROPERTY, TRUE);
e_cal_util_component_remove_property_by_kind (subcomp, I_CAL_ATTENDEE_PROPERTY, TRUE);
}
comp = e_cal_component_new_from_icalcomponent (g_object_ref (subcomp));
if (comp) {
itip_view_add_attachments_from_message (view, comp);
g_clear_object (&comp);
if (e_cal_util_component_has_property (subcomp, I_CAL_ATTACH_PROPERTY)) {
ECalComponent *comp;
comp = e_cal_component_new_from_icalcomponent (g_object_ref (subcomp));
if (comp) {
itip_view_add_attachments_from_message (view, comp);
g_clear_object (&comp);
}
}
}
@ -5740,7 +5815,7 @@ import_item (ItipView *view)
g_clear_object (&iter);
view->priv->update_item_response = ITIP_VIEW_RESPONSE_IMPORT;
view->priv->update_item_response = bare_import ? ITIP_VIEW_RESPONSE_IMPORT_BARE : ITIP_VIEW_RESPONSE_IMPORT;
e_cal_client_receive_objects (
view->priv->current_client,
@ -6793,7 +6868,8 @@ view_response_cb (ItipView *view,
idle_open_cb, g_object_ref (view), g_object_unref);
return;
case ITIP_VIEW_RESPONSE_IMPORT:
import_item (view);
case ITIP_VIEW_RESPONSE_IMPORT_BARE:
import_item (view, response == ITIP_VIEW_RESPONSE_IMPORT_BARE);
break;
default:
break;

View File

@ -81,7 +81,8 @@ typedef enum {
ITIP_VIEW_RESPONSE_REFRESH,
ITIP_VIEW_RESPONSE_OPEN,
ITIP_VIEW_RESPONSE_SAVE,
ITIP_VIEW_RESPONSE_IMPORT
ITIP_VIEW_RESPONSE_IMPORT,
ITIP_VIEW_RESPONSE_IMPORT_BARE
} ItipViewResponse;
typedef enum {