From bd61a909cedd26d989d1c68a583c5b70e323dc4c Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Thu, 11 Jun 2026 13:46:15 +0800 Subject: [PATCH] feat(waybar): update colors, disable dae, rewrite update checker --- .config/waybar/colors.css | 88 ++++---- .config/waybar/config.jsonc | 2 +- .config/waybar/scripts/check-updates.sh | 263 ++++++++++++++++++++---- 3 files changed, 265 insertions(+), 88 deletions(-) mode change 100755 => 100644 .config/waybar/scripts/check-updates.sh diff --git a/.config/waybar/colors.css b/.config/waybar/colors.css index 50278d3..c43ff69 100755 --- a/.config/waybar/colors.css +++ b/.config/waybar/colors.css @@ -3,103 +3,103 @@ * Generated with Matugen */ - @define-color background #101417; + @define-color background #11140e; @define-color error #ffb4ab; @define-color error_container #93000a; - @define-color inverse_on_surface #2d3135; + @define-color inverse_on_surface #2e312a; - @define-color inverse_primary #226488; + @define-color inverse_primary #48672e; - @define-color inverse_surface #dfe3e7; + @define-color inverse_surface #e2e3d9; - @define-color on_background #dfe3e7; + @define-color on_background #e2e3d9; @define-color on_error #690005; @define-color on_error_container #ffdad6; - @define-color on_primary #00344c; + @define-color on_primary #1c3704; - @define-color on_primary_container #c7e7ff; + @define-color on_primary_container #c9eea7; - @define-color on_primary_fixed #001e2e; + @define-color on_primary_fixed #0c2000; - @define-color on_primary_fixed_variant #004c6c; + @define-color on_primary_fixed_variant #324e19; - @define-color on_secondary #21323e; + @define-color on_secondary #29341f; - @define-color on_secondary_container #d2e5f5; + @define-color on_secondary_container #dae7c9; - @define-color on_secondary_fixed #0b1d29; + @define-color on_secondary_fixed #141e0c; - @define-color on_secondary_fixed_variant #374955; + @define-color on_secondary_fixed_variant #3f4a34; - @define-color on_surface #dfe3e7; + @define-color on_surface #e2e3d9; - @define-color on_surface_variant #c1c7ce; + @define-color on_surface_variant #c4c8ba; - @define-color on_tertiary #342b4b; + @define-color on_tertiary #003736; - @define-color on_tertiary_container #e9ddff; + @define-color on_tertiary_container #bbece9; - @define-color on_tertiary_fixed #1f1635; + @define-color on_tertiary_fixed #00201f; - @define-color on_tertiary_fixed_variant #4b4263; + @define-color on_tertiary_fixed_variant #1e4e4d; - @define-color outline #8b9198; + @define-color outline #8e9286; - @define-color outline_variant #41484d; + @define-color outline_variant #44483e; - @define-color primary #93cdf6; + @define-color primary #aed18d; - @define-color primary_container #004c6c; + @define-color primary_container #324e19; - @define-color primary_fixed #c7e7ff; + @define-color primary_fixed #c9eea7; - @define-color primary_fixed_dim #93cdf6; + @define-color primary_fixed_dim #aed18d; @define-color scrim #000000; - @define-color secondary #b6c9d8; + @define-color secondary #becbae; - @define-color secondary_container #374955; + @define-color secondary_container #3f4a34; - @define-color secondary_fixed #d2e5f5; + @define-color secondary_fixed #dae7c9; - @define-color secondary_fixed_dim #b6c9d8; + @define-color secondary_fixed_dim #becbae; @define-color shadow #000000; - @define-color source_color #80c6f4; + @define-color source_color #84a467; - @define-color surface #101417; + @define-color surface #11140e; - @define-color surface_bright #353a3d; + @define-color surface_bright #373a33; - @define-color surface_container #1c2024; + @define-color surface_container #1e211a; - @define-color surface_container_high #262a2e; + @define-color surface_container_high #282b24; - @define-color surface_container_highest #313539; + @define-color surface_container_highest #33362e; - @define-color surface_container_low #181c20; + @define-color surface_container_low #1a1d16; - @define-color surface_container_lowest #0a0f12; + @define-color surface_container_lowest #0c0f09; - @define-color surface_dim #101417; + @define-color surface_dim #11140e; - @define-color surface_tint #93cdf6; + @define-color surface_tint #aed18d; - @define-color surface_variant #41484d; + @define-color surface_variant #44483e; - @define-color tertiary #cdc0e9; + @define-color tertiary #a0cfcd; - @define-color tertiary_container #4b4263; + @define-color tertiary_container #1e4e4d; - @define-color tertiary_fixed #e9ddff; + @define-color tertiary_fixed #bbece9; - @define-color tertiary_fixed_dim #cdc0e9; + @define-color tertiary_fixed_dim #a0cfcd; diff --git a/.config/waybar/config.jsonc b/.config/waybar/config.jsonc index 9e1ad00..f1beb7c 100755 --- a/.config/waybar/config.jsonc +++ b/.config/waybar/config.jsonc @@ -28,7 +28,7 @@ "custom/wfrec", "custom/left_div#2", // "idle_inhibitor", - "custom/dae", +// "custom/dae", "custom/colorpicker", "power-profiles-daemon", "custom/left_div#11", diff --git a/.config/waybar/scripts/check-updates.sh b/.config/waybar/scripts/check-updates.sh old mode 100755 new mode 100644 index 90b05f6..2193e85 --- a/.config/waybar/scripts/check-updates.sh +++ b/.config/waybar/scripts/check-updates.sh @@ -1,60 +1,237 @@ #!/bin/bash +# ============================================================================== +# 功能:Waybar 更新检测后台守护脚本 +# 特性:定期检查 Pacman 和 AUR 更新,生成 JSON 和 txt 供前端极速读取。 +# 修复:引入动态信号屏蔽与 FORCE_UPDATE 标志,完美解决高频触发导致的并发地狱。 +# ============================================================================== -# === 配置部分 === -CACHE_FILE="$HOME/.cache/waybar-updates.json" +set -euo pipefail -# === 函数定义 === +# === 配置区域 === +CACHE_DIR="$HOME/.cache/shorin-check-arch-updates" +CACHE_FILE="$CACHE_DIR/updates.json" +LOCK_FILE="/tmp/waybar-updates.lock" +MAX_LINES=50 +CHECK_INTERVAL=3600 +PACMAN_LOG="/var/log/pacman.log" + +# 确保缓存目录存在 +mkdir -p "$CACHE_DIR" + +# 全局状态标志:0=按需检查,1=强制无视缓存检查 +FORCE_UPDATE=0 + +# === 自动检测 AUR Helper === +if command -v paru &> /dev/null; then + AUR_HELPER="paru" +elif command -v yay &> /dev/null; then + AUR_HELPER="yay" +else + AUR_HELPER="" +fi + +# === 信号处理函数 === +# 不再粗暴删除文件,仅修改标志位 +on_sigusr1() { + FORCE_UPDATE=1 +} + +# 初始绑定信号 +trap 'on_sigusr1' SIGUSR1 + +# === 上次系统更新时间 === +format_age() { + local seconds=$1 + + if [[ "$seconds" -lt 0 ]]; then + seconds=0 + fi + + if [[ "$seconds" -lt 60 ]]; then + printf '刚刚' + elif [[ "$seconds" -lt 3600 ]]; then + printf '%d 分钟前' $((seconds / 60)) + elif [[ "$seconds" -lt 86400 ]]; then + printf '%d 小时前' $((seconds / 3600)) + elif [[ "$seconds" -lt 2592000 ]]; then + printf '%d 天前' $((seconds / 86400)) + elif [[ "$seconds" -lt 31536000 ]]; then + printf '%d 个月前' $((seconds / 2592000)) + else + printf '%d 年前' $((seconds / 31536000)) + fi +} + +get_last_system_update_info() { + if [[ ! -r "$PACMAN_LOG" ]]; then + printf '上次系统更新:未知' + return + fi + + local last_line timestamp last_update current_time age + # Count only full system upgrade commands, not AUR/local package upgrades. + last_line=$(tac "$PACMAN_LOG" 2>/dev/null | grep -m1 -E "\[PACMAN\] Running 'pacman ([^']*-S[^[:space:]']*u|[^']*-S[[:space:]][^']*[[:space:]](-u|--sysupgrade)|[^']*--sync[^']*[[:space:]](-u|--sysupgrade))" || true) + + if [[ -z "$last_line" ]]; then + printf '上次系统更新:无记录' + return + fi + + timestamp=${last_line%%]*} + timestamp=${timestamp#\[} + last_update=$(date -d "$timestamp" +%s 2>/dev/null || true) + + if [[ -z "$last_update" ]]; then + printf '上次系统更新:未知' + return + fi + + current_time=$(date +%s) + age=$((current_time - last_update)) + printf '上次系统更新:%s' "$(format_age "$age")" +} + +# === 生成 JSON 函数 === generate_json() { local updates=$1 local count + local last_update_info + + last_update_info=$(get_last_system_update_info) - if [ -z "$updates" ]; then + updates=$(echo "$updates" | grep -v '^\s*$' || true) + + if [[ -z "$updates" ]]; then count=0 + printf '{"text": "", "alt": "updated", "tooltip": "System is up to date\\n----------------\\n%s"}\n' "$last_update_info" + return else count=$(echo "$updates" | wc -l) fi - if [ "$count" -gt 0 ]; then - local tooltip=$(echo "$updates" | awk '{printf "%s\\n", $0}' | sed 's/"/\\"/g' | head -c -2) - printf '{"text": "%s", "alt": "has-updates", "tooltip": "%s"}\n' "$count" "$tooltip" + local tooltip_text="" + if [[ "$count" -gt "$MAX_LINES" ]]; then + local remainder=$((count - MAX_LINES)) + local top_list=$(echo "$updates" | head -n "$MAX_LINES") + local escaped_list=$(echo "$top_list" | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}' ) + tooltip_text="${escaped_list}----------------\\n⚠️ ... and ${remainder} more updates" else - printf '{"text": "", "alt": "updated", "tooltip": "System is up to date"}\n' + tooltip_text=$(echo "$updates" | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}' | head -c -2 || true) + fi + + tooltip_text="${tooltip_text}\\n----------------\\n${last_update_info}" + + printf '{"text": "%s", "alt": "has-updates", "tooltip": "%s"}\n' "$count" "$tooltip_text" +} + +# === 从缓存文本重新生成输出,避免 tooltip 的相对时间被 JSON 缓存卡住 === +emit_cached_json() { + local repo_cache="${CACHE_FILE%.json}-repo.txt" + local aur_cache="${CACHE_FILE%.json}-aur.txt" + local REPO_UPDATES="" + local AUR_UPDATES="" + local ALL_UPDATES="" + + if [[ ! -f "$repo_cache" && ! -f "$aur_cache" ]]; then + cat "$CACHE_FILE" + return + fi + + if [[ -f "$repo_cache" ]]; then + REPO_UPDATES=$(<"$repo_cache") + fi + + if [[ -f "$aur_cache" ]]; then + AUR_UPDATES=$(<"$aur_cache") + fi + + if [[ -n "$REPO_UPDATES" ]] && [[ -n "$AUR_UPDATES" ]]; then + ALL_UPDATES="$REPO_UPDATES"$'\n'"$AUR_UPDATES" + elif [[ -n "$REPO_UPDATES" ]]; then + ALL_UPDATES="$REPO_UPDATES" + else + ALL_UPDATES="$AUR_UPDATES" + fi + + generate_json "$ALL_UPDATES" +} + +# === 真正的检查逻辑 === +perform_update_check() { + local REPO_UPDATES="" + local STATUS=0 + REPO_UPDATES=$(checkupdates 2>/dev/null) || STATUS=$? + + local AUR_UPDATES="" + if [[ -n "$AUR_HELPER" ]]; then + AUR_UPDATES=$("$AUR_HELPER" -Qua 2>/dev/null || true) + fi + + local ALL_UPDATES="" + if [[ $STATUS -eq 0 ]] || [[ $STATUS -eq 2 ]]; then + if [[ -n "$REPO_UPDATES" ]] && [[ -n "$AUR_UPDATES" ]]; then + ALL_UPDATES="$REPO_UPDATES"$'\n'"$AUR_UPDATES" + elif [[ -n "$REPO_UPDATES" ]]; then + ALL_UPDATES="$REPO_UPDATES" + else + ALL_UPDATES="$AUR_UPDATES" + fi + + echo "$REPO_UPDATES" > "${CACHE_FILE%.json}-repo.txt" + echo "$AUR_UPDATES" > "${CACHE_FILE%.json}-aur.txt" + generate_json "$ALL_UPDATES" > "$CACHE_FILE" + else + return 1 fi } -# === 主逻辑 === - -# 尝试获取更新 -# 捕获输出 -NEW_UPDATES=$(checkupdates 2>/dev/null) -STATUS=$? - -# === 关键修正 === -# checkupdates 退出代码说明: -# 0 = 有更新 -# 2 = 无更新 (这是正常情况,不是错误!) -# 1 = 发生错误 (如网络断开、锁被占用) - -if [ $STATUS -eq 0 ]; then - # --- 情况A:发现更新 --- - OUTPUT=$(generate_json "$NEW_UPDATES") - echo "$OUTPUT" > "$CACHE_FILE" - echo "$OUTPUT" - -elif [ $STATUS -eq 2 ]; then - # --- 情况B:正常运行,但没有更新 --- - # 必须清空缓存或者写入 0 状态,而不是读取旧缓存 - OUTPUT=$(generate_json "") - echo "$OUTPUT" > "$CACHE_FILE" - echo "$OUTPUT" - -else - # --- 情况C:真的出错了 (Exit 1) --- - # 比如没网,或者 pacman 锁死 - # 只有这种时候才读取旧缓存来保底 - if [ -f "$CACHE_FILE" ]; then - cat "$CACHE_FILE" - else - printf '{"text": "?", "alt": "updated", "tooltip": "Check failed"}\n' +# === 主控制逻辑 === +run_check() { + # 1. 检查缓存是否新鲜 (如果收到刷新信号 FORCE_UPDATE=1,则跳过判断) + if [[ $FORCE_UPDATE -eq 0 ]] && [[ -f "$CACHE_FILE" ]]; then + local current_time file_time age + current_time=$(date +%s) + file_time=$(stat -c %Y "$CACHE_FILE") + age=$((current_time - file_time)) + + if [[ $age -lt $((CHECK_INTERVAL - 10)) ]]; then + emit_cached_json + return + fi fi -fi + + # 准备干脏活累活前,重置标志位 + FORCE_UPDATE=0 + + # 【核心修复】:动态屏蔽 SIGUSR1 信号! + # 在执行耗时的网络和数据库操作时,无视一切 Ctrl+R 带来的外部干扰。 + trap '' SIGUSR1 + + # 2. 获取锁进行更新 + ( + if flock -x -n 9; then + perform_update_check || true + else + flock -x -w 120 9 || true + fi + ) 9>"$LOCK_FILE" || true + + # 【核心修复】:干完活了,重新恢复对 SIGUSR1 信号的监听 + trap 'on_sigusr1' SIGUSR1 + + # 3. 最终输出缓存内容 + if [[ -f "$CACHE_FILE" ]]; then + emit_cached_json + else + printf '{"text": "...", "alt": "updated", "tooltip": "Checking...\\n----------------\\n%s"}\n' "$(get_last_system_update_info)" + fi +} + +# === 主循环 === +while true; do + run_check + sleep "$CHECK_INTERVAL" & + + # 即使 sleep 被信号强行打断,|| true 也能保住脚本的命 + wait $! || true +done