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:
parent
6f41e344ac
commit
b5a252c480
263 changed files with 645 additions and 16167 deletions
306
.config/scripts/control-center.sh
Executable file
306
.config/scripts/control-center.sh
Executable 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue