This commit is contained in:
soraefir
2026-06-13 19:21:33 +02:00
parent 6117dca845
commit aace131a0e
12 changed files with 374 additions and 244 deletions

View File

@@ -26,4 +26,6 @@ $border-radius: 8px;
$border-width: 2px; $border-width: 2px;
$gaps-screen: 8px; $gaps-screen: 8px;
$gaps-window: 4px; $gaps-window: 4px;
$panel-font-size: 10pt;

View File

@@ -1,66 +1,90 @@
.radio-win {
//margin: $gaps-screen; .radio-accent { background-color: $base0D; }
//padding: .5em;
// Now playing
.radio-now-playing {
margin-bottom: 8pt;
} }
.album_art, .station_art { .radio-art {
background-repeat: no-repeat; background-repeat: no-repeat;
@include border-radius; @include border-radius;
@include background-base2;
min-width: 72px;
min-height: 72px;
} }
.album_art { .radio-art-icon {
background-size: 240px; font-size: 2em;
min-height: 240px;
min-width: 240px;
margin: $gaps-screen;
}
.song {
@include color-accent;
font-size: 24px;
font-weight: bold;
margin: 20px 0 0;
}
.artist {
color: $base0E;
font-size: 16px;
font-weight: normal;
margin: 0 0 $gaps-screen;
}
.btn_bar {
@include color-body; @include color-body;
font-size: 20px; }
.radio-song {
font-size: 0.88em;
font-weight: bold; font-weight: bold;
margin: $gaps-screen 0; @include color-base;
margin-bottom: 2pt;
} }
.btn_play { .radio-artist {
font-size: 48px; font-size: 0.74em;
font-weight: bold; @include color-body;
margin: 0 12px;
&:hover { @include color-base; }
} }
.station_list { // Controls
border-right: $border-width solid $base03; .radio-controls {
margin-right: $gaps-screen; margin-top: 6pt;
} }
.station_art { .radio-ctrl-btn {
background-size: 50px; font-size: 2em;
min-height: 50px; padding: 4pt 20pt;
min-width: 50px; @include border-radius;
margin: $gaps-window; @include color-body;
margin-right: $gaps-screen; &:hover { @include background-active; @include color-base; }
@include background-base;
border: $border-width solid $base00;
&:hover { border-color: $base04; }
} }
.station_sel { // Station list
border-color: $base03; .station-list {}
scrollbar {
background-color: transparent;
border: none;
min-width: 6px;
}
scrollbar trough {
@include background-base2;
@include border-radius;
min-width: 6px;
}
scrollbar slider {
background-color: $base04;
@include border-radius;
min-width: 6px;
min-height: 20px;
&:hover { background-color: $base05; }
}
.station-row {
padding: 4pt 3pt;
@include border-radius;
&:hover { @include background-base2; }
}
.station-row-active {
.station-name { @include color-accent; }
}
.station-icon {
background-repeat: no-repeat;
@include border-radius;
@include background-base2;
min-width: 28px;
min-height: 28px;
margin-right: 8pt;
}
.station-name {
font-size: 0.76em;
@include color-body;
} }

View File

@@ -7,7 +7,7 @@
.cpubar, .gpubar, .membar, .batbar { @include background-base2; margin: $gaps-window 0; } .cpubar, .gpubar, .membar, .batbar { @include background-base2; margin: $gaps-window 0; }
// Window chrome // Window chrome
.sys-win { padding: 10pt; } .sys-win { padding: 10pt; font-size: $panel-font-size; }
.sys-section { margin-bottom: 0; } .sys-section { margin-bottom: 0; }
.sys-section-header { margin-bottom: 10pt; } .sys-section-header { margin-bottom: 10pt; }
@@ -48,7 +48,7 @@
.ram-ring { color: $base08; } .ram-ring { color: $base08; }
.swap-ring { color: $base09; } .swap-ring { color: $base09; }
// Ring margins freq rings use larger margins for concentric overlay effect // Ring margins - freq rings use larger margins for concentric overlay effect
.cpu-usage-ring, .gpu-ring { margin: 3pt; } .cpu-usage-ring, .gpu-ring { margin: 3pt; }
.ram-ring, .bat-ring { margin: 4pt; } .ram-ring, .bat-ring { margin: 4pt; }
.swap-ring { margin: 3.5pt; } .swap-ring { margin: 3.5pt; }

