LibrePortal/scripts/webui/data/utils/webui_app_icons.sh
librelad 2d24a764a8 refactor(storage): route elevation tests and the WebUI tree through paths.sh
Two mechanical sweeps, no behaviour change on a single-root install.

The 14 `[[ "$p" == "$containers_dir"* ]]` prefix tests that decide
manager-vs-container-user elevation become pathIsContainerData, so a file
on a second storage root is no longer misclassified as manager-owned —
which would have written it with the wrong owner and failed later, far
from the cause. The 65 references to the WebUI's own tree become
webuiDir(), which is pinned to the primary root by design.

Two traps found while doing it:

run_privileged.sh is sourced directly by init.sh without paths.sh, so it
needs a fallback. Defining one named pathIsContainerData was wrong:
generate_function_manifest.sh indexes top-level definitions, and the
resulting autoload stub would have shadowed the real multi-root
implementation with the primary-only fallback — silently classifying
every file on a second disk as manager-owned, which is exactly the bug
this sweep exists to prevent. Renamed to _runCfgIsContainerPath, which
delegates when the real one is loaded.

setup_lock.sh built its path in a top-level assignment, so it was
evaluated at source time and needed the file flagged eager. Made it a
function instead: the path resolves on call, and the file drops off
LP_EAGER_FILES entirely.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 04:04:19 +01:00

85 lines
3.3 KiB
Bash
Executable File

#!/bin/bash
# Sync app icons from container template dirs to the LibrePortal frontend.
#
# apps.json references /core/icons/apps/<app>.<ext> unconditionally (see
# webui_config.sh), so the icon file must physically exist in the frontend
# icons dir or the apps page falls back to the default icon.
# Copy a single app's icon into the frontend icons dir. Returns 0 if an
# icon was copied, 1 if the app has no icon (or no app name given).
# Idempotent — cheap enough to call on every install/uninstall.
webuiSyncAppIcon() {
local app_name="$1"
[[ -z "$app_name" ]] && return 1
local icons_dir="$(webuiDir)/frontend/core/icons/apps"
runFileOp mkdir -p "$icons_dir"
# Icons live in the install template dir — copy_build_context.sh
# excludes *.svg from the install→deployed copy, so the deployed
# container dir can't be relied on as the source.
local src_dir="${install_containers_dir}/${app_name}"
local ext
for ext in svg png; do
local src="${src_dir}/${app_name}.${ext}"
if [[ -f "$src" ]]; then
# cp to a temp name then mv so the webserver never serves a
# half-written file.
local dest="${icons_dir}/${app_name}.${ext}"
if runFileWrite "${dest}.tmp.$$" < "$src" 2>/dev/null; then
runFileOp mv "${dest}.tmp.$$" "$dest" 2>/dev/null
fi
return 0
fi
done
return 1
}
# Sync every app's icon. Used by the full WebUI update pass.
webuiSyncAppIcons() {
echo "Syncing app icons from installed containers to LibrePortal frontend..."
if [ -d "$install_containers_dir" ]; then
find "$install_containers_dir" -maxdepth 1 -type d -not -path "$install_containers_dir" | while read -r dir; do
local app_name
app_name=$(basename "$dir")
if webuiSyncAppIcon "$app_name"; then
echo "✅ Copied icon for $app_name"
else
echo "⚠️ No icon found for $app_name"
fi
done
else
echo "❌ Install containers directory not found: $install_containers_dir"
fi
webuiPruneAppIcons
echo "Icon sync completed!"
}
# Drop icons whose app template no longer exists. The sync above only ever
# ADDS, so removing an app from the catalogue left its icon being served
# forever — harmless-looking, but it is a file the portal keeps offering for
# something that is gone, and they accumulate release after release.
# Only ever removes icons it can match to a missing template, never anything
# else in the directory.
webuiPruneAppIcons() {
local icons_dir="$(webuiDir)/frontend/core/icons/apps"
[[ -d "$icons_dir" ]] || return 0
[[ -d "$install_containers_dir" ]] || return 0
local f base app removed=0
while IFS= read -r f; do
[[ -n "$f" ]] || continue
base="$(basename "$f")"
app="${base%.*}"
# Keep anything whose template is still present.
[[ -d "${install_containers_dir}/${app}" ]] && continue
runFileOp rm -f "$f" 2>/dev/null && removed=$((removed + 1))
echo "🧹 Removed orphaned icon for $app"
done < <(runFileOp find "$icons_dir" -maxdepth 1 -type f \( -name '*.svg' -o -name '*.png' \) 2>/dev/null)
(( removed > 0 )) && echo "Pruned $removed orphaned icon(s)."
return 0
}