installer: TUI without ASCII logo

This commit is contained in:
Dushnilin
2026-08-03 14:48:04 +03:00
parent 280aa2bfac
commit e371f7a52e
3 changed files with 397 additions and 14 deletions
+58 -14
View File
@@ -6,6 +6,11 @@ INSTALLER_VERSION="2.0.1"
REPO_OWNER="Dushnilin"
REPO_NAME="tachyon"
# ─── Source TUI helpers (self-contained, no external deps) ───────────────────
_TUI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}" 2>/dev/null)" && pwd)"
[ -f "$_TUI_DIR/installer_tui.sh" ] && . "$_TUI_DIR/installer_tui.sh"
unset _TUI_DIR
REQUIRED_SPACE_KB=15360
CONNECT_TIMEOUT_SECONDS=15
METADATA_TIMEOUT_SECONDS=60
@@ -59,18 +64,30 @@ log_line() {
msg() {
log_line "INFO $1"
[ "$QUIET" -eq 1 ] && return 0
printf '\033[32;1m%s\033[0m\n' "$1"
if command -v tui_info >/dev/null 2>&1; then
tui_info "$1"
else
printf '\033[32;1m%s\033[0m\n' "$1"
fi
}
warn() {
log_line "WARN $1"
printf '\033[33;1m%s\033[0m\n' "$1" >&2
if command -v tui_warn >/dev/null 2>&1; then
tui_warn "$1"
else
printf '\033[33;1m%s\033[0m\n' "$1" >&2
fi
}
fail() {
log_line "FAIL $1"
printf '\033[31;1m%s\033[0m\n' "$1" >&2
printf '\033[31;1m%s\033[0m\n' "See $LOG_FILE for details." >&2
if command -v tui_err >/dev/null 2>&1; then
tui_err "$1"
else
printf '\033[31;1m%s\033[0m\n' "$1" >&2
printf '\033[31;1m%s\033[0m\n' "See $LOG_FILE for details." >&2
fi
exit 1
}
@@ -81,13 +98,16 @@ debug() {
}
step() {
# Announce a top-level installation stage, numbered for clarity.
step_no="$1"
step_total="$2"
step_text="$3"
log_line "STEP [$step_no/$step_total] $step_text"
[ "$QUIET" -eq 1 ] && return 0
printf '\033[34;1m[%s/%s]\033[0m \033[1m%s\033[0m\n' "$step_no" "$step_total" "$step_text"
if command -v tui_step >/dev/null 2>&1; then
tui_step "$step_no" "$step_total" "$step_text"
else
printf '\033[34;1m[%s/%s]\033[0m \033[1m%s\033[0m\n' "$step_no" "$step_total" "$step_text"
fi
}
usage() {
@@ -1956,6 +1976,11 @@ main() {
detect_fetcher
check_system
# Print TUI banner
if [ "$QUIET" -eq 0 ] && command -v tui_banner >/dev/null 2>&1; then
tui_banner
fi
if [ "$DRY_RUN" -eq 1 ]; then
warn "Dry-run mode: no packages, files, or configuration will be changed."
fi
@@ -2006,16 +2031,35 @@ print_summary() {
elapsed=$((end_time - START_TIME))
[ "$elapsed" -ge 0 ] 2>/dev/null || elapsed=0
printf '\n'
if [ "$DRY_RUN" -eq 1 ]; then
msg "Dry run complete in ${elapsed}s — no changes were made."
if command -v tui_box_start >/dev/null 2>&1; then
tui_box_start
if [ "$DRY_RUN" -eq 1 ]; then
tui_box_line "Dry run complete in ${elapsed}s — no changes were made."
else
tui_box_line_color "Tachyon $TACHYON_PACKAGE_VERSION installed successfully (${elapsed}s)" "$_c_green"
fi
tui_box_line "Release: ${REPO_OWNER}/${REPO_NAME}@${TACHYON_RELEASE_TAG}"
[ "$TACHYON_LEGACY_DETECTED" -eq 1 ] && tui_box_line "Legacy installation migrated and removed."
tui_box_line "Log: $LOG_FILE"
if command -v tui_box_divider >/dev/null 2>&1; then
tui_box_divider
else
tui_divider
fi
tui_box_line_color "Open LuCI and review your rules before enabling Tachyon" "$_c_yellow"
tui_box_end
else
msg "Tachyon $TACHYON_PACKAGE_VERSION has been installed successfully (${elapsed}s)"
printf '\n'
if [ "$DRY_RUN" -eq 1 ]; then
msg "Dry run complete in ${elapsed}s — no changes were made."
else
msg "Tachyon $TACHYON_PACKAGE_VERSION has been installed successfully (${elapsed}s)"
fi
msg "Source release: ${REPO_OWNER}/${REPO_NAME}@${TACHYON_RELEASE_TAG}"
[ "$TACHYON_LEGACY_DETECTED" -eq 1 ] && msg "Legacy installation migrated and removed."
msg "Full log: $LOG_FILE"
warn "Open LuCI and review your rules before enabling Tachyon"
fi
msg "Source release: ${REPO_OWNER}/${REPO_NAME}@${TACHYON_RELEASE_TAG}"
[ "$TACHYON_LEGACY_DETECTED" -eq 1 ] && msg "Legacy installation migrated and removed."
msg "Full log: $LOG_FILE"
warn "Open LuCI and review your rules before enabling Tachyon"
}
main "$@"
+306
View File
@@ -0,0 +1,306 @@
#!/bin/sh
# shellcheck shell=dash
# ─── TUI helpers for Tachyon installer ───────────────────────────────────────
# POSIX-compatible, works with dash/bash/mksh on OpenWrt.
# Degrades gracefully when TERM is dumb or stdout is not a terminal.
# ─── Color detection ──────────────────────────────────────────────────────────
_tui_colors=0
if [ -t 1 ] 2>/dev/null; then
case "${TERM:-dumb}" in
dumb) _tui_colors=0 ;;
*) _tui_colors=1 ;;
esac
fi
if [ "$_tui_colors" -eq 1 ]; then
_c_reset='\033[0m'
_c_bold='\033[1m'
_c_dim='\033[2m'
_c_red='\033[31;1m'
_c_green='\033[32;1m'
_c_yellow='\033[33;1m'
_c_blue='\033[34;1m'
_c_cyan='\033[36;1m'
_c_magenta='\033[35;1m'
_c_white='\033[37;1m'
_c_bg_blue='\033[44m'
_c_bg_green='\033[42m'
_c_bg_red='\033[41m'
_c_bg_yellow='\033[43m'
_c_underline='\033[4m'
else
_c_reset=''
_c_bold=''
_c_dim=''
_c_red=''
_c_green=''
_c_yellow=''
_c_blue=''
_c_cyan=''
_c_magenta=''
_c_white=''
_c_bg_blue=''
_c_bg_green=''
_c_bg_red=''
_c_bg_yellow=''
_c_underline=''
fi
# ─── Terminal width ──────────────────────────────────────────────────────────
_tui_width() {
if [ -t 1 ] 2>/dev/null && command -v stty >/dev/null 2>&1; then
w="$(stty size 2>/dev/null | awk '{print $2}')"
[ -n "$w" ] && [ "$w" -gt 0 ] 2>/dev/null && printf '%s' "$w" && return 0
fi
printf '72'
}
# ─── Horizontal line ─────────────────────────────────────────────────────────
_tui_hline() {
_w="$(_tui_width)"
_char="${1:--}"
_i=0
while [ "$_i" -lt "$_w" ]; do
printf '%s' "$_char"
_i=$((_i + 1))
done
}
# ─── Center text ──────────────────────────────────────────────────────────────
_tui_center() {
_text="$1"
_w="$(_tui_width)"
_len=${#_text}
_pad=$((_w - _len))
[ "$_pad" -lt 0 ] 2>/dev/null && _pad=0
_left=$((_pad / 2))
_right=$((_pad - _left))
_i=0
while [ "$_i" -lt "$_left" ]; do
printf ' '
_i=$((_i + 1))
done
printf '%s' "$_text"
_i=0
while [ "$_i" -lt "$_right" ]; do
printf ' '
_i=$((_i + 1))
done
}
# ─── Pad/truncate to width ──────────────────────────────────────────────────
_tui_pad() {
_text="$1"
_target="${2:-0}"
_len=${#_text}
_i=$_len
while [ "$_i" -lt "$_target" ]; do
printf ' '
_i=$((_i + 1))
done
}
# ─── Print banner ────────────────────────────────────────────────────────────
tui_banner() {
printf '\n'
printf ' %s%sTachyon Installer%s v%s%s\n' "$_c_cyan" "$_c_bold" "$_c_reset" "$_c_bold" "$INSTALLER_VERSION"
printf '%s\n' ""
printf '%s%s%s\n' "$_c_dim" "$(_tui_hline '─')" "$_c_reset"
}
# ─── Print step header ──────────────────────────────────────────────────────
tui_step() {
_step_no="$1"
_step_total="$2"
_step_text="$3"
_step_icon=""
printf '\n'
printf ' %s%s[ %s/%s ]%s %s%s%s\n' \
"$_c_blue" "$_c_bold" \
"$_step_no" "$_step_total" \
"$_c_reset" \
"$_c_bold" "$_step_text" "$_c_reset"
printf ' %s%s\n' "$_c_dim" "$(_tui_hline '·')"
printf '%s' "$_c_reset"
}
# ─── Success message ─────────────────────────────────────────────────────────
tui_ok() {
printf ' %s%s✓%s %s\n' "$_c_green" "$_c_bold" "$_c_reset" "$1"
}
# ─── Warning message ─────────────────────────────────────────────────────────
tui_warn() {
printf ' %s%s⚠%s %s%s\n' "$_c_yellow" "$_c_bold" "$_c_reset" "$1" "$_c_reset" >&2
}
# ─── Error message ───────────────────────────────────────────────────────────
tui_err() {
printf ' %s%s✗%s %s%s\n' "$_c_red" "$_c_bold" "$_c_reset" "$1" "$_c_reset" >&2
printf ' %s%s Log: %s%s\n' "$_c_dim" "$_c_reset" "$LOG_FILE" "$_c_reset" >&2
}
# ─── Info message ────────────────────────────────────────────────────────────
tui_info() {
printf ' %s▸%s %s\n' "$_c_cyan" "$_c_reset" "$1"
}
# ─── Download progress ───────────────────────────────────────────────────────
tui_download() {
_label="$1"
_attempt="${2:-1}"
_max="${3:-3}"
printf ' %s%s↓%s %s %s(%s/%s)%s\n' \
"$_c_cyan" "$_c_bold" "$_c_reset" \
"$_label" \
"$_c_dim" "$_attempt" "$_max" "$_c_reset"
}
# ─── Progress bar ────────────────────────────────────────────────────────────
tui_progress() {
_current="$1"
_total="$2"
_label="${3:-}"
_w=$((_tui_width() - 8))
[ "$_w" -lt 10 ] 2>/dev/null && _w=10
_pct=0
[ "$_total" -gt 0 ] 2>/dev/null && _pct=$((_current * 100 / _total))
_filled=$((_pct * _w / 100))
[ "$_filled" -gt "$_w" ] 2>/dev/null && _filled=$_w
_empty=$((_w - _filled))
printf '\r %s' "$_c_dim"
_i=0
while [ "$_i" -lt "$_filled" ]; do
printf '━'
_i=$((_i + 1))
done
_i=0
while [ "$_i" -lt "$_empty" ]; do
printf '─'
_i=$((_i + 1))
done
printf '%s' "$_c_reset"
printf ' %s%3d%%%s' "$_c_bold" "$_pct" "$_c_reset"
[ -n "$_label" ] && printf ' %s' "$_label"
}
# ─── Spinner (call in background, kill when done) ───────────────────────────
tui_spinner_start() {
_spinner_text="${1:-Working...}"
_spinner_chars='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
_spinner_pid=""
# Only spin on real terminals
[ -t 1 ] 2>/dev/null || { printf ' %s\n' "$_spinner_text"; return 0; }
(
while true; do
for _ch in $_spinner_chars; do
printf '\r %s%s%s %s' "$_c_cyan" "$_ch" "$_c_reset" "$_spinner_text"
sleep 0.1 2>/dev/null || sleep 1
done
done
) &
_spinner_pid=$!
printf '%s' "$_spinner_pid"
}
tui_spinner_stop() {
_pid="$1"
_text="${2:-}"
if [ -n "$_pid" ] && kill -0 "$_pid" 2>/dev/null; then
kill "$_pid" 2>/dev/null
wait "$_pid" 2>/dev/null
fi
# Clear spinner line
printf '\r%s' "$(_tui_hline ' ')"
printf '\r'
[ -n "$_text" ] && tui_ok "$_text"
}
# ─── Boxed section ───────────────────────────────────────────────────────────
tui_box_start() {
_w="$(_tui_width)"
_w=$((_w - 4))
[ "$_w" -lt 10 ] 2>/dev/null && _w=10
printf '\n'
printf ' %s╔' "$_c_blue"
_i=0; while [ "$_i" -lt "$_w" ]; do printf '═'; _i=$((_i + 1)); done
printf '╗%s\n' "$_c_reset"
}
tui_box_line() {
_text="$1"
_w="$(_tui_width)"
_w=$((_w - 4))
_len=${#_text}
_pad=$((_w - _len - 2))
[ "$_pad" -lt 0 ] 2>/dev/null && _pad=0
printf ' %s║%s %s' "$_c_blue" "$_c_reset" "$_text"
_i=0; while [ "$_i" -lt "$_pad" ]; do printf ' '; _i=$((_i + 1)); done
printf '%s║%s\n' "$_c_blue" "$_c_reset"
}
tui_box_line_color() {
_text="$1"
_color="$2"
_w="$(_tui_width)"
_w=$((_w - 4))
_len=${#_text}
_pad=$((_w - _len - 2))
[ "$_pad" -lt 0 ] 2>/dev/null && _pad=0
printf ' %s║%s %s%s' "$_c_blue" "$_c_reset" "$_color" "$_text"
_i=0; while [ "$_i" -lt "$_pad" ]; do printf ' '; _i=$((_i + 1)); done
printf '%s║%s\n' "$_c_reset" "$_c_blue"
}
tui_box_end() {
_w="$(_tui_width)"
_w=$((_w - 4))
[ "$_w" -lt 10 ] 2>/dev/null && _w=10
printf ' %s╚' "$_c_blue"
_i=0; while [ "$_i" -lt "$_w" ]; do printf '═'; _i=$((_i + 1)); done
printf '╝%s\n' "$_c_reset"
}
# ─── Section divider ─────────────────────────────────────────────────────────
tui_divider() {
printf '\n %s%s%s\n' "$_c_dim" "$(_tui_hline '─')" "$_c_reset"
}
tui_box_divider() {
_w="$(_tui_width)"
_w=$((_w - 4))
[ "$_w" -lt 10 ] 2>/dev/null && _w=10
printf ' %s║%s' "$_c_blue" "$_c_reset"
_i=0; while [ "$_i" -lt "$_w" ]; do printf '─'; _i=$((_i + 1)); done
printf '%s║%s\n' "$_c_blue" "$_c_reset"
}
# ─── Interactive menu (returns choice) ──────────────────────────────────────
tui_menu() {
_prompt="$1"
shift
_options="$@"
printf '\n %s%s%s\n' "$_c_bold" "$_prompt" "$_c_reset"
_i=1
for _opt in $_options; do
printf ' %s%s)%s %s\n' "$_c_cyan" "$_c_bold" "$_c_reset" "$_opt"
_i=$((_i + 1))
done
printf '\n'
printf ' %s▸%s ' "$_c_cyan" "$_c_reset"
}
# ─── Confirmation prompt ────────────────────────────────────────────────────
tui_confirm() {
_prompt="$1"
printf ' %s%s?%s %s %s' "$_c_yellow" "$_c_bold" "$_c_reset" "$_prompt" "$_c_dim"
printf '(%s/%s)%s ' "y" "n" "$_c_reset"
}
+33
View File
@@ -0,0 +1,33 @@
#!/bin/sh
. /tachyon/installer_tui.sh
INSTALLER_VERSION="1.2.56"
tui_banner
tui_step 1 10 "Updating package lists"
tui_ok "Package lists updated"
tui_step 2 10 "Resolving latest Tachyon release version"
tui_info "Fetching release metadata..."
tui_ok "Resolved: 1.2.56"
tui_step 3 10 "Downloading Tachyon release packages"
tui_download "tachyon_1.2.56.apk" 1 3
tui_download "luci-app-tachyon_1.2.56.apk" 2 3
tui_download "sha256sums.txt" 3 3
tui_ok "All packages downloaded"
tui_step 4 10 "Installing Tachyon backend package"
tui_info "Ensuring optional kernel module dependencies..."
tui_warn "Could not install kmod-inet-diag (built-in)"
tui_ok "tachyon 1.2.56 installed"
tui_step 5 10 "Done"
tui_box_start
tui_box_line_color "Tachyon 1.2.56 installed successfully (42s)" "$_c_green"
tui_box_line "Release: Dushnilin/tachyon@1.2.56"
tui_box_line "Log: /tmp/tachyon-install.log"
tui_box_divider
tui_box_line_color "Open LuCI and review your rules before enabling Tachyon" "$_c_yellow"
tui_box_end