Signed-off-by: Hadi <hadi@example.com>
This commit is contained in:
Hadi
2026-07-29 10:32:10 +02:00
parent a393b84c92
commit c37f3fc5e4
16 changed files with 517 additions and 55 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ in {
iw
hyprsunset
]
++ (with scripts; [vol-up vol-down vol-mute mic-mute bright-up bright-down nightshift-toggle focus-toggle waybar-toggle wifi-toggle bluetooth-toggle]);
++ (with scripts; [vol-up vol-down vol-mute mic-mute bright-up bright-down nightshift-toggle focus-toggle waybar-toggle wifi-toggle bluetooth-toggle dnd-toggle output-cycle input-cycle color-pick screenshot-edit record-toggle power-cycle airplane-toggle clipboard-menu emoji-picker caffeine-toggle mic-status]);
wayland.windowManager.hyprland.settings.exec-once = [
"waybar"
+264 -23
View File
@@ -31,35 +31,111 @@
OSD_TEXT="󰃠 $BRIGHT%"
fi
'';
# Résout $src : source par défaut, sinon première source disponible.
# Certaines machines n'ont pas de source audio par défaut (@DEFAULT_AUDIO_SOURCE@ non résolu).
micSource = ''
src=$(${pkgs.wireplumber}/bin/wpctl inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
if [ -z "$src" ]; then
src=$(${pkgs.pipewire}/bin/pw-dump | ${pkgs.jq}/bin/jq -r \
'[.[] | select(.info.props."media.class"=="Audio/Source") | .id] | .[0] // empty')
fi
'';
# tofi en mode dmenu vertical : la config globale est un lanceur horizontal de
# 36px de haut, inutilisable pour une liste. On surcharge la géométrie.
tofiMenu = "${pkgs.tofi}/bin/tofi --horizontal false --anchor center --width 700 --height 500 --margin-top 0 --margin-left 0 --margin-right 0 --num-results 10";
in {
bluetoothScript = pkgs.writeShellScript "waybar-bluetooth" ''
if bluetoothctl show 2>/dev/null | grep -q "Powered: yes"; then
device=$(bluetoothctl devices Connected 2>/dev/null | head -1 | cut -d' ' -f3-)
if [ -n "$device" ]; then
printf '{"text": "%s", "class": "connected", "tooltip": "Bluetooth\\n %s"}\n' "$device" "$device"
else
printf '{"text": "󰂰", "class": "on", "tooltip": "Bluetooth on"}\n'
fi
jq=${pkgs.jq}/bin/jq
nl=$'\n'
# bluetoothctl bloque sans contrôleur par défaut toujours borné par timeout.
bt() { timeout 3 ${pkgs.bluez}/bin/bluetoothctl "$@" 2>/dev/null; }
powered=$(bt show | awk '/Powered:/ { print $2; exit }')
if [ "$powered" != "yes" ]; then
"$jq" -cn '{ text: "󰂲", class: "off", tooltip: "Bluetooth off" }'
exit 0
fi
tip=""
add_tip() { tip="''${tip:+$tip$nl}$1"; }
count=0
for mac in $(bt devices Connected | awk '{ print $2 }'); do
count=$((count + 1))
info=$(bt info "$mac")
name=$(printf '%s' "$info" | sed -n 's/^[[:space:]]*Name: //p' | head -1)
[ -z "$name" ] && name="$mac"
batt=$(printf '%s' "$info" | sed -n 's/.*Battery Percentage:.*(\([0-9][0-9]*\)).*/\1/p' | head -1)
add_tip "󰂱 $name''${batt:+ · $batt%}"
done
if [ "$count" -gt 0 ]; then
"$jq" -cn --arg tooltip "$tip" '{ text: "󰂰", class: "connected", tooltip: $tooltip }'
else
printf '{"text": "󰂲", "class": "off", "tooltip": "Bluetooth off"}\n'
"$jq" -cn '{ text: "󰂰", class: "on", tooltip: "Bluetooth on" }'
fi
'';
networkScript = pkgs.writeShellScript "waybar-network" ''
for iface in $(${pkgs.iproute2}/bin/ip -br link show | awk '$2 == "UP" {print $1}' | grep -vE '^(lo|tun|proton|wg[0-9]|ppp|vpn|docker|br-|veth|virbr)'); do
ip=$(${pkgs.iproute2}/bin/ip addr show "$iface" 2>/dev/null | grep 'inet ' | awk '{print $2}' | cut -d/ -f1 | head -1)
if [ -n "$ip" ]; then
if [[ "$iface" == wl* ]]; then
ssid=$(${pkgs.iw}/bin/iw dev "$iface" link 2>/dev/null | grep SSID | sed 's/.*SSID: //')
signal=$(${pkgs.iw}/bin/iw dev "$iface" link 2>/dev/null | grep signal | awk '{print $2}')
printf '{"text": "󰤨", "class": "wifi", "tooltip": " %s\\n %s dBm"}\n' "$ssid" "$signal"
else
printf '{"text": "󰛳", "class": "ethernet", "tooltip": " %s\\n %s"}\n' "$iface" "$ip"
fi
exit 0
nmcli=${pkgs.networkmanager}/bin/nmcli
ip=${pkgs.iproute2}/bin/ip
jq=${pkgs.jq}/bin/jq
nl=$'\n'
text=""
tip=""
class="disconnected"
add_seg() { text="''${text:+$text }$1"; }
add_tip() { tip="''${tip:+$tip$nl}$1"; }
# Ethernet
eth=$("$nmcli" -t -f DEVICE,TYPE,STATE device status 2>/dev/null \
| awk -F: '$2 == "ethernet" && $3 == "connected" { print $1; exit }')
if [ -n "$eth" ]; then
eth_ip=$("$ip" -4 -br addr show "$eth" 2>/dev/null | awk '{ print $3 }' | cut -d/ -f1)
add_seg "󰛳"
class="ethernet"
add_tip "󰛳 Ethernet''${eth_ip:+ · $eth_ip}"
fi
# Wi-Fi
wifi=$("$nmcli" -t -f ACTIVE,SSID,SIGNAL device wifi 2>/dev/null | grep -m1 '^yes:')
if [ -n "$wifi" ]; then
ssid=$(printf '%s' "$wifi" | cut -d: -f2)
signal=$(printf '%s' "$wifi" | cut -d: -f3)
if [ "''${signal:-0}" -ge 80 ]; then icon="󰤨"
elif [ "''${signal:-0}" -ge 60 ]; then icon="󰤥"
elif [ "''${signal:-0}" -ge 40 ]; then icon="󰤢"
elif [ "''${signal:-0}" -ge 20 ]; then icon="󰤟"
else icon="󰤯"
fi
done
printf '{"text": "󰤭", "class": "disconnected", "tooltip": "Disconnected"}\n'
add_seg "$icon"
[ "$class" = "disconnected" ] && class="wifi"
add_tip "$icon ''${ssid:-Wi-Fi}''${signal:+ · $signal%}"
fi
# VPN (nmcli, fallback interfaces)
vpn=$("$nmcli" -t -f TYPE,NAME connection show --active 2>/dev/null \
| awk -F: '$1 == "vpn" || $1 == "wireguard" { print $2; exit }')
if [ -z "$vpn" ]; then
vpn=$("$ip" -br link show 2>/dev/null \
| awk '($2 == "UP" || $2 == "UNKNOWN") && $1 ~ /^(tun|wg|proton|ppp)/ { sub(/@.*/, "", $1); print $1; exit }')
fi
if [ -n "$vpn" ]; then
add_seg "󰦝"
add_tip "󰦝 VPN · $vpn"
fi
# Rien
if [ -z "$text" ]; then
text="󰤭"
tip="Disconnected"
fi
"$jq" -cn --arg text "$text" --arg class "$class" --arg tooltip "$tip" \
'{ text: $text, class: $class, tooltip: $tooltip }'
'';
vol-up = pkgs.writeShellScriptBin "vol-up" ''
@@ -81,8 +157,12 @@ in {
'';
mic-mute = pkgs.writeShellScriptBin "mic-mute" ''
${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_SOURCE@ toggle
if ${pkgs.wireplumber}/bin/wpctl get-volume @DEFAULT_SOURCE@ | grep -q MUTED; then
wpctl=${pkgs.wireplumber}/bin/wpctl
${micSource}
[ -z "$src" ] && exit 0
"$wpctl" set-mute "$src" toggle
if "$wpctl" get-volume "$src" | grep -q MUTED; then
OSD_TEXT="󰍭 Muted"
else
OSD_TEXT="󰍬 Live"
@@ -90,6 +170,15 @@ in {
${updateOsd}
'';
mic-status = pkgs.writeShellScriptBin "mic-status" ''
${micSource}
if [ -n "$src" ] && ${pkgs.wireplumber}/bin/wpctl get-volume "$src" | grep -q MUTED; then
echo true
else
echo false
fi
'';
bright-up = pkgs.writeShellScriptBin "bright-up" ''
${pkgs.brightnessctl}/bin/brightnessctl set 5%+
${brightGetText}
@@ -160,5 +249,157 @@ in {
fi
'';
dnd-toggle = pkgs.writeShellScriptBin "dnd-toggle" ''
state=$(${pkgs.swaynotificationcenter}/bin/swaync-client -d)
if [ "$state" = "true" ]; then
OSD_TEXT="󰂛 Do Not Disturb On"
else
OSD_TEXT="󰂚 Do Not Disturb Off"
fi
${updateOsd}
'';
output-cycle = pkgs.writeShellScriptBin "output-cycle" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
jq=${pkgs.jq}/bin/jq
pwdump=${pkgs.pipewire}/bin/pw-dump
# IDs des sinks dans l'ordre de pw-dump.
ids=($("$pwdump" | "$jq" -r '.[] | select(.info.props."media.class"=="Audio/Sink") | .id'))
n=''${#ids[@]}
[ "$n" -eq 0 ] && exit 0
cur=$("$wpctl" inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
next_index=0
for i in "''${!ids[@]}"; do
if [ "''${ids[$i]}" = "$cur" ]; then
next_index=$(( (i + 1) % n ))
break
fi
done
next=''${ids[$next_index]}
"$wpctl" set-default "$next"
desc=$("$pwdump" | "$jq" -r --argjson id "$next" '.[] | select(.id==$id) | .info.props."node.description"')
OSD_TEXT="󰓃 ''${desc:-Output}"
${updateOsd}
'';
input-cycle = pkgs.writeShellScriptBin "input-cycle" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
jq=${pkgs.jq}/bin/jq
pwdump=${pkgs.pipewire}/bin/pw-dump
# IDs des sources dans l'ordre de pw-dump.
ids=($("$pwdump" | "$jq" -r '.[] | select(.info.props."media.class"=="Audio/Source") | .id'))
n=''${#ids[@]}
[ "$n" -eq 0 ] && exit 0
cur=$("$wpctl" inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
next_index=0
for i in "''${!ids[@]}"; do
if [ "''${ids[$i]}" = "$cur" ]; then
next_index=$(( (i + 1) % n ))
break
fi
done
next=''${ids[$next_index]}
"$wpctl" set-default "$next"
desc=$("$pwdump" | "$jq" -r --argjson id "$next" '.[] | select(.id==$id) | .info.props."node.description"')
OSD_TEXT="󰍬 ''${desc:-Input}"
${updateOsd}
'';
color-pick = pkgs.writeShellScriptBin "color-pick" ''
# hyprpicker -a copie déjà la couleur dans le presse-papier.
color=$(${pkgs.hyprpicker}/bin/hyprpicker -a 2>/dev/null)
if [ -n "$color" ]; then
OSD_TEXT="󰈊 $color"
else
OSD_TEXT="󰈊 Cancelled"
fi
${updateOsd}
'';
screenshot-edit = pkgs.writeShellScriptBin "screenshot-edit" ''
${pkgs.hyprshot}/bin/hyprshot -m region --raw 2>/dev/null \
| ${pkgs.satty}/bin/satty --filename -
'';
record-toggle = pkgs.writeShellScriptBin "record-toggle" ''
if pgrep -x wf-recorder >/dev/null; then
# -INT laisse wf-recorder finaliser le fichier proprement.
pkill -INT -x wf-recorder
OSD_TEXT="󰕧 Recording saved"
else
dir="$HOME/Videos"
mkdir -p "$dir"
file="$dir/rec-$(date +%Y%m%d-%H%M%S).mp4"
${pkgs.wf-recorder}/bin/wf-recorder -f "$file" >/dev/null 2>&1 &
OSD_TEXT="󰑊 Recording"
fi
${updateOsd}
'';
power-cycle = pkgs.writeShellScriptBin "power-cycle" ''
ppd=${pkgs.power-profiles-daemon}/bin/powerprofilesctl
cur=$("$ppd" get)
case "$cur" in
power-saver) next=balanced; icon="󰾅" ;;
balanced) next=performance; icon="󰓅" ;;
performance) next=power-saver; icon="󰌪" ;;
*) next=balanced; icon="󰾅" ;;
esac
"$ppd" set "$next"
OSD_TEXT="$icon ''${next^}"
${updateOsd}
'';
airplane-toggle = pkgs.writeShellScriptBin "airplane-toggle" ''
# Réutilise nmcli + bluetoothctl (sans privilège) plutôt que rfkill.
on=false
nmcli radio wifi 2>/dev/null | grep -q enabled && on=true
bluetoothctl show 2>/dev/null | grep -q "Powered: yes" && on=true
if $on; then
nmcli radio wifi off 2>/dev/null
bluetoothctl power off >/dev/null 2>&1 || true
OSD_TEXT="󰀝 Airplane On"
else
nmcli radio wifi on 2>/dev/null
bluetoothctl power on >/dev/null 2>&1 || true
OSD_TEXT="󰀞 Airplane Off"
fi
${updateOsd}
'';
clipboard-menu = pkgs.writeShellScriptBin "clipboard-menu" ''
${pkgs.cliphist}/bin/cliphist list \
| ${tofiMenu} --prompt-text "Clipboard: " \
| ${pkgs.cliphist}/bin/cliphist decode \
| ${pkgs.wl-clipboard}/bin/wl-copy
'';
emoji-picker = pkgs.writeShellScriptBin "emoji-picker" ''
export PATH="${pkgs.wtype}/bin:${pkgs.wl-clipboard}/bin:$PATH"
export BEMOJI_PICKER_CMD="${tofiMenu} --prompt-text 'emoji: '"
# -t tape l'emoji (wtype), -c le copie aussi.
exec ${pkgs.bemoji}/bin/bemoji -t -c
'';
caffeine-toggle = pkgs.writeShellScriptBin "caffeine-toggle" ''
# Met hypridle en pause (reste éveillé) ou le réactive.
if systemctl --user is-active --quiet hypridle; then
systemctl --user stop hypridle
OSD_TEXT="󰅶 Keep Awake On"
else
systemctl --user start hypridle
OSD_TEXT="󰾫 Keep Awake Off"
fi
${updateOsd}
'';
# TODO: Run in background
}
+2 -1
View File
@@ -1,5 +1,6 @@
{
config,
pkgs,
networkScript,
bluetoothScript,
...
@@ -48,7 +49,7 @@ in {
"custom/bluetooth" = {
exec = "${bluetoothScript}";
exec-if = "bluetoothctl show 2>/dev/null | grep -q Controller";
exec-if = "${pkgs.bluez}/bin/bluetoothctl list 2>/dev/null | grep -q Controller";
return-type = "json";
interval = 5;
on-click-right = "blueman-manager &";