Task Notifications
Apple devices offer the ability to display alerts or notifications regarding current and upcoming events. OmniFocus uses the native notification abilities of the Apple device to display user-defined task-related notifications. Using Omni Automation, notifications can be created, assigned, and removed from tasks.
Notification-related properties and functions of the Task class:
notifications (Array of Task.Notification r/o) • An array of the notifications that are active for this task.
addNotification(info: Number or Date) → (Task.Notification) • Add a notification from the specification in info. Supplying a Date creates an absolute notification that will fire at that date. Supplying a Double (number) will create a due-relative notification. Specifying a due relative notification when this task’s effectiveDueDate is not set will result in an error.
removeNotification(notification:Task.Notification) → ( ) • Remove an active notification for this task. Supplying a notification that is not in this task’s notifications array, or a notification that has task to something other than this task results in an error.
These properties and functions are used in conjunction with properties of the Notification class to assign and remove notifications to and from tasks.
In this first example script, a notifications designed to be triggered three days from the current time, are assigned to the selected tasks. NOTE: properties and functions of the Calendar class are used to derive the future date/time.
Add Specific Date/Time Notification to Selected Tasks (Absolute)
tasks = document.windows[0].selection.tasks
if (tasks != undefined){
// derive the notification date/time
now = new Date()
dc = new DateComponents()
dc.day = 3
targetDate = Calendar.current.dateByAddingDateComponents(now,dc)
tasks.forEach(task =>{
// supplying a Date object creates an absolute notification
task.addNotification(targetDate)
})
}
Notifications are defined as “absolute” when a fixed date/time is used when creating the notification. The following example script demonstrates how to remove all absolute notifications from the selected task:
Remove Absolute Notifications from Selected Task
task = document.windows[0].selection.tasks[0]
task.notifications.forEach(notif =>{
if (notif.kind === Task.Notification.Kind.Absolute){
task.removeNotification(notif)
}
})
The Task.Notification Class
Here are the properties of an instance of the Task.Notification class:
absoluteFireDate (Date) • The absolute date at which this notification will fire, if its kind is absolute. Getting or setting this property throws an error if this notification’s kind is not absolute.
initialFireDate (Date r/o) • The time at which this notification will fire. For due or defer-relative notifications, this date will change with its task object’s due and defer dates.
isSnoozed (Boolean r/o) • Whether or not this notification has been snoozed.
kind (Task.Notification.Kind r/o) • This notification’s kind. A kind of unknown indicates that the notification is in an invalid state.
nextFireDate (Date or null r/o) • The next time at which this notification will fire. This will only have a value if the initialFireDate is not yet reached, or this notification’s repeatInterval is greater than 0.
relativeFireOffset (Number) • The relative offset in minutes at which this notification will fire from the specified date on its task. Getting or setting this property throws an error if this notification’s kind is not either DueRelative or DeferRelative.
repeatInterval (Number) • How often in seconds this notification will fire once its initialFireDate is reached. Setting this to 0 or any negative number will cease repetition of this notification.
task (Task or null r/o) • The Task object this notification will fire for.
usesFloatingTimeZone (Boolean r/o) • Whether or not the notification’s fire date uses floating time zones. This can only return true if the notification’s kind is absolute. This can be changed by setting shouldUseFloatingTimeZone on this notification's task
Task.Notification.Kind
Absolute (Task.Notification.Kind r/o) • This notification fires on a given date, regardless of its task’s due and defer dates.
DueRelative (Task.Notification.Kind r/o) • This notification fires at a time relative to its task’s due date.
Unknown (Task.Notification.Kind r/o) • It is not known what this notification’s fire date is relative to.
all (Array of Task.Notification.Kind r/o) • An array of all items of this enumeration. This property is often used in the creation of forms.
Notifications Timed Relative to Task Due Date
To set a notification relative to the due date (before or after), provide a positive or negative integer, indicating the number of seconds before (negative), or after (positive), to due date/time for the notification to occur.
Notify 5-minutes Before Due
tasks = document.windows[0].selection.tasks
if (tasks != undefined){
relativeOffset = -300 // seconds
tasks.forEach(task => {
if (task.dueDate){
task.addNotification(relativeOffset)
}
})
}
Remove Relative Notifications from Selected Task
task = document.windows[0].selection.tasks[0]
task.notifications.forEach(notif =>{
if (notif.kind === Task.Notification.Kind.DueRelative){
task.removeNotification(notif)
}
})
Add Standard Notifications
The following script will add these notifications to the selected task, after removing any existing notifications:
- day before task due time
- morning of task due date (9:00 AM)
- hour before task due time
Set to Standard Notifications
task = document.windows[0].selection.tasks[0]
if(task && task.dueDate !== null){
task.notifications.forEach(notif => task.removeNotification(notif))
dateObj = task.dueDate
// day before
task.addNotification(-86400)
// morning of
dc = Calendar.current.dateComponentsFromDate(dateObj)
dc.hour = 9 // 9:00AM
dc.minute = 0
notificationDateObj = Calendar.current.dateFromDateComponents(dc)
task.addNotification(notificationDateObj)
// hour before
task.addNotification(-3600)
}
NOTE: the previous script uses the Date Components class (LINK) of the Calendar class to derive a relative date.
Assign a “Morning Due” Notification
Here is a script that will assign the chosen morning due notification to the selected task or project:
Assign a “Morning Due” Notification
(async () => {
sel = document.windows[0].selection
selCount = sel.tasks.length + sel.projects.length
if(selCount === 1){
if (sel.tasks.length === 1){
var item = sel.tasks[0]
if (!item.dueDate){
throw {name:"No Due Date", message: "The selected task has no assigned due date."}
}
} else {
var item = sel.projects[0]
if (!item.dueDate){
throw {name:"No Due Date", message: "The selected project has no assigned due date."}
}
}
notifcationTimes = ["5:00", "5:15", "5:30", "5:45", "6:00", "6:15", "6:30", "6:45", "7:00", "7:15", "7:30", "7:45", "8:00", "8:15", "8:30", "8:45", "9:00", "9:15", "9:30", "9:45", "10:00"]
menuIndexes = notifcationTimes.map((item, index) => index)
notificationOptionsMenu = new Form.Field.Option(
"menuID",
null,
menuIndexes,
notifcationTimes,
0
)
inputForm = new Form()
inputForm.addField(notificationOptionsMenu)
formPrompt = "Choose a morning time:"
buttonTitle = "Continue"
formObject = await inputForm.show(formPrompt, buttonTitle)
index = formObject.values["menuID"]
timeString = notifcationTimes[index]
hoursMinutes = timeString.split(":")
dc = Calendar.current.dateComponentsFromDate(item.dueDate)
dc.hour = Number(hoursMinutes[0])
dc.minute = Number(hoursMinutes[1])
dc.second = 0
notifDateObj = Calendar.current.dateFromDateComponents(dc)
item.addNotification(notifDateObj)
} else {
throw {name: "Selection Issue", message: "Please select a single project or task with an assigned due date."}
}
})().catch(err => {
if(err.name !== "Error"){
new Alert(err.name, err.message).show()
}
})
Clear Notifications from Projects and/or Tasks
Clears notifications from the selected tasks and/or projects:
Clear All Notifications
try {
sel = document.windows[0].selection
selCount = sel.tasks.length + sel.projects.length
if(selCount > 0){
sel.databaseObjects.forEach(item => {
if(item instanceof Project){
item.task.notifications.forEach(notif => item.task.removeNotification(notif))
} else if (item instanceof Task){
item.notifications.forEach(notif => item.removeNotification(notif))
}
})
} else {
throw {name: "Selection Issue", message: "Please select projects and/or tasks."}
}
}
catch(err){
new Alert(err.name, err.message).show()
}