#!/bin/bash RESET="\033[0m" BOLD="\033[1m" DIM="\033[2m" BLACK="\033[0;30m" RED="\033[0;31m" GREEN="\033[0;32m" YELLOW="\033[0;33m" BLUE="\033[0;34m" CYAN="\033[0;36m" WHITE="\033[0;37m" BRED="\033[1;31m" BGREEN="\033[1;32m" BYELLOW="\033[1;33m" BBLUE="\033[1;34m" BCYAN="\033[1;36m" BWHITE="\033[1;37m" print_header() { local title="${1:-INSTALLER}" local version="${2:-}" local width=60 local line printf -v line '%*s' "$width" '' line="${line// /─}" echo "" printf "${BCYAN}${line}${RESET}\n" printf "${BCYAN} %-56s${RESET}\n" "" printf "${BCYAN} ${BWHITE}%-54s${BCYAN} ${RESET}\n" "$title ${DIM}${version}${RESET}" printf "${BCYAN} %-56s${RESET}\n" "" printf "${BCYAN}${line}${RESET}\n" echo "" } print_section() { local label="$1" echo "" printf "${DIM}${CYAN}┌─${RESET} ${BWHITE}${label}${RESET}\n" } print_divider() { printf "${DIM}────────────────────────────────────────────────────────────${RESET}\n" } label_ok() { printf " ${BGREEN}[ OK ]${RESET} %s\n" "$1"; } label_warn() { printf " ${BYELLOW}[ WARN ]${RESET} %s\n" "$1"; } label_error() { printf " ${BRED}[ ERROR]${RESET} %s\n" "$1"; } label_info() { printf " ${BCYAN}[ INFO ]${RESET} %s\n" "$1"; } label_skip() { printf " ${DIM}[ SKIP ]${RESET} %s\n" "$1"; } label_simple() { printf " ${DIM}[SIMPLE]${RESET} %s\n" "$1"; } label_connected() { printf " ${BGREEN}[CONNECTED ]${RESET} %s\n" "$1"; } label_disconnect() { printf " ${BRED}[DISCONNECTED]${RESET} %s\n" "$1"; } label_step() { printf " ${BBLUE}[ %-2s/%-2s ]${RESET} %s\n" "$2" "$3" "$1"; } progress_bar() { local current=$1 local total=$2 local label="${3:-}" local width=40 local filled=$(( current * width / total )) local empty=$(( width - filled )) local pct=$(( current * 100 / total )) local bar_filled bar_empty printf -v bar_filled '%*s' "$filled" '' printf -v bar_empty '%*s' "$empty" '' bar_filled="${bar_filled// /#}" bar_empty="${bar_empty// /·}" printf "\r ${DIM}[${RESET}${BGREEN}${bar_filled}${RESET}${DIM}${bar_empty}${RESET}${DIM}]${RESET} ${BWHITE}%3d%%${RESET} ${DIM}%s${RESET} " \ "$pct" "$label" } progress_simulate() { local steps="${1:-20}" local label="${2:-loading}" for i in $(seq 1 "$steps"); do progress_bar "$i" "$steps" "$label" sleep 0.04 done echo "" } SPINNER_PID="" start_spinner() { local msg="${1:-Processing...}" local frames=('─' '\\' '│' '/') ( local i=0 while true; do printf "\r ${BCYAN}${frames[$i]}${RESET} ${DIM}%s${RESET} " "$msg" i=$(( (i + 1) % 4 )) sleep 0.1 done ) & SPINNER_PID=$! disown "$SPINNER_PID" 2>/dev/null } stop_spinner() { local result_msg="${1:-}" if [ -n "$SPINNER_PID" ]; then kill "$SPINNER_PID" 2>/dev/null wait "$SPINNER_PID" 2>/dev/null SPINNER_PID="" fi printf "\r%*s\r" 60 "" [ -n "$result_msg" ] && label_ok "$result_msg" }