Compare commits

..

7 Commits

Author SHA1 Message Date
soraefir 0a3fef0b1c scaling 2026-06-13 22:15:53 +02:00
soraefir aace131a0e Radio 2026-06-13 22:01:58 +02:00
soraefir 6117dca845 add quick actions tab 2026-06-13 17:06:21 +02:00
soraefir 43a074f355 Weather&Audio 2026-06-13 12:19:46 +02:00
soraefir 58af37ea8c Single panel mode 2026-06-13 11:22:51 +02:00
soraefir da76e6c12a CSS cleanup 2026-06-13 10:56:25 +02:00
soraefir ce804942a9 radio-win 2026-06-13 01:26:40 +02:00
38 changed files with 1086 additions and 565 deletions
-14
View File
@@ -1,14 +0,0 @@
{
"permissions": {
"allow": [
"WebFetch(domain:elkowar.github.io)",
"WebFetch(domain:github.com)",
"WebFetch(domain:raw.githubusercontent.com)",
"WebSearch",
"WebFetch(domain:deepwiki.com)",
"Bash(amdgpu_top -J -s 1000 -d 1)",
"Bash(amdgpu_top -J -s 1000 -n 1)",
"Bash(sensors -j)"
]
}
}
@@ -1,48 +1,108 @@
.calendar-win {
}
calendar { calendar {
padding: 5pt; padding: $popup-scale * 1.75pt $popup-scale * 1pt;
font-size: $popup-scale * 8pt;
:selected { header {
color: $base0C; padding: $popup-scale * 2pt 0;
@include color-body;
} }
.header { :selected { @include color-accent; }
color: $base05; .highlight { @include color-accent; font-weight: bold; }
} :indeterminate { color: $base03; }
.highlight {
color: $base0C;
font-weight: bold;
}
label {
font-size: 20pt;
color: $base0C;
}
:indeterminate {
color: $base03;
}
} }
.cal-box .sys-section-header { margin-bottom: $popup-scale * 4pt; }
.hour, .month { .hour, .month {
font-weight: bolder; font-weight: bolder;
} }
.minute, .month { .minute, .month {
margin-top: -4pt; margin-top: $popup-scale * -4pt;
} }
.date { .date {
color: $base0C; @include color-accent;
background-color: $base01; @include background-base;
border-radius: $border-radius; @include border-radius;
} }
.datetime { .datetime {
padding: $gaps-window; padding: $gaps-window;
} }
// Clock window accents
.weather-accent { background-color: $base0A; }
.cal-accent { background-color: $base0B; }
.bri-accent { background-color: $base09; }
.vol-accent { background-color: $base0D; }
.quick-accent { background-color: $base0E; }
// Quick actions
.quick-grid { margin-top: $popup-scale * 2pt; }
.quick-btn {
@include background-base2;
@include border-radius;
padding: $popup-scale * 8pt $popup-scale * 4pt;
margin: $popup-scale * 4px;
min-width: 0;
min-height: 0;
border: none;
&:hover {
@include background-active;
.quick-icon, .quick-label {color: $base01;}
}
}
.quick-btn-active {
.quick-icon { @include color-accent; }
.quick-label { @include color-accent; }
}
.quick-icon { font-size: 1.5em; @include color-body; }
.quick-label { font-size: 0.68em; margin-top: $popup-scale * 3pt; @include color-body; }
// Weather section
.weather-main { margin-bottom: $popup-scale * 8pt; }
.weather-icon { font-size: 2.2em; margin-right: $popup-scale * 12pt; @include color-accent; }
.weather-temp { font-size: 1.3em; font-weight: bold; @include color-base; }
.weather-desc { font-size: 0.78em; @include color-body; }
.weather-stats { margin-top: $popup-scale * 4pt; }
// Volume section
.ctrl-row { margin-bottom: $popup-scale * 4pt; }
.ctrl-icon { font-size: 1.1em; min-width: $popup-scale * 22pt; @include border-radius; @include color-body; }
.ctrl-icon:hover { @include background-active; }
.ctrl-muted { @include color-inactive; }
.ctrl-value { font-size: 0.72em; min-width: $popup-scale * 28pt; @include color-active; }
scale.ctrl-slider.ctrl-slider-muted {
trough {
highlight { background-color: $base03; }
slider { background-color: $base03; }
}
}
scale.ctrl-slider {
padding: $popup-scale * 2pt $popup-scale * 4pt;
trough {
@include border-radius;
@include background-base2;
min-height: 5px;
highlight { background-color: $base0C; @include border-radius; }
}
slider {
background-color: $base07;
min-height: 11px;
min-width: 11px;
@include border-radius;
margin: -3px;
border: none;
}
}
@@ -27,3 +27,6 @@ $border-width: 2px;
$gaps-screen: 8px; $gaps-screen: 8px;
$gaps-window: 4px; $gaps-window: 4px;
$panel-font-size: 10pt;
$popup-scale: 1;
+26 -14
View File
@@ -1,24 +1,36 @@
// Bar icons // Bar icons
.net-icon { font-size: 14px; padding: 3pt 0; } .net-icon { font-size: 14px; padding: 3pt 0; }
.net-active { color: $base07; } .net-active, .blt-on { @include color-base; }
.net-dim { color: $base02; } .net-dim { @include color-inactive; }
.blt-on { color: $base07; } .blt-connected { @include color-accent; }
.blt-connected { color: $base0D; }
// Popup window section accents // Popup window section accents
.wifi-accent { background-color: $base0C; } .wifi-accent { background-color: $base0C; }
.eth-accent { background-color: $base0B; } .eth-accent { background-color: $base0B; }
.blt-accent { background-color: $base0D; } .blt-accent { background-color: $base0D; }
.usb-accent { background-color: $base09; }
// Netinfo rows // Netinfo rows
.netinfo-row { margin-bottom: 3pt; } .netinfo-row { margin-bottom: $popup-scale * 3pt; }
.netinfo-label { font-size: 0.72em; color: $base04; min-width: 60px; } .netinfo-label, .netinfo-value, .netinfo-dim { font-size: 0.72em; }
.netinfo-value { font-size: 0.72em; color: $base05; } .netinfo-label { @include color-active; min-width: $popup-scale * 60px; }
.netinfo-dim { font-size: 0.72em; color: $base03; margin-bottom: 4pt; } .netinfo-value { @include color-body; }
.netinfo-dim { color: $base03; margin-bottom: $popup-scale * 4pt; }
// Section toggle button
.net-toggle-btn {
padding: $popup-scale * 2pt $popup-scale * 4pt;
@include border-radius;
font-size: 1.1em;
}
// Bluetooth device list // Bluetooth device list
.bt-device-row { margin-bottom: 4pt; } .bt-device-row { margin-bottom: $popup-scale * 4pt; }
.bt-device-name { font-size: 0.78em; color: $base05; } .bt-device-name { font-size: 0.78em; @include color-body; }
.bt-device-btn { padding: 2pt 6pt; border-radius: $border-radius; font-size: 1em; } .bt-device-btn { padding: $popup-scale * 2pt $popup-scale * 6pt; @include border-radius; font-size: 1em; }
.bt-btn-on { color: $base0D; }
.bt-btn-off { color: $base03; } // Shared button states
.net-toggle-btn:hover,
.bt-device-btn:hover { @include background-active; }
.net-toggle-on, .bt-btn-on { @include color-base; }
.net-toggle-off, .bt-btn-off { @include color-inactive; }
@@ -1,26 +1,21 @@
.powermenu-box { .powermenu-box {
padding-left: 2.5rem; padding: 3rem 2.5rem;
padding-right: 2.5rem; margin: 0;
padding-top: 3rem;
padding-bottom: 3rem;
margin:0 0 0 0;
}
.powermenu-entry { .powermenu-entry {
margin: 0 0.5rem; margin: 0 0.5rem;
}
.powermenu-button { .powermenu-button {
background-color: $base02; @include background-active;
border-radius: 1rem; border-radius: 1rem;
transition: 0.3s; transition: 0.3s;
padding: 3.25rem 4rem; padding: 3.25rem 4rem;
}
.powermenu-button:hover { &:hover { background-color: $base03; }
background-color:$base03; }
} }
.powermenu-icon { .powermenu-icon {
font-size: 4rem; font-size: 4rem;
}
} }
@@ -1,75 +1,90 @@
.radio-win { .radio-accent { background-color: $base0D; }
//margin: $gaps-screen;
//padding: .5em;
}
.album_art { // Now playing
background-repeat: no-repeat; .radio-now-playing {
background-size: 240px; margin-bottom: $popup-scale * 8pt;
min-height: 240px;
min-width: 240px;
margin: $gaps-screen;
border-radius: $border-radius;
} }
.song { .radio-art {
color: $base0C; background-repeat: no-repeat;
font-size: 24px; @include border-radius;
font-weight: bold; @include background-base2;
margin: 20px 0px 0px 0px; min-width: $popup-scale * 72px;
min-height: $popup-scale * 72px;
} }
.artist { .radio-art-icon {
color: $base0E; font-size: 2em;
font-size: 16px; @include color-body;
font-weight: normal;
margin: 0px 0px $gaps-screen 0px;
} }
.btn_bar { .radio-song {
color: $base05; font-size: 0.88em;
font-size: 20px; font-weight: bold;
font-weight: bold; @include color-base;
margin: $gaps-screen 0px; margin-bottom: $popup-scale * 2pt;
} }
.btn_play { .radio-artist {
font-size: 48px; font-size: 0.74em;
font-weight: bold; @include color-body;
margin: 0 12px;
} }
.btn_play:hover { // Controls
color: $base07; .radio-controls {
margin-top: $popup-scale * 6pt;
} }
.radio-ctrl-btn {
.station_list { font-size: 2em;
border-right-color: $base03; padding: $popup-scale * 4pt $popup-scale * 20pt;
border-right-style: solid; @include border-radius;
border-right-width: $border-width; @include color-body;
margin-right: $gaps-screen; &:hover { @include background-active; @include color-base; }
} }
.station_art { // Station list
background-repeat: no-repeat; .station-list {}
background-size: 50px;
min-height: 50px; scrollbar {
min-width: 50px; background-color: transparent;
margin: $gaps-window; border: none;
margin-right: $gaps-screen; min-width: 6px;
background-color: $base00; }
border-radius: $border-radius; scrollbar trough {
border-color: $base00; @include background-base2;
border-style: solid; @include border-radius;
border-width: $border-width; min-width: 6px;
}
scrollbar slider {
background-color: $base04;
@include border-radius;
min-width: 6px;
min-height: 20px;
&:hover { background-color: $base05; }
} }
.station_art:hover { .station-row {
border-color: $base04; padding: $popup-scale * 4pt $popup-scale * 3pt;
@include border-radius;
&:hover { @include background-base2; }
} }
.station_sel { .station-row-active {
border-color: $base03; .station-name { @include color-accent; }
}
.station-icon {
background-repeat: no-repeat;
@include border-radius;
@include background-base2;
min-width: $popup-scale * 28px;
min-height: $popup-scale * 28px;
margin-right: $popup-scale * 8pt;
}
.station-name {
font-size: 0.76em;
@include color-body;
} }
+46 -139
View File
@@ -4,36 +4,24 @@
.gpubar { color: $base0E; } .gpubar { color: $base0E; }
.membar { color: $base08; } .membar { color: $base08; }
.batbar { color: $base0B; } .batbar { color: $base0B; }
.cpubar, .gpubar, .membar, .batbar { @include background-base2; margin: $gaps-window 0; }
.cpubar, .gpubar, .membar, .batbar { // Window chrome
background-color: $bg0; .sys-win { padding: $popup-scale * 10pt; font-size: $popup-scale * $panel-font-size; }
margin: $gaps-window 0; .sys-section { margin-bottom: 0; }
} .sys-section-header { margin-bottom: $popup-scale * 10pt; }
// Window
.sys-win {
padding: 10pt;
}
.sys-section {
margin-bottom: 0;
}
.sys-section-header {
margin-bottom: 10pt;
}
.sys-label { .sys-label {
font-size: 0.72em; font-size: 0.72em;
font-weight: bold; font-weight: bold;
letter-spacing: 0.14em; letter-spacing: 0.14em;
color: $base05; @include color-body;
} }
.section-accent { .section-accent {
min-width: 3px; min-width: 3px;
border-radius: 2px; border-radius: 2px;
margin-right: 8pt; margin-right: $popup-scale * 8pt;
} }
.cpu-accent { background-color: $base0C; } .cpu-accent { background-color: $base0C; }
@@ -42,145 +30,64 @@
.bat-accent { background-color: $base0B; } .bat-accent { background-color: $base0B; }
.section-sep { .section-sep {
background-color: $base02; background-color: $base03;
min-height: 2px; min-height: 2px;
margin: 6pt 0 10pt 0; margin: $popup-scale * 6pt 0 $popup-scale * 10pt;
} }
.sys-sublabel { // All rings and progress tracks share the same background
font-size: 0.72em; .cpu-usage-ring, .cpu-freq-ring,
color: $base04; .gpu-ring, .gpu-freq-ring,
margin-right: 8pt; .ram-ring, .swap-ring, .bat-ring,
} .vram-bar { @include background-base2; }
// CPU grid // Ring colors
.cpu-usage-ring { .cpu-usage-ring { color: $base0C; }
color: $base0C; .cpu-freq-ring, .gpu-freq-ring { color: $base0D; }
background-color: $bg0; .gpu-ring { color: $base0E; }
margin: 3pt; .ram-ring { color: $base08; }
} .swap-ring { color: $base09; }
// Inner freq ring margin shrinks it inside overlay for concentric effect // Ring margins - freq rings use larger margins for concentric overlay effect
// 0% = cpu min freq, 100% = cpu max freq .cpu-usage-ring, .gpu-ring { margin: $popup-scale * 3pt; }
.cpu-freq-ring { .ram-ring, .bat-ring { margin: $popup-scale * 4pt; }
color: $base0D; .swap-ring { margin: $popup-scale * 3.5pt; }
background-color: $bg0; .cpu-freq-ring { margin: $popup-scale * 12px; }
margin: 12px; .gpu-freq-ring { margin: $popup-scale * 13px; }
}
.cpu-core-label { // Shared label patterns
font-size: 0.7em; .gpu-ring-value, .gpu-stat-value, .ram-used-label { font-weight: bold; @include color-body; }
color: $base05; .gpu-ring-value { font-size: 0.82em; }
} .gpu-stat-value { font-size: 0.85em; }
.ram-used-label { font-size: 0.95em; }
// GPU rings .gpu-ring-label, .gpu-stat-label,
.gpu-ring { .vram-usage-label, .swap-section-label { font-size: 0.62em; @include color-active; }
color: $base0E; .gpu-ring-label, .vram-usage-label, .swap-section-label { margin-top: 2pt; }
background-color: $bg0;
margin: 3pt;
}
.gpu-freq-ring { .cpu-core-label { font-size: 0.7em; @include color-active; }
color: $base0D; .bat-ring-label { font-size: 0.7em; @include color-body; }
background-color: $bg0; .ram-total-label { font-size: 0.72em; @include color-active; }
margin: 13px;
}
.gpu-ring-value {
font-size: 0.82em;
font-weight: bold;
color: $base05;
}
.gpu-ring-label {
font-size: 0.62em;
color: $base04;
margin-top: 2pt;
}
// GPU stats row // GPU stats row
.gpu-stats-row { .gpu-stats-row { margin-top: $popup-scale * 6pt; margin-bottom: $popup-scale * 2pt; }
margin-top: 6pt;
margin-bottom: 2pt;
}
.gpu-stat-value { // VRAM
font-size: 0.85em; .vram-row { margin-top: $popup-scale * 6pt; }
font-weight: bold;
color: $base05;
}
.gpu-stat-label {
font-size: 0.62em;
color: $base04;
}
// VRAM bar
.vram-row {
margin-top: 6pt;
}
.vram-bar { .vram-bar {
background-color: $bg0; @include border-radius;
border-radius: $border-radius; padding: $popup-scale * 2pt;
padding: 4pt;
} }
.vram-bar trough * { .vram-bar trough * {
background-color: $base0E; background-color: $base0E;
border-radius: $border-radius; @include border-radius;
}
.vram-usage-label {
font-size: 0.62em;
color: $base04;
margin-top: 2pt;
}
// RAM ring
.ram-ring {
color: $base08;
background-color: $bg0;
margin: 4pt;
} }
// RAM cached ring overrides group background
.ram-cached-ring { .ram-cached-ring {
color: $base02; @include color-active;
background-color: transparent; background-color: transparent;
margin: 4pt; margin: $popup-scale * 4pt;
}
.ram-used-label {
font-size: 0.95em;
font-weight: bold;
color: $base05;
}
.ram-total-label {
font-size: 0.72em;
color: $base04;
}
// Swap ring
.swap-ring {
color: $base09;
background-color: $bg0;
margin: 3pt;
}
.swap-section-label {
font-size: 0.62em;
color: $base04;
margin-top: 2pt;
}
// Battery ring
.bat-ring {
background-color: $bg0;
margin: 4pt;
}
.bat-ring-label {
font-size: 0.7em;
color: $base05;
} }
@@ -1,35 +1,28 @@
.tray * { .tray * {
padding: $border-width 0px; padding: $border-width 0;
} }
.tray menu { .tray menu {
background-color: $base01; @include border-radius;
color: $base07; @include border-active;
@include border-radius; @include background-base;
@include border-active; @include color-base;
padding: 10px 0;
padding: 10px 0px; > menuitem {
margin: 2px $border-width;
padding: 0 10px;
>menuitem { &:disabled label { @include color-active; }
margin: 2px $border-width; &:hover { @include background-accent; }
padding: 0px 10px; }
&:disabled label { separator {
color: $base04; @include background-base2;
} padding-top: 1px;
margin: 10px 0;
&:hover { &:last-child { padding: unset; }
background-color: $base0C; }
}
}
separator {
background-color: $base03;
padding-top: 1px;
margin:10px 0px;
&:last-child {
padding: unset;
}
}
} }
+51 -37
View File
@@ -18,8 +18,45 @@
border-color: $base04; border-color: $base04;
} }
@mixin test { @mixin background-base {
background-color: $base01;
}
@mixin background-base2 {
background-color: $base02;
}
@mixin background-active {
background-color: $base04;
}
@mixin background-accent {
background-color: $base0C;
}
@mixin color-base {
color: $base07;
}
@mixin color-inactive {
color: $base02;
}
@mixin color-active {
color: $base04;
}
@mixin color-accent {
color: $base0C;
}
@mixin color-body {
color: $base05;
}
@mixin panel-base {
@include border-radius;
@include border-inactive;
@include background-base;
@include color-base;
}
@mixin mod-edge {
border-right-style: none;
border-bottom-right-radius: 0;
border-top-right-radius: 0;
} }
/* GENERAL */ /* GENERAL */
@@ -31,9 +68,9 @@
} }
tooltip { tooltip {
background: $base01; @include border-active;
border: $border-width solid $base04; @include border-radius;
border-radius: $border-radius; @include background-base;
label { label {
font-size: 1rem; font-size: 1rem;
@@ -49,33 +86,17 @@ tooltip {
font-weight: 900; font-weight: 900;
} }
.grey { /* WORKSPACE COLORS - emitted dynamically by scripts/workspaces as class names */
color: $base02; .grey { color: $base02; }
} .red { color: $base0F; }
.orange { color: $base08; }
.red { .green { color: $base0B; }
color: $base0F; .blue { color: $base0C; }
}
.orange {
color: $base08;
}
.green {
color: $base0B;
}
.blue {
color: $base0C;
}
/* WINDOW WRAPPER CSS */ /* WINDOW WRAPPER CSS */
.winevent { .winevent {
background-color: $base01; @include panel-base;
color: $base07;
@include border-radius;
@include border-inactive;
} }
.winevent:hover { .winevent:hover {
@include border-active; @include border-active;
@@ -91,19 +112,12 @@ tooltip {
/* MODULE WRAPPER CSS */ /* MODULE WRAPPER CSS */
.modevent { .modevent {
background-color: $base01; @include panel-base;
color: $base07; @include mod-edge;
@include border-radius;
@include border-inactive;
border-right-style: none;
border-bottom-right-radius: 0;
border-top-right-radius: 0;
} }
.modevent:hover { .modevent:hover {
@include border-active; @include border-active;
border-right-style: none; @include mod-edge;
border-bottom-right-radius: 0;
border-top-right-radius: 0;
} }
.modinner { .modinner {
+4 -1
View File
@@ -5,9 +5,12 @@
(include "modules/systray.yuck") (include "modules/systray.yuck")
(include "modules/clock.yuck") (include "modules/clock.yuck")
(include "windows/calendar.yuck") (defvar active-panel "")
(include "windows/sys.yuck") (include "windows/sys.yuck")
(include "windows/net.yuck") (include "windows/net.yuck")
(include "windows/clock.yuck")
(include "windows/popup.yuck")
(include "windows/radio.yuck") (include "windows/radio.yuck")
(include "windows/powermenu.yuck") (include "windows/powermenu.yuck")
@@ -5,7 +5,7 @@
(eventbox (eventbox
:onhover "${EWW_CMD} update date_rev=true" :onhover "${EWW_CMD} update date_rev=true"
:onhoverlost "${EWW_CMD} update date_rev=false" :onhoverlost "${EWW_CMD} update date_rev=false"
:onclick "(sleep 0.1 && eww-open-on-current-screen calendar --toggle)" :onclick "(sleep 0.1 && scripts/panel-toggle clock)"
:onrightclick "(sleep 0.1 && eww-open-on-current-screen powermenu --toggle)" :onrightclick "(sleep 0.1 && eww-open-on-current-screen powermenu --toggle)"
(box (box
:class "datetime" :class "datetime"
@@ -1,5 +1,5 @@
(deflisten net (deflisten net
:initial '{"wifi":{"connected":false,"icon":"󰤮","ssid":""},"ethernet":{"connected":false}}' :initial '{"wifi":{"connected":false,"enabled":false,"icon":"󰤮","ssid":""},"ethernet":{"connected":false},"usb":{"connected":false}}'
"scripts/net/net") "scripts/net/net")
(deflisten bluetooth (deflisten bluetooth
@@ -9,12 +9,17 @@
(defwidget net-mod [] (defwidget net-mod []
(module (module
(eventbox (eventbox
:onclick "(sleep 0.1 && eww-open-on-current-screen net --toggle)" :onclick "(sleep 0.1 && scripts/panel-toggle net)"
(box :orientation "v" (box :orientation "v"
(label (label
:class "net-icon ${net.ethernet.connected ? 'net-active' : 'net-dim'}" :class "net-icon ${net.ethernet.connected ? 'net-active' : 'net-dim'}"
:tooltip {net.ethernet.connected ? "Ethernet: Connected" : "Ethernet: Disconnected"} :tooltip {net.ethernet.connected ? "Ethernet: Connected" : "Ethernet: Disconnected"}
:text "󰈀") :text "󰈀")
(label
:visible {net.usb.connected}
:class "net-icon net-active"
:tooltip "USB: Connected"
:text "󰌷")
(label (label
:class "net-icon ${net.wifi.connected ? 'net-active' : 'net-dim'}" :class "net-icon ${net.wifi.connected ? 'net-active' : 'net-dim'}"
:tooltip {net.wifi.connected ? "WiFi: ${net.wifi.ssid}" : "WiFi: Disconnected"} :tooltip {net.wifi.connected ? "WiFi: ${net.wifi.ssid}" : "WiFi: Disconnected"}
@@ -1,4 +1,3 @@
(deflisten cpu :initial '{}' "scripts/sys/cpu")
(deflisten gpu :initial '{"gfx_pct":0,"mem_pct":0,"media_pct":0,"sclk":0,"mclk":0,"sclk_pct":0,"mclk_pct":0,"vclk":0,"vclk_pct":0,"temp":0,"power":0,"vram_used":0,"vram_total":1}' "scripts/sys/gpu") (deflisten gpu :initial '{"gfx_pct":0,"mem_pct":0,"media_pct":0,"sclk":0,"mclk":0,"sclk_pct":0,"mclk_pct":0,"vclk":0,"vclk_pct":0,"temp":0,"power":0,"vram_used":0,"vram_total":1}' "scripts/sys/gpu")
(deflisten memory :initial '{"human":{"used":"0G","total":"0G","cached":"0G"},"used":0.0,"total":1.0,"cached":0.0}' "scripts/sys/memory") (deflisten memory :initial '{"human":{"used":"0G","total":"0G","cached":"0G"},"used":0.0,"total":1.0,"cached":0.0}' "scripts/sys/memory")
@@ -7,7 +6,7 @@
(defwidget sys-mod [] (defwidget sys-mod []
(module (module
(eventbox (eventbox
:onclick "(sleep 0.1 && eww-open-on-current-screen sys --toggle)" :onclick "(sleep 0.1 && scripts/panel-toggle sys)"
(box :orientation "v" (box :orientation "v"
(circular-progress (circular-progress
:value {EWW_CPU.avg} :value {EWW_CPU.avg}
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
BACKLIGHT="/sys/class/backlight"
DEV=$(ls "$BACKLIGHT" 2>/dev/null | head -n1)
gen_output() {
if [ -z "$DEV" ]; then
echo '{"percent":0,"available":false}'
return
fi
max=$(cat "$BACKLIGHT/$DEV/max_brightness")
cur=$(cat "$BACKLIGHT/$DEV/actual_brightness" 2>/dev/null || cat "$BACKLIGHT/$DEV/brightness")
percent=$(awk -v c="$cur" -v m="$max" 'BEGIN{print int(c/m*100+0.5)}')
printf '{"percent":%d,"available":true}\n' "$percent"
}
case "$1" in
set)
[ -z "$DEV" ] && exit 0
brightnessctl -d "$DEV" set "${2}%" -q 2>/dev/null
;;
*)
gen_output
[ -z "$DEV" ] && exit 0
# Poll for changes every 2s (sysfs files don't support inotify reliably)
while true; do sleep 2; gen_output; done
;;
esac
@@ -6,6 +6,7 @@ emit() {
if bluetoothctl show 2>/dev/null | grep -q "Powered: yes"; then if bluetoothctl show 2>/dev/null | grep -q "Powered: yes"; then
powered=true powered=true
while IFS= read -r line; do while IFS= read -r line; do
local mac info
mac=$(echo "$line" | awk '{ print $2 }') mac=$(echo "$line" | awk '{ print $2 }')
info=$(bluetoothctl info "$mac" 2>/dev/null) info=$(bluetoothctl info "$mac" 2>/dev/null)
if echo "$info" | grep -q "Connected: yes"; then if echo "$info" | grep -q "Connected: yes"; then
@@ -20,8 +21,18 @@ emit() {
} }
emit emit
bluetoothctl monitor 2>/dev/null | while IFS= read -r line; do
case "$line" in tmp=$(mktemp -d)
*"Powered"*|*"Connected"*|*"Device"*) emit ;; pipe="$tmp/bt-events"
esac mkfifo "$pipe"
trap 'rm -rf "$tmp"; kill 0 2>/dev/null' EXIT INT TERM
# Poll every 2s as reliable fallback for missed events
(while true; do sleep 2; echo poll; done) > "$pipe" &
# bluetoothctl monitor for reactive device connect/disconnect events
(bluetoothctl monitor 2>/dev/null | grep --line-buffered -E "Powered|Connected|Device") > "$pipe" &
while IFS= read -r _ < "$pipe"; do
emit
done done
@@ -16,8 +16,18 @@ emit() {
} }
emit emit
bluetoothctl monitor 2>/dev/null | while IFS= read -r line; do
case "$line" in tmp=$(mktemp -d)
*"Powered"*|*"Connected"*|*"Device"*) emit ;; pipe="$tmp/bt-dev-events"
esac mkfifo "$pipe"
trap 'rm -rf "$tmp"; kill 0 2>/dev/null' EXIT INT TERM
# Poll every 3s as fallback for missed events
(while true; do sleep 3; echo poll; done) > "$pipe" &
# Reactive updates from D-Bus
(bluetoothctl monitor 2>/dev/null | grep --line-buffered -E "Connected|Device|Powered") > "$pipe" &
while IFS= read -r _ < "$pipe"; do
emit
done done
@@ -4,6 +4,13 @@ get_wifi_iface() {
awk 'NR > 2 { gsub(":", "", $1); print $1; exit }' /proc/net/wireless awk 'NR > 2 { gsub(":", "", $1); print $1; exit }' /proc/net/wireless
} }
get_usb_iface() {
ip link 2>/dev/null | awk '
/^[0-9]+: usb[0-9]/ { gsub(":", "", $2); print $2; exit }
/^[0-9]+: enx/ { gsub(":", "", $2); print $2; exit }
'
}
signal_icon() { signal_icon() {
local dbm="$1" local dbm="$1"
if [ -z "$dbm" ]; then echo "󰤮"; return; fi if [ -z "$dbm" ]; then echo "󰤮"; return; fi
@@ -27,8 +34,18 @@ make_content() {
[ "$eth_state" = "UP" ] && eth_connected=true [ "$eth_state" = "UP" ] && eth_connected=true
fi fi
# WiFi — use IP presence as connection indicator (more reliable than wpa_cli) # USB tethering
local wifi_connected=false wifi_icon="󰤮" wifi_ssid="" local usb_iface usb_connected=false
usb_iface=$(get_usb_iface)
if [ -n "$usb_iface" ] && ip -4 addr show "$usb_iface" 2>/dev/null | grep -q "inet "; then
usb_connected=true
fi
# WiFi - use IP presence as connection indicator (more reliable than wpa_cli)
local wifi_connected=false wifi_enabled=false wifi_icon="󰤮" wifi_ssid=""
if ! rfkill list wlan 2>/dev/null | grep -q "Soft blocked: yes"; then
wifi_enabled=true
fi
if [ -n "$wifi_iface" ] && ip -4 addr show "$wifi_iface" 2>/dev/null | grep -q "inet "; then if [ -n "$wifi_iface" ] && ip -4 addr show "$wifi_iface" 2>/dev/null | grep -q "inet "; then
wifi_connected=true wifi_connected=true
wifi_ssid=$(wpa_cli -g "/run/wpa_supplicant/$wifi_iface" status 2>/dev/null \ wifi_ssid=$(wpa_cli -g "/run/wpa_supplicant/$wifi_iface" status 2>/dev/null \
@@ -37,8 +54,8 @@ make_content() {
wifi_icon=$(signal_icon "$signal") wifi_icon=$(signal_icon "$signal")
fi fi
printf '{"wifi":{"connected":%s,"icon":"%s","ssid":"%s"},"ethernet":{"connected":%s}}\n' \ printf '{"wifi":{"connected":%s,"enabled":%s,"icon":"%s","ssid":"%s"},"ethernet":{"connected":%s},"usb":{"connected":%s}}\n' \
"$wifi_connected" "$wifi_icon" "$wifi_ssid" "$eth_connected" "$wifi_connected" "$wifi_enabled" "$wifi_icon" "$wifi_ssid" "$eth_connected" "$usb_connected"
} }
make_content make_content
@@ -4,6 +4,13 @@ get_wifi_iface() {
awk 'NR > 2 { gsub(":", "", $1); print $1; exit }' /proc/net/wireless awk 'NR > 2 { gsub(":", "", $1); print $1; exit }' /proc/net/wireless
} }
get_usb_iface() {
ip link 2>/dev/null | awk '
/^[0-9]+: usb[0-9]/ { gsub(":", "", $2); print $2; exit }
/^[0-9]+: enx/ { gsub(":", "", $2); print $2; exit }
'
}
freq_band() { freq_band() {
local f="$1" local f="$1"
if [ "$f" -ge 6000 ] 2>/dev/null; then echo "6 GHz" if [ "$f" -ge 6000 ] 2>/dev/null; then echo "6 GHz"
@@ -51,11 +58,19 @@ make_content() {
fi fi
fi fi
local usb_iface usb_ip=""
usb_iface=$(get_usb_iface)
if [ -n "$usb_iface" ] && ip -4 addr show "$usb_iface" 2>/dev/null | grep -q "inet "; then
usb_ip=$(ip -4 addr show "$usb_iface" | awk '/inet / { print $2 }')
fi
# shellcheck disable=SC2059 # shellcheck disable=SC2059
printf '{"wifi":{"ssid":"%s","ip":"%s","freq":%s,"band":"%s","gen":"%s","signal":%s},' \ printf '{"wifi":{"ssid":"%s","ip":"%s","freq":%s,"band":"%s","gen":"%s","signal":%s},' \
"$wifi_ssid" "$wifi_ip" "${wifi_freq:-0}" "$wifi_band" "$wifi_gen" "${wifi_signal:-0}" "$wifi_ssid" "$wifi_ip" "${wifi_freq:-0}" "$wifi_band" "$wifi_gen" "${wifi_signal:-0}"
printf '"ethernet":{"state":"%s","ip":"%s","speed":"%s","interface":"%s"}}\n' \ printf '"ethernet":{"state":"%s","ip":"%s","speed":"%s","interface":"%s"},' \
"$eth_state" "$eth_ip" "$eth_speed" "${eth_iface:-}" "$eth_state" "$eth_ip" "$eth_speed" "${eth_iface:-}"
printf '"usb":{"interface":"%s","ip":"%s"}}\n' \
"${usb_iface:-}" "$usb_ip"
} }
make_content make_content
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
case "$1" in
status)
pgrep -x wlsunset >/dev/null 2>&1 && echo true || echo false
;;
*)
if pgrep -x wlsunset >/dev/null 2>&1; then
pkill -x wlsunset && echo false
else
wlsunset -T 4500 -t 3200 & echo true
fi
;;
esac
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
PANEL="$1"
# 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
eww update active-panel=""
eww close popup 2>/dev/null
else
eww update active-panel="$PANEL"
open_popup
fi
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
current=$(eww state 2>/dev/null | grep '^power-save:' | awk '{print $2}')
if [ "$current" = "true" ]; then
powerprofilesctl set balanced 2>/dev/null || true
echo false
else
powerprofilesctl set power-saver 2>/dev/null || true
echo true
fi
+183 -65
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
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
DIR="$HOME/Pictures/Screenshots"
mkdir -p "$DIR"
FILE="$DIR/$(date +%Y-%m-%d_%H-%M-%S).png"
grim -g "$(slurp)" "$FILE" && wl-copy < "$FILE"
@@ -1 +0,0 @@
#!/usr/bin/env zsh
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
volicons=("󰕿" "󰖀" "󰕾")
vol() { wpctl get-volume @DEFAULT_AUDIO_"$1"@ | awk '{print int($2*100)}'; }
ismuted() { wpctl get-volume @DEFAULT_AUDIO_"$1"@ | rg -qi muted; echo -n $?; }
setvol() { wpctl set-volume @DEFAULT_AUDIO_"$1"@ "$(awk -v n="$2" 'BEGIN{print n/100}')"; }
setmute() { wpctl set-mute @DEFAULT_AUDIO_"$1"@ toggle; }
gen_output() {
percent=$(vol "SINK")
lvl=$(awk -v n="$percent" 'BEGIN{print int(n/34)}')
sink_muted=$(ismuted "SINK")
source_muted=$(ismuted "SOURCE")
sink=$(wpctl inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null | grep -m1 'node\.nick' | sed 's/.*= "\(.*\)"/\1/')
[ "$sink_muted" = 0 ] && icon="󰝟" || icon="${volicons[$lvl]}"
[ "$source_muted" = 0 ] && mic_icon="󰍭" || mic_icon="󰍬"
printf '{"icon":"%s","percent":%s,"sink_muted":%s,"mic_icon":"%s","microphone":%s,"source_muted":%s,"sink":"%s"}\n' \
"$icon" "$percent" "$([ "$sink_muted" = 0 ] && echo true || echo false)" \
"$mic_icon" "$(vol SOURCE)" "$([ "$source_muted" = 0 ] && echo true || echo false)" "$sink"
}
case "$1" in
mute) setmute "$2" ;;
setvol) setvol "$2" "$3" ;;
*)
gen_output
tmp=$(mktemp -d)
pipe="$tmp/vol-events"
mkfifo "$pipe"
trap 'rm -rf "$tmp"; kill 0 2>/dev/null' EXIT INT TERM
# 1s polling fallback
(while true; do sleep 1; echo poll; done) > "$pipe" &
# PipeWire property-change events (fires on mute/volume change)
(pw-cli -m 2>/dev/null | grep --line-buffered "changed") > "$pipe" &
while IFS= read -r _ < "$pipe"; do
gen_output
done
;;
esac
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
nohup bash "$HOME/.config/script/wallpaper.sh" >/dev/null 2>&1 &
+100
View File
@@ -0,0 +1,100 @@
#!/usr/bin/env bash
FALLBACK='{"temp":0,"feelslike":0,"humidity":0,"wind":0,"desc":"Unavailable","icon":"󰖐","city":""}'
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/eww"
LOC_CACHE="$CACHE_DIR/weather-location"
UA="eww-bar/1.0 cedric.hoelzl@gmail.com"
mkdir -p "$CACHE_DIR"
get_location() {
# Cache location for 1 hour; IP rarely changes
if [ -f "$LOC_CACHE" ] && [ -n "$(find "$LOC_CACHE" -mmin -60 2>/dev/null)" ]; then
cat "$LOC_CACHE"
return 0
fi
data=$(curl -sf --max-time 5 "http://ip-api.com/json?fields=lat,lon,city") || return 1
echo "$data" | tee "$LOC_CACHE"
}
icon_for() {
case "$1" in
*thunder*) echo "󰖔" ;;
*snow*|*sleet*) echo "󰖘" ;;
heavyrain*|*heavyrainshowers*) echo "󰖖" ;;
*rain*|*shower*) echo "󰖗" ;;
fog*) echo "󰖑" ;;
cloudy*) echo "󰖐" ;;
partlycloudy*) echo "󰖕" ;;
fair*|clearsky*) echo "󰖙" ;;
*) echo "󰖐" ;;
esac
}
desc_for() {
case "$(echo "$1" | sed 's/_day//;s/_night//;s/_polartwilight//')" in
clearsky) echo "Clear sky" ;;
fair) echo "Fair" ;;
partlycloudy) echo "Partly cloudy" ;;
cloudy) echo "Cloudy" ;;
fog) echo "Foggy" ;;
lightrain) echo "Light rain" ;;
rain) echo "Rain" ;;
heavyrain) echo "Heavy rain" ;;
lightrainshowers) echo "Light showers" ;;
rainshowers) echo "Rain showers" ;;
heavyrainshowers) echo "Heavy showers" ;;
lightrainandthunder) echo "Light rain & thunder" ;;
rainandthunder) echo "Rain & thunder" ;;
heavyrainandthunder) echo "Heavy rain & thunder" ;;
*showersandthunder) echo "Showers & thunder" ;;
lightsleet|lightsleetshowers) echo "Light sleet" ;;
sleet|sleetshowers) echo "Sleet" ;;
heavysleet|heavysleetshowers) echo "Heavy sleet" ;;
*sleetandthunder) echo "Sleet & thunder" ;;
lightsnow|lightsnowshowers) echo "Light snow" ;;
snow|snowshowers) echo "Snow" ;;
heavysnow|heavysnowshowers) echo "Heavy snow" ;;
*snowandthunder) echo "Snow & thunder" ;;
*) echo "$1" ;;
esac
}
fetch() {
loc=$(get_location) || { echo "$FALLBACK"; return; }
lat=$(echo "$loc" | jq -r '.lat')
lon=$(echo "$loc" | jq -r '.lon')
city=$(echo "$loc" | jq -r '.city')
data=$(curl -sf --max-time 8 \
-H "User-Agent: $UA" \
-H "Accept: application/json" \
"https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=$lat&lon=$lon") \
|| { echo "$FALLBACK"; return; }
d='.properties.timeseries[0].data'
temp=$( echo "$data" | jq -r "${d}.instant.details.air_temperature | round")
humidity=$(echo "$data" | jq -r "${d}.instant.details.relative_humidity | round")
wind_ms=$( echo "$data" | jq -r "${d}.instant.details.wind_speed")
wind=$( echo "$wind_ms" | awk '{printf "%d", $1 * 3.6}')
code=$( echo "$data" | jq -r \
"(${d}.next_1_hours.summary.symbol_code) // (${d}.next_6_hours.summary.symbol_code) // \"cloudy\"")
# Simplified apparent temperature: wind chill below 10°C, else = temp
feelslike=$(echo "$temp $wind" | awk '{
t=$1; v=$2
if (v > 4.8 && t < 10)
printf "%d", 13.12 + 0.6215*t - 11.37*(v^0.16) + 0.3965*t*(v^0.16)
else
printf "%d", t
}')
icon=$(icon_for "$code")
desc=$(desc_for "$code")
printf '{"temp":%s,"feelslike":%s,"humidity":%s,"wind":%s,"desc":"%s","icon":"%s","city":"%s"}\n' \
"$temp" "$feelslike" "$humidity" "$wind" "$desc" "$icon" "$city"
}
fetch
while true; do sleep 600; fetch; done
@@ -1,9 +0,0 @@
(defwindow calendar
:monitor 0
:geometry (geometry
:x "0%"
:y "0%"
:anchor "bottom right"
:width "0px"
:height "0px")
(window (calendar)))
@@ -0,0 +1,126 @@
(deflisten weather
:initial '{"temp":0,"feelslike":0,"humidity":0,"wind":0,"desc":"","icon":"󰖐","city":""}'
"scripts/weather")
(deflisten volume
:initial '{"icon":"󰕾","percent":50,"sink_muted":false,"mic_icon":"󰍬","microphone":50,"source_muted":false,"sink":""}'
"scripts/volume")
(deflisten brightness
:initial '{"percent":0,"available":false}'
"scripts/brightness")
; --- Weather ---
(defwidget weather-section []
(box :orientation "v" :space-evenly false :class "sys-section"
(section-header
:title {weather.city != "" ? "Weather · ${weather.city}" : "Weather"}
:accent "weather-accent")
(box :orientation "h" :space-evenly false :halign "center" :class "weather-main"
(label :class "weather-icon" :valign "center" :text {weather.icon})
(box :orientation "v" :space-evenly false :valign "center"
(label :class "weather-temp" :text "${weather.temp}°C")
(label :class "weather-desc" :text {weather.desc})))
(box :orientation "h" :space-evenly true :class "weather-stats"
(box :orientation "v" :space-evenly false :halign "center"
(label :class "gpu-stat-value" :text "${weather.feelslike}°C")
(label :class "gpu-stat-label" :text "feels like"))
(box :orientation "v" :space-evenly false :halign "center"
(label :class "gpu-stat-value" :text "${weather.humidity}%")
(label :class "gpu-stat-label" :text "humidity"))
(box :orientation "v" :space-evenly false :halign "center"
(label :class "gpu-stat-value" :text "${weather.wind} km/h")
(label :class "gpu-stat-label" :text "wind")))))
; --- Volume ---
(defwidget vol-row [icon value onchange onclick muted]
(box :orientation "h" :space-evenly false :valign "center" :class "ctrl-row"
(button
:class "ctrl-icon ${muted ? 'ctrl-muted' : ''}"
:onclick onclick
(label :text icon))
(scale
:min 0 :max 100 :value value
:hexpand true
:class "ctrl-slider ${muted ? 'ctrl-slider-muted' : ''}"
:onchange {muted ? "true" : onchange})
(label :class "ctrl-value ${muted ? 'ctrl-muted' : ''}" :halign "end" :text "${value}%")))
(defwidget volume-section []
(box :orientation "v" :space-evenly false :class "sys-section"
(section-header
:title {volume.sink != "" ? "Volume · ${volume.sink}" : "Volume"}
:accent "vol-accent")
(vol-row
:icon {volume.icon}
:value {volume.percent}
:muted {volume.sink_muted}
:onchange "scripts/volume setvol SINK {}"
:onclick "scripts/volume mute SINK")
(vol-row
:icon {volume.mic_icon}
:value {volume.microphone}
:muted {volume.source_muted}
:onchange "scripts/volume setvol SOURCE {}"
:onclick "scripts/volume mute SOURCE")))
; --- Quick Actions ---
(defvar power-save false)
(defvar night-light false)
(defwidget quick-btn [icon label onclick active]
(button :class "quick-btn ${active ? 'quick-btn-active' : ''}"
:onclick onclick
(box :orientation "v" :space-evenly false :halign "center" :valign "center"
(label :class "quick-icon" :text icon)
(label :class "quick-label" :text label))))
(defwidget quick-section []
(box :orientation "v" :space-evenly false :class "sys-section"
(section-header :title "Quick Actions" :accent "quick-accent")
(box :orientation "v" :space-evenly false :class "quick-grid" :spacing 4
(box :orientation "h" :space-evenly true
(quick-btn :icon "󰸉" :label "Wallpaper" :onclick "scripts/wallpaper" :active false)
(quick-btn :icon "󱐋" :label "Power Save" :onclick "eww update power-save=$(scripts/power-save)" :active {power-save})
(quick-btn :icon "󰌵" :label "Night Light" :onclick "eww update night-light=$(scripts/nightlight)" :active {night-light}))
(box :orientation "h" :space-evenly true
(quick-btn :icon "󰹑" :label "Screenshot" :onclick "scripts/screenshot" :active false)
(quick-btn :icon "󰌾" :label "Lock" :onclick "swaylock" :active false)
(quick-btn :icon "󱉨" :label "Color Pick" :onclick "hyprpicker -a" :active false)))))
; --- Brightness ---
(defwidget brightness-section []
(box :orientation "v" :space-evenly false :class "sys-section"
:visible {brightness.available}
(section-header :title "Brightness" :accent "bri-accent")
(box :orientation "h" :space-evenly false :valign "center" :class "ctrl-row"
(label :class "ctrl-icon" :text "󰃠")
(scale
:min 1 :max 100 :value {brightness.percent}
:hexpand true
:class "ctrl-slider"
:onchange "scripts/brightness set {}")
(label :class "ctrl-value" :halign "end" :text "${brightness.percent}%"))))
; --- Root ---
(defwidget clock-win []
(box :class "sys-win" :orientation "v" :space-evenly false
(volume-section)
(brightness-section)
(box :class "section-sep")
(quick-section)
(box :class "section-sep")
(weather-section)
(box :class "section-sep")
(box :orientation "v" :space-evenly false :class "sys-section cal-box"
(section-header :title "Calendar" :accent "cal-accent")
(calendar :show-week-numbers false))
))
@@ -1,25 +1,37 @@
(defpoll netinfo (deflisten netinfo
:interval "5s" :initial '{"wifi":{"ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"state":"down","ip":"","speed":"","interface":""},"usb":{"interface":"","ip":""}}'
:initial '{"wifi":{"ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"state":"down","ip":"","speed":"","interface":""}}'
"scripts/net/netinfo") "scripts/net/netinfo")
(deflisten bt-devices (deflisten bt-devices
:initial "[]" :initial "[]"
"scripts/net/bt-devices") "scripts/net/bt-devices")
; --- Shared row widget --- ; --- Shared widgets ---
(defwidget netinfo-row [label value] (defwidget netinfo-row [label value]
(box :orientation "h" :space-evenly false :class "netinfo-row" (box :orientation "h" :space-evenly false :class "netinfo-row"
(label :class "netinfo-label" :halign "start" :text label) (label :class "netinfo-label" :halign "start" :text label)
(label :class "netinfo-value" :halign "end" :hexpand true :text value))) (label :class "netinfo-value" :halign "end" :hexpand true :text value)))
(defwidget section-header-toggle [title accent enabled onclick icon-on icon-off]
(box :orientation "h" :space-evenly false :valign "center" :class "sys-section-header"
(box :class "section-accent ${accent}")
(label :class "sys-label" :text title :hexpand true :halign "start")
(button
:class "net-toggle-btn ${enabled ? 'net-toggle-on' : 'net-toggle-off'}"
:onclick onclick
(label :text {enabled ? icon-on : icon-off}))))
; --- WiFi --- ; --- WiFi ---
(defwidget wifi-net-section [] (defwidget wifi-net-section []
(box :orientation "v" :space-evenly false :class "sys-section" (box :orientation "v" :space-evenly false :class "sys-section"
(section-header :title "WiFi" :accent "wifi-accent") (section-header-toggle
:title "WiFi" :accent "wifi-accent"
:enabled {net.wifi.enabled}
:onclick {net.wifi.enabled ? "rfkill block wlan" : "rfkill unblock wlan"}
:icon-on "󰤨" :icon-off "󰖪")
(box :orientation "v" :space-evenly false (box :orientation "v" :space-evenly false
:visible {net.wifi.connected} :visible {net.wifi.connected}
(netinfo-row :label "SSID" :value {netinfo.wifi.ssid}) (netinfo-row :label "SSID" :value {netinfo.wifi.ssid})
@@ -28,7 +40,15 @@
(netinfo-row :label "Freq" :value "${netinfo.wifi.freq} MHz · ${netinfo.wifi.band} · ${netinfo.wifi.gen}")) (netinfo-row :label "Freq" :value "${netinfo.wifi.freq} MHz · ${netinfo.wifi.band} · ${netinfo.wifi.gen}"))
(label :class "netinfo-dim" :halign "start" (label :class "netinfo-dim" :halign "start"
:visible {!net.wifi.connected} :visible {!net.wifi.connected}
:text "Not connected"))) :text {net.wifi.enabled ? "Not connected" : "Disabled"})))
; --- USB ---
(defwidget usb-net-section []
(box :orientation "v" :space-evenly false :class "sys-section"
(section-header :title "USB" :accent "usb-accent")
(netinfo-row :label "Interface" :value {netinfo.usb.interface})
(netinfo-row :label "IP" :value {netinfo.usb.ip})))
; --- Ethernet --- ; --- Ethernet ---
@@ -57,26 +77,29 @@
(defwidget bluetooth-net-section [] (defwidget bluetooth-net-section []
(box :orientation "v" :space-evenly false :class "sys-section" (box :orientation "v" :space-evenly false :class "sys-section"
(section-header :title "Bluetooth" :accent "blt-accent") (section-header-toggle
(box :orientation "v" :space-evenly false :title "Bluetooth" :accent "blt-accent"
(for device in {bt-devices} :enabled {bluetooth.powered}
(bt-device-row :device {device}))))) :onclick {bluetooth.powered ? "bluetoothctl power off" : "bluetoothctl power on"}
:icon-on "󰂯" :icon-off "󰂲")
(scroll :vscroll true :hscroll false :height 90
:visible {bluetooth.powered}
(box :orientation "v" :space-evenly false
(for device in {bt-devices}
(bt-device-row :device {device}))))
(label :class "netinfo-dim" :halign "start"
:visible {!bluetooth.powered}
:text "Disabled")))
; --- Root --- ; --- Root ---
(defwidget net-win [] (defwidget net-win []
(box :class "sys-win" :space-evenly false :orientation "v" (box :class "sys-win" :space-evenly false :orientation "v"
(wifi-net-section) (box :visible {net.usb.connected} :space-evenly false :orientation "v"
(box :class "section-sep") (usb-net-section)
(box :class "section-sep"))
(ethernet-net-section) (ethernet-net-section)
(box :class "section-sep") (box :class "section-sep")
(wifi-net-section)
(box :class "section-sep")
(bluetooth-net-section))) (bluetooth-net-section)))
(defwindow net
:monitor 0
:stacking "overlay"
:geometry (geometry
:x "0%" :y "0%"
:anchor "bottom right"
:width "300px" :height "0px")
(window (net-win)))
@@ -0,0 +1,20 @@
(defwidget popup-win []
(box :space-evenly false :orientation "v"
(revealer :reveal {active-panel == "sys"} :transition "slidedown" :duration 120
(sys-win))
(revealer :reveal {active-panel == "net"} :transition "slidedown" :duration 120
(net-win))
(revealer :reveal {active-panel == "clock"} :transition "slidedown" :duration 120
(clock-win))
(revealer :reveal {active-panel == "radio"} :transition "slidedown" :duration 120
(radio-win))))
(defwindow popup
:monitor 0
:stacking "overlay"
:geometry (geometry
:x "0%" :y "0%"
:anchor "bottom right"
:width "320px" :height "0px")
(window (popup-win)))
@@ -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
:monitor 0
:geometry (geometry
:x "0%"
:y "0%"
:anchor "bottom right"
:width "0px"
:height "0px")
(window (radio-win)))
(deflisten radio
:initial '{"is_paused":1,"song":{"artist":"","song":"","image600":""},"radio":0,"stations":[],"media":{"player":"","status":"Stopped","artist":"","title":"","art":""}}'
"scripts/radio")
(defvar radio-vol 80)
(defvar radio-muted false)
(defwidget radio-win [] (defwidget radio-win []
(box (box :class "sys-win" :orientation "v" :space-evenly false
:space-evenly false
:orientation "h"
(revealer
:visible radio_rev
:reveal radio_rev
:transition "slideleft"
(radio-selector))
(box
:space-evenly false
:orientation "v"
(box ; --- Now Playing ---
:class "album_art" (box :orientation "v" :space-evenly false :class "sys-section"
:style "background-size:cover; background-image: url('${radio.song.image600?:'https://www.radiorecord.ru/upload/stations_images/record_image600_white_fill.png'}');") (section-header :title "Media" :accent "radio-accent")
(box (box :orientation "h" :space-evenly false :valign "center" :spacing 10 :class "radio-now-playing"
:space-evenly false (box :class "radio-art"
:orientation "v" :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;"
(label (label :class "radio-art-icon" :halign "center" :valign "center"
:halign "center" :visible {radio.is_paused == 0
:class "song" ? radio.song.image600 == ""
:wrap "true" : (radio.media.status != "Stopped"
:limit-width 18 ? radio.media.art == ""
:text "${radio.song.song?:'...'}") : radio.song.image600 == "")}
(label :text "󰝚"))
:halign "center" (box :orientation "v" :space-evenly false :hexpand true :valign "center"
:class "artist" (label :class "radio-song" :halign "start" :wrap true :limit-width 20
:wrap "true" :text {radio.is_paused == 0
:limit-width 22 ? (radio.song.song != "" ? radio.song.song : "Tuning in...")
:text "${radio.song.artist?:'...'}") : (radio.media.status != "Stopped"
(box ? (radio.media.title != "" ? radio.media.title : "Playing")
:space-evenly true : (radio.song.song != "" ? radio.song.song : "Nothing playing"))})
:orientation "h" (label :class "radio-artist" :halign "start" :wrap true :limit-width 22
:halign "center" :text {radio.is_paused == 0
:class "btn_bar" ? radio.song.artist
: (radio.media.status != "Stopped"
? (radio.media.artist != "" ? radio.media.artist : radio.media.player)
: "")})))
(button ; Controls - hidden only in placeholder state
:class "btn_left" (box :visible {radio.is_paused == 0 || radio.radio > 0 || radio.media.status != "Stopped"}
:onclick "${EWW_CMD} update radio_rev=${!radio_rev}" :orientation "v" :space-evenly false :class "radio-controls"
(box "󰷐")) (box :orientation "h" :space-evenly true :halign "center"
(button :visible {radio.is_paused == 1 && radio.media.status != "Stopped"}
:class "radio-ctrl-btn" :timeout "2s" :onclick "playerctl previous"
(label :text "󰒮"))
(button :class "radio-ctrl-btn" :timeout "2s"
:onclick {radio.is_paused == 1 && radio.media.status != "Stopped" ? "playerctl play-pause" : "scripts/radio toggle"}
(label :text {radio.is_paused == 0 ? "󰏥" : (radio.media.status == "Playing" ? "󰏥" : "󰐌")}))
(button :visible {radio.is_paused == 1 && radio.media.status != "Stopped"}
:class "radio-ctrl-btn" :timeout "2s" :onclick "playerctl next"
(label :text "󰒭")))
(vol-row
:icon "󰕾"
:value {radio-vol}
:onchange "scripts/radio vol {}"
:onclick "scripts/radio mute"
:muted {radio-muted})))
(button (box :class "section-sep")
:class "btn_play"
:timeout "2s"
:onclick "scripts/radio toggle"
"${radio.is_paused==1 ? "󰐌" : "󰏥"}")
(button ; --- Stations ---
:class "btn_right" (box :orientation "v" :space-evenly false :class "sys-section"
:onclick "" (section-header :title "Radio Stations" :accent "radio-accent")
(box :visible false "󰔶")) (scroll :vscroll true :hscroll false :height 130
) (box :class "station-list" :space-evenly false :orientation "v"
) (for station in {radio.stations}
)
)
)
(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 "󰝚")
)
)
)
)
@@ -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
@@ -161,7 +161,7 @@
(box :orientation "v" :space-evenly false :halign "center" :valign "center" (box :orientation "v" :space-evenly false :halign "center" :valign "center"
(overlay (overlay
(circular-progress (circular-progress
:width 60 :height 60 :width 72 :height 72
:value {100*swap.used/swap.total} :value {100*swap.used/swap.total}
:start-at 0 :clockwise true :thickness 7 :start-at 0 :clockwise true :thickness 7
:class "swap-ring" :class "swap-ring"
@@ -209,14 +209,3 @@
(bat-sys-win) (bat-sys-win)
) )
) )
(defwindow sys
:monitor 0
:stacking "overlay"
:geometry (geometry
:x "0%"
:y "0%"
:anchor "bottom right"
:width "320px"
:height "0px")
(window (sys-win)))
@@ -59,6 +59,9 @@ 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;
$popup-scale: 1.25;
''; '';
}; };
} }
+1
View File
@@ -35,6 +35,7 @@ in {
brightnessctl brightnessctl
awww awww
playerctl
]; ];
xdg.mimeApps = { xdg.mimeApps = {
+1
View File
@@ -24,6 +24,7 @@
startupScript = pkgs.writeShellScriptBin "hyprland-start" '' startupScript = pkgs.writeShellScriptBin "hyprland-start" ''
eww open bar &
awww-daemon & awww-daemon &
sleep 2 sleep 2
+2 -1
View File
@@ -1,4 +1,5 @@
{ ... }: { { lib, ... }: {
services.fwupd.enable = true; services.fwupd.enable = true;
hardware.enableAllFirmware = false; hardware.enableAllFirmware = false;
services.power-profiles-daemon.enable = lib.mkDefault true;
} }
@@ -1,5 +1,6 @@
{ lib, config, pkgs, ... }: { { lib, config, pkgs, ... }: {
config = lib.mkIf (config.syscfg.make.power) { config = lib.mkIf (config.syscfg.make.power) {
services.power-profiles-daemon.enable = false; # conflicts with TLP
services.tlp = { services.tlp = {
enable = true; enable = true;
settings = { settings = {