Adds a Download-random-wallpaper button and a 3-way content filter (SFW/Sketchy/NSFW) to our Wallpaper settings page, backed by a new WallpaperDownload service and its own download script under surfaces/quickshell/scripts/wallpaper/ — not ii's scripts/colors tree, which is going away. Only the 'wallpapers apply' IPC target still comes from ii and moves with it when the base is vendored. Downloads are named by wallhaven id so the library accumulates instead of overwriting a single wallhaven_wallpaper.<ext>. Purity is read from and written to background.wallhaven.purity in config.json (not in the upstream Config.options schema). Anchors the root scripts/ gitignore to / so shipped surface scripts are tracked.
253 lines
13 KiB
Shell
Executable file
253 lines
13 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
# Compose the Souveraine quickshell config (`qs -c souveraine`).
|
|
#
|
|
# Model: ~/.config/quickshell/souveraine is BUILT by this script —
|
|
# - our files (this repo) are symlinked in, repo stays source of truth
|
|
# - untouched upstream directories are borrowed as whole-dir symlinks
|
|
# into the ii tree (so upstream updates flow through)
|
|
# - directories where we override any file are composed file-by-file
|
|
# The ii tree itself is DEPLOYED from this repo (ii-base/, the pinned base —
|
|
# vendored 2026-07-21 after laptop/phone drifted ~900 files): every run
|
|
# rsyncs ii-base -> ~/.config/quickshell/ii, so "borrowed from ii" means
|
|
# borrowed from the same pin on every device. On the phone (aarch64) the
|
|
# ii-phone/ overlay is applied on top — the declared home for phone-only
|
|
# files (Cellular, mobile bar/OSK/wallpaper behavior). Never hand-edit
|
|
# ~/.config/quickshell/ii; change ii-base/ (or ii-phone/) and redeploy.
|
|
#
|
|
# deploy.sh compose ~/.config/quickshell/souveraine
|
|
# deploy.sh -u remove the souveraine config dir (ii untouched)
|
|
# deploy.sh --legacy-clean remove the OLD overlay symlinks from ii and
|
|
# restore its .upstream backups (one-time migration)
|
|
# deploy.sh --phone rsync this surface to the phone and deploy there
|
|
set -euo pipefail
|
|
|
|
SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
QS="${HOME}/.config/quickshell"
|
|
II="${QS}/ii"
|
|
SV="${QS}/souveraine"
|
|
|
|
# Manifest: "<repo-relative> <target-relative-to-~/.config/quickshell>"
|
|
MANIFEST="
|
|
shell.qml souveraine/shell.qml
|
|
GlobalStates.qml souveraine/GlobalStates.qml
|
|
settings.qml souveraine/settings.qml
|
|
settings-phone.qml souveraine/settings-phone.qml
|
|
panelFamilies/SouveraineFamily.qml souveraine/panelFamilies/SouveraineFamily.qml
|
|
services/Souveraine.qml souveraine/services/Souveraine.qml
|
|
services/Ai.qml souveraine/services/Ai.qml
|
|
services/TaskbarApps.qml souveraine/services/TaskbarApps.qml
|
|
services/GlobalFocusGrab.qml souveraine/services/GlobalFocusGrab.qml
|
|
services/Idle.qml souveraine/services/Idle.qml
|
|
services/IdleCoordinator.qml souveraine/services/IdleCoordinator.qml
|
|
services/LockContentPolicy.qml souveraine/services/LockContentPolicy.qml
|
|
services/WallpaperAssets.qml souveraine/services/WallpaperAssets.qml
|
|
services/WallpaperDownload.qml souveraine/services/WallpaperDownload.qml
|
|
scripts/wallpaper/download_wallhaven.sh souveraine/scripts/wallpaper/download_wallhaven.sh
|
|
services/ConflictKiller.qml souveraine/services/ConflictKiller.qml
|
|
services/SessionEvents.qml souveraine/services/SessionEvents.qml
|
|
services/SessiondBridge.qml souveraine/services/SessiondBridge.qml
|
|
services/StepUpAuth.qml souveraine/services/StepUpAuth.qml
|
|
services/SessionAudit.qml souveraine/services/SessionAudit.qml
|
|
services/Speech.qml souveraine/services/Speech.qml
|
|
services/NotifyEvents.qml souveraine/services/NotifyEvents.qml
|
|
services/CrashReporter.qml souveraine/services/CrashReporter.qml
|
|
modules/ii/sidebarLeft/SidebarLeft.qml souveraine/modules/ii/sidebarLeft/SidebarLeft.qml
|
|
modules/ii/sidebarLeft/AiChat.qml souveraine/modules/ii/sidebarLeft/AiChat.qml
|
|
modules/ii/sidebarRight/SidebarRight.qml souveraine/modules/ii/sidebarRight/SidebarRight.qml
|
|
modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml souveraine/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml
|
|
modules/ii/bar/UtilButtons.qml souveraine/modules/ii/bar/UtilButtons.qml
|
|
modules/common/Config.qml souveraine/modules/common/Config.qml
|
|
modules/common/ShellModel.qml souveraine/modules/common/ShellModel.qml
|
|
modules/common/functions/Session.qml souveraine/modules/common/functions/Session.qml
|
|
modules/common/widgets/ContentPage.qml souveraine/modules/common/widgets/ContentPage.qml
|
|
modules/common/widgets/StyledToolTip.qml souveraine/modules/common/widgets/StyledToolTip.qml
|
|
modules/settings/DeviceConfig.qml souveraine/modules/settings/DeviceConfig.qml
|
|
modules/settings/LockConfig.qml souveraine/modules/settings/LockConfig.qml
|
|
modules/settings/WallpaperConfig.qml souveraine/modules/settings/WallpaperConfig.qml
|
|
modules/settings/DockConfig.qml souveraine/modules/settings/DockConfig.qml
|
|
modules/settings/NavigationConfig.qml souveraine/modules/settings/NavigationConfig.qml
|
|
modules/settings/KeyboardConfig.qml souveraine/modules/settings/KeyboardConfig.qml
|
|
modules/settings/IdleConfig.qml souveraine/modules/settings/IdleConfig.qml
|
|
modules/settings/SpeechConfig.qml souveraine/modules/settings/SpeechConfig.qml
|
|
modules/ii/polkit/Polkit.qml souveraine/modules/ii/polkit/Polkit.qml
|
|
modules/ii/dock/Dock.qml souveraine/modules/ii/dock/Dock.qml
|
|
modules/ii/dock/DockManifest.qml souveraine/modules/ii/dock/DockManifest.qml
|
|
modules/ii/dock/DockApps.qml souveraine/modules/ii/dock/DockApps.qml
|
|
modules/ii/dock/DockAppButton.qml souveraine/modules/ii/dock/DockAppButton.qml
|
|
modules/ii/dock/DockButton.qml souveraine/modules/ii/dock/DockButton.qml
|
|
modules/ii/dock/DockSeparator.qml souveraine/modules/ii/dock/DockSeparator.qml
|
|
modules/ii/dock/DockStack.qml souveraine/modules/ii/dock/DockStack.qml
|
|
modules/ii/appInventory/AppInventory.qml souveraine/modules/ii/appInventory/AppInventory.qml
|
|
modules/ii/appInventory/AppInventoryScope.qml souveraine/modules/ii/appInventory/AppInventoryScope.qml
|
|
modules/ii/overview/Overview.qml souveraine/modules/ii/overview/Overview.qml
|
|
modules/ii/onScreenKeyboard/OnScreenKeyboard.qml souveraine/modules/ii/onScreenKeyboard/OnScreenKeyboard.qml
|
|
modules/common/Persistent.qml souveraine/modules/common/Persistent.qml
|
|
modules/common/panels/lock/LockScreen.qml souveraine/modules/common/panels/lock/LockScreen.qml
|
|
modules/ii/lock/Lock.qml souveraine/modules/ii/lock/Lock.qml
|
|
modules/ii/lock/TouchLockSurface.qml souveraine/modules/ii/lock/TouchLockSurface.qml
|
|
modules/souveraine/lock/LockMediaCard.qml souveraine/modules/souveraine/lock/LockMediaCard.qml
|
|
modules/souveraine/lock/LockAgentCard.qml souveraine/modules/souveraine/lock/LockAgentCard.qml
|
|
modules/souveraine/lock/LockNotifyCard.qml souveraine/modules/souveraine/lock/LockNotifyCard.qml
|
|
modules/souveraine/lock/LockSurfaceHost.qml souveraine/modules/souveraine/lock/LockSurfaceHost.qml
|
|
modules/souveraine/lock/qmldir souveraine/modules/souveraine/lock/qmldir
|
|
modules/souveraine/navigation/SystemGestureRail.qml souveraine/modules/souveraine/navigation/SystemGestureRail.qml
|
|
modules/souveraine/navigation/qmldir souveraine/modules/souveraine/navigation/qmldir
|
|
modules/souveraine/boot/BootBloom.qml souveraine/modules/souveraine/boot/BootBloom.qml
|
|
modules/souveraine/boot/BootBloom.frag.qsb souveraine/modules/souveraine/boot/BootBloom.frag.qsb
|
|
modules/souveraine/boot/souvie.png souveraine/modules/souveraine/boot/souvie.png
|
|
modules/souveraine/boot/qmldir souveraine/modules/souveraine/boot/qmldir
|
|
modules/ii/sessionScreen/SessionScreen.qml souveraine/modules/ii/sessionScreen/SessionScreen.qml
|
|
qmldir souveraine/qmldir
|
|
panelFamilies/qmldir souveraine/panelFamilies/qmldir
|
|
services/qmldir souveraine/services/qmldir
|
|
modules/common/qmldir souveraine/modules/common/qmldir
|
|
modules/common/functions/qmldir souveraine/modules/common/functions/qmldir
|
|
modules/common/panels/lock/qmldir souveraine/modules/common/panels/lock/qmldir
|
|
modules/common/widgets/qmldir souveraine/modules/common/widgets/qmldir
|
|
modules/ii/appInventory/qmldir souveraine/modules/ii/appInventory/qmldir
|
|
modules/ii/bar/qmldir souveraine/modules/ii/bar/qmldir
|
|
modules/ii/dock/qmldir souveraine/modules/ii/dock/qmldir
|
|
modules/ii/lock/qmldir souveraine/modules/ii/lock/qmldir
|
|
modules/ii/onScreenKeyboard/qmldir souveraine/modules/ii/onScreenKeyboard/qmldir
|
|
modules/ii/overview/qmldir souveraine/modules/ii/overview/qmldir
|
|
modules/ii/polkit/qmldir souveraine/modules/ii/polkit/qmldir
|
|
modules/ii/sessionScreen/qmldir souveraine/modules/ii/sessionScreen/qmldir
|
|
modules/ii/sidebarLeft/qmldir souveraine/modules/ii/sidebarLeft/qmldir
|
|
modules/ii/sidebarRight/qmldir souveraine/modules/ii/sidebarRight/qmldir
|
|
modules/ii/sidebarRight/volumeMixer/qmldir souveraine/modules/ii/sidebarRight/volumeMixer/qmldir
|
|
modules/settings/qmldir souveraine/modules/settings/qmldir
|
|
"
|
|
|
|
# wifi fallback: PHONE_HOST=casey@10.10.20.234 ./deploy.sh --phone
|
|
PHONE_USB="${PHONE_HOST:-casey@172.16.42.1}"
|
|
PHONE_DEST="souveraine-surfaces/quickshell"
|
|
|
|
manifest_lines() { printf '%s\n' "$MANIFEST" | sed '/^[[:space:]]*$/d'; }
|
|
|
|
# Compile the boot bloom shader to .qsb (Qt RHI) if the source is newer. The
|
|
# .qsb is architecture-independent (SPIR-V + reflection), so we build it once
|
|
# here and the manifest symlink / phone rsync carries it — no qsb on the phone.
|
|
compile_shaders() {
|
|
local frag="$SRC/modules/souveraine/boot/BootBloom.frag"
|
|
local qsb_out="$SRC/modules/souveraine/boot/BootBloom.frag.qsb"
|
|
[[ -f "$frag" ]] || return 0
|
|
if [[ ! -f "$qsb_out" || "$frag" -nt "$qsb_out" ]]; then
|
|
local qsb
|
|
qsb="$(command -v qsb || echo /usr/lib/qt6/bin/qsb)"
|
|
if [[ ! -x "$qsb" ]]; then
|
|
echo "ERROR: qsb not found (need qt6-shadertools) to build BootBloom.frag.qsb" >&2
|
|
exit 1
|
|
fi
|
|
# --glsl 100es,120,150 + --hlsl/--msl targets so it runs on the Adreno
|
|
# GLES backend the phone uses; -O optimizes.
|
|
"$qsb" --glsl "100es,120,150" --hlsl 50 --msl 12 -O -o "$qsb_out" "$frag"
|
|
echo "compiled BootBloom.frag -> BootBloom.frag.qsb"
|
|
fi
|
|
}
|
|
compile_shaders
|
|
|
|
if [[ "${1:-}" == "--manifest" ]]; then
|
|
manifest_lines
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "${1:-}" == "--phone" ]]; then
|
|
ssh_i=(ssh -i "$HOME/.ssh/ani" -o ConnectTimeout=5)
|
|
"${ssh_i[@]}" "$PHONE_USB" "mkdir -p ~/$PHONE_DEST"
|
|
rsync -a --delete -e "ssh -i $HOME/.ssh/ani" "$SRC/" "$PHONE_USB:$PHONE_DEST/"
|
|
"${ssh_i[@]}" "$PHONE_USB" "bash ~/$PHONE_DEST/deploy.sh"
|
|
# Phone-only: install the mobile settings launcher into the app grid.
|
|
"${ssh_i[@]}" "$PHONE_USB" "mkdir -p ~/.local/share/applications && ln -sf ~/$PHONE_DEST/souveraine-settings.desktop ~/.local/share/applications/souveraine-settings.desktop"
|
|
echo "Deployed to phone. Hyprland starts qs -c souveraine; no secondary shell is required."
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "${1:-}" == "-u" || "${1:-}" == "--uninstall" ]]; then
|
|
rm -rf "$SV"
|
|
echo "removed $SV (ii tree untouched)"
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "${1:-}" == "--legacy-clean" ]]; then
|
|
# One-time migration: strip the old overlay out of ii.
|
|
# 1. remove any symlink in ii that points into a souveraine checkout
|
|
find "$II" -type l | while read -r l; do
|
|
case "$(readlink "$l")" in
|
|
*souveraine*) rm -f "$l"; echo "unlinked ${l#$QS/}" ;;
|
|
esac
|
|
done
|
|
# 2. restore upstream backups
|
|
find "$II" -name '*.upstream' | while read -r u; do
|
|
mv -f "$u" "${u%.upstream}"
|
|
echo "restored ${u%.upstream}"
|
|
done
|
|
exit 0
|
|
fi
|
|
|
|
# --- Sync the pinned ii base --------------------------------------------
|
|
# --exclude .git: the pin carries no VCS dirs, and any nested .git already
|
|
# on a device (e.g. widgets/shapes) is left alone rather than deleted.
|
|
rsync -a --delete --exclude='.git' "$SRC/ii-base/" "$II/"
|
|
if [[ "$(uname -m)" == "aarch64" ]]; then
|
|
rsync -a "$SRC/ii-phone/" "$II/"
|
|
echo "ii synced from pin + phone overlay"
|
|
else
|
|
echo "ii synced from pin"
|
|
fi
|
|
|
|
# --- Compose -------------------------------------------------------------
|
|
# Targets under souveraine/, relative to $SV
|
|
SV_TARGETS="$(manifest_lines | awk '$2 ~ /^souveraine\// {sub(/^souveraine\//, "", $2); print $2}')"
|
|
|
|
is_replaced() { # exact file override
|
|
grep -qxF "$1" <<< "$SV_TARGETS"
|
|
}
|
|
is_touched() { # dir contains an override somewhere below
|
|
grep -q "^$1/" <<< "$SV_TARGETS"
|
|
}
|
|
|
|
compose_dir() { # $1 = path relative to ii root ("" for root)
|
|
local rel="$1" entry name erel
|
|
mkdir -p "$SV${rel:+/$rel}"
|
|
for entry in "$II${rel:+/$rel}"/*; do
|
|
[[ -e "$entry" ]] || continue
|
|
name="$(basename "$entry")"
|
|
[[ "$name" == *.upstream ]] && continue
|
|
erel="${rel:+$rel/}$name"
|
|
if [[ -d "$entry" ]]; then
|
|
if is_touched "$erel"; then
|
|
compose_dir "$erel"
|
|
else
|
|
ln -sfn "$II/$erel" "$SV/$erel"
|
|
fi
|
|
else
|
|
# root files and files inside touched dirs: link individually,
|
|
# skipping ones our manifest replaces
|
|
is_replaced "$erel" && continue
|
|
ln -sf "$II/$erel" "$SV/$erel"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Rebuild from scratch each run: cheap, and guarantees no stale links.
|
|
rm -rf "$SV"
|
|
compose_dir ""
|
|
|
|
# Our files on top (this also creates dirs that exist only in our tree,
|
|
# e.g. brand-new settings pages)
|
|
mkdir -p "$QS/pill"
|
|
while read -r rel target; do
|
|
[[ -z "$rel" ]] && continue
|
|
src="$SRC/$rel"; t="$QS/$target"
|
|
[[ -f "$src" ]] || { echo "missing $src" >&2; exit 1; }
|
|
mkdir -p "$(dirname "$t")"
|
|
ln -sf "$src" "$t"
|
|
done < <(manifest_lines)
|
|
|
|
n_ours=$(manifest_lines | grep -c .)
|
|
n_borrowed_dirs=$(find "$SV" -maxdepth 3 -type l -xtype d | wc -l)
|
|
echo "souveraine config composed at $SV ($n_ours files ours, $n_borrowed_dirs dirs borrowed from ii)"
|
|
if grep -q 'qsConfig", "ii"' "$HOME/.config/hypr/hyprland/variables.lua" 2>/dev/null; then
|
|
echo "NOTE: hyprland qsConfig is still 'ii' — flip variables.lua to 'souveraine' to switch."
|
|
fi
|
|
echo "Run with: qs -c souveraine (restart: pkill -f 'qs -c souveraine')"
|