diff --git a/home/.config/eww/css/windows/_radio_menu.scss b/home/.config/eww/css/windows/_radio_menu.scss new file mode 100644 index 0000000..f22ffee --- /dev/null +++ b/home/.config/eww/css/windows/_radio_menu.scss @@ -0,0 +1,46 @@ +.radio-menu-box { + @include window; + background-color: $bg; + border: 1px solid $border; + color: $text; + font-family: "Jost *", "JetBrains Mono", "Font Awesome 6 Free", sans-serif; + + .icon, .icon label { + font-family: "Material Symbols Outlined"; + font-size: 1.15rem; + } + + .text-row { + margin: 1rem 1.5rem 0; + + .title { font-size: 1.2rem; } + } + + .element-row { + margin: .5rem .7rem; + + label { + font-size: 1rem; + margin: 0 .1rem; + } + } + + .element { + @include rounding; + background-color: $surface0; + margin: .3rem; + + button { + @include rounding; + padding: 1rem; + + label { + font-size: 1.5rem; + } + + &:hover { + background-color: $overlay0; + } + } + } +} diff --git a/home/.config/eww/eww.scss b/home/.config/eww/eww.scss index cbad062..db63e1a 100644 --- a/home/.config/eww/eww.scss +++ b/home/.config/eww/eww.scss @@ -17,6 +17,7 @@ } @import "css/windows/calendar"; +@import "css/windows/radio_menu"; @import "css/modules/clock"; @import "css/modules/volume"; @import "css/modules/bitcoin"; diff --git a/home/.config/eww/eww.yuck b/home/.config/eww/eww.yuck index 284a4d8..fd754a9 100644 --- a/home/.config/eww/eww.yuck +++ b/home/.config/eww/eww.yuck @@ -15,6 +15,7 @@ (include "./modules/gammarelay.yuck") (include "./windows/calendar.yuck") +(include "./windows/radio-menu.yuck") (defwidget sep [] (label :class "separ module" :text "|")) diff --git a/home/.config/eww/modules/variables.yuck b/home/.config/eww/modules/variables.yuck index 85d1683..c675528 100644 --- a/home/.config/eww/modules/variables.yuck +++ b/home/.config/eww/modules/variables.yuck @@ -49,3 +49,12 @@ (deflisten temperature `scripts/gammarelay temperature watch`) (deflisten brightness `scripts/gammarelay brightness watch`) (deflisten gamma `scripts/gammarelay gamma watch`) + +(defpoll net + :interval "3s" + :initial '{"essid":"N/A","icon":"󱛇","state":"unknown","signal":"0"}' + `scripts/net status`) +(defpoll bluetooth + :interval "3s" + :initial '{"icon":"󰂲","status":"unknown","name":"","mac":"","battery":""}' + `scripts/bluetooth status`) diff --git a/home/.config/eww/scripts/bluetooth b/home/.config/eww/scripts/bluetooth new file mode 100755 index 0000000..7b80ba4 --- /dev/null +++ b/home/.config/eww/scripts/bluetooth @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +ICON_IDLE="󰂯" +ICON_CONNECTED="󰂱" +ICON_OFF="󰂲" + +toggle() { + status=$(rfkill -J | jq -r '.rfkilldevices[] | select(.type == "bluetooth") | .soft' | head -1) + + if [ "$status" = "unblocked" ]; then + rfkill block bluetooth + else + rfkill unblock bluetooth + fi +} + +get_report() { + status=$(rfkill -J | jq -r '.rfkilldevices[] | select(.type == "bluetooth") | .soft' | head -1) + if [ "$status" = "blocked" ] || ! systemctl -q is-active bluetooth.service || ! command -v bluetoothctl >/dev/null 2>&1; then + jq -n -c --monochrome-output \ + --arg icon "$ICON_OFF" \ + --arg status "unknown" \ + --arg name "" \ + --arg mac "" \ + --arg battery "" \ + '$ARGS.named' + + return + fi + + status="$(bluetoothctl show)" + + powered="$(echo "$status" | grep Powered | cut -d' ' -f 2-)" + if [ "$powered" != "yes" ]; then + jq -n -c --monochrome-output \ + --arg icon "$ICON_OFF" \ + --arg status "unpowered" \ + --arg name "" \ + --arg mac "" \ + --arg battery "" \ + '$ARGS.named' + + return + fi + + status="$(bluetoothctl info)" + if [ "$status" == "Missing device address argument" ]; then + jq -n -c --monochrome-output \ + --arg icon "$ICON_IDLE" \ + --arg status "idle" \ + --arg name "" \ + --arg mac "" \ + --arg battery "" \ + '$ARGS.named' + + return + fi + + name="$(echo "$status" | grep Name | cut -d' ' -f 2-)" + mac="$(echo "$status" | head -1 | awk '{print $2}' | tr ':' '_')" + + if [ "$(echo "$status" | grep Percentage)" != "" ] && command -v upower >/dev/null 2>&1; then + battery="$(upower -i /org/freedesktop/UPower/devices/headset_dev_"$mac" | grep percentage | awk '{print $2}' | cut -f 1 -d '%')%" + else + battery="" + fi + + jq -n -c --monochrome-output \ + --arg icon "$ICON_CONNECTED" \ + --arg status "connected" \ + --arg name "$name" \ + --arg mac "$mac" \ + --arg battery "$battery" \ + '$ARGS.named' +} + +case "$1" in + "status") get_report ;; + "toggle") toggle ;; + *) >&2 echo "Invalid usage, argument '$1' not recognized."; exit 1 ;; +esac diff --git a/home/.config/eww/scripts/net b/home/.config/eww/scripts/net new file mode 100755 index 0000000..7d84697 --- /dev/null +++ b/home/.config/eww/scripts/net @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# shellcheck source=include +source "./scripts/include" + +STRENGTH_ICONS=("󰤫" "󰤯" "󰤟" "󰤢" "󰤥" "󰤨") +DISCONNECTED_ICON="󰤮" +WIFI_OFF="󰖪" + +toggle() { + status=$(rfkill -J | jq -r '.rfkilldevices[] | select(.type == "wlan") | .soft' | head -1) + + if [ "$status" = "unblocked" ]; then + rfkill block wlan + else + rfkill unblock wlan + fi +} + +get_report() { + connection_details="$(nmcli -t -f NAME,TYPE,DEVICE connection show --active | grep wireless | head -n1)" + essid="$(echo $connection_details | cut -d':' -f1)" + device="$(echo $connection_details | cut -d':' -f3)" + if [ -n "$device" ]; then + state="$(nmcli -t -f DEVICE,STATE device status | grep "$device" | head -n1 | cut -d':' -f2)" + signal="$(nmcli -t -f in-use,signal dev wifi | grep "\*" | cut -d':' -f2)" + else + state="unknown" + signal="0" + fi + + if [ "$state" = "disconnected" ] ; then + icon="$DISCONNECTED_ICON" + elif [ "$state" = "unknown" ]; then + icon="$WIFI_OFF" + else + icon="$(pick_icon "$signal" 0 100 "${STRENGTH_ICONS[@]}")" + fi + + jq -n -c --monochrome-output \ + --arg essid "$essid" \ + --arg icon "$icon" \ + --arg state "$state" \ + --arg signal "$signal" \ + '$ARGS.named' +} + +case "$1" in + "toggle") toggle ;; + "status") get_report ;; + *) >&2 echo "Invalid usage, argument '$1' not recognized."; exit 1 ;; +esac diff --git a/home/.config/eww/windows/radio-menu.yuck b/home/.config/eww/windows/radio-menu.yuck new file mode 100644 index 0000000..c072d65 --- /dev/null +++ b/home/.config/eww/windows/radio-menu.yuck @@ -0,0 +1,76 @@ +(defwidget radio-menu-win [] + (box + :class "radio-menu-box" + :space-evenly false + :orientation "v" + + (box + :class "text-row" + :space-evenly false + (label + :class "title" + :text "Radio/Connections Panel")) + + (box + :class "element-row" + + (box + :class "wifi-box" + :space-evenly false + :orientation "v" + (box + :class "element icon" + :space-evenly false + (button + :class "wifi-button" + :tooltip "${net.state} (strength: ${net.signal}%)" + :onclick "scripts/net toggle" + {net.icon}) + (label + :class "separator" + :text "│") + (button + :class "wifi-arrow-btn" + :onclick "eww close radio-menu && nm-connection-editor &" + "󰅂")) + (label + :text {net.essid} + :xalign 0.5 + :limit-width 15)) + + (box + :class "bluetooth-box" + :space-evenly false + :orientation "v" + (box + :class "element icon" + :space-evenly false + (button + :class "bluetooth-button" + :onclick "scripts/bluetooth toggle" + :tooltip "${bluetooth.name} (${bluetooth.mac}) ${bluetooth.battery}" + {bluetooth.icon}) + (label + :class "separator" + :text "│") + (button + :class "bluetooth-arrow-btn" + :onclick "eww close radio-menu && blueberry" + "󰅂")) + (label + :text {bluetooth.name} + :xalign 0.5 + :tooltip "${bluetooth.name} (${bluetooth.mac}) ${bluetooth.battery}" + :limit-width 15))) + )) + +(defwindow radio-menu + :stacking "fg" + :monitor 0 + :geometry (geometry + :x "0" + :y "0" + :width "0%" + :height "0%" + :anchor "right top") + (radio-menu-win))