mirror of
https://github.com/arthur-pbty/arthur-os.git
synced 2026-08-01 20:28:16 +02:00
Improve actionable notification wrapper
This commit is contained in:
@@ -245,8 +245,9 @@ stop_screenrecording() {
|
||||
ffmpeg -y -i "$filename" -ss 00:00:00.1 -vframes 1 -q:v 2 "$preview" -loglevel quiet 2>/dev/null
|
||||
|
||||
(
|
||||
ACTION=$(notify-send -a omarchy-action "Screen recording saved" "Open with Super + Alt + , (or click this)" -t 10000 --hint="string:image-path:${preview:-$filename}" -A "default=open")
|
||||
[[ $ACTION == "default" ]] && mpv "$filename"
|
||||
if [[ -n $(omarchy-notification-send "Screen recording saved" "Open with Super + Alt + , (or click this)" -t 10000 --image "${preview:-$filename}" -a) ]]; then
|
||||
mpv "$filename"
|
||||
fi
|
||||
rm -f "$preview"
|
||||
) &
|
||||
fi
|
||||
|
||||
@@ -133,8 +133,9 @@ case "$PROCESSING" in
|
||||
wl-copy --type image/png <"$FILEPATH"
|
||||
|
||||
(
|
||||
ACTION=$(notify-send -a omarchy-action "Screenshot saved to clipboard and file" "Edit with Super + Alt + , (or click this)" -t 10000 --hint="string:image-path:$FILEPATH" -A "default=edit")
|
||||
[[ $ACTION == "default" ]] && open_editor "$FILEPATH"
|
||||
if [[ -n $(omarchy-notification-send "Screenshot saved to clipboard and file" "Edit with Super + Alt + , (or click this)" -t 10000 --image "$FILEPATH" -a) ]]; then
|
||||
open_editor "$FILEPATH"
|
||||
fi
|
||||
) >/dev/null 2>&1 &
|
||||
;;
|
||||
copy)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Send an Omarchy desktop notification
|
||||
# omarchy:args=[-g <glyph>] [-u <low|normal|critical>] <headline> [description] [notify-send options]
|
||||
# omarchy:args=[-a] [--app-name <app-name>] [-g <glyph>] [-u <low|normal|critical>] [--image <path-or-uri>] <headline> [description] [notify-send options]
|
||||
# omarchy:examples=omarchy notification send "Reminder" "5 minutes are up" -g
|
||||
|
||||
set -euo pipefail
|
||||
@@ -10,7 +10,11 @@ headline=""
|
||||
description=""
|
||||
glyph=
|
||||
urgency="low"
|
||||
app_name="omarchy-action"
|
||||
image=
|
||||
click_action=0
|
||||
args=()
|
||||
parsed_option_args=0
|
||||
|
||||
parse_omarchy_option() {
|
||||
case $1 in
|
||||
@@ -20,6 +24,7 @@ parse_omarchy_option() {
|
||||
exit 1
|
||||
fi
|
||||
glyph=$2
|
||||
parsed_option_args=2
|
||||
return 0
|
||||
;;
|
||||
-u | --urgency)
|
||||
@@ -28,6 +33,30 @@ parse_omarchy_option() {
|
||||
exit 1
|
||||
fi
|
||||
urgency="$2"
|
||||
parsed_option_args=2
|
||||
return 0
|
||||
;;
|
||||
--app-name)
|
||||
if (($# < 2)); then
|
||||
echo "Missing value for $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
app_name=$2
|
||||
parsed_option_args=2
|
||||
return 0
|
||||
;;
|
||||
--image)
|
||||
if (($# < 2)); then
|
||||
echo "Missing value for $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
image=$2
|
||||
parsed_option_args=2
|
||||
return 0
|
||||
;;
|
||||
-a | --action)
|
||||
click_action=1
|
||||
parsed_option_args=1
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
@@ -37,14 +66,14 @@ parse_omarchy_option() {
|
||||
|
||||
while (($# > 0)); do
|
||||
if parse_omarchy_option "$@"; then
|
||||
shift 2
|
||||
shift "$parsed_option_args"
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if (($# < 1)); then
|
||||
echo "Usage: omarchy-notification-send [-g <glyph>] [-u <low|normal|critical>] <headline> [description] [notify-send options]"
|
||||
echo "Usage: omarchy-notification-send [-a] [--app-name <app-name>] [-g <glyph>] [-u <low|normal|critical>] [--image <path-or-uri>] <headline> [description] [notify-send options]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -58,20 +87,26 @@ fi
|
||||
|
||||
while (($# > 0)); do
|
||||
if parse_omarchy_option "$@"; then
|
||||
shift 2
|
||||
shift "$parsed_option_args"
|
||||
else
|
||||
args+=("$1")
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
# Tag as a user-action toast so it pops through DND. See dnd-fix-plan.md.
|
||||
args+=("-a" "omarchy-action" "-u" "$urgency")
|
||||
# Tag as a user-action toast so it pops through DND.
|
||||
args+=("-a" "$app_name" "-u" "$urgency")
|
||||
|
||||
# Keep Omarchy action toasts compact by rendering glyphs inline instead of
|
||||
# forcing the notification card's icon slot.
|
||||
if [[ -n $glyph ]]; then
|
||||
headline="$glyph $headline"
|
||||
args+=("--hint=string:omarchy-glyph:$glyph")
|
||||
fi
|
||||
|
||||
if [[ -n $image ]]; then
|
||||
args+=("--hint=string:image-path:$image")
|
||||
fi
|
||||
|
||||
if ((click_action)); then
|
||||
args+=("-A" "default=default")
|
||||
fi
|
||||
|
||||
if [[ -n $description ]]; then
|
||||
|
||||
@@ -5,7 +5,6 @@ set -e
|
||||
# Remove this hook after use
|
||||
rm -f "$0"
|
||||
|
||||
(
|
||||
action=$(notify-send -a omarchy-action -u critical --hint=string:omarchy-glyph: "Install Dictation with Voxtype" "Click to install voice dictation for Omarchy." -A "default=Install")
|
||||
[[ $action == "default" ]] && omarchy-launch-floating-terminal-with-presentation omarchy-voxtype-install
|
||||
) >/dev/null 2>&1 &
|
||||
if [[ -n $(omarchy-notification-send -u critical -g "Install Dictation with Voxtype" "Click to install voice dictation for Omarchy." -a) ]]; then
|
||||
omarchy-launch-floating-terminal-with-presentation omarchy-voxtype-install
|
||||
fi >/dev/null 2>&1 &
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
(
|
||||
action=$(notify-send -a omarchy-action -u critical --hint=string:omarchy-glyph: "Learn Keybindings" "Super + K for cheatsheet.\nSuper + Space for application launcher.\nSuper + Alt + Space for Omarchy Menu." -A "default=Open")
|
||||
[[ $action == "default" ]] && omarchy-menu-keybindings
|
||||
if [[ -n $(omarchy-notification-send -u critical -g "Learn Keybindings" "Super + K for cheatsheet.\nSuper + Space for application launcher.\nSuper + Alt + Space for Omarchy Menu." -a) ]]; then
|
||||
omarchy-menu-keybindings
|
||||
fi
|
||||
) >/dev/null 2>&1 &
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
notify_update() {
|
||||
(
|
||||
action=$(notify-send -a omarchy-action -u critical --hint=string:omarchy-glyph: "Update System" "$1" -A "default=Update")
|
||||
[[ $action == "default" ]] && omarchy-launch-floating-terminal-with-presentation omarchy-update
|
||||
if [[ -n $(omarchy-notification-send -u critical -g "Update System" "$1" -a) ]]; then
|
||||
omarchy-launch-floating-terminal-with-presentation omarchy-update
|
||||
fi
|
||||
) >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
notify_wifi() {
|
||||
(
|
||||
action=$(notify-send -a omarchy-action -u critical --hint=string:omarchy-glyph: "Click to Setup Wi-Fi" -A "default=Setup")
|
||||
[[ $action == "default" ]] && omarchy-shell omarchy.network toggle
|
||||
if [[ -n $(omarchy-notification-send -u critical -g "Click to Setup Wi-Fi" -a) ]]; then
|
||||
omarchy-shell omarchy.network toggle
|
||||
fi
|
||||
) >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,11 @@ function shouldBypassDnd(notification, criticalUrgency) {
|
||||
return appName === "notify-send" && notification && notification.urgency === criticalUrgency
|
||||
}
|
||||
|
||||
function isEphemeralApp(appName) {
|
||||
var name = String(appName || "")
|
||||
return name === "notify-send" || name === "omarchy-action"
|
||||
}
|
||||
|
||||
function glyphFromHints(hints) {
|
||||
try {
|
||||
if (hints) {
|
||||
@@ -167,6 +172,7 @@ if (typeof module !== "undefined") {
|
||||
sanitizeBody: sanitizeBody,
|
||||
summaryStartsWithGlyph: summaryStartsWithGlyph,
|
||||
shouldBypassDnd: shouldBypassDnd,
|
||||
isEphemeralApp: isEphemeralApp,
|
||||
glyphFromHints: glyphFromHints,
|
||||
snapshotOf: snapshotOf,
|
||||
historyEntry: historyEntry,
|
||||
|
||||
@@ -133,15 +133,15 @@ Item {
|
||||
// - app_name is "notify-send" (the CLI default — means the sender
|
||||
// didn't bother declaring an identity, so it's almost certainly
|
||||
// ephemeral test/feedback noise)
|
||||
// - app_name is "omarchy-action" (omarchy's own user-action
|
||||
// confirmation toasts — the user just triggered them, they don't
|
||||
// - app_name is "omarchy-action" (Omarchy's own user-action
|
||||
// toasts — the user just triggered them, they don't
|
||||
// need to be archived)
|
||||
var transient = false
|
||||
try {
|
||||
transient = !!(notification.hints && notification.hints["transient"])
|
||||
} catch (e) { transient = false }
|
||||
var appName = String(notification.appName || "")
|
||||
var ephemeralApp = appName === "notify-send" || appName === "omarchy-action"
|
||||
var ephemeralApp = NotificationLogic.isEphemeralApp(appName)
|
||||
if (transient || ephemeralApp) {
|
||||
if (service.doNotDisturb && !shouldBypassDnd(notification)) {
|
||||
notification.tracked = false
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
tmpdir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
stub="$tmpdir/notify-send"
|
||||
args_file="$tmpdir/args"
|
||||
|
||||
printf '%s\n' \
|
||||
'#!/bin/bash' \
|
||||
'printf "%s\n" "$@" >"$OMARCHY_TEST_NOTIFY_ARGS"' \
|
||||
>"$stub"
|
||||
chmod +x "$stub"
|
||||
|
||||
OMARCHY_TEST_NOTIFY_ARGS="$args_file" PATH="$tmpdir:$ROOT/bin:$PATH" \
|
||||
omarchy-notification-send --app-name custom-app -g K -u critical --image /tmp/image.png "Learn Keybindings" "Body" -a
|
||||
|
||||
mapfile -t args <"$args_file"
|
||||
|
||||
[[ ${args[0]} == "-a" ]] || fail "notification wrapper passes app flag"
|
||||
[[ ${args[1]} == "custom-app" ]] || fail "notification wrapper uses custom app name"
|
||||
[[ ${args[2]} == "-u" ]] || fail "notification wrapper passes urgency flag"
|
||||
[[ ${args[3]} == "critical" ]] || fail "notification wrapper uses custom urgency"
|
||||
[[ ${args[4]} == "--hint=string:omarchy-glyph:K" ]] || fail "notification wrapper converts glyph to hint"
|
||||
[[ ${args[5]} == "--hint=string:image-path:/tmp/image.png" ]] || fail "notification wrapper converts image to hint"
|
||||
[[ ${args[6]} == "-A" ]] || fail "notification wrapper passes default action flag"
|
||||
[[ ${args[7]} == "default=default" ]] || fail "notification wrapper enables default action"
|
||||
[[ ${args[8]} == "Learn Keybindings" ]] || fail "notification wrapper preserves headline"
|
||||
[[ ${args[9]} == "Body" ]] || fail "notification wrapper preserves description"
|
||||
pass "notification wrapper supports app, glyph, urgency, image, and action options"
|
||||
@@ -42,6 +42,8 @@ assert(notifications.shouldBypassDnd({ appName: 'omarchy-action', urgency: 1 },
|
||||
assert(notifications.shouldBypassDnd({ appName: 'notify-send', urgency: 2 }, 2), 'critical notify-send bypasses DND')
|
||||
assert(!notifications.shouldBypassDnd({ appName: 'notify-send', urgency: 1 }, 2), 'normal notify-send does not bypass DND')
|
||||
assert(!notifications.shouldBypassDnd({ appName: 'Slack', urgency: 2 }, 2), 'critical app notifications do not bypass DND')
|
||||
assert(!notifications.shouldBypassDnd({ appName: 'omarchy-menu-keybindings', urgency: 1 }, 2), 'omarchy command app names do not bypass DND')
|
||||
assert(!notifications.isEphemeralApp('omarchy-menu-keybindings'), 'notifications treat omarchy command app names as normal apps')
|
||||
|
||||
const notification = {
|
||||
id: 12,
|
||||
|
||||
Reference in New Issue
Block a user