#!/usr/bin/env bash set -euo pipefail project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" phone_controls="$project_root/config/dot/quickshell/modules/quicksettings/PhoneControls.qml" system_settings="$project_root/config/dot/quickshell/services/SystemSettings.qml" fail() { printf 'Phone Messages contract: %s\n' "$1" >&2 exit 1 } [[ -f "$phone_controls" ]] || fail 'Phone controls component is missing' [[ -f "$system_settings" ]] || fail 'System settings service is missing' # This is a static contract only: it starts no shell, sends no IPC, and never # evaluates the launch branch. Its only Flatpak use is source-text inspection. rg -Fq '"bluebubbles": ["flatpak", "run", "app.bluebubbles.BlueBubbles"]' "$system_settings" \ || fail 'BlueBubbles does not use the fixed Flatpak argument vector' rg -Fq 'readonly property bool bluebubblesAvailable: root.bluebubblesDetected' "$system_settings" \ || fail 'BlueBubbles availability is not exposed independently' rg -Fq 'command: ["flatpak", "info", "app.bluebubbles.BlueBubbles"]' "$system_settings" \ || fail 'BlueBubbles installed-state probe is missing' for action in share clipboard ring messages; do rg -Fq "id: \"$action\"" "$phone_controls" \ || fail "Phone actions do not include $action" done if rg -Fq '.filter(' "$phone_controls"; then fail 'Phone actions are filtered instead of keeping four stable columns' fi rg -Fq 'columns: 4' "$phone_controls" \ || fail 'Phone actions do not use four equal columns' rg -Fq 'root.actionModels.length - 1' "$phone_controls" \ || fail 'Phone action widths are not calculated from the fixed model count' rg -Fq 'SystemSettings.bluebubblesAvailable' "$phone_controls" \ || fail 'Messages enablement does not read BlueBubbles availability' rg -Fq 'KdeConnect.phoneReachable' "$phone_controls" \ || fail 'KDE action reachability semantics are missing' rg -Fq 'KdeConnect.supports(actionButton.modelData.id)' "$phone_controls" \ || fail 'KDE action capability semantics are missing' rg -Fq 'else if (action === "messages")' "$phone_controls" \ || fail 'Messages has no independent invocation branch' rg -Fq 'SystemSettings.openApplication("bluebubbles")' "$phone_controls" \ || fail 'Messages does not use the allow-listed BlueBubbles launcher' rg -Fq 'BlueBubbles is not installed' "$phone_controls" \ || fail 'Missing BlueBubbles has no quiet explanatory row' # A static negative guard keeps the Messages branch from accidentally inheriting # KDE Connect reachability, transfer, or plugin conditions. messages_branch="$(sed -n '/else if (action === "messages")/,/^ }/p' "$phone_controls")" printf '%s\n' "$messages_branch" | rg -Fq 'KdeConnect.' \ && fail 'Messages is coupled to KDE Connect' printf 'Phone Messages contract: PASS\n'