Commit 0a2a46f6 authored by Milan Crha's avatar Milan Crha

I#11 - Updated Draft message not re-downloaded

Closes https://gitlab.gnome.org/GNOME/evolution-ews/issues/11
parent 2a2d13d7
......@@ -1898,6 +1898,7 @@ camel_ews_folder_new (CamelStore *store,
static void
sync_updated_items (CamelEwsFolder *ews_folder,
EEwsConnection *cnc,
gboolean is_drafts_folder,
GSList *updated_items,
CamelFolderChangeInfo *change_info,
GCancellable *cancellable,
......@@ -1968,7 +1969,7 @@ sync_updated_items (CamelEwsFolder *ews_folder,
EEwsAdditionalProps *add_props;
add_props = e_ews_additional_props_new ();
add_props->field_uri = g_strdup (SUMMARY_MESSAGE_FLAGS);
add_props->field_uri = g_strdup (is_drafts_folder ? SUMMARY_MESSAGE_PROPS : SUMMARY_MESSAGE_FLAGS);
add_props->extended_furis = ews_folder_get_summary_message_mapi_flags ();
e_ews_connection_get_items_sync (
......@@ -1980,7 +1981,7 @@ sync_updated_items (CamelEwsFolder *ews_folder,
e_ews_additional_props_free (add_props);
}
camel_ews_utils_sync_updated_items (ews_folder, items, change_info);
camel_ews_utils_sync_updated_items (ews_folder, cnc, is_drafts_folder, items, change_info, cancellable);
items = NULL;
if (local_error) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
......@@ -1992,7 +1993,7 @@ sync_updated_items (CamelEwsFolder *ews_folder,
EEwsAdditionalProps *add_props;
add_props = e_ews_additional_props_new ();
add_props->field_uri = g_strdup (SUMMARY_ITEM_FLAGS);
add_props->field_uri = g_strdup (is_drafts_folder ? SUMMARY_ITEM_PROPS : SUMMARY_ITEM_FLAGS);
add_props->extended_furis = ews_folder_get_summary_followup_mapi_flags ();
e_ews_connection_get_items_sync (
......@@ -2003,7 +2004,7 @@ sync_updated_items (CamelEwsFolder *ews_folder,
e_ews_additional_props_free (add_props);
}
camel_ews_utils_sync_updated_items (ews_folder, items, change_info);
camel_ews_utils_sync_updated_items (ews_folder, cnc, is_drafts_folder, items, change_info, cancellable);
if (local_error) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
......@@ -2022,9 +2023,20 @@ exit:
}
}
void
camel_ews_folder_remove_cached_message (CamelEwsFolder *ews_folder,
const gchar *uid)
{
g_return_if_fail (CAMEL_IS_EWS_FOLDER (ews_folder));
g_return_if_fail (uid != NULL);
ews_data_cache_remove (ews_folder->cache, "cur", uid, NULL);
}
static void
sync_created_items (CamelEwsFolder *ews_folder,
EEwsConnection *cnc,
gboolean is_drafts_folder,
GSList *created_items,
GHashTable *updating_summary_uids,
CamelFolderChangeInfo *change_info,
......@@ -2112,7 +2124,7 @@ sync_created_items (CamelEwsFolder *ews_folder,
goto exit;
}
camel_ews_utils_sync_created_items (ews_folder, cnc, items, change_info, cancellable);
camel_ews_utils_sync_created_items (ews_folder, cnc, is_drafts_folder, items, change_info, cancellable);
items = NULL;
......@@ -2138,7 +2150,7 @@ sync_created_items (CamelEwsFolder *ews_folder,
goto exit;
}
camel_ews_utils_sync_created_items (ews_folder, cnc, items, change_info, cancellable);
camel_ews_utils_sync_created_items (ews_folder, cnc, is_drafts_folder, items, change_info, cancellable);
items = NULL;
if (generic_item_ids) {
......@@ -2157,7 +2169,7 @@ sync_created_items (CamelEwsFolder *ews_folder,
e_ews_additional_props_free (add_props);
}
camel_ews_utils_sync_created_items (ews_folder, cnc, items, change_info, cancellable);
camel_ews_utils_sync_created_items (ews_folder, cnc, is_drafts_folder, items, change_info, cancellable);
if (local_error) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
......@@ -2238,6 +2250,7 @@ ews_refresh_info_sync (CamelFolder *folder,
gchar *id;
gchar *sync_state;
gboolean includes_last_item = FALSE;
gboolean is_drafts_folder;
gint64 last_folder_update_time;
GError *local_error = NULL;
......@@ -2273,9 +2286,7 @@ ews_refresh_info_sync (CamelFolder *folder,
camel_operation_push_message (cancellable, _("Refreshing folder “%s”"), camel_folder_get_display_name (folder));
if (camel_ews_summary_get_version (CAMEL_EWS_SUMMARY (folder_summary)) < CAMEL_EWS_SUMMARY_VERSION) {
updating_summary_uids = camel_folder_summary_get_hash (folder_summary);
}
is_drafts_folder = camel_ews_utils_folder_is_drafts_folder (ews_folder);
/* Sync folder items does not return the fields ToRecipients,
* CCRecipients. With the item_type unknown, its not possible
......@@ -2284,6 +2295,12 @@ ews_refresh_info_sync (CamelFolder *folder,
* SyncFolderItem request and fetch the item using the
* GetItem request. */
sync_state = camel_ews_summary_dup_sync_state (CAMEL_EWS_SUMMARY (folder_summary));
if (!sync_state ||
camel_ews_summary_get_version (CAMEL_EWS_SUMMARY (folder_summary)) < CAMEL_EWS_SUMMARY_VERSION) {
updating_summary_uids = camel_folder_summary_get_hash (folder_summary);
}
do {
GSList *items_created = NULL, *items_updated = NULL;
GSList *items_deleted = NULL;
......@@ -2322,7 +2339,7 @@ ews_refresh_info_sync (CamelFolder *folder,
camel_ews_utils_sync_deleted_items (ews_folder, items_deleted, change_info);
if (items_created)
sync_created_items (ews_folder, cnc, items_created, updating_summary_uids, change_info, cancellable, &local_error);
sync_created_items (ews_folder, cnc, is_drafts_folder, items_created, updating_summary_uids, change_info, cancellable, &local_error);
if (local_error) {
if (items_updated) {
......@@ -2334,7 +2351,7 @@ ews_refresh_info_sync (CamelFolder *folder,
}
if (items_updated)
sync_updated_items (ews_folder, cnc, items_updated, change_info, cancellable, &local_error);
sync_updated_items (ews_folder, cnc, is_drafts_folder, items_updated, change_info, cancellable, &local_error);
if (local_error)
break;
......
......@@ -73,6 +73,8 @@ GType camel_ews_folder_get_type (void);
/* implemented */
CamelFolder * camel_ews_folder_new (CamelStore *store, const gchar *folder_dir, const gchar *folder_name, GCancellable *cancellable, GError **error);
void ews_update_summary ( CamelFolder *folder, GList *item_list, GCancellable *cancellable, GError **error);
void camel_ews_folder_remove_cached_message (CamelEwsFolder *ews_folder,
const gchar *uid);
G_END_DECLS
......
......@@ -1430,7 +1430,7 @@ static SystemFolder system_folder[] = {
{"calendar", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_EVENTS},
{"contacts", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_CONTACTS},
{"deleteditems", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_TRASH},
{"drafts", CAMEL_FOLDER_SYSTEM},
{"drafts", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_DRAFTS},
{"inbox", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_INBOX},
{"journal", CAMEL_FOLDER_SYSTEM | CAMEL_EWS_FOLDER_TYPE_JOURNAL},
{"notes", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_MEMOS},
......@@ -1867,13 +1867,21 @@ ews_authenticate_sync (CamelService *service,
if (!old_sync_state) {
initial_setup = TRUE;
} else {
gchar *inbox_folder_id;
gchar *folder_id;
inbox_folder_id = camel_ews_store_summary_get_folder_id_from_folder_type (ews_store->summary, CAMEL_FOLDER_TYPE_INBOX);
if (!inbox_folder_id || !*inbox_folder_id)
folder_id = camel_ews_store_summary_get_folder_id_from_folder_type (ews_store->summary, CAMEL_FOLDER_TYPE_INBOX);
if (!folder_id || !*folder_id)
initial_setup = TRUE;
g_free (inbox_folder_id);
g_free (folder_id);
if (!initial_setup) {
folder_id = camel_ews_store_summary_get_folder_id_from_folder_type (ews_store->summary, CAMEL_FOLDER_TYPE_DRAFTS);
if (!folder_id || !*folder_id)
initial_setup = TRUE;
g_free (folder_id);
}
}
e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, old_sync_state,
......
......@@ -115,6 +115,7 @@ summary_header_load (CamelFolderSummary *s,
CamelFIRecord *mir)
{
CamelEwsSummary *ews_summary = CAMEL_EWS_SUMMARY (s);
const gchar *sync_state = NULL;
gchar *part;
if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_ews_summary_parent_class)->summary_header_load (s, mir))
......@@ -129,11 +130,20 @@ summary_header_load (CamelFolderSummary *s,
if (part && part++ && strcmp (part, "(null)") &&
ews_summary->priv->version >= CAMEL_EWS_SUMMARY_VERSION) {
camel_ews_summary_set_sync_state (ews_summary, part);
} else {
camel_ews_summary_set_sync_state (ews_summary, NULL);
sync_state = part;
}
/* Do not call camel_ews_summary_set_sync_state() here,
to not mark the summary dirty after load. */
g_mutex_lock (&ews_summary->priv->property_lock);
if (g_strcmp0 (ews_summary->priv->sync_state, sync_state) != 0) {
g_free (ews_summary->priv->sync_state);
ews_summary->priv->sync_state = g_strdup (sync_state);
}
g_mutex_unlock (&ews_summary->priv->property_lock);
return TRUE;
}
......@@ -294,6 +304,8 @@ void
camel_ews_summary_set_sync_state (CamelEwsSummary *ews_summary,
const gchar *sync_state)
{
gboolean changed = FALSE;
g_return_if_fail (CAMEL_IS_EWS_SUMMARY (ews_summary));
g_mutex_lock (&ews_summary->priv->property_lock);
......@@ -301,9 +313,13 @@ camel_ews_summary_set_sync_state (CamelEwsSummary *ews_summary,
if (g_strcmp0 (ews_summary->priv->sync_state, sync_state) != 0) {
g_free (ews_summary->priv->sync_state);
ews_summary->priv->sync_state = g_strdup (sync_state);
changed = TRUE;
}
g_mutex_unlock (&ews_summary->priv->property_lock);
if (changed)
camel_folder_summary_touch (CAMEL_FOLDER_SUMMARY (ews_summary));
}
gchar *
......
......@@ -70,6 +70,12 @@ camel_ews_utils_build_folder_info (CamelEwsStore *store,
g_free (folder_name);
if ((fi->flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_DRAFTS) {
/* Do not propagate the Drafts flag to Evolution, because
it removes the Drafts icon in the folders tree when set */
fi->flags = fi->flags & (~CAMEL_FOLDER_TYPE_DRAFTS);
}
if (!(fi->flags & CAMEL_FOLDER_TYPE_MASK)) {
switch (camel_ews_store_summary_get_folder_type (ews_summary, fid, NULL)) {
case E_EWS_FOLDER_TYPE_CALENDAR:
......@@ -794,10 +800,85 @@ camel_ews_utils_update_read_receipt_flags (EEwsItem *item,
return changed;
}
gboolean
camel_ews_utils_folder_is_drafts_folder (CamelEwsFolder *ews_folder)
{
CamelStore *parent_store;
CamelEwsStore *ews_store;
gchar *drafts_uid, *folder_uid;
gboolean is_drafts_folder;
g_return_val_if_fail (CAMEL_IS_EWS_FOLDER (ews_folder), FALSE);
parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (ews_folder));
if (!parent_store)
return FALSE;
ews_store = CAMEL_EWS_STORE (parent_store);
g_return_val_if_fail (ews_store != NULL, FALSE);
drafts_uid = camel_ews_store_summary_get_folder_id_from_folder_type (ews_store->summary, CAMEL_FOLDER_TYPE_DRAFTS);
if (!drafts_uid)
return FALSE;
folder_uid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary,
camel_folder_get_full_name (CAMEL_FOLDER (ews_folder)));
is_drafts_folder = g_strcmp0 (drafts_uid, folder_uid) == 0;
g_free (drafts_uid);
g_free (folder_uid);
return is_drafts_folder;
}
static void
ews_utils_copy_message_info (CamelMessageInfo *des_mi,
const CamelMessageInfo *src_mi)
{
gboolean had_cal;
g_return_if_fail (CAMEL_IS_MESSAGE_INFO (des_mi));
g_return_if_fail (CAMEL_IS_MESSAGE_INFO (src_mi));
g_return_if_fail (g_strcmp0 (camel_message_info_get_uid (des_mi), camel_message_info_get_uid (src_mi)) == 0);
camel_message_info_property_lock (des_mi);
had_cal = camel_message_info_get_user_flag (des_mi, "$has_cal");
camel_message_info_set_flags (des_mi, ~CAMEL_MESSAGE_FOLDER_FLAGGED, camel_message_info_get_flags (src_mi));
camel_message_info_take_user_flags (des_mi, camel_message_info_dup_user_flags (src_mi));
camel_message_info_take_user_tags (des_mi, camel_message_info_dup_user_tags (src_mi));
camel_message_info_set_subject (des_mi, camel_message_info_get_subject (src_mi));
camel_message_info_set_from (des_mi, camel_message_info_get_from (src_mi));
camel_message_info_set_to (des_mi, camel_message_info_get_to (src_mi));
camel_message_info_set_cc (des_mi, camel_message_info_get_cc (src_mi));
camel_message_info_set_mlist (des_mi, camel_message_info_get_mlist (src_mi));
camel_message_info_set_size (des_mi, camel_message_info_get_size (src_mi));
camel_message_info_set_date_sent (des_mi, camel_message_info_get_date_sent (src_mi));
camel_message_info_set_date_received (des_mi, camel_message_info_get_date_received (src_mi));
camel_message_info_set_message_id (des_mi, camel_message_info_get_message_id (src_mi));
camel_message_info_take_references (des_mi, camel_message_info_dup_references (src_mi));
camel_message_info_take_headers (des_mi, camel_message_info_dup_headers (src_mi));
if (had_cal)
camel_message_info_set_user_flag (des_mi, "$has_cal", TRUE);
if (CAMEL_IS_EWS_MESSAGE_INFO (des_mi) && CAMEL_IS_EWS_MESSAGE_INFO (src_mi)) {
camel_ews_message_info_set_change_key (CAMEL_EWS_MESSAGE_INFO (des_mi),
camel_ews_message_info_get_change_key (CAMEL_EWS_MESSAGE_INFO (src_mi)));
}
camel_message_info_property_unlock (des_mi);
}
void
camel_ews_utils_sync_updated_items (CamelEwsFolder *ews_folder,
EEwsConnection *cnc,
gboolean is_drafts_folder,
GSList *items_updated,
CamelFolderChangeInfo *change_info)
CamelFolderChangeInfo *change_info,
GCancellable *cancellable)
{
CamelFolder *folder;
CamelFolderSummary *folder_summary;
......@@ -824,33 +905,59 @@ camel_ews_utils_sync_updated_items (CamelEwsFolder *ews_folder,
continue;
}
mi = camel_folder_summary_get (folder_summary, id->id);
if (mi) {
guint32 server_flags;
gboolean changed, was_changed;
camel_message_info_freeze_notifications (mi);
was_changed = camel_message_info_get_folder_flagged (mi);
if (is_drafts_folder) {
mi = camel_folder_summary_get (folder_summary, id->id);
if (mi) {
CamelMessageInfo *tmp_mi;
if (g_strcmp0 (camel_ews_message_info_get_change_key (CAMEL_EWS_MESSAGE_INFO (mi)), id->change_key) != 0)
camel_ews_folder_remove_cached_message (ews_folder, id->id);
/* There can changed also subject and other values in the Drafts folder,
thus recreate it and update it. */
tmp_mi = camel_ews_utils_item_to_message_info (ews_folder, cnc, item, cancellable);
if (!tmp_mi) {
g_warn_if_reached ();
g_object_unref (mi);
g_object_unref (item);
continue;
}
server_flags = ews_utils_get_server_flags (item);
ews_utils_merge_server_user_flags (item, mi);
changed = camel_ews_update_message_info_flags (folder_summary, mi, server_flags, NULL);
changed = camel_ews_utils_update_follow_up_flags (item, mi) || changed;
changed = camel_ews_utils_update_read_receipt_flags (item, mi, server_flags, FALSE) || changed;
ews_utils_copy_message_info (mi, tmp_mi);
camel_ews_message_info_set_change_key (CAMEL_EWS_MESSAGE_INFO (mi), id->change_key);
if (changed)
camel_folder_change_info_change_uid (change_info, id->id);
camel_ews_message_info_set_change_key (CAMEL_EWS_MESSAGE_INFO (mi), id->change_key);
if (!was_changed) {
/* do not save to the server what was just read, when did not change locally before */
camel_message_info_set_folder_flagged (mi, FALSE);
g_clear_object (&tmp_mi);
g_clear_object (&mi);
}
} else {
mi = camel_folder_summary_get (folder_summary, id->id);
if (mi) {
guint32 server_flags;
gboolean changed, was_changed;
camel_message_info_freeze_notifications (mi);
was_changed = camel_message_info_get_folder_flagged (mi);
server_flags = ews_utils_get_server_flags (item);
ews_utils_merge_server_user_flags (item, mi);
changed = camel_ews_update_message_info_flags (folder_summary, mi, server_flags, NULL);
changed = camel_ews_utils_update_follow_up_flags (item, mi) || changed;
changed = camel_ews_utils_update_read_receipt_flags (item, mi, server_flags, FALSE) || changed;
if (changed)
camel_folder_change_info_change_uid (change_info, id->id);
camel_ews_message_info_set_change_key (CAMEL_EWS_MESSAGE_INFO (mi), id->change_key);
if (!was_changed) {
/* do not save to the server what was just read, when did not change locally before */
camel_message_info_set_folder_flagged (mi, FALSE);
}
camel_message_info_thaw_notifications (mi);
g_clear_object (&mi);
g_object_unref (item);
continue;
camel_message_info_thaw_notifications (mi);
g_clear_object (&mi);
}
}
g_object_unref (item);
......@@ -972,6 +1079,7 @@ camel_ews_utils_item_to_message_info (CamelEwsFolder *ews_folder,
void
camel_ews_utils_sync_created_items (CamelEwsFolder *ews_folder,
EEwsConnection *cnc,
gboolean is_drafts_folder,
GSList *items_created,
CamelFolderChangeInfo *change_info,
GCancellable *cancellable)
......@@ -988,7 +1096,7 @@ camel_ews_utils_sync_created_items (CamelEwsFolder *ews_folder,
for (l = items_created; l != NULL; l = g_slist_next (l)) {
EEwsItem *item = (EEwsItem *) l->data;
CamelMessageInfo *mi;
CamelMessageInfo *mi, *tmp_mi;
const EwsId *id;
if (!item)
......@@ -1008,33 +1116,46 @@ camel_ews_utils_sync_created_items (CamelEwsFolder *ews_folder,
}
mi = camel_folder_summary_get (folder_summary, id->id);
if (mi) {
/* If it didn't change, then skip it. */
if (mi && g_strcmp0 (camel_ews_message_info_get_change_key (CAMEL_EWS_MESSAGE_INFO (mi)), id->change_key) == 0) {
g_clear_object (&mi);
g_object_unref (item);
continue;
} else if (mi && is_drafts_folder) {
/* The message in the Drafts folder changed, thus reload also locally cached message */
camel_ews_folder_remove_cached_message (ews_folder, id->id);
}
mi = camel_ews_utils_item_to_message_info (ews_folder, cnc, item, cancellable);
if (!mi) {
tmp_mi = camel_ews_utils_item_to_message_info (ews_folder, cnc, item, cancellable);
if (!tmp_mi) {
g_warn_if_reached ();
g_clear_object (&mi);
g_object_unref (item);
continue;
}
camel_folder_summary_add (folder_summary, mi, FALSE);
if (mi) {
ews_utils_copy_message_info (mi, tmp_mi);
camel_ews_message_info_set_change_key (CAMEL_EWS_MESSAGE_INFO (mi), id->change_key);
/* camel_folder_summary_add() sets folder_flagged flag
* on the message info, but this is a fresh item downloaded
* from the server, thus unset it, to avoid resync up to the server
* on folder leave/store
*/
camel_message_info_set_folder_flagged (mi, FALSE);
camel_folder_change_info_change_uid (change_info, id->id);
} else {
camel_folder_summary_add (folder_summary, tmp_mi, FALSE);
camel_folder_change_info_add_uid (change_info, id->id);
camel_folder_change_info_recent_uid (change_info, id->id);
/* camel_folder_summary_add() sets folder_flagged flag
* on the message info, but this is a fresh item downloaded
* from the server, thus unset it, to avoid resync up to the server
* on folder leave/store
*/
camel_message_info_set_folder_flagged (tmp_mi, FALSE);
camel_folder_change_info_add_uid (change_info, id->id);
camel_folder_change_info_recent_uid (change_info, id->id);
}
g_object_unref (mi);
g_object_unref (tmp_mi);
g_object_unref (item);
g_clear_object (&mi);
}
g_slist_free (items_created);
......
......@@ -67,13 +67,17 @@ void camel_ews_utils_sync_deleted_items
void camel_ews_utils_sync_created_items
(CamelEwsFolder *ews_folder,
EEwsConnection *cnc,
gboolean is_drafts_folder,
GSList *items_created,
CamelFolderChangeInfo *change_info,
GCancellable *cancellable);
void camel_ews_utils_sync_updated_items
(CamelEwsFolder *ews_folder,
EEwsConnection *cnc,
gboolean is_drafts_folder,
GSList *items_updated,
CamelFolderChangeInfo *change_info);
CamelFolderChangeInfo *change_info,
GCancellable *cancellable);
GSList * ews_utils_gather_server_user_flags
(ESoapMessage *msg,
CamelMessageInfo *mi);
......@@ -94,6 +98,9 @@ CamelMessageInfo * /* (transfer full) */
EEwsConnection *cnc,
EEwsItem *item,
GCancellable *cancellable);
gboolean camel_ews_utils_folder_is_drafts_folder
(CamelEwsFolder *ews_folder);
G_END_DECLS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment