用 Noctalia Shell 替代各种琐碎组件

This commit is contained in:
2026-05-19 20:19:28 +08:00
parent f1b8e14be3
commit bcc383a383
15 changed files with 127 additions and 265 deletions
+153
View File
@@ -0,0 +1,153 @@
#!/bin/bash
set -euo pipefail
THIS_COMMAND=$(basename "$0")
IMG_MAGICK="magick"
SERVICE_NAME="swaybg.service"
WP_DIR="${XDG_CACHE_HOME:-$HOME/.cache}"
WP_FILE="$WP_DIR/wallpaper"
BLUR_WP="$WP_DIR/wallpaper_blur"
usage() {
cat << EOF
Usage: $THIS_COMMAND [-d output_path] image1 image2 ...
Options:
-d, --dir OUTPUT_PATH Directory to store chosen image. (default: $WP_DIR)
-h, --help Show this help message and exit.
Notes:
- This script needs 'swaybg.service' to be set up for overview background support (unless awww #521 solved). See niri documentation for details.
- Web URLs are also supported (via 'curl' or 'wget' downloading).
- If multiple images are provided, one will be randomly picked each time the script is executed.
EOF
exit 1
}
# showing help shouldn't require any dependencies.
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--dir)
if [[ $# -lt 2 ]]; then echo "Missing argument for $1"; usage; fi
WP_DIR="$2"; shift 2 ;;
-h|--help)
usage ;;
--)
shift; break ;;
-*)
echo "Unknown option: $1"; usage ;;
*)
break ;;
esac
done
if ! command -v awww >/dev/null 2>&1; then
echo "x) 'awww' not found. Unable to comply." >&2
exit 2
fi
if command -v magick >/dev/null 2>&1; then
IMG_MAGICK="magick"
elif command -v convert >/dev/null 2>&1; then
IMG_MAGICK="convert"
else
echo "x) 'magick' or 'convert' not found. Image processing unavailable." >&2
exit 2
fi
set_wallpaper() {
fsize=$($IMG_MAGICK identify -format "%w %h" -- "$1" 2>/dev/null) || {
echo "Invalid image file." >&2
exit 10
}
finput=$1
read -r fw fh <<< "$fsize"
(( fw > 3840 && fh > 2160 )) && {
finput=$(mktemp "${TMPDIR:-/tmp}/chbg.XXXXXXXX.webp")
trap 'rm -f "$finput"' EXIT
echo " -> image too large, resizing ..."
# echo "DEBUG: resized image at $finput"
$IMG_MAGICK "$1" -resize "3840x2160^" \
-quality 90 \
-define webp:method=6 \
-define webp:alpha-quality=100 "$finput"
}
echo -n " -> making blurred version of '${1##*/}' ... "
cp "$finput" "$WP_FILE"
$IMG_MAGICK "$WP_FILE" -filter Gaussian -blur 0x30 "$BLUR_WP"
echo "Done."
awww img "$WP_FILE" --transition-type=random
if [[ -f "$HOME/.config/systemd/user/niri.service.wants/$SERVICE_NAME" ]]; then
echo " -> restarting $SERVICE_NAME ..."
systemctl --user restart "$SERVICE_NAME"
else
echo " !) '$SERVICE_NAME' didn't loaded by niri. Won't reload backdrop." >&2
echo " => See niri documentation for setting up swaybg systemd unit." >&2
echo " => Or wait for awww #521 on codeberg being resolved." >&2
exit 1
fi
}
imagepool=()
lastresult=""
# Read from stdin if data is available
if [ ! -t 0 ]; then
while IFS= read -r line; do
imagepool+=("$line")
done
fi
# Read from positional arguments
for arg in "$@"; do
imagepool+=("$arg")
done
if [ ${#imagepool[@]} -eq 0 ]; then
echo "No images provided." >&2
exit 1
fi
mkdir -p -- "$WP_DIR" "/tmp/$USER"
if [ -f "/tmp/$USER/chbg.last-slide.log" ]; then
lastresult=$(cat "/tmp/$USER/chbg.last-slide.log")
fi
# Select a random image from the pool and set it as wallpaper
while : ; do
randomimage="${imagepool[RANDOM % ${#imagepool[@]}]}"
if [[ "$randomimage" == "http://"* || "$randomimage" == "https://"* ]]; then
break
fi
if [ "$randomimage" != "$lastresult" ] || [ ${#imagepool[@]} -eq 1 ]; then
echo "$randomimage" > "/tmp/$USER/chbg.last-slide.log"
break
fi
done
echo "Selected: $randomimage"
request_wallpaper() {
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT
if command -v curl >/dev/null 2>&1; then
curl -sSL "$1" -o "$tmpfile"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$tmpfile" "$1"
else
echo "x) Unable to fetch image without 'curl' or 'wget'." >&2
exit 2
fi
set_wallpaper "$tmpfile"
}
if [ -f "$randomimage" ]; then
set_wallpaper "$randomimage"
else
request_wallpaper "$randomimage"
fi
+5
View File
@@ -0,0 +1,5 @@
[main]
style=/home/agxcoy/.config/gtklock/style.css
time-format=%H:%M:%S
date-format=%Y-%m-%d, %A
monitor-priority=HDMI-A-1;eDP-1
+15
View File
@@ -0,0 +1,15 @@
*{
transition: 1000ms ease ;
}
window {
background-image: url("/home/agxcoy/.cache/wallpaper_blur");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-color: rgba(0,0,0,0.3);
font-family: 'monospace';
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7)
}
#input-field {
background-color: rgba(3, 3, 3, 0.15)
}
+29
View File
@@ -0,0 +1,29 @@
sort=-time
layer=overlay
output=eDP-1
background-color=#1e1e2e
width=360
height=560
border-size=1
border-color=#45475a
border-radius=12
icons=1
max-icon-size=32
default-timeout=5000
ignore-timeout=1
font=MesloLGSNF 11
padding=8
[urgency=low]
border-color=#45475a
[urgency=normal]
border-color=#45475a
[urgency=high]
border-color=#f38ba8
default-timeout=0
[category=mpd]
default-timeout=2000
group-by=category
+103
View File
@@ -0,0 +1,103 @@
{
"layer": "top",
"modules-left": [
"niri/workspaces",
"niri/window"
// 我参考的那两人还用 sway,甚至大杂烩。而我只知道 niri,甚至一度也不想知道(不习惯)。
],
"modules-center": [
"clock"
],
"modules-right": [
"mpris",
"tray",
"battery",
"cpu",
"memory",
"temperature",
"pulseaudio"
],
"sway/scratchpad": {
"format": "󱂬 {count}"
},
"pulseaudio": {
"format": " {volume}%",
"format-muted": "x {volume}%",
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
"on-click-right": "pavucontrol-qt"
},
"niri/workspaces": {
"format": "{index}"
},
"niri/window": {
"format": "{}",
"icon": true,
"max-length": 40,
"icon-size": 14,
"rewrite": {
"(.*) — Mozilla Firefox": "$1",
"(.*) - Google Chrome": "$1",
"(.*) - Visual Studio Code": "$1",
"(.*) - VLC media player": "$1",
"Yazi: (.*)": "$1"
}
},
// 这玩意说实话没想象中那么好用,但移植雪叶那个脚本,效果甚至还没这个好。
"mpris": {
"format": "{status_icon} {title}",
"format-stopped": "",
"max-length": 40,
"status-icons": {
"paused": "",
"playing": "󰐊"
},
"interval": "3"
},
"clock": {
"format": "{:%d %b %H:%M}",
"interval": 1,
"tooltip-format": "{:%A %d %B %Y}"
},
"tray": {
"spacing": 12
},
// 忘记用哪个工具确定设备节点了。实在不行终端开 yazi 来回翻。
"temperature": {
// "thermal-zone": 1,
"hwmon-path-abs": "/sys/devices/platform/coretemp.0/hwmon",
"input-filename": "temp1_input",
"critical-threshold": 90,
// "format-critical": "{temperatureC}°C {icon}",
"format": "{icon} {temperatureC}°C",
"format-icons": [
"",
"",
""
]
},
"memory": {
"format": " {percentage}%",
"interval": 5
},
"cpu": {
"format": " {usage}%",
"interval": 2
},
"battery": {
"format": "{icon} {capacity}%",
"format-charging": "{icon} {capacity}% ",
"format-icons": [
"󰁺",
"󰁻",
"󰁼",
"󰁽",
"󰁾",
"󰁿",
"󰂀",
"󰂁",
"󰂂",
"󰁹"
],
"interval": 1
}
}
+74
View File
@@ -0,0 +1,74 @@
window#waybar {
background-color: rgba(25, 23, 36, 0.75);
color: #cdd6f4;
transition-property: background-color;
transition-duration: .5s;
border-bottom: 1px solid rgba(144, 140, 170, 0.35);
}
* {
font-family: "Symbols Nerd Font", monospace;
font-size: 10pt;
}
#workspaces button {
padding-top: 4px;
padding-bottom: 4px;
padding-left: 8px;
padding-right: 8px;
background-color: transparent;
border-radius: 100%;
border: 6px #f5c2e7;
font-weight: 800;
color: #a6adc8;
}
#workspaces button.urgent {
color: #fab387;
}
#workspaces button:hover {
background: rgba(69, 71, 90, 0.65);
color: #cdd6f4;
border: 12px #f5c2e7;
transition: none;
}
#workspaces button.focused {
color: #f5c2e7;
border: 12px #f5c2e7;
}
label.module {
padding: 0 10px 0 10px;
}
box.module button:hover {
box-shadow: none;
outline: none;
font-style: normal;
text-shadow: none;
}
#tray {
padding: 0 8 0 8;
}
menu {
background-color: #181825;
color: #cdd6f4;
border: 1px solid #494d64;
padding: 6px;
border-radius: 12px;
}
#tray menu menuitem:hover {
background-color: #1e1e2e;
color: #f5c2e7;
border-radius: 5px;
}
#window {
font-weight: 800;
padding: 0px 8px 0px 8px;
}