control centre, notification overhaul, and cleanup

One centred rofi panel (super+x, or the gear in the bar) now drives network,
bluetooth, audio, WireGuard, display, notifications, clipboard, emoji,
screenshots, wallpaper, the particle layer, the bar and power. The separate
per-function menus are gone.

dunst: icons and images were disabled outright (icon_position=off,
max_icon_size=0). Now icons resolve through Papirus, images render, progress
bars are styled, notifications gap and stack, and fullscreen windows are not
covered unless the message is critical. Volume up/down never notified at all;
they now show a stacking OSD with a progress bar.

Removed things that were broken or belonged to whoever this rice came from:
- vpn-launcher.sh (mullvad/openvpn) and dc-multivpn
- audio/bluetooth/network/power rofi menus, folded into the control centre
- untar-all, unzip-all, resetxdgportal (unreferenced)
- a sxhkd binding hardcoded to /home/sarthak/projects/scribe
- clipboard-manager.sh keyed off XDG_SESSION_TYPE, which is 'tty' here, so it
  only ever printed a Russian error; rewritten on greenclip
- toggle-bar.sh was bound to super+b but did not exist; written

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cn3dHfbgNYdbZvzb1b3GQt
This commit is contained in:
Sarthak 2026-09-04 00:48:26 +05:30
parent 6f41e344ac
commit b5a252c480
263 changed files with 645 additions and 16167 deletions

306
.config/scripts/control-center.sh Executable file
View file

