diff --git a/hyprland/.local/bin/weather.sh b/hyprland/.local/bin/weather.sh index c6ff881..c8beced 100755 --- a/hyprland/.local/bin/weather.sh +++ b/hyprland/.local/bin/weather.sh @@ -1,8 +1,10 @@ #!/usr/bin/env bash # Print the current weather as a short icon+temp string, e.g. "🌦️ +83°F". -# Caches the wttr.in response for CACHE_MAX_AGE seconds so the lock screen and -# waybar don't hit the network on every refresh. Override the location with -# WEATHER_CITY or edit CITY below. +# Caches the wttr.in response so the lock screen and waybar don't hit the +# network on every refresh. A cached value is served immediately -- even when +# stale -- and refreshed in the background, so a slow network never delays the +# lock screen's first frame. Override the location with WEATHER_CITY or edit +# CITY below. set -u CITY="${WEATHER_CITY:-Denver}" @@ -11,24 +13,36 @@ CACHE="${CACHE_DIR}/wttr.cache" CACHE_MAX_AGE=1800 # 30 minutes URL="https://wttr.in/${CITY}?format=%c+%t" -cache_age() { - [ -f "${CACHE}" ] || return 1 - now=$(date +%s) - mtime=$(stat -c %Y "${CACHE}") - [ "$(( now - mtime ))" -lt "${CACHE_MAX_AGE}" ] +fetch() { + TMP="${CACHE}.tmp.$$" + if curl -fsS --connect-timeout 2 --max-time 5 "${URL}" > "${TMP}" 2>/dev/null; then + mv "${TMP}" "${CACHE}" + cat "${CACHE}" + else + rm -f "${TMP}" || true + return 1 + fi } -if cache_age; then +# Fresh cache: print it. +if [ -f "${CACHE}" ] && [ "$(( $(date +%s) - $(stat -c %Y "${CACHE}") ))" -lt "${CACHE_MAX_AGE}" ]; then cat "${CACHE}" exit 0 fi -TMP="${CACHE}.tmp.$$" -if curl -fsS --max-time 10 "${URL}" > "${TMP}" 2>/dev/null; then - mv "${TMP}" "${CACHE}" +# Stale cache: print it immediately, then refresh in the background so the +# caller never blocks. flock keeps a pile-up of refreshes from several clients +# (lock screen, waybar) from running concurrent curls. +if [ -f "${CACHE}" ]; then cat "${CACHE}" -else - rm -f "${TMP}" || true - # Offline: fall back to whatever we cached last, even if stale. - [ -f "${CACHE}" ] && cat "${CACHE}" + ( + exec 9>"${CACHE}.lock" + flock -n 9 || exit 0 + fetch >/dev/null 2>&1 + ) & + disown + exit 0 fi + +# No cache at all: fetch synchronously, but with tight timeouts. +fetch diff --git a/hyprlock/.config/hypr/hyprlock.conf b/hyprlock/.config/hypr/hyprlock.conf index 0e61e90..341d248 100644 --- a/hyprlock/.config/hypr/hyprlock.conf +++ b/hyprlock/.config/hypr/hyprlock.conf @@ -11,13 +11,13 @@ general { } # Authentication -# Fingerprint is disabled: GDM's login worker (pam/gdm-fingerprint) holds the -# device for the whole session, so hyprlock can never claim it -- the failed -# claim blocked the auth thread and made unlocks appear stuck. Fingerprint is -# still available at the GDM login screen; hyprlock is password-only. +# Fingerprint via hyprlock's native fprintd support. PAM is password-only +# (/etc/pam.d/hyprlock) so typing a password never fights hyprlock for the +# fingerprint sensor. The device is not held by GDM for the user session, so +# the old stuck-unlock issue no longer applies. auth { fingerprint { - enabled = false + enabled = true ready_message = Scan fingerprint to unlock present_message = Scanning... retry_delay = 250 # in milliseconds diff --git a/hyprlock/.local/bin/hyprlock b/hyprlock/.local/bin/hyprlock index b67d486..7a8d3bc 100755 --- a/hyprlock/.local/bin/hyprlock +++ b/hyprlock/.local/bin/hyprlock @@ -4,15 +4,23 @@ # If the real hyprlock dies, this restarts it so the session doesn't end up in a # "lockscreen app died" state. Requires misc:allow_session_lock_restore = true # in Hyprland config for the replacement lock to be accepted. +# +# --immediate-render: present the first frame as soon as the background is up +# instead of waiting for every resource (labels run scripts like weather.sh). +# Assets pop in when ready, so the "lock screen took seconds to appear" stalls +# (Hyprland "Lockdead frames") don't happen. set -u REAL_HYPRLOCK=/usr/bin/hyprlock MAX_RESTARTS=20 +# hyprlock logs to stdout/stderr; capture them so the last lock cycle is +# readable for debugging (fprint claim/verify, auth results). +LOGFILE="${XDG_RUNTIME_DIR:-/tmp}/hyprlock.log" restart=0 while true; do - "$REAL_HYPRLOCK" "$@" + "$REAL_HYPRLOCK" --immediate-render "$@" >"${LOGFILE}" 2>&1 code=$? # 0: exited cleanly (e.g. unlocked) -- done. diff --git a/monique/.config/monique/profiles/laptop.json b/monique/.config/monique/profiles/laptop.json index a7b73be..a2e00f3 100644 --- a/monique/.config/monique/profiles/laptop.json +++ b/monique/.config/monique/profiles/laptop.json @@ -56,5 +56,5 @@ } ], "workspace_rules": [], - "last_applied_time": 1788832965.6726744 + "last_applied_time": 1789241254.0499482 } diff --git a/nvim/.config/nvim b/nvim/.config/nvim index b548abc..2906689 160000 --- a/nvim/.config/nvim +++ b/nvim/.config/nvim @@ -1 +1 @@ -Subproject commit b548abcf80a4c99573aaa8323bdadfd6fb764069 +Subproject commit 2906689a299e500740f026f59938c08635e1996f