r3 - 06 Oct 2006 - 16:22:06 - BryanStearnsYou are here: OSAF >  Journal Web  >  ContributorNotes > BryanStearnsNotes > RecurringReminderNotes
This page outlines how we model reminders on recurring events.

Overview

There are four types of reminders, distinguished by the attributes set on them:
    userCreated promptUser etc
Absolute The "custom" choice in the detail view's alarm popup. True True absoluteTime=datetime(?)
Relative The "after" or "before" choices in the detail view's alarm popup. True True delta=timedelta(?), relativeTo=EventStamp.effectiveStartTime.name
Snooze Set when the user snoozes a user-set reminder in the reminder dialog box. False True absoluteTime=datetime(?)
TriageStatus Set automatically (by a schema.observer) when startTime changes, if the new startTime is in the future False False absoluteTime=datetime(?)

In general, reminders and the items they belong to ('remindables') are connected via two bi-ref lists:

  • Remindable.reminders <-> Reminder.reminderItems: Established when a reminder in the future (or due) for a particular event.
  • Remindable.expiredReminders <-> Reminder.expiredReminderItems: Established for dismissed user-created reminders.

The attributes on reminders determine how the reminders behave:

  • userCreated=True means that this is a reminder created by the user using the detail view's popups. An item can only have one userCreated reminder, though it could be referred to by either one of the bi-ref lists. Also, only userCreated=True reminders will be moved to the expiredReminders list when the reminder is dismissed (the others are simply deleted).
  • promptUser=True means that when the reminder time arrives, the reminder will be presented to the user in the reminder dialog.

We keep a collection of items with pending reminders (appropriately-named 'itemsWithReminders'), sorted by the next due reminder (of any type) on each item. (The actual filterexpression is "view.hasTrueValue(uuid, '%s')" % (Remindable.reminders.name,), and is further filtered by Trash.)

A user-interface mechanism looks at the first item in the collection and sets a timer to go off when that reminder is due. (If the first pending reminder is found to be due in the past, the timer is set to go off "shortly".)

When the timer goes off, each due reminder is processed:

  • If the user isn't supposed to be prompted, this is a triageStatus reminder; triageStatus on the item is set to Now, and triageStatusChanged is set to the time that the reminder was due (which keeps everything in order if a bunch of these reminders come due while Chandler isn't running). The reminder is then deleted.
  • Otherwise, the reminder is presented to the user in the reminder dialog's list.
  • When the user dismisses a reminder, it's moved to expiredReminders (if userCreated) or deleted (eg, a snooze reminder).
  • When the user snoozes a reminder, it's moved to expiredReminders or deleted (if it was already a snooze reminder) and a separate snooze reminder is created for "five minutes from now".

Occurrences vs. master events

In alpha4, the calendar shows occurrences, and displays them in the detail view; the dashboard shows master events and displays them in the detail view.

Showing the master event and letting the user make changes to it (in both the summary and the detail view) is a big problem, and the solutions aren't good. I predict alpha4 will have bugs whenever users edit master events this way. I'm thinking about making master events read-only in alpha4, even though I know this will make recurring events useless (for instance, once you make an event recurring in the dashboard, you can't make it non-recurring again); the alternative is to add a bunch of more detailed special-case code, which seems like a waste of time.

Reminders on recurring events

Relative reminders:

  • should be referenced by one of the two reflists on every occurrence in the sequence
  • It should be placed on the expiredReminders list on the master, to keep the master from being included in the itemsWithReminders collection.
  • dismissing one on an occurrence moves it to the expiredReminders reflist on that one instance.
  • on exception occurrences
    • The relative reminder is either exceptional, or not. If it's exceptional, it only exists on the exception occurrence, and no other userCreated reminder exists on that occurrence. If it's not exceptional, it's handled like a non-exceptional occurrence.

Absolute reminders:

  • There's no real point in having an absolute reminder on a recurring event; I think we have these choices:
    • When an event with an absolute reminder is made to recur, we convert the absolute reminder to a relative reminder (delta = reminder.absoluteTime - master.effectiveStartTime) and apply it to every instance.
    • We apply the absolute reminder to the occurrence after the reminder would fire. This leads to a further question: Should that instance becomes an exception? Yes would be nice because if the user adds a reminder to another occurrence in the series, and chooses to make it an all-occurrences event, there's no conflict.

Snooze reminders:

  • These don't conflict with user reminders; I think they should exist on individual occurrences, and if something happens that necessitates rebuilding the recurrence series, they can be discarded.

TriageStatus? reminders:

  • Given that the dashboard is the only place (in alpha4, anyway) that the user can interact with TriageStatus?, and that we don't maintain triagestatus properly on occurrences anyway (bug 6700), I think that we shouldn't update triagestatus on recurring events in alpha4 (and so, we shouldn't create reminders on them).
  • Once bug 6700 is fixed and we can store triageStatus somehow, I think we should avoid attaching triagestatus reminders to every occurrence; instead, we should maintain one on the next due occurrence, and when it fires, the reminder-fired processor should move it to the next occurrence on which it should fire.

Tasks

  • Disable creation of triagestatus reminders on recurring events
  • Put snooze reminders on individual occurrences only.
  • When making an event recur, convert absolute reminders to relative, and attach to every occurrence.
  • Deal with each case of dismissing a reminder on a recurring event.

-- BryanStearns - 03 Oct 2006

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r3 < r2 < r1 | More topic actions
 
Open Source Applications Foundation
Except where otherwise noted, this site and its content are licensed by OSAF under an Creative Commons License, Attribution Only 3.0.
See list of page contributors for attributions.