calendar: Correct handling of recurring events
When a recurring event has deleted a single instance, it's received as an event modification, thus make sure all of the old instances are removed before adding the event to the list of events. Closes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4592 Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2328>
This commit is contained in:
parent
66ae4c7ff3
commit
a6244e34de
@ -273,6 +273,15 @@ class DBusEventSource extends EventSourceBase {
|
|||||||
this._lastRequestEnd = null;
|
this._lastRequestEnd = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_removeMatching(uidPrefix) {
|
||||||
|
let changed = false;
|
||||||
|
for (const id of this._events.keys()) {
|
||||||
|
if (id.startsWith(uidPrefix))
|
||||||
|
changed = this._events.delete(id) || changed;
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
_onNameAppeared() {
|
_onNameAppeared() {
|
||||||
this._initialized = true;
|
this._initialized = true;
|
||||||
this._resetCache();
|
this._resetCache();
|
||||||
@ -287,12 +296,21 @@ class DBusEventSource extends EventSourceBase {
|
|||||||
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
|
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
|
||||||
const [appointments = []] = argArray;
|
const [appointments = []] = argArray;
|
||||||
let changed = false;
|
let changed = false;
|
||||||
|
const handledRemovals = new Set();
|
||||||
|
|
||||||
for (let n = 0; n < appointments.length; n++) {
|
for (let n = 0; n < appointments.length; n++) {
|
||||||
const [id, summary, startTime, endTime] = appointments[n];
|
const [id, summary, startTime, endTime] = appointments[n];
|
||||||
const date = new Date(startTime * 1000);
|
const date = new Date(startTime * 1000);
|
||||||
const end = new Date(endTime * 1000);
|
const end = new Date(endTime * 1000);
|
||||||
let event = new CalendarEvent(id, date, end, summary);
|
let event = new CalendarEvent(id, date, end, summary);
|
||||||
|
/* It's a recurring event */
|
||||||
|
if (!id.endsWith('\n')) {
|
||||||
|
const parentId = id.substr(0, id.lastIndexOf('\n') + 1);
|
||||||
|
if (!handledRemovals.has(parentId)) {
|
||||||
|
handledRemovals.add(parentId);
|
||||||
|
this._removeMatching(parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
this._events.set(event.id, event);
|
this._events.set(event.id, event);
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
@ -307,7 +325,7 @@ class DBusEventSource extends EventSourceBase {
|
|||||||
|
|
||||||
let changed = false;
|
let changed = false;
|
||||||
for (const id of ids)
|
for (const id of ids)
|
||||||
changed ||= this._events.delete(id);
|
changed = this._removeMatching(id) || changed;
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
this.emit('changed');
|
this.emit('changed');
|
||||||
@ -317,13 +335,7 @@ class DBusEventSource extends EventSourceBase {
|
|||||||
let [sourceUid = ''] = argArray;
|
let [sourceUid = ''] = argArray;
|
||||||
sourceUid += '\n';
|
sourceUid += '\n';
|
||||||
|
|
||||||
let changed = false;
|
if (this._removeMatching(sourceUid))
|
||||||
for (const id of this._events.keys()) {
|
|
||||||
if (id.startsWith(sourceUid))
|
|
||||||
changed ||= this._events.delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
this.emit('changed');
|
this.emit('changed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,20 +438,30 @@ app_process_added_modified_objects (App *app,
|
|||||||
GSList *objects) /* ICalComponent * */
|
GSList *objects) /* ICalComponent * */
|
||||||
{
|
{
|
||||||
ECalClient *cal_client;
|
ECalClient *cal_client;
|
||||||
|
g_autoptr(GHashTable) covered_uids = NULL;
|
||||||
GSList *link;
|
GSList *link;
|
||||||
gboolean expand_recurrences;
|
gboolean expand_recurrences;
|
||||||
|
|
||||||
cal_client = e_cal_client_view_ref_client (view);
|
cal_client = e_cal_client_view_ref_client (view);
|
||||||
|
covered_uids = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
expand_recurrences = e_cal_client_get_source_type (cal_client) == E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
|
expand_recurrences = e_cal_client_get_source_type (cal_client) == E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
|
||||||
|
|
||||||
for (link = objects; link; link = g_slist_next (link))
|
for (link = objects; link; link = g_slist_next (link))
|
||||||
{
|
{
|
||||||
ECalComponent *comp;
|
ECalComponent *comp;
|
||||||
ICalComponent *icomp = link->data;
|
ICalComponent *icomp = link->data;
|
||||||
|
const gchar *uid;
|
||||||
|
gboolean fallback = FALSE;
|
||||||
|
|
||||||
if (!icomp || !i_cal_component_get_uid (icomp))
|
if (!icomp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
uid = i_cal_component_get_uid (icomp);
|
||||||
|
if (!uid || g_hash_table_contains (covered_uids, uid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_hash_table_add (covered_uids, (gpointer) uid);
|
||||||
|
|
||||||
if (expand_recurrences &&
|
if (expand_recurrences &&
|
||||||
!e_cal_util_component_is_instance (icomp) &&
|
!e_cal_util_component_is_instance (icomp) &&
|
||||||
e_cal_util_component_has_recurrences (icomp))
|
e_cal_util_component_has_recurrences (icomp))
|
||||||
@ -464,7 +474,36 @@ app_process_added_modified_objects (App *app,
|
|||||||
e_cal_client_generate_instances_for_object_sync (cal_client, icomp, app->since, app->until, NULL,
|
e_cal_client_generate_instances_for_object_sync (cal_client, icomp, app->since, app->until, NULL,
|
||||||
generate_instances_cb, &data);
|
generate_instances_cb, &data);
|
||||||
}
|
}
|
||||||
|
else if (expand_recurrences &&
|
||||||
|
e_cal_util_component_is_instance (icomp))
|
||||||
|
{
|
||||||
|
ICalComponent *main_comp = NULL;
|
||||||
|
|
||||||
|
/* Always pass whole series of the recurring events, because
|
||||||
|
* the calendar removes events with the same UID first. */
|
||||||
|
if (e_cal_client_get_object_sync (cal_client, uid, NULL, &main_comp, NULL, NULL))
|
||||||
|
{
|
||||||
|
CollectAppointmentsData data;
|
||||||
|
|
||||||
|
data.client = cal_client;
|
||||||
|
data.pappointments = &app->notify_appointments;
|
||||||
|
|
||||||
|
e_cal_client_generate_instances_for_object_sync (cal_client, main_comp, app->since, app->until, NULL,
|
||||||
|
generate_instances_cb, &data);
|
||||||
|
|
||||||
|
g_clear_object (&main_comp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fallback = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
fallback = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fallback)
|
||||||
{
|
{
|
||||||
comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (icomp));
|
comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (icomp));
|
||||||
if (!comp)
|
if (!comp)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user