Files
ja b0af3dcf12 Workstation optimization: Chrome cleanup, package purge, PCIe audit, service tuning
- Chrome/Chromium cleanup (ADR 0006): removed 10GB chromium profile, broken PWA
  shortcuts, dead BROWSER_CDP_URL from .bashrc, restored Wayland chrome-flags.conf
- Package cleanup (ADR 0007): Tier 1-4 executed, 40 packages removed (KDE Plasma,
  ruby, love, xorg-server, kscreen/kscreenlocker), 45 cascade orphans purged
- Waybar USB module: auto-mount via udisks2, yazi integration, hover details
- Service tuning: disabled bluetooth.service, NetworkManager-wait-online.service
- hypridle fix: upgraded sdbus-cpp 2.3.0->2.3.1-1 (SEGV crash loop resolved)
- PCIe audit: GPU in wrong slot (PCIEX4 vs PCIEX16), 8x bandwidth loss documented
- D-Bus cleanup: removed stale org.kde.kwalletd6.service stub
- Ansible: all changes reflected in vars/main.yml and task files
2026-05-22 16:24:18 +02:00

167 lines
5.7 KiB
Django/Jinja

#!/usr/bin/env bash
# Waybar USB module - automount, status, open in yazi, eject
# Usage:
# usb.sh -> JSON status for waybar poll (auto-mounts unmounted USBs)
# usb.sh open -> open first mounted USB in yazi (via kitty)
# usb.sh eject -> unmount + power-off all USB devices
set -euo pipefail
# --- helpers -------------------------------------------------------------------
get_usb_devices() {
# Returns JSON array of USB block devices via lsblk.
# Fields: NAME, RM (removable), SIZE, LABEL, MOUNTPOINT, FSTYPE, TRAN, MODEL
lsblk -Jbpno NAME,RM,SIZE,LABEL,MOUNTPOINT,FSTYPE,TRAN,MODEL 2>/dev/null \
| jq -c '[.blockdevices[] | select(.tran == "usb")]'
}
auto_mount_unmounted() {
local devices="$1"
# Auto-mount any USB partition that isn't mounted yet
local unmounted
unmounted=$(echo "$devices" | jq -r '.[] | select(.mountpoint == null or .mountpoint == "") | .name')
for dev in $unmounted; do
udisksctl mount -b "$dev" --no-user-interaction 2>/dev/null || true
done
}
# --- actions -------------------------------------------------------------------
do_open() {
# Open the first mounted USB in yazi via kitty
local devices
devices=$(get_usb_devices)
local mountpoint
mountpoint=$(echo "$devices" | jq -r '[.[] | select(.mountpoint != null and .mountpoint != "")] | first | .mountpoint // empty')
if [ -z "$mountpoint" ]; then
# Try children (partitions)
mountpoint=$(lsblk -Jbpno NAME,RM,SIZE,LABEL,MOUNTPOINT,FSTYPE,TRAN,MODEL 2>/dev/null \
| jq -r '[.blockdevices[] | select(.tran == "usb") | .children[]? | select(.mountpoint != null and .mountpoint != "")] | first | .mountpoint // empty')
fi
if [ -n "$mountpoint" ]; then
kitty -e yazi "$mountpoint" &
disown
else
notify-send "USB" "No mounted USB device found" -i dialog-warning
fi
}
do_eject() {
# Unmount all USB partitions, then power-off the parent device
local devices
devices=$(get_usb_devices)
local mounted
mounted=$(echo "$devices" | jq -r '.[] | select(.mountpoint != null and .mountpoint != "") | .name')
# Also check children (partitions of whole disks)
local child_mounted
child_mounted=$(lsblk -Jbpno NAME,MOUNTPOINT,TRAN 2>/dev/null \
| jq -r '[.blockdevices[] | select(.tran == "usb") | .children[]? | select(.mountpoint != null and .mountpoint != "")] | .[].name')
for dev in $mounted $child_mounted; do
udisksctl unmount -b "$dev" --no-user-interaction 2>/dev/null || true
done
# Power-off the whole USB devices
local parent_devs
parent_devs=$(echo "$devices" | jq -r '.[].name')
for dev in $parent_devs; do
udisksctl power-off -b "$dev" --no-user-interaction 2>/dev/null || true
done
notify-send "USB" "All USB devices ejected" -i media-eject
}
do_status() {
local devices
devices=$(get_usb_devices)
# Auto-mount unmounted partitions
auto_mount_unmounted "$devices"
# Re-read after automount
devices=$(get_usb_devices)
# Count mounted USBs (check both top-level and children)
local count=0
local tooltip_lines=""
# Top-level devices
while IFS= read -r line; do
if [ -z "$line" ] || [ "$line" = "null" ]; then continue; fi
local name size label mount fstype model
name=$(echo "$line" | jq -r '.name')
size=$(echo "$line" | jq -r '.size')
label=$(echo "$line" | jq -r '.label // "N/A"')
mount=$(echo "$line" | jq -r '.mountpoint // "not mounted"')
fstype=$(echo "$line" | jq -r '.fstype // "?"')
model=$(echo "$line" | jq -r '.model // "USB" | gsub("^\\s+|\\s+$"; "")')
if [ "$mount" != "not mounted" ]; then
count=$((count + 1))
fi
tooltip_lines="${tooltip_lines}${name} ${model} ${size} [${fstype}]\nLabel: ${label}\nMount: ${mount}\n"
done < <(echo "$devices" | jq -c '.[]')
# Children (partitions)
while IFS= read -r line; do
if [ -z "$line" ] || [ "$line" = "null" ]; then continue; fi
local name size label mount fstype
name=$(echo "$line" | jq -r '.name')
size=$(echo "$line" | jq -r '.size')
label=$(echo "$line" | jq -r '.label // "N/A"')
mount=$(echo "$line" | jq -r '.mountpoint // "not mounted"')
fstype=$(echo "$line" | jq -r '.fstype // "?"')
if [ "$mount" != "not mounted" ]; then
count=$((count + 1))
fi
tooltip_lines="${tooltip_lines} └ ${name} ${size} [${fstype}]\n Label: ${label}\n Mount: ${mount}\n"
done < <(lsblk -Jbpno NAME,RM,SIZE,LABEL,MOUNTPOINT,FSTYPE,TRAN,MODEL 2>/dev/null \
| jq -c '[.blockdevices[] | select(.tran == "usb") | .children[]?] | .[]')
# Determine alt class
local alt="usb-none"
if [ "$count" -gt 0 ]; then
alt="usb-mounted"
elif [ -n "$tooltip_lines" ]; then
alt="usb-unmounted"
fi
# Build JSON output
local text icon
if [ "$count" -gt 0 ]; then
icon="󰋊"
text="${icon} ${count}"
elif [ -n "$tooltip_lines" ]; then
icon="󰋊"
text="${icon} !"
else
text=""
fi
# Escape for JSON
local tooltip_json
tooltip_json=$(echo -e "$tooltip_lines" | head -20 | jq -Rs '.')
if [ -n "$text" ]; then
printf '{"text":%s,"tooltip":%s,"alt":%s}\n' \
"$(jq -n --arg t "$text" '$t')" \
"$tooltip_json" \
"$(jq -n --arg a "$alt" '$a')"
else
echo '{"text":"","tooltip":"","alt":"usb-none"}'
fi
}
# --- main ----------------------------------------------------------------------
case "${1:-}" in
open) do_open ;;
eject) do_eject ;;
*) do_status ;;
esac