View File

@@ -41,7 +41,7 @@ make_content() {
usb_connected=true usb_connected=true
fi fi
# WiFi use IP presence as connection indicator (more reliable than wpa_cli) # WiFi - use IP presence as connection indicator (more reliable than wpa_cli)
local wifi_connected=false wifi_enabled=false wifi_icon="󰤮" wifi_ssid="" local wifi_connected=false wifi_enabled=false wifi_icon="󰤮" wifi_ssid=""
if ! rfkill list wlan 2>/dev/null | grep -q "Soft blocked: yes"; then if ! rfkill list wlan 2>/dev/null | grep -q "Soft blocked: yes"; then
wifi_enabled=true wifi_enabled=true

View File

@@ -1,12 +1,30 @@
#!/usr/bin/env bash #!/usr/bin/env bash
PANEL="$1" PANEL="$1"
CURRENT=$(eww state 2>/dev/null | grep '^active-panel:' | sed 's/^active-panel: //' | tr -d '"')
# Drop concurrent invocations, but recover from stale locks (dead processes)
LOCK="/tmp/eww_panel_toggle.lock"
if [ -f "$LOCK" ] && kill -0 "$(cat "$LOCK" 2>/dev/null)" 2>/dev/null; then
exit 0
fi
echo $$ > "$LOCK"
trap 'rm -f "$LOCK"' EXIT
CURRENT=$(eww get active-panel 2>/dev/null | tr -d '"')
open_popup() {
local screen
screen=$(hyprctl monitors -j 2>/dev/null | jq -r '.[] | select(.focused == true) | .name' | head -n1)
if [ -n "$screen" ]; then
eww open popup --screen "$screen"
else
eww open popup
fi
}
if [ "$CURRENT" = "$PANEL" ]; then if [ "$CURRENT" = "$PANEL" ]; then
eww close popup
eww update active-panel="" eww update active-panel=""
eww close popup 2>/dev/null
else else
eww update active-panel="$PANEL" eww update active-panel="$PANEL"
SCREEN=$(hyprctl monitors -j 2>/dev/null | jq -r '.[] | select(.focused == true) | .name' | head -n1) open_popup
[ -n "$SCREEN" ] && eww open popup --screen "$SCREEN" || eww open popup
fi fi

View File

@@ -1,106 +1,224 @@
#!/usr/bin/env bash #!/usr/bin/env bash
get_time_ms() {
date -u +%s%3N
}
URL_BASE="https://www.radiorecord.ru/api" URL_BASE="https://www.radiorecord.ru/api"
MPV_PID_FILE="/tmp/mpv_radio_pid" MPV_PID_FILE="/tmp/mpv_radio_pid"
RADIO_ID_FILE="/tmp/radio_id" RADIO_ID_FILE="/tmp/radio_id"
STATIONS="[]" STATION_IDS='[507,522,523,536,537,42532,42602]'
PID=$( [ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0 ) # Custom (non-radiorecord) stations
RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) # id must be a unique integer >= 1000000 to avoid collision with radiorecord IDs.
RADIO_URL="" # icon_fill_white: URL to station icon image, or "" for none.
INFO='{"id":null,"artist":null,"song":null,"image600":null}' CUSTOM_STATIONS='[
PAUSED=$(( $PID == 0 || $RADIO_ID == 0 ? 1 : 0 )) ]'
STATIONS="[]"
DEFAULT_INFO='{"artist":"","song":"","image600":""}'
DEFAULT_MEDIA='{"player":"","status":"Stopped","artist":"","title":"","art":""}'
PID=$([ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0)
RADIO_ID=$([ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0)
PAUSED=$(( PID == 0 ? 1 : 0 ))
INFO="$DEFAULT_INFO"
MEDIA="$DEFAULT_MEDIA"
STATUS="{}" STATUS="{}"
get_radio() { get_stations() {
echo "$STATIONS" | jq -r --argjson sel_id "$RADIO_ID" 'map(select(.id == $sel_id)).[0]' local rr
rr=$(curl -s --compressed "$URL_BASE/stations/" 2>/dev/null \
| jq --argjson ids "$STATION_IDS" \
'.result.stations | map(select(.id | IN($ids[]))) | map({id, title, stream_hls, icon_fill_white, "radiorecord": true})' 2>/dev/null)
jq -n \
--argjson rr "${rr:-[]}" \
--argjson custom "$CUSTOM_STATIONS" \
'$rr + ($custom | map(. + {"radiorecord": false}))'
} }
get_song() { get_song() {
echo $(curl -s "$URL_BASE/station/history/?id=$RADIO_ID" | jq '.result.history[0] | ({id, artist, song, image600})') curl -s --compressed "$URL_BASE/station/history/?id=$RADIO_ID" \
| jq '.result.history[0] | {artist, song, image600}'
} }
get_stream_url() {
update() { echo "$STATIONS" | jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].stream_hls // empty'
PID=$( [ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0 )
RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 )
PAUSED=$(( $PID == 0 && $RADIO_ID > 0 ? 1 : 0 ))
} }
start() { get_player_info() {
STATIONS=$(curl -s "$URL_BASE/stations/" | jq --argjson ids '[507,522,523,536,537,42532,42602]' '.result.stations | map(select(.id | IN($ids[]))) | map({id, title, stream_hls, icon_fill_white})') local player status artist title art
RADIO_URL=$(get_radio | jq -r '.stream_hls') # exclude mpv (radio) so it never appears as "external player"
if [ "$PAUSED" = 0 ]; then player=$(playerctl -l 2>/dev/null | grep -Ev '^mpv' | head -1)
kill -9 $PID if [ -z "$player" ]; then
echo '{"player":"","status":"Stopped","artist":"","title":"","art":""}'
return
fi fi
mpv "$RADIO_URL" & echo $! > "$MPV_PID_FILE" status=$(playerctl -p "$player" status 2>/dev/null || echo "Stopped")
echo $RADIO_ID > "$RADIO_ID_FILE" artist=$(playerctl -p "$player" metadata artist 2>/dev/null || echo "")
title=$(playerctl -p "$player" metadata title 2>/dev/null || echo "")
art=$(playerctl -p "$player" metadata mpris:artUrl 2>/dev/null || echo "")
jq -cnr --arg player "$player" --arg status "$status" \
--arg artist "$artist" --arg title "$title" --arg art "$art" \
'{player:$player, status:$status, artist:$artist, title:$title, art:$art}'
} }
update_state() {
PID=$([ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0)
RADIO_ID=$([ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0)
if [ "$PID" -gt 0 ] && ! kill -0 "$PID" 2>/dev/null; then
PID=0
rm -f "$MPV_PID_FILE"
fi
PAUSED=$(( PID == 0 ? 1 : 0 ))
}
toggle() { emit_status() {
if [ "$PAUSED" = 1 ]; then jq -cnr \
echo $RADIO_ID $PID --argjson stations "${STATIONS:-[]}" \
start --argjson radio_id "${RADIO_ID:-0}" \
--argjson is_paused "${PAUSED:-1}" \
--argjson info "${INFO:-$DEFAULT_INFO}" \
--argjson media "${MEDIA:-$DEFAULT_MEDIA}" \
'{"is_paused": $is_paused, "song": $info, "radio": $radio_id, "stations": $stations, "media": $media}'
}
get_mpv_node() {
wpctl status 2>/dev/null | awk '
/Streams:/ { in_s = 1 }
/Sinks:|Sources:|Clients:/ { in_s = 0 }
in_s && /[0-9]+\..*mpv/ { match($0, /[0-9]+/); print substr($0, RSTART, RLENGTH); exit }
'
}
get_volume() {
if [ "$PID" -gt 0 ] && kill -0 "$PID" 2>/dev/null; then
local node_id; node_id=$(get_mpv_node)
[ -n "$node_id" ] && wpctl get-volume "$node_id" 2>/dev/null \
| awk '{printf "%d", $2 * 100}'
else else
kill -9 "$PID" local player; player=$(playerctl -l 2>/dev/null | grep -Ev '^mpv' | head -1)
rm -f $MPV_PID_FILE [ -n "$player" ] && playerctl -p "$player" volume 2>/dev/null \
| awk '{printf "%d", $1 * 100}'
fi fi
} }
status() { do_vol() {
echo $(jq -cnr --argjson pid "$PID" --argjson stations "$STATIONS" --argjson radio_id "$RADIO_ID" --argjson is_paused "$PAUSED" --argjson info "$INFO" '{"is_paused": $is_paused, "song": $info, "radio": $radio_id, "stations": $stations}') local vol="${1%.*}"
if [ "$PID" -gt 0 ] && kill -0 "$PID" 2>/dev/null; then
local node_id; node_id=$(get_mpv_node)
[ -n "$node_id" ] && wpctl set-volume "$node_id" "${vol}%"
else
playerctl volume "$(awk -v v="$vol" 'BEGIN{printf "%.2f", v/100}')" 2>/dev/null
fi
eww update radio-vol="$vol"
} }
do_mute() {
if [ "$PID" -gt 0 ] && kill -0 "$PID" 2>/dev/null; then
local node_id; node_id=$(get_mpv_node)
if [ -n "$node_id" ]; then
wpctl set-mute "$node_id" toggle
if wpctl get-volume "$node_id" 2>/dev/null | grep -q MUTED; then
eww update radio-muted=true
else
eww update radio-muted=false
fi
fi
else
wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
if wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null | grep -q MUTED; then
eww update radio-muted=true
else
eww update radio-muted=false
fi
fi
}
do_start() {
[ "$RADIO_ID" -le 0 ] && return
STATIONS=$(get_stations)
RADIO_URL=$(get_stream_url)
[ -z "$RADIO_URL" ] || [ "$RADIO_URL" = "null" ] && return
[ "$PID" -gt 0 ] && kill "$PID" 2>/dev/null
nohup mpv --no-video --quiet "$RADIO_URL" >/dev/null 2>&1 &
echo $! > "$MPV_PID_FILE"
echo "$RADIO_ID" > "$RADIO_ID_FILE"
}
status_loop() { status_loop() {
STATUS=$(status) STATIONS=$(get_stations)
echo $STATUS echo "$(emit_status)"
STATIONS=$(curl -s "$URL_BASE/stations/" | jq --argjson ids '[507,522,523,536,537,42532,42602]' '.result.stations | map(select(.id | IN($ids[]))) | map({id, title, stream_hls, icon_fill_white})')
last_time_info=0 last_pid_check=0
last_time=0 last_song_fetch=0
last_media_fetch=0
while true; do while true; do
current_time=$(get_time_ms) now=$(date -u +%s%3N)
delta=$((current_time - last_time))
delta_i=$((current_time - last_time_info)) if (( now - last_pid_check > 1000 )); then
if [[ $delta -gt 1000 ]]; then update_state
PID=$( [ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0 ) NEW_STATUS=$(emit_status)
RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) if [ "$NEW_STATUS" != "$STATUS" ]; then STATUS=$NEW_STATUS; echo "$STATUS"; fi
PAUSED=$(( $PID == 0 && $RADIO_ID > 0 ? 1 : 0 )) last_pid_check=$now
NEW_STATUS=$(status)
if [[ "$NEW_STATUS" != "$STATUS" ]]; then
STATUS=$NEW_STATUS
echo $STATUS
fi
last_time=$current_time
fi fi
if [[ $delta_i -gt 15000 ]]; then
if [ "$PAUSED" = 1 ]; then if (( now - last_song_fetch > 15000 )); then
INFO="{\"id\":null,\"artist\":null,\"song\":null,\"image600\": \"$(get_radio | jq -r '.icon_fill_white')\"}" if [ "$PAUSED" = 0 ]; then
IS_RR=$(echo "$STATIONS" | jq --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].radiorecord // true')
if [ "$IS_RR" = "true" ]; then
FETCHED=$(get_song)
INFO=$(echo "$INFO" "$FETCHED" | jq -s '
reduce .[] as $x ({}; . + ($x | with_entries(select(.value != null))))')
else
STATION_TITLE=$(echo "$STATIONS" | jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].title // ""')
INFO=$(jq -cnr --arg title "$STATION_TITLE" '{artist:"",song:$title,image600:""}')
fi
else else
INFO=$(echo "$INFO" "$(get_song)" | jq -s ' reduce .[] as $item ( {}; . + ( STATION_IMG=$(echo "$STATIONS" \
reduce ($item | to_entries[]) as $entry ( {}; if $entry.value != null then .[$entry.key] = $entry.value else . end | jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].icon_fill_white // ""')
)) )') STATION_TITLE=$(echo "$STATIONS" \
| jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].title // ""')
INFO=$(jq -cnr --arg img "$STATION_IMG" --arg title "$STATION_TITLE" \
'{artist:"",song:$title,image600:$img}')
fi fi
last_time_info=$current_time NEW_STATUS=$(emit_status)
if [ "$NEW_STATUS" != "$STATUS" ]; then STATUS=$NEW_STATUS; echo "$STATUS"; fi
last_song_fetch=$now
fi fi
if (( now - last_media_fetch > 3000 )); then
MEDIA=$(get_player_info)
NEW_STATUS=$(emit_status)
if [ "$NEW_STATUS" != "$STATUS" ]; then STATUS=$NEW_STATUS; echo "$STATUS"; fi
VOL=$(get_volume)
[ -n "$VOL" ] && eww update radio-vol="$VOL" 2>/dev/null
last_media_fetch=$now
fi
sleep 0.5
done done
} }
# Main script
case "$1" in case "$1" in
"start") start)
RADIO_ID=$2 RADIO_ID="$2"
start echo "$RADIO_ID" > "$RADIO_ID_FILE"
do_start
;; ;;
"toggle") vol)
toggle do_vol "$2"
;;
mute)
update_state
do_mute
;;
toggle)
update_state
if [ "$PAUSED" = 1 ]; then
[ "$RADIO_ID" -gt 0 ] && do_start
else
[ "$PID" -gt 0 ] && kill "$PID" 2>/dev/null
rm -f "$MPV_PID_FILE"
fi
;; ;;
*) *)
status_loop status_loop

