From c48020f02d50ddab0f1188148a6a7e39f7a522de Mon Sep 17 00:00:00 2001 From: 28allday Date: Fri, 3 Jul 2026 19:44:30 +0100 Subject: [PATCH] Center TUI copy, shrink window to 520x400 via own app-id windowrule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .desktop now uses --app-id=omatether; install writes a marker-delimited float/center/size rule block into ~/.config/hypr/windows.conf (backed up once, removed on uninstall). Dropped udevadm trigger from install — it wedges an already-connected iPhone (device unconfigured); targeted usbmuxd restart instead. Co-Authored-By: Claude Fable 5 --- README.md | 2 +- omatether.sh | 86 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9f87447..c2dee0f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ the phone's Wi-Fi if it's on one, cellular otherwise. Works headless too. ## TUI Run `omatether.sh` with no arguments (or launch **iPhone Tether** from Walker — -it opens as a floating window). The dashboard shows phone / tether / route +it opens as a small floating window). The dashboard shows phone / tether / route state live and offers only the actions that make sense right now: ``` diff --git a/omatether.sh b/omatether.sh index a98177d..00011c7 100755 --- a/omatether.sh +++ b/omatether.sh @@ -12,6 +12,7 @@ set -euo pipefail NETFILE="/etc/systemd/network/10-iphone-tether.network" DESKTOP_FILE="$HOME/.local/share/applications/omatether.desktop" +WINDOWS_CONF="$HOME/.config/hypr/windows.conf" # Route metrics: Omarchy ships ethernet=100, wifi=600, wwan=700. METRIC_FALLBACK=750 # tether used only when nothing better is up (default) @@ -110,6 +111,31 @@ reload_networkd() { fi } +# Small centered floating window for the TUI (user-level Hyprland rule; +# remove-then-append so re-installs stay idempotent). +install_windowrules() { + [[ -f $WINDOWS_CONF ]] || return 0 # not a Hyprland/Omarchy box — skip + if ! grep -q 'omatether windowrules begin' "$WINDOWS_CONF"; then + cp "$WINDOWS_CONF" "$WINDOWS_CONF.bak.$(date +%s)" + fi + sed -i '/>>> omatether windowrules begin/,/<<< omatether windowrules end/d' "$WINDOWS_CONF" + cat >> "$WINDOWS_CONF" <<'EOF' +# >>> omatether windowrules begin +# omatether — small floating window, centered. +windowrule = float on, match:class ^(omatether)$ +windowrule = center on, match:class ^(omatether)$ +windowrule = size 520 400, match:class ^(omatether)$ +# <<< omatether windowrules end +EOF + hyprctl reload >/dev/null 2>&1 || true +} + +remove_windowrules() { + [[ -f $WINDOWS_CONF ]] || return 0 + sed -i '/>>> omatether windowrules begin/,/<<< omatether windowrules end/d' "$WINDOWS_CONF" + hyprctl reload >/dev/null 2>&1 || true +} + # --------------------------------------------------------- CLI commands ---- cmd_install() { @@ -121,7 +147,8 @@ cmd_install() { reload_networkd ok "networkd profile written: $NETFILE (fallback priority, metric $METRIC_FALLBACK)" - # Floating TUI launcher for Walker (Omarchy TUI.float pattern). + # Floating TUI launcher for Walker. Uses a dedicated app-id (rather than + # Omarchy's generic TUI.float) so our own windowrule can size it smaller. local self self=$(realpath "$0") mkdir -p "$(dirname "$DESKTOP_FILE")" @@ -129,17 +156,22 @@ cmd_install() { [Desktop Entry] Name=iPhone Tether Comment=Use an iPhone's internet over USB -Exec=xdg-terminal-exec --app-id=TUI.float -e $self +Exec=xdg-terminal-exec --app-id=omatether -e $self Icon=phone Terminal=false Type=Application Categories=Network; EOF systemctl --user restart elephant.service 2>/dev/null || true - ok "Walker launcher installed: 'iPhone Tether' (floating window)" + install_windowrules + ok "Walker launcher installed: 'iPhone Tether' (small floating window)" - # Nudge udev in case the phone was already plugged in before install. - as_root udevadm trigger -s usb --action=add 2>/dev/null || true + # If the phone was plugged in before usbmuxd existed it won't be seen yet; + # restart usbmuxd to rescan. (Do NOT `udevadm trigger` — re-firing add + # events on a connected iPhone wedges it: "device unconfigured".) + if phone_on_usb && ! phone_visible; then + revive_usbmuxd + fi say "" say "Run '$0' (no arguments) for the TUI, or '$0 pair' to pair now." @@ -251,9 +283,10 @@ cmd_priority() { cmd_uninstall() { as_root rm -f "$NETFILE" rm -f "$DESKTOP_FILE" + remove_windowrules as_root networkctl reload systemctl --user restart elephant.service 2>/dev/null || true - ok "Removed $NETFILE and the Walker launcher (usbmuxd/libimobiledevice left installed)" + ok "Removed $NETFILE, the Walker launcher and windowrules (usbmuxd/libimobiledevice left installed)" } # ----------------------------------------------------------------- TUI ----- @@ -272,9 +305,29 @@ poll_terminal_size() { done } +# Visible length of a string (ANSI codes stripped; multibyte-aware). +vis_len() { + local s + s=$(printf '%s' "$1" | sed 's/\x1b\[[0-9;]*m//g') + printf '%s' "${#s}" +} + +# Print a line horizontally centered in the terminal. Uses $TW (measured +# once per redraw) — tput inside redirected loops can misread the width. +center_line() { + local pad + pad=$(( (${TW:-80} - $(vis_len "$1")) / 2 )) + (( pad < 0 )) && pad=0 + printf '%*s%s\n' "$pad" '' "$1" +} + tui_header() { - gum style --border rounded --padding "0 2" --margin "0 0 1 0" \ - --border-foreground 212 --bold " OMATETHER" "${DIM}iPhone USB internet${RST}" + local line + while IFS= read -r line; do + center_line "$line" + done < <(gum style --border rounded --padding "0 2" --align center \ + --border-foreground 212 --bold " OMATETHER" "${DIM}iPhone USB internet${RST}") + echo } tui_connect() { @@ -340,6 +393,7 @@ cmd_tui() { poll_terminal_size while true; do + TW=$(tput cols 2>/dev/null || echo 80) clear tui_header @@ -382,7 +436,10 @@ cmd_tui() { uplink_line="${RED}󰈂${RST} No internet route" fi - printf '%s\n%s\n%s\n\n' "$phone_line" "$tether_line" "$uplink_line" + center_line "$phone_line" + center_line "$tether_line" + center_line "$uplink_line" + echo # --- context-aware menu --- local -a menu=() @@ -398,8 +455,17 @@ cmd_tui() { fi menu+=("Status (full check)" "Refresh" "Quit") + # Center the menu as a block: pad every label by a common offset + # (2 extra cols account for gum's cursor prefix). + local maxlen=0 mpad m + for m in "${menu[@]}"; do (( ${#m} > maxlen )) && maxlen=${#m}; done + mpad=$(( (TW - maxlen) / 2 - 2 )); (( mpad < 0 )) && mpad=0 + local -a pmenu=() + for m in "${menu[@]}"; do pmenu+=("$(printf '%*s%s' "$mpad" '' "$m")"); done + local choice - choice=$(gum choose --header "What do you want to do?" "${menu[@]}") || break + choice=$(gum choose --header "$(printf '%*s%s' "$((mpad + 2))" '' 'What do you want to do?')" "${pmenu[@]}") || break + choice=${choice#"${choice%%[![:space:]]*}"} # trim the centering pad case $choice in "Install tethering support") cmd_install; gum input --placeholder "Press Enter…" >/dev/null || true ;; "Connect phone") tui_connect ;;