diff --git a/.gitignore b/.gitignore index ed921c9..107caf2 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,9 @@ swaylock/* swayidle/* !swayidle/config +!waybar +!bin + # flameshot !flameshot flameshot/* diff --git a/bin/waybar-custom-cider.sh b/bin/waybar-custom-cider.sh new file mode 100755 index 0000000..54c5208 --- /dev/null +++ b/bin/waybar-custom-cider.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +url="http://localhost:10767/api/v1/playback" + +status_raw=$(curl -s --max-time 2 "$url/is-playing") + +# CASE 1: API is totally unreachable (App closed) +if [[ -z "$status_raw" ]]; then + echo '{"text": "offline", "class": "offline", "alt": "offline"}' + exit 0 +fi + +# Extract playing status, defaulting to false if null +is_playing=$(echo "$status_raw" | jq -r '.is_playing // false') + +# 2. Get song info +info_raw=$(curl -s --max-time 2 "$url/now-playing") + +# CASE 2 & 3: Handle empty metadata vs. active metadata +echo "$info_raw" | jq -c \ + --argjson is_playing "$is_playing" \ + ' + # Helper function to escape & for Pango + def pango_escape: sub("&"; "&"; "g"); + + if (.info.name == null or .info.name == "") then + {text: "idle", class: "paused"} + else + { + text: "\(.info.name | pango_escape) - \(.info.artistName | pango_escape)", + tooltip: "\(.info.albumName | pango_escape // "Unknown")", + class: (if $is_playing then "playing" else "paused" end) + } + end' diff --git a/waybar/config.jsonc b/waybar/config.jsonc new file mode 100644 index 0000000..1925550 --- /dev/null +++ b/waybar/config.jsonc @@ -0,0 +1,201 @@ +{ + "layer": "top", + "position": "top", + "height": 45, + "spacing": 1, + "margin": 0, + "modules-left": [ + "clock", + ], + "modules-center": [ + "sway/workspaces", + "sway/mode", + "sway/scratchpad", + ], + "modules-right": [ + "custom/cider", + "pulseaudio", + "network", + "power-profiles-daemon", + "cpu", + "memory", + "temperature", + "backlight", + "battery", + "tray", + "custom/notification" + ], + // Modules configuration + "sway/workspaces": { + "disable-scroll": true, + // "all-outputs": true, + "format": "{icon}", + "format-icons": { + "1": "I", + "2": "II", + "3": "III", + "4": "IV", + "5": "V", + "6": "VI", + "7": "VII", + "8": "VIII", + "9": "IX", + "10": "X", + } + + }, + "sway/mode": { + "format": "{}" + }, + "sway/scratchpad": { + "format": "{icon} {count}", + "show-empty": false, + "format-icons": ["", ""], + "tooltip": true, + "tooltip-format": "{app}: {title}" + }, + "custom/cider": { + "format": "{}", + "return-type": "json", + "max-length": 18, + "interval": 1, + "tooltip": true, + "exec": "~/.config/bin/waybar-custom-cider.sh", + "on-click": "curl -s -X POST http://localhost:10767/api/v1/playback/playpause", + "on-click-right": "curl -s -X POST http://localhost:10767/api/v1/playback/next", + }, + "tray": { + "icon-size": 18, + "spacing": 10 + }, + "clock": { + "interval": 1, + "format": "{:%Y/%m/%d %H:%M:%S}", + "tooltip-format": "{:%Y %B}\n{calendar}", + }, + "cpu": { + "format": "cpu:{usage}%", + "tooltip": false, + "on-click": "ghostty -e htop" + }, + "memory": { + "interval": 10, + "format": "ram:{}%", + "tooltip-format": "total: {total:0.2f}GiB\nused: {used:0.2f}GiB\navailable: {avail:0.2f}GiB\nswap: {swapUsed:0.2f}/{swapTotal:0.2f}GiB", + "on-click": "ghostty -e htop" + }, + "temperature": { + // "thermal-zone": 2, + // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input", + "critical-threshold": 80, + // "format-critical": "{temperatureC}°C {icon}", + "format": "{temperatureC}°C {icon}", + "format-icons": ["", "", ""], + "on-click": "ghostty -e s-tui", + "tooltip": false + }, + "backlight": { + // "device": "acpi_video1", + "format": "{percent}% {icon}", + "format-icons": ["", "", "", "", "", "", "", "", ""], + "tooltip": false + }, + "battery": { + "states": { + // "good": 95, + "warning": 30, + "critical": 15 + }, + "format": "{capacity}% {icon}", + "format-full": "{capacity}% {icon}", + "format-charging": "{capacity}% ", + "format-plugged": "{capacity}% ", + "format-alt": "{time} {icon}", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": ["", "", "", "", ""] + }, + "power-profiles-daemon": { + "format": "{icon}", + "tooltip-format": "Power profile: {profile}\nDriver: {driver}", + "tooltip": true, + "format-icons": { + "default": "", + "performance": "", + "balanced": "", + "power-saver": "" + } + }, + "network": { + // "interface": "wlp2*", // (Optional) To force the use of this interface + "format-wifi": "{essid} ({signalStrength}%) ", + "format-ethernet": "ipv4:{ipaddr}/{cidr}", + "tooltip-format": "{ifname} via {gwaddr} ", + "format-linked": "{ifname} (No IP) ", + "format-disconnected": "Disconnected ⚠", + "format-alt": "{ifname}: {ipaddr}/{cidr}" + }, + "pulseaudio": { + // "scroll-step": 1, // %, can be a float + "format": "vol:{volume}%/{format_source}", + "format-bluetooth": "{volume}% {icon} {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": " {format_source}", + "format-source": "{volume}%", + "format-source-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pavucontrol" + }, + "custom/media": { + "format": "{icon} {text}", + "return-type": "json", + "max-length": 40, + "format-icons": { + "spotify": "", + "default": "🎜" + }, + "escape": true, + "exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null" // Script in resources folder + // "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name + }, + "custom/power": { + "format" : "⏻ ", + "tooltip": false, + "menu": "on-click", + "menu-file": "$HOME/.config/waybar/power_menu.xml", // Menu file in resources folder + "menu-actions": { + "shutdown": "shutdown", + "reboot": "reboot", + "suspend": "systemctl suspend", + "hibernate": "systemctl hibernate" + } + }, + "custom/notification": { + "tooltip": true, + "format": "{0} {icon} ", + "format-icons": { + "notification": "󱅫", + "none": "󰂜", + "dnd-notification": "󰂠", + "dnd-none": "󰪓", + "inhibited-notification": "󰂛", + "inhibited-none": "󰪑", + "dnd-inhibited-notification": "󰂛", + "dnd-inhibited-none": "󰪑" + }, + "return-type": "json", + "exec-if": "which swaync-client", + "exec": "swaync-client -swb", + "on-click": "swaync-client -t -sw", + "on-click-right": "swaync-client -d -sw", + "escape": true + } +} diff --git a/waybar/style.css b/waybar/style.css new file mode 100644 index 0000000..ded80f6 --- /dev/null +++ b/waybar/style.css @@ -0,0 +1,330 @@ +/* ----------------------------------------------------------------------------- + * Gruvbox Material Dark Palette + * ----------------------------------------------------------------------------- */ +@define-color background #282828; +@define-color background-light #3c3836; +@define-color foreground #d4be98; +@define-color black #1d2021; +@define-color gray #928374; +@define-color red #ea6962; +@define-color green #a9b665; +@define-color yellow #d8a657; +@define-color blue #7daea3; +@define-color magenta #d3869b; +@define-color cyan #89b482; +@define-color white #ddc7a1; +@define-color orange #e78a4e; + +/* ----------------------------------------------------------------------------- + * Module Colors (Neovim/Muted Style) + * ----------------------------------------------------------------------------- */ +@define-color workspaces-color @gray; +@define-color workspaces-focused-bg @background-light; +@define-color workspaces-focused-fg @foreground; +@define-color workspaces-urgent-bg @red; +@define-color workspaces-urgent-fg @background; + +@define-color cider-color @red; +@define-color clock-color @foreground; +@define-color pulseaudio-color @blue; +@define-color pulseaudio-muted-color @gray; +@define-color network-color @magenta; +@define-color network-disconnected-color @red; +@define-color cpu-color @orange; +@define-color memory-color @cyan; +@define-color temperature-color @yellow; +@define-color temperature-critical-color @red; +@define-color backlight-color @white; +@define-color battery-color @foreground; +@define-color battery-charging-color @green; +@define-color battery-warning-color @yellow; +@define-color battery-critical-color @red; + +/* ----------------------------------------------------------------------------- + * Global Setup + * ----------------------------------------------------------------------------- */ +* { + font-family: "JetBrainsMono Nerd Font"; + font-size: 14px; +} + +window#waybar { + background-color: transparent; + font-weight: bold; + color: #ffffff; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar.hidden { + opacity: 0.2; +} + +/* This targets every module */ +#waybar .module { + background-color: #1e1e2e; /* Your desired module color */ + border-radius: 7px; + border: 2px solid #d4be98; +} + +/* Specific grouping (Optional: if you want modules to stick together in islands) */ +.modules-left, .modules-center, .modules-right { + background: transparent; + margin: 12px 10px 5px 10px; +} + +button { + box-shadow: none; + border: none; + border-radius: 0; +} + +button:hover { + background: inherit; + box-shadow: none; +} + +/* ----------------------------------------------------------------------------- + * Workspaces + * ----------------------------------------------------------------------------- */ +#workspaces button { + padding: 0 8px; + background-color: transparent; + color: @workspaces-color; + margin: 0; +} + +#workspaces button:hover { + background: @background-light; + color: @foreground; + box-shadow: none; +} + +/* The "Neovim Buffer" Look: + Active workspace is lighter background + cream text. + No flashy underlines. */ +#workspaces button.focused { + background-color: @background-light; + color: @workspaces-focused-fg; + box-shadow: none; +} + +#workspaces button.urgent { + background-color: @workspaces-urgent-bg; + color: @workspaces-urgent-fg; +} + +/* ----------------------------------------------------------------------------- + * Modules + * ----------------------------------------------------------------------------- */ +#mode, +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#wireplumber, +#custom-media, +#tray, +#idle_inhibitor, +#scratchpad, +#power-profiles-daemon, +#mpd, +#custom-cider { + color: @clock-color; + font-weight: bold; + padding: 0 10px; + margin: 0 2px; + background-color: transparent; + border: none; /* Removed the underlines for a cleaner look */ +} + +#window, +#workspaces { + margin: 0 4px; +} + +.modules-left > widget:first-child > #workspaces { margin-left: 0; } +.modules-right > widget:last-child > #workspaces { margin-right: 0; } + +/* ----------------------------------------------------------------------------- + * Module Specifics + * ----------------------------------------------------------------------------- */ + + +#battery { + color: @battery-color; +} + +#battery.charging, #battery.plugged { + color: @battery-charging-color; +} + +#battery.warning:not(.charging) { + color: @battery-warning-color; +} + +@keyframes blink { + to { + background-color: @red; + color: @background; + } +} + +#battery.critical:not(.charging) { + color: @battery-critical-color; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: steps(12); + animation-iteration-count: infinite; + animation-direction: alternate; +} + +/* #cpu { */ +/* color: @cpu-color; */ +/* } */ +/**/ +/* #memory { */ +/* color: @memory-color; */ +/* } */ +/**/ +/* #disk { */ +/* color: @yellow; */ +/* } */ +/**/ +/* #backlight { */ +/* color: @backlight-color; */ +/* } */ +/**/ +/* #network { */ +/* color: @network-color; */ +/* } */ +/**/ +/* #network.disconnected { */ +/* color: @network-disconnected-color; */ +/* } */ +/**/ +/* #pulseaudio { */ +/* color: @pulseaudio-color; */ +/* } */ +/**/ +/* #pulseaudio.muted { */ +/* color: @pulseaudio-muted-color; */ +/* } */ +/**/ +/* #wireplumber { */ +/* color: @foreground; */ +/* } */ +/**/ +/* #wireplumber.muted { */ +/* color: @red; */ +/* } */ + +#custom-media { + color: @green; + min-width: 100px; +} + +#temperature { + color: @temperature-color; +} + +#temperature.critical { + color: @temperature-critical-color; +} + +#tray { + background-color: @background-light; + border-radius: 4px; /* Slight roundness for the tray container */ + padding: 0 8px; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; + color: @red; +} + +#idle_inhibitor { + color: @gray; +} + +#idle_inhibitor.activated { + color: @foreground; +} + +#mpd { + color: @green; +} + +#mpd.disconnected { + color: @red; +} + +#mpd.stopped { + color: @gray; +} + +#mpd.paused { + color: @blue; +} + +#language { + background: @background-light; + color: @foreground; + padding: 0 5px; + margin: 0 5px; + min-width: 16px; +} + +#keyboard-state { + color: @foreground; + padding: 0 0px; + margin: 0 5px; + min-width: 16px; +} + +#keyboard-state > label.locked { + color: @red; +} + +#scratchpad { + background: transparent; + color: @gray; +} + +#scratchpad.empty { + background-color: transparent; +} + +#privacy { + padding: 0; +} + +#privacy-item { + padding: 0 5px; + color: @foreground; +} + +#privacy-item.screenshare { + color: @orange; +} + +#privacy-item.audio-in { + color: @green; +} + +#privacy-item.audio-out { + color: @blue; +} + +/* #custom-cider { */ +/* color: @cider-color; */ +/* } */