View File

@@ -82,23 +82,15 @@
(defwidget quick-section [] (defwidget quick-section []
(box :orientation "v" :space-evenly false :class "sys-section" (box :orientation "v" :space-evenly false :class "sys-section"
(section-header :title "Quick Actions" :accent "quick-accent") (section-header :title "Quick Actions" :accent "quick-accent")
(box :orientation "h" :homogeneous true :class "quick-grid" (box :orientation "v" :space-evenly false :class "quick-grid" :spacing 4
(quick-btn (box :orientation "h" :space-evenly true
:icon "󰸉" :label "Wallpaper" (quick-btn :icon "󰸉" :label "Wallpaper" :onclick "scripts/wallpaper" :active false)
:onclick "scripts/wallpaper" (quick-btn :icon "󱐋" :label "Power Save" :onclick "eww update power-save=$(scripts/power-save)" :active {power-save})
:active false) (quick-btn :icon "󰌵" :label "Night Light" :onclick "eww update night-light=$(scripts/nightlight)" :active {night-light}))
(quick-btn (box :orientation "h" :space-evenly true
:icon "󱐋" :label "Power Save" (quick-btn :icon "󰹑" :label "Screenshot" :onclick "scripts/screenshot" :active false)
:onclick "eww update power-save=$(scripts/power-save)" (quick-btn :icon "󰌾" :label "Lock" :onclick "swaylock" :active false)
:active {power-save}) (quick-btn :icon "󱉨" :label "Color Pick" :onclick "hyprpicker -a" :active false)))))
(quick-btn
:icon "󰌵" :label "Night Light"
:onclick "eww update night-light=$(scripts/nightlight)"
:active {night-light})
(quick-btn
:icon "󰹑" :label "Screenshot"
:onclick "scripts/screenshot"
:active false))))
; --- Brightness --- ; --- Brightness ---

