Files
attention-required/EffectCatalog.js
T
alan 401b46c886 Attention Required: notification rules with effects for Omarchy
Rules watch every notification for words and apps and answer with an
effect: nudge, flash, banner, airplane, confetti, blink, sound, focus,
or a command. Silenced notifications that match a rule are let through.
Settings popup behind a bar bell, rules kept in one JSON file.
2026-09-08 16:55:43 +01:00

132 lines
5.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Every effect the settings popup knows how to configure, in the order the
// chips are shown. `rows` are sliders (duration / intensity / speed and the
// odd extra), `options` are choices or free text. Scripts in effects/ and
// overlays in the shell read the same keys.
//
// Not a .pragma library: the shell caches those across plugin reloads.
var EFFECTS = [
{
type: "nudge", label: "Nudge", icon: "󰕦",
subtitle: "Shakes the screen, like a phone buzzing",
rows: [
{ key: "duration", label: "Duration", min: 0.2, max: 5, step: 0.1, fallback: 1, unit: " s" },
{ key: "intensity", label: "Intensity", min: 0.5, max: 30, step: 0.5, fallback: 1.5, unit: "" },
{ key: "speed", label: "Speed", min: 10, max: 400, step: 10, fallback: 200, unit: " /s" }
],
options: []
},
{
type: "flash", label: "Flash", icon: "󰉁",
subtitle: "A glow pulses in from the edges of the screen",
rows: [
{ key: "duration", label: "Duration", min: 0.2, max: 10, step: 0.1, fallback: 1, unit: " s" },
{ key: "intensity", label: "Intensity", min: 0.05, max: 1, step: 0.05, fallback: 0.9, unit: "" },
{ key: "speed", label: "Pulses", min: 0.5, max: 12, step: 0.5, fallback: 3, unit: " /s" },
{ key: "thickness", label: "Thickness", min: 8, max: 400, step: 8, fallback: 64, unit: " px" }
],
options: [
{ key: "color", label: "Color", type: "enum", fallback: "accent",
values: [{ value: "accent", label: "Accent" }, { value: "urgent", label: "Urgent" }, { value: "foreground", label: "Text" }] }
]
},
{
type: "banner", label: "Banner", icon: "",
subtitle: "The message drops in as a big card",
rows: [
{ key: "duration", label: "Stays for", min: 0.5, max: 30, step: 0.5, fallback: 3, unit: " s" },
{ key: "intensity", label: "Size", min: 0.5, max: 2.5, step: 0.1, fallback: 1, unit: "×" },
{ key: "speed", label: "Slide", min: 1, max: 10, step: 0.5, fallback: 4, unit: " /s" }
],
options: [
{ key: "position", label: "Position", type: "enum", fallback: "top",
values: [{ value: "top", label: "Top" }, { value: "center", label: "Centre" }, { value: "bottom", label: "Bottom" }] },
{ key: "color", label: "Color", type: "enum", fallback: "accent",
values: [{ value: "accent", label: "Accent" }, { value: "urgent", label: "Urgent" }, { value: "foreground", label: "Text" }] },
{ key: "text", label: "Text", type: "text", fallback: "", placeholder: "empty: {summary} and the body · also {app}, {rule}" }
]
},
{
type: "airplane", label: "Airplane", icon: "󰀝",
subtitle: "A plane tows the message across the screen",
rows: [
{ key: "duration", label: "Flight", min: 2, max: 20, step: 0.5, fallback: 7, unit: " s" },
{ key: "intensity", label: "Size", min: 0.5, max: 3, step: 0.1, fallback: 1, unit: "×" },
{ key: "altitude", label: "Altitude", min: 0.05, max: 0.95, step: 0.05, fallback: 0.2, unit: "" }
],
options: [
{ key: "direction", label: "Direction", type: "enum", fallback: "ltr",
values: [{ value: "ltr", label: "Left to right" }, { value: "rtl", label: "Right to left" }] },
{ key: "text", label: "Text", type: "text", fallback: "", placeholder: "empty: {summary} · also {body}, {app}, {rule}" }
]
},
{
type: "confetti", label: "Confetti", icon: "",
subtitle: "Confetti pops up across the screen",
rows: [
{ key: "duration", label: "Duration", min: 0.5, max: 15, step: 0.5, fallback: 1, unit: " s" },
{ key: "intensity", label: "Amount", min: 0.2, max: 3, step: 0.1, fallback: 1, unit: "×" },
{ key: "speed", label: "Power", min: 0.3, max: 3, step: 0.1, fallback: 1, unit: "×" }
],
options: [
{ key: "style", label: "Comes from", type: "enum", fallback: "cannons",
values: [{ value: "cannons", label: "Bottom corners, shot up" }, { value: "burst", label: "The centre, outwards" }, { value: "rain", label: "The top, falling" }] }
]
},
{
type: "blink", label: "Blink", icon: "󰌵",
subtitle: "The screen dims and comes back",
rows: [
{ key: "duration", label: "Duration", min: 0.2, max: 5, step: 0.1, fallback: 1, unit: " s" },
{ key: "intensity", label: "Darkness", min: 0.1, max: 1, step: 0.05, fallback: 0.6, unit: "" },
{ key: "speed", label: "Blinks", min: 1, max: 10, step: 0.5, fallback: 2, unit: " /s" }
],
options: []
},
{
type: "sound", label: "Sound", icon: "󰕾",
subtitle: "Plays a chime",
rows: [
{ key: "intensity", label: "Volume", min: 0, max: 1, step: 0.05, fallback: 1, unit: "" },
{ key: "speed", label: "Repeat", min: 1, max: 5, step: 1, fallback: 1, unit: " ×" }
],
options: [
{ key: "file", label: "File", type: "text", fallback: "", placeholder: "empty: the default chime · or a path to a sound file" }
]
},
{
type: "focus", label: "Focus app", icon: "",
subtitle: "Brings the app's window to the front",
rows: [],
options: [
{ key: "window", label: "Window", type: "text", fallback: "", placeholder: "empty: the app that sent it · or a window class or title" }
]
},
{
type: "command", label: "Command", icon: "󰆍",
subtitle: "Runs a command of yours",
rows: [],
options: [
{ key: "run", label: "Run", type: "text", fallback: "", placeholder: "empty: nothing runs · sees $AR_SUMMARY, $AR_BODY, $AR_APP, $AR_RULE" }
]
}
]
function find(type) {
for (var i = 0; i < EFFECTS.length; i++) if (EFFECTS[i].type === type) return EFFECTS[i]
return null
}
function labelFor(type) {
var e = find(type)
return e ? e.label : String(type)
}
function fallbackFor(type, key) {
var e = find(type)
if (!e) return undefined
for (var i = 0; i < e.rows.length; i++) if (e.rows[i].key === key) return e.rows[i].fallback
for (var j = 0; j < e.options.length; j++) if (e.options[j].key === key) return e.options[j].fallback
return undefined
}