@ -0,0 +1,306 @@
#!/usr/bin/env bash
# Sakura Line - control centre
#
# One centred panel for network, bluetooth, audio, vpn, session and desktop
# toggles. Submenus reuse the same window, so it reads as a single panel
# rather than a pile of separate menus.
set -uo pipefail
RASI="$HOME/.config/rofi/control.rasi"
menu() { # menu <prompt> [rofi args...]
local prompt="$1"; shift
rofi -dmenu -i -theme "$RASI" -p "$prompt" "$@"
}
notify() { notify-send -a "Control" "$@" >/dev/null 2>&1; }
have() { command -v "$1" >/dev/null 2>&1; }
# sxhkd inherits a bare PATH, so ~/.local/bin needs adding back by hand
export PATH="$HOME/.local/bin:$PATH"
# ------------------------------------------------------------------ status
wifi_status() {
have nmcli || { echo "unavailable"; return; }
if [ "$(nmcli -t -f WIFI radio 2>/dev/null)" != "enabled" ]; then echo "off"; return; fi
local eth ssid
eth=$(nmcli -t -f TYPE,STATE device status 2>/dev/null | grep -c '^ethernet:connected')
[ "$eth" -gt 0 ] && { echo "ethernet"; return; }
ssid=$(nmcli -t -f NAME,TYPE connection show --active 2>/dev/null | awk -F: '$2 ~ /wireless/ {print $1; exit}')
[ -n "$ssid" ] && echo "$ssid" || echo "on, not connected"
}
bt_status() {
have bluetoothctl || { echo "unavailable"; return; }
bluetoothctl show 2>/dev/null | grep -q "Powered: yes" || { echo "off"; return; }
local n
n=$(bluetoothctl devices Connected 2>/dev/null | grep -c '^Device')
[ "${n:-0}" -gt 0 ] && echo "$n connected" || echo "on"
}
vol_status() {
have wpctl || { echo "unavailable"; return; }
local out
out=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null) || { echo "unavailable"; return; }
grep -q MUTED <<<"$out" && { echo "muted"; return; }
awk '{printf "%d%%", $2*100}' <<<"$out"
}
mic_status() {
have wpctl || { echo "unavailable"; return; }
local out
out=$(wpctl get-volume @DEFAULT_AUDIO_SOURCE@ 2>/dev/null) || { echo "unavailable"; return; }
grep -q MUTED <<<"$out" && echo "muted" || awk '{printf "%d%%", $2*100}' <<<"$out"
}
vpn_status() {
local ifs
ifs=$(ip -br link show type wireguard 2>/dev/null | awk '{print $1}' | paste -sd, -)
[ -n "$ifs" ] && echo "$ifs" || echo "off"
}
dnd_status() {
have dunstctl || { echo "unavailable"; return; }
[ "$(dunstctl is-paused 2>/dev/null)" = true ] && echo "paused" || echo "on"
}
display_status() {
have xrandr || { echo "unavailable"; return; }
xrandr --current 2>/dev/null | awk '/\*/{print $1; exit}'
}
bar_status() { pgrep -x polybar >/dev/null 2>&1 && echo "shown" || echo "hidden"; }
particles_status() {
have particles || { echo "not installed"; return; }
particles --status 2>/dev/null | grep -q running && echo "on" || echo "off"
}
# ------------------------------------------------------------- submenus
wifi_menu() {
local radio choice ssid pass
radio=$(nmcli -t -f WIFI radio 2>/dev/null)
{
[ "$radio" = enabled ] && echo "󰖪 Turn Wi-Fi off" || echo "󰖩 Turn Wi-Fi on"
echo "󰑓 Rescan"
if [ "$radio" = enabled ]; then
nmcli -t -f IN-USE,SIGNAL,SECURITY,SSID device wifi list 2>/dev/null |
awk -F: 'length($4){
icon = ($1=="*") ? "󰸞" : (($3=="" || $3=="--") ? "󰖩" : "󰤪")
printf "%s %s\t%s%%\n", icon, $4, $2 }' | sort -u -k1,1
fi
} > /tmp/.cc-wifi.$$
choice=$(menu "Wi-Fi" < /tmp/.cc-wifi.$$); rm -f /tmp/.cc-wifi.$$
[ -z "$choice" ] && return
case "$choice" in
*"Turn Wi-Fi off") nmcli radio wifi off; notify "Wi-Fi" "Turned off" ;;
*"Turn Wi-Fi on") nmcli radio wifi on; notify "Wi-Fi" "Turned on" ;;
*Rescan) nmcli device wifi rescan >/dev/null 2>&1; notify "Wi-Fi" "Rescanning"; wifi_menu ;;
*) ssid=$(sed 's/^[^ ]* //; s/\t.*$//' <<<"$choice")
if nmcli -t -f NAME connection show 2>/dev/null | grep -qx "$ssid"; then
nmcli connection up id "$ssid" >/dev/null 2>&1 \
&& notify "Wi-Fi" "Connected to $ssid" || notify -u critical "Wi-Fi" "Failed: $ssid"
else
pass=$(menu "Password for $ssid" -password)
[ -z "$pass" ] && return
nmcli device wifi connect "$ssid" password "$pass" >/dev/null 2>&1 \
&& notify "Wi-Fi" "Connected to $ssid" || notify -u critical "Wi-Fi" "Failed: $ssid"
fi ;;
esac
}
bt_menu() {
local powered choice mac
powered=$(bluetoothctl show 2>/dev/null | grep -q "Powered: yes" && echo yes || echo no)
{
[ "$powered" = yes ] && echo "󰂲 Turn Bluetooth off" || echo "󰂯 Turn Bluetooth on"
if [ "$powered" = yes ]; then
echo "󰑓 Scan for devices"
bluetoothctl devices 2>/dev/null | while read -r _ mac name; do
if bluetoothctl info "$mac" 2>/dev/null | grep -q "Connected: yes"; then
printf "󰂱 %s\t%s\n" "$name" "$mac"
else
printf "󰂲 %s\t%s\n" "$name" "$mac"
fi
done
fi
} > /tmp/.cc-bt.$$
choice=$(menu "Bluetooth" < /tmp/.cc-bt.$$); rm -f /tmp/.cc-bt.$$
[ -z "$choice" ] && return
case "$choice" in
*"Turn Bluetooth off") bluetoothctl power off >/dev/null; notify "Bluetooth" "Turned off" ;;
*"Turn Bluetooth on") bluetoothctl power on >/dev/null; notify "Bluetooth" "Turned on" ;;
*"Scan for devices") notify "Bluetooth" "Scanning for 10s"
bluetoothctl --timeout 10 scan on >/dev/null 2>&1; bt_menu ;;
*) mac=$(awk -F'\t' '{print $2}' <<<"$choice")
[ -z "$mac" ] && return
if bluetoothctl info "$mac" 2>/dev/null | grep -q "Connected: yes"; then
bluetoothctl disconnect "$mac" >/dev/null && notify "Bluetooth" "Disconnected"
else
notify "Bluetooth" "Connecting..."
bluetoothctl connect "$mac" >/dev/null 2>&1 \
&& notify "Bluetooth" "Connected" || notify -u critical "Bluetooth" "Connection failed"
fi ;;
esac
}
audio_menu() {
local choice sink
{
echo "󰝟 Toggle mute $(vol_status)"
echo "󰝞 Volume down -5%"
echo "󰝝 Volume up +5%"
echo "󰍬 Toggle mic mute $(mic_status)"
pactl list short sinks 2>/dev/null | while read -r id name _; do
printf "󰓃 %s\t%s\n" "$(pactl list sinks 2>/dev/null | grep -A2 "Name: $name" | awk -F': ' '/Description/{print $2; exit}')" "$name"
done
} > /tmp/.cc-audio.$$
choice=$(menu "Audio" < /tmp/.cc-audio.$$); rm -f /tmp/.cc-audio.$$
[ -z "$choice" ] && return
case "$choice" in
*"Toggle mute") wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle; audio_menu ;;
*"Volume down"*) wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-; audio_menu ;;
*"Volume up"*) wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ -l 1.0; audio_menu ;;
*"Toggle mic mute") wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle; audio_menu ;;
*) sink=$(awk -F'\t' '{print $2}' <<<"$choice")
[ -n "$sink" ] && pactl set-default-sink "$sink" && notify "Audio" "Output switched" ;;
esac
}
vpn_menu() {
local choice iface up
{
for iface in $(ip -br link show type wireguard 2>/dev/null | awk '{print $1}'); do
printf "󰕥 %s\tdown\n" "$iface"
done
# wg-quick@<name> units systemd knows about, minus the ones already up
systemctl list-units --all --type=service --no-legend 'wg-quick@*' 2>/dev/null |
awk '{print $1}' | sed 's/^wg-quick@//; s/\.service$//' | while read -r n; do
[ -z "$n" ] && continue
ip link show "$n" >/dev/null 2>&1 || printf "󰖂 %s\tup\n" "$n"
done
} > /tmp/.cc-vpn.$$
if [ ! -s /tmp/.cc-vpn.$$ ]; then
echo "󰅚 No WireGuard interfaces found" > /tmp/.cc-vpn.$$
echo "󰐕 Start one by name…" >> /tmp/.cc-vpn.$$
fi
choice=$(menu "VPN" < /tmp/.cc-vpn.$$); rm -f /tmp/.cc-vpn.$$
[ -z "$choice" ] && return
case "$choice" in
*"No WireGuard"*) return ;;
*"Start one by name"*)
iface=$(menu "Interface name (e.g. wg0)")
[ -z "$iface" ] && return
systemctl start "wg-quick@${iface}" && notify "VPN" "$iface up" \
|| notify -u critical "VPN" "Could not start $iface" ;;
*) iface=$(sed 's/^[^ ]* //; s/\t.*$//' <<<"$choice")
up=$(awk -F'\t' '{print $2}' <<<"$choice")
if [ "$up" = down ]; then
systemctl stop "wg-quick@${iface}" && notify "VPN" "$iface down" \
|| notify -u critical "VPN" "Could not stop $iface"
else
systemctl start "wg-quick@${iface}" && notify "VPN" "$iface up" \
|| notify -u critical "VPN" "Could not start $iface"
fi ;;
esac
}
lock_screen() {
if have betterlockscreen; then betterlockscreen -l blur
elif have i3lock; then i3lock -c 0f0d17
elif have xsecurelock; then xsecurelock &
elif have slock; then slock
else notify -u critical "Lock" "No screen locker installed (try i3lock)"; return 1
fi
}
power_menu() {
local choice
choice=$(printf '%s\n' \
"󰌾 Lock" \
"󰍃 Log out" \
"󰒲 Suspend" \
"󰜉 Reboot" \
"󰐥 Shut down" | menu "Power")
case "$choice" in
*Lock) lock_screen ;;
*"Log out") bspc quit ;;
*Suspend) lock_screen; systemctl suspend ;;
*Reboot) systemctl reboot ;;
*"Shut down") systemctl poweroff ;;
esac
}
notif_menu() {
local choice paused
paused=$(dunstctl is-paused 2>/dev/null)
choice=$(printf '%s\n' \
"$([ "$paused" = true ] && echo "󰂚 Resume notifications" || echo "󰂛 Do not disturb")" \
"󰋚 Show last notification" \
"󰎟 Show all history" \
"󰆴 Clear all" | menu "Notifications")
case "$choice" in
*"Do not disturb") dunstctl set-paused true; notify "Notifications" "Paused" ;;
*"Resume notifications") dunstctl set-paused false; notify "Notifications" "Resumed" ;;
*"Show last notification") dunstctl history-pop ;;
*"Show all history") for _ in $(seq 6); do dunstctl history-pop; done ;;
*"Clear all") dunstctl close-all ;;
esac
}
display_menu() {
local out choice mode
out=$(xrandr --current 2>/dev/null | awk '/ connected/{print $1; exit}')
[ -z "$out" ] && { notify -u critical "Display" "No output found"; return; }
choice=$(xrandr --current 2>/dev/null | sed -n "/^$out connected/,/^[^ ]/p" |
awk '/^ /{printf "󰍹 %s\t%s\n", $1, $2}' | head -12 | menu "Display ($out)")
[ -z "$choice" ] && return
mode=$(sed 's/^[^ ]* //; s/\t.*$//' <<<"$choice")
xrandr --output "$out" --mode "$mode" && notify "Display" "$out set to $mode"
}
shot_menu() {
local choice
have flameshot || { notify -u critical "Screenshot" "flameshot is not installed"; return; }
choice=$(printf '%s\n' \
"󰩭 Region" \
"󰹑 Full screen" \
"󰆊 Region, delayed 3s" | menu "Screenshot")
case "$choice" in
*Region) flameshot gui ;;
*"Full screen") flameshot full -c -p "$HOME/pictures" 2>/dev/null || flameshot full -c ;;
*"delayed 3s") flameshot gui -d 3000 ;;
esac
}
# ---------------------------------------------------------------- main panel
main_menu() {
local choice
choice=$(printf '%s\n' \
"󰖩 Network $(wifi_status)" \
"󰂯 Bluetooth $(bt_status)" \
"󰕾 Audio $(vol_status)" \
"󰍬 Microphone $(mic_status)" \
"󰖂 VPN $(vpn_status)" \
"󰍺 Display $(display_status)" \
"󰂚 Notifications $(dnd_status)" \
"󰅍 Clipboard" \
"󰞅 Emoji" \
"󰹑 Screenshot" \
"󰸉 Wallpaper shuffle" \
"󰠹 Particles $(particles_status)" \
"󰍹 Bar $(bar_status)" \
"󰐥 Power" | menu "Control")
case "$choice" in
󰖩*) wifi_menu ;;
󰂯*) bt_menu ;;
󰕾*) audio_menu ;;
󰍬*) have wpctl && wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
notify "Microphone" "Now $(mic_status)" ;;
󰖂*) vpn_menu ;;
󰍺*) display_menu ;;
󰂚*) notif_menu ;;
󰅍*) sh "$HOME/.config/scripts/rofi-menus/clipboard-manager.sh" ;;
󰞅*) sh "$HOME/.config/scripts/rofi-menus/rofimoji.sh" ;;
󰹑*) shot_menu ;;
󰸉*) sh "$HOME/.config/scripts/set-wallpaper.sh" >/dev/null 2>&1
notify "Wallpaper" "Shuffled" ;;
󰠹*) if have particles; then particles >/dev/null 2>&1
notify "Particles" "Now $(particles_status)"
else notify -u critical "Particles" "Not installed"; fi ;;
󰍹*) sh "$HOME/.config/scripts/toggle-bar.sh" ;;
󰐥*) power_menu ;;
esac
}
main_menu