mirror of
https://github.com/Nexoniarz/nexoniarz-config-nixos.git
synced 2026-11-03 04:24:27 +00:00
nixos config
This commit is contained in:
commit
5dc9fb020e
46 changed files with 6194 additions and 0 deletions
32
modules/scripts/brightness-ctl.sh
Executable file
32
modules/scripts/brightness-ctl.sh
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env bash
|
||||
# Brightness control abstraction: prefers the kernel backlight class (laptop
|
||||
# panels, via brightnessctl); falls back to DDC/CI over I2C (external
|
||||
# monitors, via ddcutil) when no backlight device exists. Keeps the rest of
|
||||
# the config (Quickshell's brightness popup) hardware-agnostic.
|
||||
set -euo pipefail
|
||||
|
||||
has_backlight() {
|
||||
[ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]
|
||||
}
|
||||
|
||||
case "${1:-get}" in
|
||||
get)
|
||||
if has_backlight; then
|
||||
brightnessctl -m | cut -d, -f4 | tr -d '%'
|
||||
else
|
||||
ddcutil getvcp 10 --brief 2>/dev/null | awk '{print $4}'
|
||||
fi
|
||||
;;
|
||||
set)
|
||||
pct="${2:?usage: brightness-ctl set <0-100>}"
|
||||
if has_backlight; then
|
||||
brightnessctl set "${pct}%" > /dev/null
|
||||
else
|
||||
ddcutil setvcp 10 "$pct" > /dev/null
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "usage: brightness-ctl [get|set <0-100>]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
54
modules/scripts/cursor-preview-all.sh
Normal file
54
modules/scripts/cursor-preview-all.sh
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env bash
|
||||
# Extracts a small preview PNG (closest to 32px) for every installed
|
||||
# cursor theme's "left_ptr" cursor into a cache directory, one per theme
|
||||
# named "<theme>.png". Xcursor files are a binary format QML's Image
|
||||
# element can't decode directly, so this is a one-time render step —
|
||||
# already-cached themes are skipped.
|
||||
#
|
||||
# usage: cursor-preview-all <cache-dir>
|
||||
set -euo pipefail
|
||||
|
||||
cache_dir="${1:?usage: cursor-preview-all <cache-dir>}"
|
||||
mkdir -p "$cache_dir"
|
||||
|
||||
dirs=(
|
||||
"$HOME/.icons"
|
||||
"$HOME/.local/share/icons"
|
||||
"/run/current-system/sw/share/icons"
|
||||
"/etc/profiles/per-user/$USER/share/icons"
|
||||
)
|
||||
|
||||
render_one() {
|
||||
local theme="$1"
|
||||
local src="$2"
|
||||
local out="$cache_dir/$theme.png"
|
||||
[ -e "$out" ] && return 0
|
||||
|
||||
local tmp
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' RETURN
|
||||
|
||||
xcur2png -q -d "$tmp" -c "$tmp/conf" -i 1 "$src" > /dev/null 2>&1 || return 0
|
||||
|
||||
local best=""
|
||||
local best_diff=999999
|
||||
for png in "$tmp"/*.png; do
|
||||
[ -e "$png" ] || continue
|
||||
local w
|
||||
w=$(identify -format "%w" "$png" 2>/dev/null || echo 0)
|
||||
local diff=$(( w > 32 ? w - 32 : 32 - w ))
|
||||
if [ "$diff" -lt "$best_diff" ]; then
|
||||
best_diff=$diff
|
||||
best="$png"
|
||||
fi
|
||||
done
|
||||
[ -n "$best" ] && cp "$best" "$out"
|
||||
}
|
||||
|
||||
for d in "${dirs[@]}"; do
|
||||
[ -d "$d" ] || continue
|
||||
for theme_dir in "$d"/*/; do
|
||||
[ -f "${theme_dir}cursors/left_ptr" ] || continue
|
||||
render_one "$(basename "$theme_dir")" "${theme_dir}cursors/left_ptr"
|
||||
done
|
||||
done
|
||||
16
modules/scripts/cursor-set.sh
Executable file
16
modules/scripts/cursor-set.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
# Applies a cursor theme immediately (hyprctl) and persists it across
|
||||
# restarts by writing env vars to a file hyprland.conf sources on startup.
|
||||
set -euo pipefail
|
||||
|
||||
theme="${1:?usage: cursor-set <theme-name> [size]}"
|
||||
size="${2:-24}"
|
||||
|
||||
hyprctl setcursor "$theme" "$size" > /dev/null
|
||||
|
||||
mkdir -p "$HOME/.config/hypr"
|
||||
cat > "$HOME/.config/hypr/cursor.conf" <<EOF
|
||||
env = HYPRCURSOR_THEME,$theme
|
||||
env = XCURSOR_THEME,$theme
|
||||
env = XCURSOR_SIZE,$size
|
||||
EOF
|
||||
37
modules/scripts/display-set.sh
Normal file
37
modules/scripts/display-set.sh
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env bash
|
||||
# Applies a monitor mode/position/scale/transform immediately (hyprctl)
|
||||
# AND persists it into ~/.config/hypr/display.conf, which hyprland.conf
|
||||
# sources — without that file, hyprland.conf's generic fallback rule
|
||||
# ("monitor = , preferred, auto, 1") is the only thing on record, and
|
||||
# ANYTHING that makes Hyprland re-evaluate monitor state (observed: even
|
||||
# changing the cursor theme via `hyprctl setcursor` does this) reapplies
|
||||
# that fallback, silently dropping back to "preferred" refresh rate
|
||||
# instead of whatever the user actually picked.
|
||||
set -euo pipefail
|
||||
|
||||
mon="${1:?usage: display-set <monitor> <mode> <x> <y> <scale> [transform]}"
|
||||
mode="${2:?mode required}"
|
||||
x="${3:?x required}"
|
||||
y="${4:?y required}"
|
||||
scale="${5:?scale required}"
|
||||
transform="${6:-0}"
|
||||
|
||||
descriptor="$mon,$mode,${x}x${y},$scale"
|
||||
[ "$transform" != "0" ] && descriptor="$descriptor,transform,$transform"
|
||||
|
||||
conf="$HOME/.config/hypr/display.conf"
|
||||
mkdir -p "$(dirname "$conf")"
|
||||
touch "$conf"
|
||||
|
||||
line="monitor = $descriptor"
|
||||
if grep -q "^monitor = $mon," "$conf" 2>/dev/null; then
|
||||
tmp=$(mktemp)
|
||||
awk -v prefix="monitor = $mon," -v newline="$line" '
|
||||
index($0, prefix) == 1 { print newline; next } { print }
|
||||
' "$conf" > "$tmp"
|
||||
mv "$tmp" "$conf"
|
||||
else
|
||||
echo "$line" >> "$conf"
|
||||
fi
|
||||
|
||||
hyprctl keyword monitor "$descriptor" > /dev/null
|
||||
119
modules/scripts/gtk-theme-set.sh
Normal file
119
modules/scripts/gtk-theme-set.sh
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env bash
|
||||
# Regenerates GTK3/4 CSS + settings.ini to match the current Quickshell
|
||||
# theme (accent color + dark/light mode). These used to be static,
|
||||
# Nix-rebuild-only files (symlinked straight into the store) — this makes
|
||||
# them live-editable instead, the same way cursor.conf/display.conf work,
|
||||
# so the Theme picker can actually reach GTK apps like Thunar.
|
||||
set -euo pipefail
|
||||
|
||||
accent="${1:?usage: gtk-theme-set <accent> <bg> <bgAlt> <fg> <fgDim> <border> <dark:1|0>}"
|
||||
bg="${2:?bg required}"
|
||||
bg_alt="${3:?bgAlt required}"
|
||||
fg="${4:?fg required}"
|
||||
fg_dim="${5:?fgDim required}"
|
||||
border="${6:?border required}"
|
||||
dark="${7:?dark required}"
|
||||
|
||||
dir3="$HOME/.config/gtk-3.0"
|
||||
dir4="$HOME/.config/gtk-4.0"
|
||||
mkdir -p "$dir3" "$dir4"
|
||||
|
||||
css_file=$(mktemp)
|
||||
cat > "$css_file" <<EOF
|
||||
/* Squared corners + accent colors, generated by gtk-theme-set from the
|
||||
Quickshell Theme picker — GTK's CSS is a subset of real CSS: no
|
||||
!important, and zero still needs a unit.
|
||||
|
||||
The @define-color block matters more than it looks: plain selector
|
||||
overrides (window, .background, .view, ...) only get you so far —
|
||||
Thunar's icon-view content area and sidebar tree view turned out to
|
||||
pull their actual fill color from these named theme variables
|
||||
internally, not from the generic background-color cascade. Verified
|
||||
live: without redefining theme_base_color specifically, the sidebar
|
||||
and file grid stayed white no matter how broad the selector list got. */
|
||||
@define-color theme_bg_color $bg;
|
||||
@define-color theme_base_color $bg;
|
||||
@define-color theme_fg_color $fg;
|
||||
@define-color theme_text_color $fg;
|
||||
@define-color theme_selected_bg_color $accent;
|
||||
@define-color theme_selected_fg_color $bg;
|
||||
@define-color borders $border;
|
||||
|
||||
* {
|
||||
border-radius: 0px;
|
||||
-gtk-outline-radius: 0px;
|
||||
}
|
||||
window, .background, .view, iconview, treeview, treeview.view, list, row,
|
||||
notebook, notebook > stack, scrolledwindow, viewport {
|
||||
background-color: $bg;
|
||||
color: $fg;
|
||||
}
|
||||
iconview.cell, iconview text {
|
||||
background-color: $bg;
|
||||
color: $fg;
|
||||
}
|
||||
treeview.view:selected, row:selected, iconview:selected {
|
||||
background-color: $accent;
|
||||
color: $bg;
|
||||
}
|
||||
headerbar, .titlebar {
|
||||
background-color: $bg_alt;
|
||||
color: $fg;
|
||||
border-color: $border;
|
||||
box-shadow: none;
|
||||
}
|
||||
button {
|
||||
border-color: $border;
|
||||
}
|
||||
button:hover {
|
||||
background-color: $bg_alt;
|
||||
}
|
||||
selection, *:selected {
|
||||
background-color: $accent;
|
||||
color: $bg;
|
||||
}
|
||||
EOF
|
||||
|
||||
cp "$css_file" "$dir3/gtk.css"
|
||||
cp "$css_file" "$dir4/gtk.css"
|
||||
rm -f "$css_file"
|
||||
|
||||
prefer_dark="false"
|
||||
theme_name="Adwaita"
|
||||
icon_theme="Gruvbox-Plus-Light"
|
||||
if [ "$dark" = "1" ]; then
|
||||
prefer_dark="true"
|
||||
theme_name="Adwaita-dark"
|
||||
icon_theme="Gruvbox-Plus-Dark"
|
||||
fi
|
||||
|
||||
ini_file=$(mktemp)
|
||||
cat > "$ini_file" <<EOF
|
||||
[Settings]
|
||||
gtk-application-prefer-dark-theme=$prefer_dark
|
||||
gtk-theme-name=$theme_name
|
||||
gtk-icon-theme-name=$icon_theme
|
||||
gtk-font-name=Noto Sans, 10
|
||||
gtk-enable-animations=true
|
||||
EOF
|
||||
|
||||
cp "$ini_file" "$dir3/settings.ini"
|
||||
cp "$ini_file" "$dir4/settings.ini"
|
||||
rm -f "$ini_file"
|
||||
|
||||
# settings.ini alone isn't enough: GTK3 binds gtk-theme-name/icon-theme-name
|
||||
# to org.gnome.desktop.interface via GSettings whenever that schema and a
|
||||
# dconf backend are present (they are here — dconf-service was already
|
||||
# running), and that binding wins over settings.ini unconditionally. This
|
||||
# machine's dconf database had hard values left over (gtk-theme='Breeze',
|
||||
# icon-theme='breeze') that silently overrode every settings.ini edit —
|
||||
# which is why neither accent/dark-mode nor the Gruvbox icon switch ever
|
||||
# reached Thunar. Writing the same values to dconf keeps both sources in
|
||||
# sync so it doesn't matter which one GTK actually reads from.
|
||||
if command -v dconf >/dev/null 2>&1; then
|
||||
color_scheme="default"
|
||||
[ "$dark" = "1" ] && color_scheme="prefer-dark"
|
||||
dconf write /org/gnome/desktop/interface/gtk-theme "'$theme_name'"
|
||||
dconf write /org/gnome/desktop/interface/icon-theme "'$icon_theme'"
|
||||
dconf write /org/gnome/desktop/interface/color-scheme "'$color_scheme'"
|
||||
fi
|
||||
33
modules/scripts/hotspot-start.sh
Executable file
33
modules/scripts/hotspot-start.sh
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env bash
|
||||
# Starts a Wi-Fi hotspot with explicit security/band control — the simple
|
||||
# `nmcli device wifi hotspot` one-liner doesn't expose those.
|
||||
# hotspot-start <ssid> <password> <wpa2|wpa3> <auto|bg|a>
|
||||
set -euo pipefail
|
||||
|
||||
ssid="${1:?usage: hotspot-start <ssid> <password> <wpa2|wpa3> <auto|bg|a>}"
|
||||
password="${2:?password required}"
|
||||
security="${3:-wpa2}"
|
||||
band="${4:-auto}"
|
||||
|
||||
iface=$(nmcli -t -f DEVICE,TYPE device | awk -F: '$2=="wifi"{print $1; exit}')
|
||||
if [ -z "$iface" ]; then
|
||||
echo "No Wi-Fi device found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Idempotent: drop any previous Hotspot profile from an earlier run first.
|
||||
nmcli connection delete Hotspot >/dev/null 2>&1 || true
|
||||
|
||||
key_mgmt="wpa-psk"
|
||||
[ "$security" = "wpa3" ] && key_mgmt="sae"
|
||||
|
||||
nmcli connection add type wifi ifname "$iface" con-name Hotspot autoconnect no ssid "$ssid" > /dev/null
|
||||
nmcli connection modify Hotspot 802-11-wireless.mode ap
|
||||
if [ "$band" != "auto" ]; then
|
||||
nmcli connection modify Hotspot 802-11-wireless.band "$band"
|
||||
fi
|
||||
nmcli connection modify Hotspot wifi-sec.key-mgmt "$key_mgmt"
|
||||
nmcli connection modify Hotspot wifi-sec.psk "$password"
|
||||
nmcli connection modify Hotspot ipv4.method shared
|
||||
|
||||
nmcli connection up Hotspot
|
||||
23
modules/scripts/hypr-theme-set.sh
Normal file
23
modules/scripts/hypr-theme-set.sh
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
# Applies Hyprland's active/inactive window border colors immediately AND
|
||||
# persists them into ~/.config/hypr/display.conf's sibling, theme.conf
|
||||
# (sourced by hyprland.conf after the static general{} block, so it
|
||||
# overrides those hardcoded defaults) — without that file, a config
|
||||
# reload/restart would silently revert to whatever's hardcoded in
|
||||
# hyprland.conf, same class of bug as the display-settings one.
|
||||
set -euo pipefail
|
||||
|
||||
accent="${1:?usage: hypr-theme-set <accent_hex_no_hash> <border_hex_no_hash>}"
|
||||
border="${2:?border required}"
|
||||
|
||||
hyprctl keyword general:col.active_border "rgba(${accent}ff)" > /dev/null
|
||||
hyprctl keyword general:col.inactive_border "rgba(${border}ff)" > /dev/null
|
||||
|
||||
conf="$HOME/.config/hypr/theme.conf"
|
||||
mkdir -p "$(dirname "$conf")"
|
||||
cat > "$conf" <<EOF
|
||||
general {
|
||||
col.active_border = rgba(${accent}ff)
|
||||
col.inactive_border = rgba(${border}ff)
|
||||
}
|
||||
EOF
|
||||
31
modules/scripts/kitty-theme-set.sh
Normal file
31
modules/scripts/kitty-theme-set.sh
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
# Regenerates ~/.config/kitty/theme.conf (included from kitty.conf) to
|
||||
# match the current Quickshell theme. No explicit reload needed — kitty
|
||||
# has a built-in config-file watcher (visible as `kitten __watch_conf__`
|
||||
# in its process list) that also watches included files, so this takes
|
||||
# effect live in already-open kitty windows.
|
||||
set -euo pipefail
|
||||
|
||||
accent="${1:?usage: kitty-theme-set <accent> <bg> <bgAlt> <fg> <fgDim> <border>}"
|
||||
bg="${2:?bg required}"
|
||||
bg_alt="${3:?bgAlt required}"
|
||||
fg="${4:?fg required}"
|
||||
fg_dim="${5:?fgDim required}"
|
||||
border="${6:?border required}"
|
||||
|
||||
conf="$HOME/.config/kitty/theme.conf"
|
||||
mkdir -p "$(dirname "$conf")"
|
||||
|
||||
cat > "$conf" <<EOF
|
||||
background $bg
|
||||
foreground $fg
|
||||
selection_background $border
|
||||
selection_foreground $fg
|
||||
cursor $fg
|
||||
active_border_color $accent
|
||||
inactive_border_color $border
|
||||
active_tab_background $bg_alt
|
||||
active_tab_foreground $fg
|
||||
inactive_tab_background $bg
|
||||
inactive_tab_foreground $fg_dim
|
||||
EOF
|
||||
22
modules/scripts/list-cursor-themes.sh
Executable file
22
modules/scripts/list-cursor-themes.sh
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
# Lists installed Xcursor themes by scanning the real XCURSOR_PATH locations
|
||||
# for a "cursors" subdirectory — no hardcoded theme names.
|
||||
set -euo pipefail
|
||||
|
||||
dirs=(
|
||||
"$HOME/.icons"
|
||||
"$HOME/.local/share/icons"
|
||||
"/run/current-system/sw/share/icons"
|
||||
# Packages installed via users.users.<name>.packages (as opposed to
|
||||
# environment.systemPackages) land here, not under
|
||||
# /run/current-system/sw — this is where bibata-cursors actually is.
|
||||
"/etc/profiles/per-user/$USER/share/icons"
|
||||
)
|
||||
|
||||
for d in "${dirs[@]}"; do
|
||||
[ -d "$d" ] || continue
|
||||
for theme in "$d"/*/; do
|
||||
[ -d "${theme}cursors" ] || continue
|
||||
basename "$theme"
|
||||
done
|
||||
done | sort -u
|
||||
36
modules/scripts/rofi-theme-set.sh
Normal file
36
modules/scripts/rofi-theme-set.sh
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env bash
|
||||
# Regenerates ~/.config/rofi/theme.rasi (imported by config.rasi) to match
|
||||
# the current Quickshell theme. Rofi has no config-file watcher — unlike
|
||||
# kitty, it's launched on demand rather than staying resident, so the next
|
||||
# time it's opened it just reads whatever is on disk. No reload step needed.
|
||||
set -euo pipefail
|
||||
|
||||
accent="${1:?usage: rofi-theme-set <accent> <bg> <bgAlt> <fg> <fgDim> <border> <dark:1|0>}"
|
||||
bg="${2:?bg required}"
|
||||
bg_alt="${3:?bgAlt required}"
|
||||
fg="${4:?fg required}"
|
||||
fg_dim="${5:?fgDim required}"
|
||||
border="${6:?border required}"
|
||||
dark="${7:?dark required}"
|
||||
|
||||
icon_theme="Gruvbox-Plus-Light"
|
||||
if [ "$dark" = "1" ]; then
|
||||
icon_theme="Gruvbox-Plus-Dark"
|
||||
fi
|
||||
|
||||
conf="$HOME/.config/rofi/theme.rasi"
|
||||
mkdir -p "$(dirname "$conf")"
|
||||
|
||||
cat > "$conf" <<EOF
|
||||
* {
|
||||
bg: ${bg}ee;
|
||||
bg-alt: ${bg_alt}ee;
|
||||
fg: ${fg}ff;
|
||||
accent: ${accent}ff;
|
||||
border-color: ${border}ff;
|
||||
placeholder: ${fg_dim}ff;
|
||||
}
|
||||
configuration {
|
||||
icon-theme: "$icon_theme";
|
||||
}
|
||||
EOF
|
||||
51
modules/scripts/screenshot.sh
Executable file
51
modules/scripts/screenshot.sh
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env bash
|
||||
# Unified screenshot helper.
|
||||
# screenshot <region|full|window> <clipboard|file|both>
|
||||
set -euo pipefail
|
||||
|
||||
mode="${1:-region}"
|
||||
action="${2:-both}"
|
||||
|
||||
geom=()
|
||||
case "$mode" in
|
||||
region)
|
||||
sel="$(slurp)" || exit 0
|
||||
[ -z "$sel" ] && exit 0
|
||||
geom=(-g "$sel")
|
||||
;;
|
||||
window)
|
||||
win="$(hyprctl activewindow -j)"
|
||||
at_x=$(echo "$win" | jq -r '.at[0]')
|
||||
at_y=$(echo "$win" | jq -r '.at[1]')
|
||||
w=$(echo "$win" | jq -r '.size[0]')
|
||||
h=$(echo "$win" | jq -r '.size[1]')
|
||||
geom=(-g "${at_x},${at_y} ${w}x${h}")
|
||||
;;
|
||||
full)
|
||||
geom=()
|
||||
;;
|
||||
*)
|
||||
echo "unknown mode: $mode (expected region|full|window)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p "$HOME/Screenshots"
|
||||
file="$HOME/Screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"
|
||||
|
||||
case "$action" in
|
||||
clipboard)
|
||||
grim "${geom[@]}" - | wl-copy
|
||||
;;
|
||||
file)
|
||||
grim "${geom[@]}" "$file"
|
||||
;;
|
||||
both)
|
||||
grim "${geom[@]}" "$file"
|
||||
wl-copy < "$file"
|
||||
;;
|
||||
*)
|
||||
echo "unknown action: $action (expected clipboard|file|both)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
26
modules/scripts/show-desktop-toggle.sh
Executable file
26
modules/scripts/show-desktop-toggle.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
# "Show desktop" for Hyprland: stashes every window on the active workspace
|
||||
# into a hidden special workspace, and restores each one to the workspace
|
||||
# it came from on the next press — regardless of which workspace you're on
|
||||
# when you press it again (a single global state file, not one keyed by
|
||||
# "current workspace", which broke the moment you switched workspaces
|
||||
# in between).
|
||||
set -euo pipefail
|
||||
|
||||
state_file="${XDG_RUNTIME_DIR:-/tmp}/hypr-show-desktop.json"
|
||||
|
||||
if [ -s "$state_file" ]; then
|
||||
jq -c '.[]' "$state_file" | while IFS= read -r entry; do
|
||||
addr=$(echo "$entry" | jq -r '.address')
|
||||
ws=$(echo "$entry" | jq -r '.workspace')
|
||||
hyprctl dispatch movetoworkspacesilent "$ws,address:$addr" > /dev/null
|
||||
done
|
||||
rm -f "$state_file"
|
||||
else
|
||||
ws_id=$(hyprctl activeworkspace -j | jq -r '.id')
|
||||
hyprctl clients -j | jq -c --argjson ws "$ws_id" \
|
||||
'[.[] | select(.workspace.id == $ws) | {address: .address, workspace: $ws}]' > "$state_file"
|
||||
jq -r '.[].address' "$state_file" | while IFS= read -r addr; do
|
||||
[ -n "$addr" ] && hyprctl dispatch movetoworkspacesilent "special:showdesktop,address:$addr" > /dev/null
|
||||
done
|
||||
fi
|
||||
24
modules/scripts/strip-metadata.sh
Executable file
24
modules/scripts/strip-metadata.sh
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: strip-metadata <file_or_directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET="$1"
|
||||
|
||||
echo "[*] Stripping metadata from: $TARGET"
|
||||
|
||||
# Remove all embedded metadata while keeping original filenames
|
||||
if command -v exiftool &> /dev/null; then
|
||||
exiftool -all= -overwrite_original -r "$TARGET"
|
||||
echo "[+] Exif metadata removed."
|
||||
else
|
||||
echo "[!] Warning: exiftool is not installed."
|
||||
fi
|
||||
|
||||
# Reset timestamps (atime and mtime) to Epoch (1970-01-01 00:00:00)
|
||||
echo "[*] Resetting timestamps..."
|
||||
find "$TARGET" -exec touch -t 197001010000.00 {} +
|
||||
|
||||
echo "[+] Operation completed successfully."
|
||||
30
modules/scripts/vault-toggle.sh
Executable file
30
modules/scripts/vault-toggle.sh
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
CIPHER_DIR="/run/media/nexoniarz/Lukas/.vault_cipher"
|
||||
MOUNT_DIR="$HOME/Vault"
|
||||
|
||||
mkdir -p "$CIPHER_DIR" "$MOUNT_DIR"
|
||||
|
||||
if mountpoint -q "$MOUNT_DIR"; then
|
||||
echo "[*] Synchronizing buffers and unmounting Vault..."
|
||||
sync
|
||||
|
||||
if fusermount -u "$MOUNT_DIR"; then
|
||||
echo "[+] Vault unmounted successfully."
|
||||
else
|
||||
echo "[!] Failed to unmount Vault. Check if any application is using $MOUNT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "[*] Mounting Vault..."
|
||||
if [ ! -f "$CIPHER_DIR/gocryptfs.conf" ]; then
|
||||
echo "[!] Container not initialized. Initializing new gocryptfs vault..."
|
||||
gocryptfs -init "$CIPHER_DIR" || exit 1
|
||||
fi
|
||||
if gocryptfs -allow_other "$CIPHER_DIR" "$MOUNT_DIR"; then
|
||||
echo "[+] Vault mounted successfully at $MOUNT_DIR"
|
||||
else
|
||||
echo "[!] Mount failed."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
30
modules/scripts/wallpaper-delete.sh
Normal file
30
modules/scripts/wallpaper-delete.sh
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env bash
|
||||
# Removes a wallpaper by moving it to the freedesktop.org trash
|
||||
# (~/.local/share/Trash), the same mechanism Thunar's own delete uses —
|
||||
# so it shows up in Thunar's Trash and can be restored from there,
|
||||
# instead of `rm` permanently destroying it with no way back.
|
||||
set -euo pipefail
|
||||
|
||||
path="${1:?usage: wallpaper-delete <path>}"
|
||||
[ -e "$path" ] || exit 0
|
||||
|
||||
trash_dir="$HOME/.local/share/Trash"
|
||||
mkdir -p "$trash_dir/files" "$trash_dir/info"
|
||||
|
||||
name="$(basename "$path")"
|
||||
dest="$trash_dir/files/$name"
|
||||
info="$trash_dir/info/$name.trashinfo"
|
||||
n=1
|
||||
while [ -e "$dest" ] || [ -e "$info" ]; do
|
||||
dest="$trash_dir/files/${name}.$n"
|
||||
info="$trash_dir/info/${name}.$n.trashinfo"
|
||||
n=$((n + 1))
|
||||
done
|
||||
|
||||
cat > "$info" <<EOF
|
||||
[Trash Info]
|
||||
Path=$path
|
||||
DeletionDate=$(date +%Y-%m-%dT%H:%M:%S)
|
||||
EOF
|
||||
|
||||
mv "$path" "$dest"
|
||||
60
modules/scripts/wallpaper-set.sh
Executable file
60
modules/scripts/wallpaper-set.sh
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env bash
|
||||
# Sets the desktop wallpaper — static images go through hyprpaper's IPC,
|
||||
# video files loop via mpvpaper. Only one backend should ever be driving
|
||||
# the background at a time, so switching to one always tears the other
|
||||
# down first.
|
||||
#
|
||||
# usage: wallpaper-set <path> [fit_mode] [muted] [speed] [auto_pause]
|
||||
# fit_mode: cover|contain (static images only, default cover)
|
||||
# muted: 1|0 (animated only, default 1)
|
||||
# speed: playback speed (animated only, default 1.0)
|
||||
# auto_pause: 1|0 (animated only — mpvpaper -p, pauses
|
||||
# playback while the wallpaper is hidden
|
||||
# behind a fullscreen window, default 1)
|
||||
set -euo pipefail
|
||||
|
||||
image="${1:?usage: wallpaper-set <path> [fit_mode] [muted] [speed] [auto_pause]}"
|
||||
fit_mode="${2:-cover}"
|
||||
muted="${3:-1}"
|
||||
speed="${4:-1.0}"
|
||||
auto_pause="${5:-1}"
|
||||
|
||||
case "${image,,}" in
|
||||
*.mp4|*.webm|*.mkv|*.mov|*.gif)
|
||||
# -9: plain SIGTERM doesn't reliably kill mpvpaper (verified live —
|
||||
# it survives pkill -f without -9), which would leave the old
|
||||
# instance still holding the layer-shell surface underneath a new
|
||||
# one. The short sleep gives it a moment to actually release that
|
||||
# surface before a replacement tries to claim it.
|
||||
pkill -9 -f mpvpaper > /dev/null 2>&1 || true
|
||||
sleep 0.3
|
||||
|
||||
mpv_opts="loop-playlist=inf speed=$speed"
|
||||
[ "$muted" = "1" ] && mpv_opts="no-audio $mpv_opts"
|
||||
|
||||
mpvpaper_flags=()
|
||||
[ "$auto_pause" = "1" ] && mpvpaper_flags+=("-p")
|
||||
|
||||
# setsid + disown so mpvpaper (which runs forever, looping the
|
||||
# video) survives after this script exits.
|
||||
setsid mpvpaper "${mpvpaper_flags[@]}" -o "$mpv_opts" '*' "$image" \
|
||||
> /dev/null 2>&1 < /dev/null &
|
||||
disown
|
||||
;;
|
||||
*)
|
||||
# -9: plain SIGTERM doesn't reliably kill mpvpaper (verified live —
|
||||
# it survives pkill -f without -9), which would leave the old
|
||||
# instance still holding the layer-shell surface underneath a new
|
||||
# one. The short sleep gives it a moment to actually release that
|
||||
# surface before a replacement tries to claim it.
|
||||
pkill -9 -f mpvpaper > /dev/null 2>&1 || true
|
||||
sleep 0.3
|
||||
# This hyprpaper version's IPC only exposes a single `wallpaper`
|
||||
# request (confirmed via `hyprctl hyprpaper --help`) — it loads
|
||||
# and swaps the image in one call. preload/unload/listloaded
|
||||
# requests it used to need don't exist anymore and error out with
|
||||
# "invalid hyprpaper request", which — combined with `set -e` —
|
||||
# was aborting this script before it ever got here.
|
||||
hyprctl hyprpaper wallpaper ",$image,$fit_mode" > /dev/null
|
||||
;;
|
||||
esac
|
||||
Loading…
Reference in a new issue