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;
|
||||
}
|
||||
|
||||
_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() {
|
||||
this._initialized = true;
|
||||
this._resetCache();
|
||||
@ -287,12 +296,21 @@ class DBusEventSource extends EventSourceBase {
|
||||
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
|
||||
const [appointments = []] = argArray;
|
||||
let changed = false;
|
||||
const handledRemovals = new Set();
|
||||
|
||||
for (let n = 0; n < appointments.length; n++) {
|
||||
const [id, summary, startTime, endTime] = appointments[n];
|
||||
const date = new Date(startTime * 1000);
|
||||
const end = new Date(endTime * 1000);
|
||||
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);
|
||||
|
||||
changed = true;
|
||||
@ -307,7 +325,7 @@ class DBusEventSource extends EventSourceBase {
|
||||
|
||||
let changed = false;
|
||||
for (const id of ids)
|
||||
changed ||= this._events.delete(id);
|
||||
changed = this._removeMatching(id) || changed;
|
||||
|
||||
if (changed)
|
||||
this.emit('changed');
|
||||
@ -317,13 +335,7 @@ class DBusEventSource extends EventSourceBase {
|
||||
let [sourceUid = ''] = argArray;
|
||||
sourceUid += '\n';
|
||||
|
||||
let changed = false;
|
||||
for (const id of this._events.keys()) {
|
||||
if (id.startsWith(sourceUid))
|
||||
changed ||= this._events.delete(id);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
if (this._removeMatching(sourceUid))
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
|
@ -438,20 +438,30 @@ app_process_added_modified_objects (App *app,
|
||||
GSList *objects) /* ICalComponent * */
|
||||
{
|
||||
ECalClient *cal_client;
|
||||
g_autoptr(GHashTable) covered_uids = NULL;
|
||||
GSList *link;
|
||||
gboolean expand_recurrences;
|
||||
|
||||
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;
|
||||
|
||||
for (link = objects; link; link = g_slist_next (link))
|
||||
{
|
||||
ECalComponent *comp;
|
||||
ICalComponent *icomp = link->data;
|
||||
const gchar *uid;
|
||||
gboolean fallback = FALSE;
|
||||
|
||||
if (!icomp || !i_cal_component_get_uid (icomp))
|
||||
if (!icomp)
|
||||
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 &&
|
||||
!e_cal_util_component_is_instance (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,
|
||||
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
|
||||
{
|
||||
fallback = TRUE;
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (icomp));
|
||||
if (!comp)
|
||||
|
Loading…
Reference in New Issue
Block a user