Notifications and dialogs
Reference for dd.notify and the dd.dialogs pickers for desktop and folder items.
dd.notify
Needs the notifications permission.
dd.notify.sync()
dd.notify.sync(entries: {
id: string; // 1..64 chars, unique within the list
at: number; // epoch ms, between now and 366 days ahead
title: string; // non-empty, up to 80 chars
body?: string; // up to 200 chars
}[]): Promise<{ scheduled: number }>Replaces this instance's entire schedule of future notifications. Cancelling one means omitting it; an empty array clears them all. There is no per-entry add or remove.
The host keeps the schedule and raises each toast itself, which is the whole point: a hidden or disabled widget stops running, and the app may restart, but the reminder still arrives. Re-send the list whenever it changes, and once on boot.
Behavior and limits:
- Caps are rejected, never silently clamped: 64 entries,
atwithin a year, title up to 80 characters, body up to 200. Control characters are stripped host-side. - An entry more than 15 minutes past its time is dropped unfired rather than stacking, so a machine that slept for a week does not wake to a week of toasts.
- The toast is a host-drawn window in the corner of the primary work area.
The widget supplies text, never markup, and does not control placement,
appearance, or timing beyond
at. At most 3 toasts are on screen at once. - Removing or disabling the instance drops its schedule. Hiding deliberately does not: surviving an unmount is the point.
dd.dialogs
Host-drawn picker windows. Both pickers share the same consent gates and lifecycle:
- Requires the real cursor inside the widget (call from a click handler), and never opens in edit mode.
- The picker is a normal OS window (taskbar, Alt-Tab, minimizable) that the host renders and owns; the widget never draws into it, and only ever receives ids back.
- No client timeout: the promise resolves whenever the user answers. The host force-settles it after 1 hour unanswered, and force-cancels on edit mode, widget reload, hide, disable, remove, or a crash.
- One picker per kind and instance. Calling again while your picker is open
surfaces the existing window, and the new call resolves
cancelledimmediately. checkedpre-checks ids (up to 1024, each up to 64 chars): pass your current selection.- The result is a replacement set:
cancelled: truemeans change nothing; otherwiseidsis the user's full new checked set, and unchecking is meaningful. Checked ids that no longer exist are carried through untouched. - 5 opens per rolling 10 seconds, shared between both pickers.
dd.dialogs.pickDesktopItems()
dd.dialogs.pickDesktopItems(opts?: { checked?: string[] }): Promise<{
cancelled: boolean;
ids: string[];
}>Needs the desktop permission. Picks from the items on the user's desktop
(the same set dd.desktop.list returns).
dd.dialogs.pickFolderItems()
dd.dialogs.pickFolderItems(settingKey: string, opts?: { checked?: string[] }): Promise<{
cancelled: boolean;
ids: string[];
}>Needs the folders permission. The same picker aimed at the folder the
named filePath setting resolves to. A blank setting value falls through to
the desktop picker behind its own desktop grant, so a drawer widget keeps
one code path.