496 lines
17 KiB
Bash
496 lines
17 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
|
||
|
|
# ==============================================================================
|
||
|
|
# 99-apps.sh - Common Applications (FZF Menu + Split Repo/AUR + Retry Logic)
|
||
|
|
# ==============================================================================
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
PARENT_DIR="$(dirname "$SCRIPT_DIR")"
|
||
|
|
source "$SCRIPT_DIR/00-utils.sh"
|
||
|
|
|
||
|
|
# --- [CONFIGURATION] ---
|
||
|
|
# LazyVim 硬性依赖列表 (Moved from niri-setup)
|
||
|
|
LAZYVIM_DEPS=("neovim" "ripgrep" "fd" "ttf-jetbrains-mono-nerd" "git")
|
||
|
|
|
||
|
|
check_root
|
||
|
|
|
||
|
|
# Ensure FZF is installed
|
||
|
|
if ! command -v fzf &> /dev/null; then
|
||
|
|
log "Installing dependency: fzf..."
|
||
|
|
pacman -S --noconfirm fzf >/dev/null 2>&1
|
||
|
|
fi
|
||
|
|
|
||
|
|
trap 'echo -e "\n ${H_YELLOW}>>> Operation cancelled by user (Ctrl+C). Skipping...${NC}"' INT
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
# 0. Identify Target User & Helper
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
section "Phase 5" "Common Applications"
|
||
|
|
|
||
|
|
log "Identifying target user..."
|
||
|
|
DETECTED_USER=$(awk -F: '$3 == 1000 {print $1}' /etc/passwd)
|
||
|
|
|
||
|
|
if [ -n "$DETECTED_USER" ]; then
|
||
|
|
TARGET_USER="$DETECTED_USER"
|
||
|
|
else
|
||
|
|
read -p " Please enter the target username: " TARGET_USER
|
||
|
|
fi
|
||
|
|
HOME_DIR="/home/$TARGET_USER"
|
||
|
|
info_kv "Target" "$TARGET_USER"
|
||
|
|
|
||
|
|
# Helper function for user commands
|
||
|
|
as_user() {
|
||
|
|
runuser -u "$TARGET_USER" -- "$@"
|
||
|
|
}
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
# 1. List Selection & User Prompt
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
if [ "$DESKTOP_ENV" == "kde" ]; then
|
||
|
|
LIST_FILENAME="kde-common-applist.txt"
|
||
|
|
else
|
||
|
|
LIST_FILENAME="common-applist.txt"
|
||
|
|
fi
|
||
|
|
LIST_FILE="$PARENT_DIR/$LIST_FILENAME"
|
||
|
|
|
||
|
|
REPO_APPS=()
|
||
|
|
AUR_APPS=()
|
||
|
|
FLATPAK_APPS=()
|
||
|
|
FAILED_PACKAGES=()
|
||
|
|
INSTALL_LAZYVIM=false
|
||
|
|
|
||
|
|
if [ ! -f "$LIST_FILE" ]; then
|
||
|
|
warn "File $LIST_FILENAME not found. Skipping."
|
||
|
|
trap - INT
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
if ! grep -q -vE "^\s*#|^\s*$" "$LIST_FILE"; then
|
||
|
|
warn "App list is empty. Skipping."
|
||
|
|
trap - INT
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo -e " Selected List: ${BOLD}$LIST_FILENAME${NC}"
|
||
|
|
echo -e " ${H_YELLOW}>>> Do you want to CUSTOMIZE the application installation?${NC}"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
read -t 60 -p " Please select[Y/n]: " choice
|
||
|
|
READ_STATUS=$?
|
||
|
|
|
||
|
|
SELECTED_RAW=""
|
||
|
|
|
||
|
|
# Case 1: Timeout (Auto Install ALL - Default to N)
|
||
|
|
if [ $READ_STATUS -ne 0 ]; then
|
||
|
|
echo ""
|
||
|
|
warn "Timeout reached (60s). Auto-installing ALL applications from list..."
|
||
|
|
SELECTED_RAW=$(grep -vE "^\s*#|^\s*$" "$LIST_FILE" | sed -E 's/[[:space:]]+#/\t#/')
|
||
|
|
|
||
|
|
# Case 2: User Input
|
||
|
|
else
|
||
|
|
# Enter defaults to Y
|
||
|
|
choice=${choice:-Y}
|
||
|
|
if [[ "$choice" =~ ^[nN]$ ]]; then
|
||
|
|
log "User chose to auto-install ALL applications without customization."
|
||
|
|
SELECTED_RAW=$(grep -vE "^\s*#|^\s*$" "$LIST_FILE" | sed -E 's/[[:space:]]+#/\t#/')
|
||
|
|
else
|
||
|
|
clear
|
||
|
|
echo -e "\n Loading application list..."
|
||
|
|
|
||
|
|
SELECTED_RAW=$(grep -vE "^\s*#|^\s*$" "$LIST_FILE" | \
|
||
|
|
sed -E 's/[[:space:]]+#/\t#/' | \
|
||
|
|
fzf --multi \
|
||
|
|
--layout=reverse \
|
||
|
|
--border \
|
||
|
|
--margin=1,2 \
|
||
|
|
--prompt="Search App > " \
|
||
|
|
--pointer=">>" \
|
||
|
|
--marker="* " \
|
||
|
|
--delimiter=$'\t' \
|
||
|
|
--with-nth=1 \
|
||
|
|
--bind 'load:select-all' \
|
||
|
|
--bind 'ctrl-a:select-all,ctrl-d:deselect-all,j:down,k:up' \
|
||
|
|
--info=inline \
|
||
|
|
--header="[TAB] TOGGLE | [ENTER] INSTALL | [CTRL-D] DE-ALL | [CTRL-A] SE-ALL" \
|
||
|
|
--preview "echo {} | cut -f2 -d$'\t' | sed 's/^# //'" \
|
||
|
|
--preview-window=down:45%:wrap:border-up \
|
||
|
|
--color=dark \
|
||
|
|
--color=fg+:white,bg+:black \
|
||
|
|
--color=hl:blue,hl+:blue:bold \
|
||
|
|
--color=header:yellow:bold \
|
||
|
|
--color=info:magenta \
|
||
|
|
--color=prompt:cyan,pointer:cyan:bold,marker:green:bold \
|
||
|
|
--color=spinner:yellow)
|
||
|
|
|
||
|
|
clear
|
||
|
|
|
||
|
|
if [ -z "$SELECTED_RAW" ]; then
|
||
|
|
log "Skipping application installation (User cancelled selection in FZF)."
|
||
|
|
trap - INT
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
# 2. Categorize Selection & Strip Prefixes (Includes LazyVim Check)
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
log "Processing selection..."
|
||
|
|
|
||
|
|
while IFS= read -r line; do
|
||
|
|
raw_pkg=$(echo "$line" | cut -f1 -d$'\t' | xargs)
|
||
|
|
[[ -z "$raw_pkg" ]] && continue
|
||
|
|
|
||
|
|
# Check for LazyVim explicitly (Case insensitive check)
|
||
|
|
if [[ "${raw_pkg,,}" == "lazyvim" ]]; then
|
||
|
|
INSTALL_LAZYVIM=true
|
||
|
|
REPO_APPS+=("${LAZYVIM_DEPS[@]}")
|
||
|
|
info_kv "Config" "LazyVim detected" "Setup deferred to Post-Install"
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [[ "$raw_pkg" == flatpak:* ]]; then
|
||
|
|
clean_name="${raw_pkg#flatpak:}"
|
||
|
|
FLATPAK_APPS+=("$clean_name")
|
||
|
|
elif [[ "$raw_pkg" == AUR:* ]]; then
|
||
|
|
clean_name="${raw_pkg#AUR:}"
|
||
|
|
AUR_APPS+=("$clean_name")
|
||
|
|
else
|
||
|
|
REPO_APPS+=("$raw_pkg")
|
||
|
|
fi
|
||
|
|
done <<< "$SELECTED_RAW"
|
||
|
|
|
||
|
|
info_kv "Scheduled" "Repo: ${#REPO_APPS[@]}" "AUR: ${#AUR_APPS[@]}" "Flatpak: ${#FLATPAK_APPS[@]}"
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
#[SETUP] GLOBAL SUDO CONFIGURATION
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
if [ ${#REPO_APPS[@]} -gt 0 ] || [ ${#AUR_APPS[@]} -gt 0 ]; then
|
||
|
|
log "Configuring temporary NOPASSWD for installation..."
|
||
|
|
SUDO_TEMP_FILE="/etc/sudoers.d/99_shorin_installer_apps"
|
||
|
|
echo "$TARGET_USER ALL=(ALL) NOPASSWD: ALL" > "$SUDO_TEMP_FILE"
|
||
|
|
chmod 440 "$SUDO_TEMP_FILE"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
# 3. Install Applications
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
# --- A. Install Repo Apps (BATCH MODE) ---
|
||
|
|
if [ ${#REPO_APPS[@]} -gt 0 ]; then
|
||
|
|
section "Step 1/3" "Official Repository Packages (Batch)"
|
||
|
|
|
||
|
|
REPO_QUEUE=()
|
||
|
|
for pkg in "${REPO_APPS[@]}"; do
|
||
|
|
if pacman -Qi "$pkg" &>/dev/null; then
|
||
|
|
log "Skipping '$pkg' (Already installed)."
|
||
|
|
else
|
||
|
|
REPO_QUEUE+=("$pkg")
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
if [ ${#REPO_QUEUE[@]} -gt 0 ]; then
|
||
|
|
BATCH_LIST="${REPO_QUEUE[*]}"
|
||
|
|
info_kv "Installing" "${#REPO_QUEUE[@]} packages via Pacman/Yay"
|
||
|
|
|
||
|
|
if ! exe as_user yay -Syu --noconfirm --needed --answerdiff=None --answerclean=None $BATCH_LIST; then
|
||
|
|
error "Batch installation failed. Some repo packages might be missing."
|
||
|
|
for pkg in "${REPO_QUEUE[@]}"; do
|
||
|
|
FAILED_PACKAGES+=("repo:$pkg")
|
||
|
|
done
|
||
|
|
else
|
||
|
|
success "Repo batch installation completed."
|
||
|
|
fi
|
||
|
|
else
|
||
|
|
log "All Repo packages are already installed."
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- B. Install AUR Apps (INDIVIDUAL MODE + RETRY) ---
|
||
|
|
if [ ${#AUR_APPS[@]} -gt 0 ]; then
|
||
|
|
section "Step 2/3" "AUR Packages "
|
||
|
|
|
||
|
|
for app in "${AUR_APPS[@]}"; do
|
||
|
|
if pacman -Qi "$app" &>/dev/null; then
|
||
|
|
log "Skipping '$app' (Already installed)."
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
|
||
|
|
|
||
|
|
log "Installing AUR: $app ..."
|
||
|
|
install_success=false
|
||
|
|
max_retries=1
|
||
|
|
|
||
|
|
for (( i=0; i<=max_retries; i++ )); do
|
||
|
|
if [ $i -gt 0 ]; then
|
||
|
|
warn "Retry $i/$max_retries for '$app' ..."
|
||
|
|
fi
|
||
|
|
|
||
|
|
if as_user yay -Syu --noconfirm --needed --answerdiff=None --answerclean=None "$app"; then
|
||
|
|
install_success=true
|
||
|
|
success "Installed $app"
|
||
|
|
break
|
||
|
|
else
|
||
|
|
warn "Attempt $((i+1)) failed for $app"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
if [ "$install_success" = false ]; then
|
||
|
|
error "Failed to install $app after $((max_retries+1)) attempts."
|
||
|
|
FAILED_PACKAGES+=("aur:$app")
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- C. Install Flatpak Apps (INDIVIDUAL MODE) ---
|
||
|
|
if [ ${#FLATPAK_APPS[@]} -gt 0 ]; then
|
||
|
|
section "Step 3/3" "Flatpak Packages (Individual)"
|
||
|
|
|
||
|
|
for app in "${FLATPAK_APPS[@]}"; do
|
||
|
|
if flatpak info "$app" &>/dev/null; then
|
||
|
|
log "Skipping '$app' (Already installed)."
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
|
||
|
|
log "Installing Flatpak: $app ..."
|
||
|
|
if ! exe flatpak install -y flathub "$app"; then
|
||
|
|
error "Failed to install: $app"
|
||
|
|
FAILED_PACKAGES+=("flatpak:$app")
|
||
|
|
else
|
||
|
|
success "Installed $app"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
# 4. Environment & Additional Configs (Virt/Wine/Steam/LazyVim)
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
section "Post-Install" "System & App Tweaks"
|
||
|
|
|
||
|
|
# --- [NEW] Virtualization Configuration (Virt-Manager) ---
|
||
|
|
if pacman -Qi virt-manager &>/dev/null && ! systemd-detect-virt -q; then
|
||
|
|
info_kv "Config" "Virt-Manager detected"
|
||
|
|
|
||
|
|
# 1. 安装完整依赖
|
||
|
|
# iptables-nft 和 dnsmasq 是默认 NAT 网络必须的
|
||
|
|
log "Installing QEMU/KVM dependencies..."
|
||
|
|
pacman -S --noconfirm --needed qemu-full virt-manager swtpm dnsmasq virt-viewer
|
||
|
|
|
||
|
|
# 2. 添加用户组 (需要重新登录生效)
|
||
|
|
log "Adding $TARGET_USER to libvirt group..."
|
||
|
|
usermod -a -G libvirt "$TARGET_USER"
|
||
|
|
# 同时添加 kvm 和 input 组以防万一
|
||
|
|
usermod -a -G kvm,input "$TARGET_USER"
|
||
|
|
|
||
|
|
# 3. 开启服务
|
||
|
|
log "Enabling libvirtd service..."
|
||
|
|
systemctl enable --now libvirtd
|
||
|
|
|
||
|
|
# 4. [修复] 强制设置 virt-manager 默认连接为 QEMU/KVM
|
||
|
|
# 解决第一次打开显示 LXC 或无法连接的问题
|
||
|
|
log "Setting default URI to qemu:///system..."
|
||
|
|
|
||
|
|
# 编译 glib schemas (防止 gsettings 报错)
|
||
|
|
glib-compile-schemas /usr/share/glib-2.0/schemas/
|
||
|
|
|
||
|
|
# 强制写入 Dconf 配置
|
||
|
|
# uris: 连接列表
|
||
|
|
# autoconnect: 自动连接的列表
|
||
|
|
as_user gsettings set org.virt-manager.virt-manager.connections uris "['qemu:///system']"
|
||
|
|
as_user gsettings set org.virt-manager.virt-manager.connections autoconnect "['qemu:///system']"
|
||
|
|
|
||
|
|
# 5. 配置网络 (Default NAT)
|
||
|
|
log "Starting default network..."
|
||
|
|
sleep 3
|
||
|
|
virsh net-start default >/dev/null 2>&1 || warn "Default network might be already active."
|
||
|
|
virsh net-autostart default >/dev/null 2>&1 || true
|
||
|
|
|
||
|
|
success "Virtualization (KVM) configured."
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- [NEW] Wine Configuration & Fonts ---
|
||
|
|
if command -v wine &>/dev/null; then
|
||
|
|
info_kv "Config" "Wine detected"
|
||
|
|
|
||
|
|
# 1. 安装 Gecko 和 Mono
|
||
|
|
log "Ensuring Wine Gecko/Mono are installed..."
|
||
|
|
pacman -S --noconfirm --needed wine wine-gecko wine-mono
|
||
|
|
|
||
|
|
# 2. 初始化 Wine (使用 wineboot -u 在后台运行,不弹窗)
|
||
|
|
WINE_PREFIX="$HOME_DIR/.wine"
|
||
|
|
if [ ! -d "$WINE_PREFIX" ]; then
|
||
|
|
log "Initializing wine prefix (This may take a minute)..."
|
||
|
|
# WINEDLLOVERRIDES prohibits popups
|
||
|
|
as_user env WINEDLLOVERRIDES="mscoree,mshtml=" wineboot -u
|
||
|
|
# Wait for completion
|
||
|
|
as_user wineserver -w
|
||
|
|
else
|
||
|
|
log "Wine prefix already exists."
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 3. 复制字体
|
||
|
|
FONT_SRC="$PARENT_DIR/resources/windows-sim-fonts"
|
||
|
|
FONT_DEST="$WINE_PREFIX/drive_c/windows/Fonts"
|
||
|
|
|
||
|
|
if [ -d "$FONT_SRC" ]; then
|
||
|
|
log "Copying Windows fonts from resources..."
|
||
|
|
|
||
|
|
# 1. 确保目标目录存在 (以用户身份创建)
|
||
|
|
if [ ! -d "$FONT_DEST" ]; then
|
||
|
|
as_user mkdir -p "$FONT_DEST"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 2. 执行复制 (关键修改:直接以目标用户身份复制,而不是 Root 复制后再 Chown)
|
||
|
|
# 使用 cp -rT 确保目录内容合并,而不是把源目录本身拷进去
|
||
|
|
# 注意:这里假设 as_user 能够接受命令参数。如果 as_user 只是简单的 su/sudo 封装:
|
||
|
|
if sudo -u "$TARGET_USER" cp -rf "$FONT_SRC"/. "$FONT_DEST/"; then
|
||
|
|
success "Fonts copied successfully."
|
||
|
|
else
|
||
|
|
error "Failed to copy fonts."
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 3. 强制刷新 Wine 字体缓存 (非常重要!)
|
||
|
|
# 字体文件放进去了,但 Wine 不一定会立刻重修构建 fntdata.dat
|
||
|
|
# 杀死 wineserver 会强制 Wine 下次启动时重新扫描系统和本地配置
|
||
|
|
log "Refreshing Wine font cache..."
|
||
|
|
if command -v wineserver &> /dev/null; then
|
||
|
|
# 必须以目标用户身份执行 wineserver -k
|
||
|
|
as_user env WINEPREFIX="$WINE_PREFIX" wineserver -k
|
||
|
|
fi
|
||
|
|
|
||
|
|
success "Wine fonts installed and cache refresh triggered."
|
||
|
|
else
|
||
|
|
warn "Resources font directory not found at: $FONT_SRC"
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
if command -v lutris &> /dev/null; then
|
||
|
|
log "Lutris detected. Installing 32-bit gaming dependencies..."
|
||
|
|
pacman -S --noconfirm --needed alsa-plugins giflib glfw gst-plugins-base-libs lib32-alsa-plugins lib32-giflib lib32-gst-plugins-base-libs lib32-gtk3 lib32-libjpeg-turbo lib32-libva lib32-mpg123 lib32-openal libjpeg-turbo libva libxslt mpg123 openal ttf-liberation
|
||
|
|
fi
|
||
|
|
# --- Steam Locale Fix ---
|
||
|
|
STEAM_desktop_modified=false
|
||
|
|
NATIVE_DESKTOP="/usr/share/applications/steam.desktop"
|
||
|
|
if [ -f "$NATIVE_DESKTOP" ]; then
|
||
|
|
log "Checking Native Steam..."
|
||
|
|
if ! grep -q "env LC_CTYPE=zh_CN.UTF-8" "$NATIVE_DESKTOP"; then
|
||
|
|
exe sed -i 's|^Exec=/usr/bin/steam|Exec=env LC_CTYPE=zh_CN.UTF-8 /usr/bin/steam|' "$NATIVE_DESKTOP"
|
||
|
|
exe sed -i 's|^Exec=steam|Exec=env LC_CTYPE=zh_CN.UTF-8 steam|' "$NATIVE_DESKTOP"
|
||
|
|
success "Patched Native Steam .desktop."
|
||
|
|
STEAM_desktop_modified=true
|
||
|
|
else
|
||
|
|
log "Native Steam already patched."
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
if flatpak list | grep -q "com.valvesoftware.Steam"; then
|
||
|
|
log "Checking Flatpak Steam..."
|
||
|
|
exe flatpak override --env=LANG=zh_CN.UTF-8 com.valvesoftware.Steam
|
||
|
|
success "Applied Flatpak Steam override."
|
||
|
|
STEAM_desktop_modified=true
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- [MOVED] LazyVim Configuration ---
|
||
|
|
if [ "$INSTALL_LAZYVIM" = true ]; then
|
||
|
|
section "Config" "Applying LazyVim Overrides"
|
||
|
|
NVIM_CFG="$HOME_DIR/.config/nvim"
|
||
|
|
|
||
|
|
if [ -d "$NVIM_CFG" ]; then
|
||
|
|
BACKUP_PATH="$HOME_DIR/.config/nvim.old.apps.$(date +%s)"
|
||
|
|
warn "Collision detected. Moving existing nvim config to $BACKUP_PATH"
|
||
|
|
mv "$NVIM_CFG" "$BACKUP_PATH"
|
||
|
|
fi
|
||
|
|
|
||
|
|
log "Cloning LazyVim starter..."
|
||
|
|
if as_user git clone https://github.com/LazyVim/starter "$NVIM_CFG"; then
|
||
|
|
rm -rf "$NVIM_CFG/.git"
|
||
|
|
success "LazyVim installed (Override)."
|
||
|
|
else
|
||
|
|
error "Failed to clone LazyVim."
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- hide desktop ---
|
||
|
|
# --- hide desktop (User Level Override) ---
|
||
|
|
|
||
|
|
section "Config" "Hiding useless .desktop files"
|
||
|
|
log "Hiding useless .desktop files"
|
||
|
|
run_hide_desktop_file
|
||
|
|
|
||
|
|
# --- Post-Dotfiles Configuration: Firefox ---
|
||
|
|
section "Config" "Firefox UI Customization"
|
||
|
|
MOZILLA_DIR="$HOME_DIR/.config/mozilla"
|
||
|
|
|
||
|
|
if [ -d "$MOZILLA_DIR" ]; then
|
||
|
|
log "Backing up existing mozilla directory..."
|
||
|
|
mv "$MOZILLA_DIR" "$MOZILLA_DIR.bak.$(date +%s)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
if mkdir -p "$MOZILLA_DIR"; then
|
||
|
|
log "directory created."
|
||
|
|
fi
|
||
|
|
if cp -rf "$PARENT_DIR/resources/firefox" "$MOZILLA_DIR/"; then
|
||
|
|
chown -R "$TARGET_USER" "$MOZILLA_DIR"
|
||
|
|
log "firefox dotfiles doployed."
|
||
|
|
fi
|
||
|
|
section "Config" "clash tun"
|
||
|
|
|
||
|
|
if command -v clash-verge; then
|
||
|
|
/usr/bin/clash-verge-service &
|
||
|
|
sleep 3
|
||
|
|
clash-verge-service-uninstall || true
|
||
|
|
sleep 3
|
||
|
|
clash-verge-service-install || true
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- mangohud ---
|
||
|
|
section "Config" "MangoHud Configuration"
|
||
|
|
if command -v mangohud &>/dev/null; then
|
||
|
|
|
||
|
|
if [ -d "$HOME_DIR/.config/MangoHud" ]; then
|
||
|
|
log "MangoHud config already exists."
|
||
|
|
else
|
||
|
|
log "Deploying MangoHud config..."
|
||
|
|
force_copy "$PARENT_DIR/resources/MangoHud" "$HOME_DIR/.config/MangoHud"
|
||
|
|
fi
|
||
|
|
|
||
|
|
fi
|
||
|
|
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
# [FIX] CLEANUP GLOBAL SUDO CONFIGURATION
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
if [ -f "$SUDO_TEMP_FILE" ]; then
|
||
|
|
log "Revoking temporary NOPASSWD..."
|
||
|
|
rm -f "$SUDO_TEMP_FILE"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
# 5. Generate Failure Report
|
||
|
|
# ------------------------------------------------------------------------------
|
||
|
|
if [ ${#FAILED_PACKAGES[@]} -gt 0 ]; then
|
||
|
|
DOCS_DIR="$HOME_DIR/Documents"
|
||
|
|
REPORT_FILE="$DOCS_DIR/安装失败的软件.txt"
|
||
|
|
|
||
|
|
if [ ! -d "$DOCS_DIR" ]; then as_user mkdir -p "$DOCS_DIR"; fi
|
||
|
|
|
||
|
|
echo -e "\n========================================================" >> "$REPORT_FILE"
|
||
|
|
echo -e " Installation Failure Report - $(date)" >> "$REPORT_FILE"
|
||
|
|
echo -e "========================================================" >> "$REPORT_FILE"
|
||
|
|
printf "%s\n" "${FAILED_PACKAGES[@]}" >> "$REPORT_FILE"
|
||
|
|
|
||
|
|
chown "$TARGET_USER:$TARGET_USER" "$REPORT_FILE"
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
warn "Some applications failed to install."
|
||
|
|
warn "A report has been saved to:"
|
||
|
|
echo -e " ${BOLD}$REPORT_FILE${NC}"
|
||
|
|
else
|
||
|
|
success "All scheduled applications processed successfully."
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Reset Trap
|
||
|
|
trap - INT
|
||
|
|
|
||
|
|
log "Module 99-apps completed."
|