Add selectable Voxtype and Superwhisper dictation (#14552)

* Add selectable dictation backends

* Move dictation migration after repository priority update

* Extract backend-specific dictation installers

* Keep dictation installer dispatcher executable

* Call dictation backend installers directly

* Drop legacy Superwhisper migration and runtime cleanup

* Separate dictation defaults from generic recording protocol

* Add backend-specific dictation removers

* Preserve existing Voxtype selection during upgrade

* Make dictation backend selection safe and retryable

* Show the dictation indicator only for selected Voxtype

* Allow switching away from stopped Superwhisper

* Remove the built-in bar dictation indicator

* Store default dictation selection under defaults

* Rename dictation backend selector to use

* Move dictation removers into their own menu category
This commit is contained in:
David Heinemeier Hansson authored and GitHub committed 2026-10-08 20:37:26 +02:00
1 parent 1554a522cc
commit c24889096e
34 files changed
+639 -141

No files matched your search

+318
View File
@@ -0,0 +1,318 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
export HOME="$test_tmp/home" XDG_CONFIG_HOME="$test_tmp/config" OMARCHY_PATH="$ROOT"
export DICTATION_LOG="$test_tmp/calls" DICTATION_INSTALLED="voxtype superwhisper"
mkdir -p "$test_tmp/bin" "$XDG_CONFIG_HOME/omarchy/defaults"
export PATH="$test_tmp/bin:$ROOT/bin:$PATH"
config="$XDG_CONFIG_HOME/omarchy/defaults/dictation"
cat > "$test_tmp/bin/omarchy-cmd-present" <<'SH'
#!/bin/bash
case "$1" in
omarchy-dictation-*|omarchy-install-dictation-*) command -v "$1" >/dev/null ;;
*) [[ " $DICTATION_INSTALLED " == *" $1 "* ]] ;;
esac
SH
cat > "$test_tmp/bin/omarchy-cmd-missing" <<'SH'
#!/bin/bash
! omarchy-cmd-present "$1"
SH
cat > "$test_tmp/bin/omarchy-launch-floating-terminal-with-presentation" <<'SH'
#!/bin/bash
printf '%s\n' "$*" > "$DICTATION_INSTALL_LOG"
SH
export DICTATION_INSTALL_LOG="$test_tmp/install"
for backend in voxtype superwhisper; do
cat > "$test_tmp/bin/$backend" <<'SH'
#!/bin/bash
printf '%s %s\n' "${0##*/}" "$*" >> "$DICTATION_LOG"
if [[ $1 == "status" ]]; then echo "${VOXTYPE_STATUS:-idle}"; exit 0; fi
if [[ -n ${FAIL_SETUP_STEP:-} && $* == "$FAIL_SETUP_STEP" ]]; then exit 7; fi
exit "${DICTATION_EXIT:-0}"
SH
done
for command in omarchy-pkg-add omarchy-notification-send hyprctl omarchy-restart-shell; do
cat > "$test_tmp/bin/$command" <<'SH'
#!/bin/bash
printf '%s %s\n' "${0##*/}" "$*" >> "$DICTATION_LOG"
exit "${SETUP_EXIT:-0}"
SH
done
cat > "$test_tmp/bin/systemctl" <<'SH'
#!/bin/bash
if [[ $* == "--user is-active --quiet superwhisper.service" ]]; then
[[ ${DICTATION_SERVICE_ACTIVE:-1} == 1 ]]
else
printf '%s %s\n' "${0##*/}" "$*" >> "$DICTATION_LOG"
exit "${SERVICE_EXIT:-0}"
fi
SH
cat > "$test_tmp/bin/omarchy-hw-vulkan" <<'SH'
#!/bin/bash
exit 1
SH
cat > "$test_tmp/bin/gum" <<'SH'
#!/bin/bash
exit "${CONFIRM_EXIT:-0}"
SH
cat > "$test_tmp/bin/bash" <<'SH'
#!/bin/bash
if [[ $1 == "/usr/share/superwhisper/setup-user" ]]; then
printf '%s\n' setup-user >> "$DICTATION_LOG"
exit "${SETUP_EXIT:-0}"
else
exec /bin/bash "$@"
fi
SH
chmod +x "$test_tmp/bin/"*
if omarchy-dictation start 2> "$test_tmp/error"; then
fail "unset backend must fail even when providers are installed"
fi
[[ ! -e $DICTATION_LOG ]] || fail "recording never configures or installs a backend"
pass "dictation requires explicit configuration"
omarchy-default-dictation superwhisper
[[ $(cat "$DICTATION_INSTALL_LOG") == "omarchy-install-dictation-superwhisper" ]] || fail "Defaults launches backend installer"
[[ ! -e $config ]] || fail "Defaults does not select before setup succeeds"
if omarchy-default-dictation unknown > "$test_tmp/output" 2>&1; then fail "missing installer must fail"; fi
if omarchy-default-dictation '../invalid' > "$test_tmp/output" 2>&1; then fail "invalid backend must fail"; fi
pass "Defaults delegates setup without prematurely selecting a backend"
for backend in voxtype superwhisper; do
printf '%s\n' "$backend" > "$config"
[[ $(omarchy-default-dictation) == "$backend" ]] || fail "configured backend is readable"
: > "$DICTATION_LOG"
for action in start stop toggle; do omarchy dictation "$action"; done
if [[ $backend == "voxtype" ]]; then
expected=$'voxtype record start\nvoxtype status\nvoxtype record stop\nvoxtype record toggle'
else
expected=$'superwhisper start\nsuperwhisper stop\nsuperwhisper record'
fi
[[ $(cat "$DICTATION_LOG") == "$expected" ]] || fail "adapter dispatches recording for $backend"
done
pass "built-in adapters implement start stop and toggle"
cat > "$test_tmp/bin/omarchy-dictation-future-backend" <<'SH'
#!/bin/bash
[[ ! -e /proc/$$/fd/9 ]] || exit 90
printf '%s\n' "$1" >> "$DICTATION_LOG"
exit "${DICTATION_EXIT:-0}"
SH
chmod +x "$test_tmp/bin/omarchy-dictation-future-backend"
cat > "$test_tmp/bin/omarchy-install-dictation-future-backend" <<'SH'
#!/bin/bash
exit 0
SH
chmod +x "$test_tmp/bin/omarchy-install-dictation-future-backend"
omarchy-default-dictation future-backend
[[ $(cat "$DICTATION_INSTALL_LOG") == "omarchy-install-dictation-future-backend" ]] || fail "third backend installer requires no selector changes"
printf '%s\n' future-backend > "$config"
: > "$DICTATION_LOG"
for action in start stop toggle; do omarchy-dictation "$action"; done
[[ $(cat "$DICTATION_LOG") == $'start\nstop\ntoggle' ]] || fail "third backend requires no dispatcher changes"
result=0
DICTATION_EXIT=7 omarchy-dictation start || result=$?
(( result == 7 )) || fail "backend failures propagate"
rm "$test_tmp/bin/omarchy-dictation-future-backend"
if omarchy-dictation start 2> "$test_tmp/error"; then fail "missing adapter must fail"; fi
printf '%s\n' '../invalid' > "$config"
if omarchy-dictation start 2> "$test_tmp/error"; then fail "invalid backend must fail"; fi
pass "external adapters follow the same protocol and errors propagate"
printf '%s\n' voxtype > "$config"
if SETUP_EXIT=1 omarchy-install-dictation-superwhisper > "$test_tmp/output" 2>&1; then fail "failed installation must fail"; fi
[[ $(cat "$config") == "voxtype" ]] || fail "failed setup must preserve selection"
if DICTATION_EXIT=7 omarchy-install-dictation-superwhisper > "$test_tmp/output" 2>&1; then fail "failed shortcut setup must fail"; fi
[[ $(cat "$config") == "voxtype" ]] || fail "failed shortcuts must preserve selection"
omarchy-install-dictation-superwhisper
[[ $(omarchy-default-dictation) == "superwhisper" ]] || fail "installer selects Superwhisper"
pass "Superwhisper installer owns setup and saves selection only after success"
DICTATION_INSTALLED=superwhisper
CONFIRM_EXIT=1 omarchy-install-dictation-voxtype
[[ $(cat "$config") == "superwhisper" ]] || fail "cancelled installation preserves selection"
omarchy-install-dictation-voxtype
[[ $(omarchy-default-dictation) == "voxtype" ]] || fail "installer selects Voxtype"
DICTATION_INSTALLED="voxtype superwhisper"
: > "$DICTATION_LOG"
omarchy-install-dictation-voxtype
grep -q 'voxtype setup --download --no-post-install' "$DICTATION_LOG" || fail "installed Voxtype retries model setup"
printf '%s\n' 'custom model configuration' > "$XDG_CONFIG_HOME/voxtype/config.toml"
printf '%s\n' superwhisper > "$config"
for step in 'setup --download --no-post-install' 'setup systemd'; do
if FAIL_SETUP_STEP="$step" omarchy-install-dictation-voxtype > "$test_tmp/output" 2>&1; then fail "incomplete setup must fail"; fi
[[ $(cat "$config") == "superwhisper" ]] || fail "incomplete setup preserves selection"
done
if SERVICE_EXIT=1 omarchy-install-dictation-voxtype > "$test_tmp/output" 2>&1; then fail "service failure must fail"; fi
[[ $(cat "$config") == "superwhisper" ]] || fail "service failure preserves selection"
omarchy-install-dictation-voxtype
[[ $(cat "$config") == "voxtype" ]] || fail "retry finishes installed Voxtype setup"
[[ $(cat "$XDG_CONFIG_HOME/voxtype/config.toml") == "custom model configuration" ]] || fail "retry preserves custom configuration"
pass "Voxtype retries incomplete model and service setup without replacing configuration"
: > "$DICTATION_LOG"
if DICTATION_EXIT=7 omarchy-dictation-use superwhisper > "$test_tmp/output" 2>&1; then fail "failed stop must prevent switching"; fi
[[ $(cat "$config") == "voxtype" ]] || fail "failed stop preserves selection"
omarchy-dictation-use superwhisper
[[ $(cat "$DICTATION_LOG") == $'voxtype status\nvoxtype record stop\nvoxtype status\nvoxtype record stop' ]] || fail "switch stops the previous backend"
[[ $(cat "$config") == "superwhisper" ]] || fail "successful stop permits switching"
: > "$DICTATION_LOG"
omarchy-dictation-use superwhisper
[[ ! -s $DICTATION_LOG ]] || fail "reselecting does not interrupt recording"
printf '%s\n' voxtype > "$config"
VOXTYPE_STATUS=stopped omarchy-dictation-use superwhisper
[[ $(cat "$config") == "superwhisper" ]] || fail "a stopped Voxtype daemon permits switching"
printf '%s\n' superwhisper > "$config"
DICTATION_SERVICE_ACTIVE=0 omarchy-dictation-use voxtype
[[ $(cat "$config") == "voxtype" ]] || fail "a stopped Superwhisper service permits switching"
printf '%s\n' removed-backend > "$config"
omarchy-dictation-use voxtype
[[ $(cat "$config") == "voxtype" ]] || fail "a removed adapter permits recovery"
pass "switching stops recordings, preserves failed stops, and recovers unavailable providers"
# Readers may run throughout a switch, but must never observe a truncated file.
(
for ((i = 0; i < 200; i++)); do
selection=$(cat "$config")
[[ $selection == "voxtype" || $selection == "superwhisper" ]] || exit 1
done
) &
reader=$!
for ((i = 0; i < 20; i++)); do
omarchy-dictation-use voxtype
omarchy-dictation-use superwhisper
done
wait "$reader" || fail "concurrent readers always see a complete selection"
printf '%s\n' voxtype > "$config"
pass "selection updates are atomic for concurrent readers"
lua <<'LUA'
local root = os.getenv("ROOT")
local configured, bindings = false, {}
o = {
shell_succeeds = function(command)
assert(command == "omarchy-default-dictation")
return configured
end,
bind = function(...) table.insert(bindings, {...}) end,
}
dofile(root .. "/default/hypr/bindings/dictation.lua")
assert(#bindings == 0, "unconfigured dictation leaves application keys available")
configured = true
dofile(root .. "/default/hypr/bindings/dictation.lua")
assert(#bindings == 5, "any configured backend receives the same bindings")
LUA
pass "dictation shortcuts require a selection without limiting backend names"
lua <<'LUA'
local root = os.getenv("ROOT")
package.path = root .. "/?.lua;" .. package.path
package.loaded["default.hypr.paths"] = { config_home = "/config" }
local selected, available, loaded = "superwhisper", true, {}
local missing = false
o = { cmd_missing = function() return missing end }
local real_open, real_popen, real_dofile = io.open, io.popen, dofile
io.popen = function(command)
assert(command == "omarchy-default-dictation 2>/dev/null")
return { read = function() return selected end, close = function() end }
end
io.open = function(path)
assert(path == "/config/" .. selected .. "/shortcuts.lua")
if available then return { close = function() end } end
end
dofile = function(path) table.insert(loaded, path) end
local function load_backend()
package.loaded["default.hypr.dictation-backend"] = nil
require("default.hypr.dictation-backend")
end
load_backend()
assert(loaded[1] == "/config/superwhisper/shortcuts.lua")
selected, available = "voxtype", false
load_backend()
assert(#loaded == 1, "a backend with no integration should need no config")
selected, available = "future-backend", true
load_backend()
assert(loaded[2] == "/config/future-backend/shortcuts.lua", "integration must not be limited to named providers")
missing = true
load_backend()
assert(#loaded == 2, "an uninstalled backend must not load a stale bridge")
missing = false
dofile = function() error("broken generated bridge") end
load_backend()
assert(#loaded == 2, "a broken bridge must not abort the desktop configuration")
dofile = function(path) table.insert(loaded, path) end
selected = "../../outside"
load_backend()
assert(#loaded == 2, "a backend must not escape the config directory")
selected = nil
load_backend()
assert(#loaded == 2, "no installed backend must leave configuration usable")
io.open, io.popen, dofile = real_open, real_popen, real_dofile
LUA
pass "desktop integration follows the selected backend without personal Hyprland config"
cat > "$test_tmp/bin/systemctl" <<'SH'
#!/bin/bash
exit 0
SH
cat > "$test_tmp/bin/omarchy-pkg-drop" <<'SH'
#!/bin/bash
printf '%s\n' "$*" >> "$DICTATION_LOG"
exit "${REMOVE_EXIT:-0}"
SH
chmod +x "$test_tmp/bin/systemctl" "$test_tmp/bin/omarchy-pkg-drop"
omarchy-remove-dictation-voxtype
[[ ! -e $config ]] || fail "removing Voxtype clears selection"
if omarchy-default-dictation 2> "$test_tmp/error"; then fail "removal must not auto-select another backend"; fi
pass "removal clears selection without automatic fallback"
cat > "$test_tmp/bin/omarchy-shell" <<'SH'
#!/bin/bash
printf '%s\n' "$*" >> "$DICTATION_LOG"
SH
chmod +x "$test_tmp/bin/omarchy-shell"
export XDG_DATA_HOME="$test_tmp/data"
mkdir -p "$HOME/.local/bin" "$XDG_DATA_HOME/superwhisper/app" "$XDG_DATA_HOME/superwhisper/models" "$XDG_CONFIG_HOME/omarchy/plugins" "$HOME/.agents/skills" "$HOME/.claude/skills"
ln -s /usr/bin/superwhisper "$HOME/.local/bin/superwhisper"
ln -s /opt/superwhisper "$XDG_DATA_HOME/superwhisper/app/current"
ln -s /opt/superwhisper/assets/omarchy-plugin/superwhisper-panel "$XDG_CONFIG_HOME/omarchy/plugins/superwhisper-panel"
ln -s /opt/superwhisper/assets/agent-skill/superwhisper "$HOME/.agents/skills/superwhisper"
ln -s /custom/skill "$HOME/.claude/skills/superwhisper"
printf '%s\n' retained > "$XDG_DATA_HOME/superwhisper/models/model"
printf '%s\n' superwhisper > "$config"
if REMOVE_EXIT=1 omarchy-remove-dictation-superwhisper > "$test_tmp/output" 2>&1; then
fail "failed package removal must fail"
fi
[[ -L $HOME/.local/bin/superwhisper && $(cat "$config") == "superwhisper" ]] || fail "failed removal preserves selection and links"
omarchy-remove-dictation-superwhisper
[[ ! -e $config ]] || fail "Superwhisper removal clears its selection"
for link in "$HOME/.local/bin/superwhisper" "$XDG_DATA_HOME/superwhisper/app/current" "$XDG_CONFIG_HOME/omarchy/plugins/superwhisper-panel" "$HOME/.agents/skills/superwhisper"; do
[[ ! -L $link ]] || fail "Superwhisper removal unlinks packaged integration"
done
[[ $(readlink "$HOME/.claude/skills/superwhisper") == "/custom/skill" ]] || fail "custom skills are preserved"
[[ -f $XDG_DATA_HOME/superwhisper/models/model ]] || fail "downloaded models are retained"
printf '%s\n' voxtype > "$config"
omarchy-remove-dictation-superwhisper
[[ $(cat "$config") == "voxtype" ]] || fail "removing Superwhisper preserves another selected backend"
pass "Superwhisper removal clears its selection and owned links while preserving user data and other backends"
cat > "$test_tmp/bin/omarchy-pkg-present" <<'SH'
#!/bin/bash
[[ ${VOXTYPE_PACKAGE:-0} == 1 && $1 == "voxtype-bin" ]]
SH
chmod +x "$test_tmp/bin/omarchy-pkg-present"
rm "$config"
VOXTYPE_PACKAGE=0 /bin/bash -euo pipefail "$ROOT/migrations/1791479273.sh"
[[ ! -e $config ]] || fail "migration does not select an uninstalled backend"
VOXTYPE_PACKAGE=1 /bin/bash -euo pipefail "$ROOT/migrations/1791479273.sh"
[[ $(cat "$config") == "voxtype" ]] || fail "existing Voxtype users keep dictation after upgrade"
printf '%s\n' future-backend > "$config"
VOXTYPE_PACKAGE=1 /bin/bash -euo pipefail "$ROOT/migrations/1791479273.sh"
[[ $(cat "$config") == "future-backend" ]] || fail "upgrade preserves explicit backend selections"
pass "one-time upgrade preserves existing Voxtype without runtime autodetection"
@@ -198,16 +198,6 @@ ShellRoot {
root.assertTrue(root.commandCount("omarchy-capture-screenrecording --stop-recording") === 1, "Screen Recording left click stops active recording")
}
var dictation = root.createIndicator("Dictation")
if (dictation) {
dictation.moduleName = "Dictation"
root.injectBar(dictation)
dictation.triggerPress(Qt.LeftButton)
dictation.triggerPress(Qt.RightButton)
root.assertTrue(root.commandCount("omarchy-voxtype-config") === 2, "Dictation clicks run config command")
root.assertTrue(root.commandCount("omarchy-voxtype-model") === 0, "Dictation clicks do not run model command")
}
var stayAwake = root.createIndicator("StayAwake")
if (stayAwake) {
stayAwake.moduleName = "StayAwake"
@@ -147,8 +147,11 @@ trap 'rm -rf "$tmpdir"' EXIT
home="$tmpdir/home"
stub_bin="$tmpdir/bin"
mkdir -p "$home" "$stub_bin"
touch "$stub_bin/voxtype"
chmod +x "$stub_bin/voxtype"
cat > "$stub_bin/omarchy-default-dictation" <<'SH'
#!/bin/bash
echo voxtype
SH
chmod +x "$stub_bin/omarchy-default-dictation"
bindings=$(PATH="$stub_bin:$PATH" list_bindings "$home")
[[ -n $bindings ]] || fail "default bindings load for the conflict check"
+19 -26
View File
@@ -144,36 +144,29 @@ no_bindings_output=$(run_omarchy_bindings "$no_bindings_home" 'omarchy_default_b
[[ -z $no_bindings_output ]] || fail "default binding variable disables all Omarchy bindings" "$no_bindings_output"
pass "default binding variable disables all Omarchy bindings"
voxtype_home="$tmpdir/voxtype-home"
voxtype_bin="$tmpdir/voxtype-bin"
mkdir -p "$voxtype_home" "$voxtype_bin"
touch "$voxtype_bin/voxtype"
chmod +x "$voxtype_bin/voxtype"
voxtype_output=$(PATH="$voxtype_bin:$PATH" run_omarchy_bindings "$voxtype_home")
grep -Fq $'SUPER + CTRL + X Toggle dictation' <<<"$voxtype_output" ||
fail "installed Voxtype enables its toggle binding"
grep -Fq $'F9 Start dictation (push-to-talk)' <<<"$voxtype_output" ||
fail "installed Voxtype enables its push-to-talk binding"
grep -Fq $'F9 Stop dictation (push-to-talk)' <<<"$voxtype_output" ||
fail "installed Voxtype enables its release binding"
pass "installed Voxtype conditionally enables dictation bindings"
voxtype_without_execute_output=$(PATH="$voxtype_bin:$PATH" run_omarchy_bindings \
"$voxtype_home" 'os.execute = function() return nil, "No child processes", 10 end')
grep -Fq $'SUPER + CTRL + X Toggle dictation' <<<"$voxtype_without_execute_output" ||
fail "Voxtype detection does not require spawning a subprocess"
pass "installed Voxtype detection works without os.execute"
dictation_home="$tmpdir/dictation-home"
missing_bin="$tmpdir/missing-bin"
mkdir -p "$missing_bin"
mkdir -p "$dictation_home" "$missing_bin"
ln -s "$(command -v lua)" "$missing_bin/lua"
ln -s "$(command -v lspci)" "$missing_bin/lspci"
ln -s "$(command -v sort)" "$missing_bin/sort"
missing_voxtype_output=$(PATH="$missing_bin" run_omarchy_bindings "$voxtype_home")
if grep -Fq $'SUPER + CTRL + X Toggle dictation' <<<"$missing_voxtype_output"; then
fail "missing Voxtype skips its bindings"
fi
pass "missing Voxtype skips dictation bindings"
dictation_output=$(PATH="$missing_bin" run_omarchy_bindings "$dictation_home")
if grep -Fq 'dictation' <<<"$dictation_output"; then fail "unconfigured dictation leaves application shortcuts available"; fi
cat > "$missing_bin/omarchy-default-dictation" <<'SH'
#!/bin/bash
echo future-backend
SH
chmod +x "$missing_bin/omarchy-default-dictation"
dictation_output=$(PATH="$missing_bin" run_omarchy_bindings "$dictation_home")
for binding in \
$'SUPER + CTRL + X\tToggle dictation' \
$'F9\tStart dictation (push-to-talk)' \
$'F9\tStop dictation (push-to-talk)' \
$'ALT + Alt_R\tStart dictation (push-to-talk)' \
$'ALT + Alt_R\tStop dictation (push-to-talk)'; do
grep -Fq "$binding" <<<"$dictation_output" || fail "dictation bindings load for any selected backend" "$binding"
done
pass "dictation bindings require a selection without hardcoding backends"
# Lazydocker is optional on new installs, while existing installs keep the hotkey.
lazydocker_bin="$tmpdir/lazydocker-bin"
+1 -1
View File
@@ -71,7 +71,7 @@ const fs = require('fs')
const defaultItems = menu.parseMenuJsonc(fs.readFileSync(path.join(root, 'default/omarchy/omarchy-menu.jsonc'), 'utf8'))
const guardText = defaultItems.map(item => `${item.when}\n${item.checked}\n${item.disabled}`).join('\n')
const repeated = [...new Set(
(guardText.match(/\$\((omarchy-[a-z0-9-]+)\)/g) || []).map(match => match.slice(2, -1))
(guardText.match(/\$\((omarchy-[a-z0-9-]+(?: [a-z0-9-]+)*)\)/g) || []).map(match => match.slice(2, -1))
)].filter(command => guardText.split(`$(${command})`).length > 2)
assertDeepEqual(
repeated.filter(command => !menu.guardReaders.includes(command)),
+2 -1
View File
@@ -325,6 +325,7 @@ assertDeepEqual(
[
'remove.package',
'remove.ai',
'remove.dictation',
'remove.service',
'remove.development',
'remove.theme',
@@ -336,7 +337,7 @@ assertDeepEqual(
'remove.preinstalls',
'remove.security'
],
'menu orders Remove categories like their Install counterparts, followed by Remove-only categories'
'menu keeps the Remove category order'
)
assert(
defaultById['setup.security.passwordless-sudo'].action.includes('omarchy-sudo-passwordless'),
@@ -9,7 +9,7 @@ const read = name => fs.readFileSync(path.join(root, name), 'utf8')
const indicator = read('shell/plugins/bar/indicators/PasswordlessSudo.qml')
const widget = read('shell/plugins/bar/widgets/Indicators.qml')
const manifest = JSON.parse(read('shell/plugins/bar/widgets/Indicators.manifest.json'))
assert(widget.match(/defaultIndicatorEntries: \[ "PasswordlessSudo", "Dictation"/), 'passwordless sudo is included in the default indicator tray')
assert(widget.match(/defaultIndicatorEntries: \[ "PasswordlessSudo", "ScreenRecording"/), 'passwordless sudo is included in the default indicator tray')
assert(manifest.barWidget.schema.find(field => field.key === 'items').options.some(option => option.value === 'PasswordlessSudo'), 'passwordless sudo is configurable alongside Night Light')
assert(indicator.includes('useActiveColor: true') && indicator.includes('activeColor: Commons.Color.urgent'), 'active passwordless sudo uses the theme danger color')
assertEqual(indicator.match(/activeText: "([^"]+)"/)[1], indicator.match(/inactiveText: "([^"]+)"/)[1], 'sudo keeps the same icon in both states')
+2 -2
View File
@@ -45,8 +45,8 @@ run_invitation_hook
[[ -f $test_home/.local/state/omarchy/done/voxtype-install-invitation ]] || fail "Voxtype invitation records completion"
[[ -f $hook_path ]] || fail "Voxtype invitation keeps its hook installed"
[[ $(grep -c '^notification$' "$log_file") -eq 1 ]] || fail "Voxtype invitation sends one notification"
grep -qx 'exec:omarchy-launch-floating-terminal-with-presentation omarchy-voxtype-install' "$log_file" ||
fail "Voxtype invitation attaches the installer to the notification"
grep -qx 'exec:omarchy-menu summon setup.default.dictation' "$log_file" ||
fail "dictation invitation opens the backend installation choices"
grep -q '^systemd-run:' "$log_file" && fail "Voxtype invitation needs no unit to hold an unanswered toast"
HOME="$test_home" PATH="$test_bin:$ROOT/bin:$PATH" TEST_LOG="$log_file" bash "$hook_path"