From f840693320b15ef3e6bea49aff42c5742f60fa7a Mon Sep 17 00:00:00 2001 From: Pepe44DEV Date: Fri, 29 May 2026 13:17:27 +0200 Subject: [PATCH] feat: fullscreen TUI with progress bar for module execution --- install.sh | 11 +++- lib/tui-fs.sh | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 lib/tui-fs.sh diff --git a/install.sh b/install.sh index f42d16f..4e101f9 100755 --- a/install.sh +++ b/install.sh @@ -9,6 +9,7 @@ export OMERON_PROJECT_DIR="$OMERON_ROOT" source "$OMERON_ROOT/lib/log.sh" source "$OMERON_ROOT/lib/tui.sh" +source "$OMERON_ROOT/lib/tui-fs.sh" source "$OMERON_ROOT/lib/utils.sh" source "$OMERON_ROOT/lib/config.sh" source "$OMERON_ROOT/lib/modules.sh" @@ -259,12 +260,16 @@ main() { local total=${#modules_to_run[@]} local idx=1 + tui_fs_init + local fs_active=$? + for module_path in "${modules_to_run[@]}"; do local description="" if source "$module_path" 2>/dev/null && declare -F "module_description" >/dev/null 2>&1; then description="$(module_description)" fi - printf '\n' + + ((fs_active == 0)) && tui_fs_set_overall "$idx" "$total" "${description:-$(basename "$module_path" .sh)}" log_step "$idx" "$total" "${description:-$(basename "$module_path" .sh)}" module_run "$module_path" || { @@ -272,15 +277,19 @@ main() { if declare -F "module_required" >/dev/null 2>&1; then source "$module_path" if module_required 2>/dev/null; then + ((fs_active == 0)) && tui_fs_exit tui_error "Required module failed. Aborting." exit $rc fi fi tui_warn "Module completed with warnings" } + ((fs_active == 0)) && tui_fs_set_progress 100 ((idx++)) done + ((fs_active == 0)) && tui_fs_exit + printf '\n' tui_header "O M E R O N — Done" tui_success "Installation Complete!" diff --git a/lib/tui-fs.sh b/lib/tui-fs.sh new file mode 100644 index 0000000..c9f93b7 --- /dev/null +++ b/lib/tui-fs.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash + +TUI_FS_ACTIVE=0 +TUI_FS_ROWS=0 +TUI_FS_COLS=0 +TUI_FS_LOG_AREA=4 +TUI_FS_OVERALL_CURRENT=0 +TUI_FS_OVERALL_TOTAL=0 +TUI_FS_MODULE_LABEL="" +TUI_FS_MODULE_PROGRESS=0 +TUI_FS_SAVED_STTY="" + +tui_fs_init() { + ((OMERON_HAS_GUM)) || return 1 + + TUI_FS_SAVED_STTY=$(stty -g 2>/dev/null || true) + TUI_FS_ROWS=$(tput lines 2>/dev/null || echo 24) + TUI_FS_COLS=$(tput cols 2>/dev/null || echo 80) + TUI_FS_LOG_AREA=4 + + tput smcup 2>/dev/null + tput civis 2>/dev/null + tput csr "$TUI_FS_LOG_AREA" $((TUI_FS_ROWS - 1)) 2>/dev/null + tput clear 2>/dev/null + + _tui_fs_draw_frame + TUI_FS_ACTIVE=1 + trap '_tui_fs_cleanup' EXIT INT TERM + + tput cup "$TUI_FS_LOG_AREA" 0 +} + +tui_fs_exit() { + [[ "$TUI_FS_ACTIVE" -eq 0 ]] && return + TUI_FS_ACTIVE=0 + trap - EXIT INT TERM + tput csr 0 $((TUI_FS_ROWS - 1)) 2>/dev/null + tput cnorm 2>/dev/null + tput rmcup 2>/dev/null + [[ -n "$TUI_FS_SAVED_STTY" ]] && stty "$TUI_FS_SAVED_STTY" 2>/dev/null || true +} + +tui_fs_set_overall() { + TUI_FS_OVERALL_CURRENT=$1 + TUI_FS_OVERALL_TOTAL=$2 + TUI_FS_MODULE_LABEL="${3:-}" + TUI_FS_MODULE_PROGRESS=0 + _tui_fs_draw_header +} + +tui_fs_set_progress() { + TUI_FS_MODULE_PROGRESS=$1 + _tui_fs_draw_header +} + +_tui_fs_cleanup() { + tui_fs_exit +} + +_tui_fs_draw_frame() { + local cols=$TUI_FS_COLS + tput cup 0 0 + printf "\033[7m %-*s\033[0m" $((cols - 2)) " Omeron — Modular System Setup" + tput cup 1 0 + printf " %-*s" $((cols - 3)) "" + tput cup 2 0 + printf " %-*s" $((cols - 3)) "" + tput cup 3 0 + printf " " + printf '%*s' $((cols - 4)) '' | tr ' ' '─' +} + +_tui_fs_draw_header() { + [[ "$TUI_FS_ACTIVE" -eq 0 ]] && return 0 + tput sc + local cols=$TUI_FS_COLS + + # Row 1: module label + overall progress + tput cup 1 0 + printf " " + if [[ -n "$TUI_FS_MODULE_LABEL" ]]; then + printf "Module: %-*s" $((cols - 35)) "$TUI_FS_MODULE_LABEL" + if ((TUI_FS_OVERALL_TOTAL > 0)); then + printf " [%d/%d]" "$TUI_FS_OVERALL_CURRENT" "$TUI_FS_OVERALL_TOTAL" + fi + fi + tput el + + # Row 2: progress bar + tput cup 2 0 + printf " " + local bar_width=$((cols - 16)) + ((bar_width < 10)) && bar_width=10 + + local progress=0 + if ((TUI_FS_OVERALL_TOTAL > 0)); then + local overall_pct=$((TUI_FS_OVERALL_CURRENT * 100 / TUI_FS_OVERALL_TOTAL)) + if ((TUI_FS_OVERALL_TOTAL == TUI_FS_OVERALL_CURRENT)) && ((TUI_FS_MODULE_PROGRESS >= 100)); then + progress=100 + else + local module_share=$((100 / TUI_FS_OVERALL_TOTAL)) + local completed_pct=$(( (TUI_FS_OVERALL_CURRENT - 1) * 100 / TUI_FS_OVERALL_TOTAL )) + local current_pct=$(( TUI_FS_MODULE_PROGRESS * module_share / 100 )) + progress=$((completed_pct + current_pct)) + ((progress > 100)) && progress=100 + fi + fi + + local filled=$(( progress * bar_width / 100 )) + local i + for ((i=0; i&2 +} + +tui_fs_log_error() { + printf ' \033[1;31m✗\033[0m %s\n' "$1" >&2 +} + +tui_fs_log_section() { + local msg="$1" + local line + printf -v line '%*s' "${#msg}" '' && line="${line// /─}" + printf ' %s\n' "$line" + printf ' %s\n' "$msg" + printf ' %s\n' "$line" +}