diff --git a/modules/home/programs/hyprland/default.nix b/modules/home/programs/hyprland/default.nix
index 5998ef7..dedc1b1 100644
--- a/modules/home/programs/hyprland/default.nix
+++ b/modules/home/programs/hyprland/default.nix
@@ -188,19 +188,82 @@ in
vibrancy_darkness = "0.0";
}
];
+ label = [
+ # Date display
+ {
+ monitor = cfg.primaryDisplay;
+ text = "cmd[update:1000] echo -e \"$(LC_TIME=en_US.UTF-8 date +\"%A, %B %d\")\"";
+ color = "#eceff4";
+ font_size = "25";
+ font_family = "JetBrainsMono NFM";
+ position = "0, 350";
+ halign = "center";
+ valign = "center";
+ }
+ # Time display
+ {
+ monitor = cfg.primaryDisplay;
+ text = "cmd[update:1000] echo \"$(date +\"%I:%M\")\"";
+ color = "#eceff4";
+ font_size = "120";
+ font_family = "JetBrainsMono NFM Bold";
+ position = "0, 230";
+ halign = "center";
+ valign = "center";
+ }
+ {
+ monitor = cfg.primaryDisplay;
+ text = "$USER";
+ color = "#eceff4";
+ outline_thickness = 2;
+ dots_size = 0.2;
+ dots_spacing = 0.2;
+ dots_center = true;
+ font_size = 18;
+ font_family = "JetBrainsMono NFM Bold";
+ position = "0, 0";
+ halign = "center";
+ valign = "center";
+ }
+ #weather
+ {
+ monitor = cfg.primaryDisplay;
+ text = "cmd[update:30000] waybar-weather --hyprlock";
+ color = "#eceff4";
+ font_size = "25";
+ font_family = "JetBrainsMono NFM";
+ position = "-100, 100";
+ halign = "right";
+ valign = "bottom";
+ }
+ ];
+ # user box
+ shape = [
+ {
+ monitor = "";
+ size = "200, 50";
+ color = "rgba(46, 52, 64, .25)";
+ rounding = -1;
+ border_size = "0";
+ position = "0, 0";
+ halign = "center";
+ valign = "center";
+ }
+ ];
input-field = [
{
size = "200, 50";
position = "0, -80";
+ font_family = "JetBrainsMono NFM";
monitor = cfg.primaryDisplay;
dots_center = true;
fade_on_empty = true;
- font_color = "rgb(202, 211, 245)";
- inner_color = "rgb(91, 96, 120)";
- outer_color = "rgb(24, 25, 38)";
+ font_color = "#eceff4";
+ inner_color = "#4c566a";
+ outer_color = "#2e3440";
bothlock_color = -1;
outline_thickness = 5;
- placeholder_text = ''Password...'';
+ placeholder_text = ''Password...'';
shadow_passes = 2;
}
];
diff --git a/modules/home/programs/waybar/default.nix b/modules/home/programs/waybar/default.nix
index 505bfea..b719b62 100755
--- a/modules/home/programs/waybar/default.nix
+++ b/modules/home/programs/waybar/default.nix
@@ -364,6 +364,11 @@ in
Reboot
+
+
+
'';
@@ -476,6 +481,7 @@ in
reboot = "reboot";
suspend = "systemctl suspend";
hibernate = "systemctl hibernate";
+ lock = "pidof hyprlock || hyprlock";
};
};
}
@@ -662,7 +668,7 @@ in
tooltip = true;
format = { };
interval = 30;
- exec = "waybar-weather";
+ exec = "waybar-weather --waybar";
return-type = "json";
markup = "pango";
};
diff --git a/modules/home/programs/waybar/scripts/media.nix b/modules/home/programs/waybar/scripts/media.nix
new file mode 100644
index 0000000..e021286
--- /dev/null
+++ b/modules/home/programs/waybar/scripts/media.nix
@@ -0,0 +1,67 @@
+{
+ config,
+ lib,
+ namespace,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.${namespace}.programs.waybar;
+
+ waybar-media = pkgs.writeScriptBin "waybar-media" ''
+ #!/usr/bin/env bash
+
+ # Get current playing song from playerctl
+ if command -v playerctl &> /dev/null; then
+ # Check if any player is running
+ if playerctl status &> /dev/null; then
+ artist=$(playerctl metadata xesam:artist 2>/dev/null)
+ title=$(playerctl metadata xesam:title 2>/dev/null)
+
+ if [[ -n "$artist" && -n "$title" ]]; then
+ echo "♪ $artist - $title"
+ elif [[ -n "$title" ]]; then
+ echo "♪ $title"
+ else
+ echo "♪ Music Playing"
+ fi
+ else
+ echo ""
+ fi
+ else
+ echo ""
+ fi
+ '';
+
+ waybar-media-art = pkgs.writeScriptBin "waybar-media-art" ''
+ #!/usr/bin/env bash
+
+ # Get current playing song from playerctl
+ if command -v playerctl &> /dev/null; then
+ # Check if any player is running
+ if playerctl status &> /dev/null; then
+ art=$(playerctl metadata mpris:artUrl 2>/dev/null)
+
+ if [[ -n "$art" ]]; then
+ echo "♪ $artist - $title"
+ else
+ echo "♪ Music Playing"
+ fi
+ else
+ echo ""
+ fi
+ else
+ echo ""
+ fi
+ '';
+in
+{
+ imports = [ ../options.nix ];
+
+ config = lib.mkIf cfg.enable {
+ home.packages = [
+ waybar-media
+ waybar-media-art
+ ];
+ };
+}
diff --git a/modules/home/programs/waybar/scripts/weather.nix b/modules/home/programs/waybar/scripts/weather.nix
index 76e0545..c205358 100644
--- a/modules/home/programs/waybar/scripts/weather.nix
+++ b/modules/home/programs/waybar/scripts/weather.nix
@@ -16,9 +16,15 @@ let
import json
import shutil
from datetime import datetime, timedelta
+ import argparse
import requests
+ parser = argparse.ArgumentParser(prog='waybar-weather')
+ parser.add_argument('--waybar', action='store_true')
+ parser.add_argument('--hyprlock', action='store_true')
+ args = parser.parse_args()
+
WWO_CODE = {
"113": "Sunny",
"116": "PartlyCloudy",
@@ -281,6 +287,12 @@ let
WEATHER_CODES_WEGO = {key: WEATHER_SYMBOL_WEGO[value] for key, value in WWO_CODE.items()}
+ CACHE_DIR = os.path.join(os.environ.get("XDG_CACHE_HOME", os.path.expanduser("~/.cache")), "waybar-weather")
+ CACHE_FILE = os.path.join(CACHE_DIR, "wttr.json")
+ CACHE_MOON_FILE = os.path.join(CACHE_DIR, "moon.json")
+ CACHE_MOON_ICON_FILE = os.path.join(CACHE_DIR, "moon-icon")
+ CACHE_TTL = timedelta(minutes=10)
+
data = {}
data["text"] = ""
@@ -415,31 +427,93 @@ let
after_sunset = time_24_hr > sunset_hour
return after_sunset or before_sunrise
- def get_wttr_json():
+ def load_cache(path, ttl):
+ """Load cached file if it is not too old."""
+ try:
+ if not os.path.exists(path):
+ return None
+
+ mtime = datetime.fromtimestamp(os.path.getmtime(path))
+ if datetime.now() - mtime > ttl:
+ return None
+
+ with open(path, "r") as f:
+ if path.endswith(".json"):
+ return json.load(f)
+ return f.read().strip()
+
+ except Exception:
+ return None
+
+
+ def save_cache(path, data):
+ """Write cache file safely."""
+ os.makedirs(os.path.dirname(path), exist_ok=True)
+ tmp = path + ".tmp"
+
+ try:
+ with open(tmp, "w") as f:
+ if isinstance(data, dict):
+ json.dump(data, f)
+ else:
+ f.write(str(data))
+
+ shutil.move(tmp, path)
+ except Exception:
+ pass
+
+
+ def get_wttr_json(hyprlock=False):
"""get the weather json"""
- weather = requests.get("https://wttr.in/?u&format=j1", timeout=30).json()
- moon = requests.get("https://wttr.in/?format=%m", timeout=30)
- moon_icon = moon.text
- current_condition = weather["current_condition"][0]
- astronomy = weather["weather"][0]['astronomy'][0]
+ # Try loading cached JSON
+ cached = load_cache(CACHE_FILE, CACHE_TTL)
+ cached_moon = load_cache(CACHE_MOON_FILE, CACHE_TTL)
+ cached_moon_icon = load_cache(CACHE_MOON_ICON_FILE, CACHE_TTL)
- text = build_text(current_condition)
+ if cached and cached_moon and cached_moon_icon:
+ current_condition = cached
+ astronomy = cached_moon
+ moon_icon = cached_moon_icon
+ else:
+ weather = requests.get("https://wttr.in/?u&format=j1", timeout=30).json()
+ moon = requests.get("https://wttr.in/?format=%m", timeout=30)
+ moon_icon = moon.text
- tooltip = build_tooltip(current_condition, astronomy, moon_icon) + build_forecast(weather["weather"])
+ current_condition = weather["current_condition"][0]
+ astronomy = weather["weather"][0]['astronomy'][0]
- data["text"] = text
- data["tooltip"] = tooltip
+ # Save cache
+ save_cache(CACHE_FILE, current_condition)
+ save_cache(CACHE_MOON_FILE, astronomy)
+ save_cache(CACHE_MOON_ICON_FILE, moon_icon)
- return json.dumps(data)
+ if hyprlock:
+ return build_tooltip(current_condition, astronomy, moon_icon)
+ else:
+ text = build_text(current_condition)
+
+ tooltip = build_tooltip(current_condition, astronomy, moon_icon) + build_forecast(weather["weather"])
+
+ data["text"] = text
+ data["tooltip"] = tooltip
+
+ return json.dumps(data)
def main():
"""main"""
- try:
- print(get_wttr_json())
- except Exception as e:
- print("error")
- print(e)
+ if args.hyprlock:
+ try:
+ print(get_wttr_json(hyprlock=True))
+ except Exception as e:
+ print("error")
+ print(e)
+ else:
+ try:
+ print(get_wttr_json())
+ except Exception as e:
+ print("error")
+ print(e)
main()
'';