View File

@@ -6,7 +6,9 @@
(revealer :reveal {active-panel == "net"} :transition "slidedown" :duration 120 (revealer :reveal {active-panel == "net"} :transition "slidedown" :duration 120
(net-win)) (net-win))
(revealer :reveal {active-panel == "clock"} :transition "slidedown" :duration 120 (revealer :reveal {active-panel == "clock"} :transition "slidedown" :duration 120
(clock-win)))) (clock-win))
(revealer :reveal {active-panel == "radio"} :transition "slidedown" :duration 120
(radio-win))))
(defwindow popup (defwindow popup
:monitor 0 :monitor 0

View File

@@ -1,111 +1,82 @@
(deflisten radio :initial '{"is_paused":1,"song":{"artist":"","song":"","image600":"https://www.radiorecord.ru/upload/stations_images/record_image600_white_fill.png"},"stations":[]}' "scripts/radio")
(defvar radio_rev false)
(defwindow radio (deflisten radio
:monitor 0 :initial '{"is_paused":1,"song":{"artist":"","song":"","image600":""},"radio":0,"stations":[],"media":{"player":"","status":"Stopped","artist":"","title":"","art":""}}'
:geometry (geometry "scripts/radio")
:x "0%" (defvar radio-vol 80)
:y "0%" (defvar radio-muted false)
:anchor "bottom right"
:width "0px"
:height "0px")
(window (radio-win)))
(defwidget radio-win []
(box :class "sys-win" :orientation "v" :space-evenly false
(defwidget radio-win [] ; --- Now Playing ---
(box (box :orientation "v" :space-evenly false :class "sys-section"
:space-evenly false (section-header :title "Media" :accent "radio-accent")
:orientation "h" (box :orientation "h" :space-evenly false :valign "center" :spacing 10 :class "radio-now-playing"
(revealer (box :class "radio-art"
:visible radio_rev :style "background-image: url('${radio.is_paused == 0 ? radio.song.image600 : (radio.media.status != 'Stopped' ? radio.media.art : radio.song.image600)}'); background-size: cover; background-position: center;"
:reveal radio_rev (label :class "radio-art-icon" :halign "center" :valign "center"
:transition "slideleft" :visible {radio.is_paused == 0
(radio-selector)) ? radio.song.image600 == ""
(box : (radio.media.status != "Stopped"
:space-evenly false ? radio.media.art == ""
:orientation "v" : radio.song.image600 == "")}
:text "󰝚"))
(box :orientation "v" :space-evenly false :hexpand true :valign "center"
(label :class "radio-song" :halign "start" :wrap true :limit-width 20
:text {radio.is_paused == 0
? (radio.song.song != "" ? radio.song.song : "Tuning in...")
: (radio.media.status != "Stopped"
? (radio.media.title != "" ? radio.media.title : "Playing")
: (radio.song.song != "" ? radio.song.song : "Nothing playing"))})
(label :class "radio-artist" :halign "start" :wrap true :limit-width 22
:text {radio.is_paused == 0
? radio.song.artist
: (radio.media.status != "Stopped"
? (radio.media.artist != "" ? radio.media.artist : radio.media.player)
: "")})))
(box ; Controls - hidden only in placeholder state
:class "album_art" (box :visible {radio.is_paused == 0 || radio.radio > 0 || radio.media.status != "Stopped"}
:style "background-size:cover; background-image: url('${radio.song.image600?:'https://www.radiorecord.ru/upload/stations_images/record_image600_white_fill.png'}');") :orientation "v" :space-evenly false :class "radio-controls"
(box (box :orientation "h" :space-evenly true :halign "center"
:space-evenly false (button :visible {radio.is_paused == 1 && radio.media.status != "Stopped"}
:orientation "v" :class "radio-ctrl-btn" :timeout "2s" :onclick "playerctl previous"
(label (label :text "󰒮"))
:halign "center" (button :class "radio-ctrl-btn" :timeout "2s"
:class "song" :onclick {radio.is_paused == 1 && radio.media.status != "Stopped" ? "playerctl play-pause" : "scripts/radio toggle"}
:wrap "true" (label :text {radio.is_paused == 0 ? "󰏥" : (radio.media.status == "Playing" ? "󰏥" : "󰐌")}))
:limit-width 18 (button :visible {radio.is_paused == 1 && radio.media.status != "Stopped"}
:text "${radio.song.song?:'...'}") :class "radio-ctrl-btn" :timeout "2s" :onclick "playerctl next"
(label (label :text "󰒭")))
:halign "center" (vol-row
:class "artist" :icon "󰕾"
:wrap "true" :value {radio-vol}
:limit-width 22 :onchange "scripts/radio vol {}"
:text "${radio.song.artist?:'...'}") :onclick "scripts/radio mute"
(box :muted {radio-muted})))
:space-evenly true
:orientation "h"
:halign "center"
:class "btn_bar"
(button (box :class "section-sep")
:class "btn_left"
:onclick "${EWW_CMD} update radio_rev=${!radio_rev}"
(box "󰷐"))
(button ; --- Stations ---
:class "btn_play" (box :orientation "v" :space-evenly false :class "sys-section"
:timeout "2s" (section-header :title "Radio Stations" :accent "radio-accent")
:onclick "scripts/radio toggle" (scroll :vscroll true :hscroll false :height 130
"${radio.is_paused==1 ? "󰐌" : "󰏥"}") (box :class "station-list" :space-evenly false :orientation "v"
(for station in {radio.stations}
(button
:class "btn_right"
:onclick ""
(box :visible false "󰔶"))
)
)
)
)
)
(defwidget radio-selector []
(scroll
:active true
:vscroll true
:hscroll false
(box
:class "station_list"
:space-evenly false
:orientation "v"
(for station in {radio.stations}
(button (button
:class "station_art ${(radio.radio == station.id)?'station_sel':''}" :class "station-row ${radio.radio == station.id ? 'station-row-active' : ''}"
:timeout "2s" :timeout "2s"
:onclick "scripts/radio start ${station.id}" :onclick "scripts/radio start ${station.id}"
:tooltip "${station.title}" :tooltip {station.title}
:style "background-size:cover; background-image: url('${station.icon_fill_white}');" (box :orientation "h" :space-evenly false :valign "center"
) (box :class "station-icon"
) :style "background-image: url('${station.icon_fill_white}'); background-size: contain; background-position: center;")
) (label :class "station-name" :text {station.title}
) :hexpand true :halign "start" :limit-width 16)))))))))
)
(defwidget radio-mod [] (defwidget radio-mod []
(module (module
(box (eventbox
:orientation "v" :onclick "(sleep 0.1 && scripts/panel-toggle radio)"
(button (box :orientation "v"
:onclick "(sleep 0.1 && eww-open-on-current-screen radio --toggle --no-daemonize)" (label :show-truncated false :class "icon-text" :text "󰝚")))))
(label
:show-truncated false
:class "icon-text"
:text "󰝚")
)
)
)
)

View File

@@ -69,7 +69,7 @@
(box :orientation "v" :space-evenly false :class "sys-section" (box :orientation "v" :space-evenly false :class "sys-section"
(section-header :title "GPU" :accent "gpu-accent") (section-header :title "GPU" :accent "gpu-accent")
(box :orientation "h" :space-evenly true (box :orientation "h" :space-evenly true
; GFX outer: activity%, inner: clock% of range ; GFX - outer: activity%, inner: clock% of range
(box :orientation "v" :space-evenly false :halign "center" (box :orientation "v" :space-evenly false :halign "center"
(overlay (overlay
(circular-progress :width 68 :height 68 (circular-progress :width 68 :height 68
@@ -84,7 +84,7 @@
(box :halign "center" :valign "center" (box :halign "center" :valign "center"
(label :class "gpu-ring-value" :text "${round(gpu.gfx_pct, 0)}%"))) (label :class "gpu-ring-value" :text "${round(gpu.gfx_pct, 0)}%")))
(label :class "gpu-ring-label" :text "GFX" :halign "center")) (label :class "gpu-ring-label" :text "GFX" :halign "center"))
; Memory outer: activity%, inner: memory clock% of range ; Memory - outer: activity%, inner: memory clock% of range
(box :orientation "v" :space-evenly false :halign "center" (box :orientation "v" :space-evenly false :halign "center"
(overlay (overlay
(circular-progress :width 68 :height 68 (circular-progress :width 68 :height 68
@@ -99,7 +99,7 @@
(box :halign "center" :valign "center" (box :halign "center" :valign "center"
(label :class "gpu-ring-value" :text "${round(gpu.mem_pct, 0)}%"))) (label :class "gpu-ring-value" :text "${round(gpu.mem_pct, 0)}%")))
(label :class "gpu-ring-label" :text "Mem" :halign "center")) (label :class "gpu-ring-label" :text "Mem" :halign "center"))
; Media outer: activity%, inner: video clock% of GPU clock max ; Media - outer: activity%, inner: video clock% of GPU clock max
(box :orientation "v" :space-evenly false :halign "center" (box :orientation "v" :space-evenly false :halign "center"
(overlay (overlay
(circular-progress :width 68 :height 68 (circular-progress :width 68 :height 68

View File

@@ -59,6 +59,8 @@ in {
$gaps-screen: ${config.colorScheme.palette.gaps-screen}px; $gaps-screen: ${config.colorScheme.palette.gaps-screen}px;
$gaps-window: ${config.colorScheme.palette.gaps-window}px; $gaps-window: ${config.colorScheme.palette.gaps-window}px;
$panel-font-size: 10pt;
''; '';
}; };
} }

View File

@@ -35,6 +35,7 @@ in {
brightnessctl brightnessctl
awww awww
playerctl
]; ];
xdg.mimeApps = { xdg.mimeApps = {