From ca55321621e5852611a031f1e5e1196fe389a449 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 22 May 2026 19:20:03 -0400 Subject: [PATCH] installer: animate dashboard and finish screens --- builder/build-iso.sh | 2 +- .../usr/local/bin/omarchy-install-dashboard | 11 ++++ .../omarchy-iso/orchestrator/phases_impl.py | 57 +++++++++++++++---- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/builder/build-iso.sh b/builder/build-iso.sh index d652162..87c477f 100755 --- a/builder/build-iso.sh +++ b/builder/build-iso.sh @@ -67,7 +67,7 @@ cp "/tmp/$NODE_FILENAME" "$build_cache_dir/airootfs/opt/packages/" # /etc/plymouth so mkinitcpio's plymouth hook picks up the Omarchy theme # when mkarchiso builds the live initramfs (otherwise plymouth shows # the default theme on boot). -arch_packages=(linux-t2 git gum jq openssl plymouth tzupdate omarchy-keyring omarchy-settings omarchy-installer lvm2 cryptsetup parted) +arch_packages=(linux-t2 git gum jq openssl plymouth python-terminaltexteffects tzupdate omarchy-keyring omarchy-settings omarchy-installer lvm2 cryptsetup parted) printf '%s\n' "${arch_packages[@]}" >> "$build_cache_dir/packages.x86_64" # Build the offline mirror: everything pacstrap might want during the target diff --git a/configs/airootfs/usr/local/bin/omarchy-install-dashboard b/configs/airootfs/usr/local/bin/omarchy-install-dashboard index b16e98f..f8ce653 100755 --- a/configs/airootfs/usr/local/bin/omarchy-install-dashboard +++ b/configs/airootfs/usr/local/bin/omarchy-install-dashboard @@ -193,6 +193,17 @@ current_whimsy() { render_static() { printf '%s' "$CLEAR" blank_line + + if command -v tte >/dev/null 2>&1 && command -v timeout >/dev/null 2>&1 && [[ -f $LOGO_PATH ]]; then + if timeout 8s tte -i "$LOGO_PATH" --canvas-width 0 --anchor-text c --frame-rate 920 laseretch 2>/dev/null; then + blank_line + return + fi + # If animation fails or times out, clear any partial frame before fallback. + printf '%s' "$CLEAR" + blank_line + fi + render_logo blank_line } diff --git a/configs/airootfs/usr/share/omarchy-iso/orchestrator/phases_impl.py b/configs/airootfs/usr/share/omarchy-iso/orchestrator/phases_impl.py index 7bbd97e..119a138 100644 --- a/configs/airootfs/usr/share/omarchy-iso/orchestrator/phases_impl.py +++ b/configs/airootfs/usr/share/omarchy-iso/orchestrator/phases_impl.py @@ -1173,22 +1173,59 @@ def _install_duration(ctx: InstallContext) -> str | None: return None +def _render_tte_logo(logo_path: Path) -> bool: + if not logo_path.exists() or not shutil.which("tte"): + return False + try: + with open("/dev/tty", "rb", buffering=0) as stdin, open("/dev/tty", "wb", buffering=0) as stdout: + subprocess.run( + [ + "tte", + "-i", str(logo_path), + "--canvas-width", "0", + "--anchor-text", "c", + "--frame-rate", "920", + "laseretch", + ], + stdin=stdin, + stdout=stdout, + stderr=subprocess.DEVNULL, + timeout=8, + check=True, + ) + return True + except (OSError, subprocess.SubprocessError): + return False + + +def _render_static_finish_logo(tty, logo_path: Path, cols: int) -> None: + green = "\033[32m" + reset = "\033[0m" + if logo_path.exists(): + logo_lines = logo_path.read_text(errors="ignore").splitlines() + logo_width = max((len(line) for line in logo_lines), default=0) + left = max((cols - logo_width) // 2, 0) + for line in logo_lines: + tty.write(" " * left + green + line + reset + "\n") + else: + tty.write(_center_text("Omarchy", cols) + "\n") + + def _render_finish_screen(ctx: InstallContext) -> None: _, cols = _tty_size() logo_path = Path("/usr/share/omarchy/logo.txt") - green = "\033[32m" - reset = "\033[0m" try: with open("/dev/tty", "w", encoding="utf-8") as tty: tty.write("\033[?25h\033[H\033[2J\n") - if logo_path.exists(): - logo_lines = logo_path.read_text(errors="ignore").splitlines() - logo_width = max((len(line) for line in logo_lines), default=0) - left = max((cols - logo_width) // 2, 0) - for line in logo_lines: - tty.write(" " * left + green + line + reset + "\n") - else: - tty.write(_center_text(green + "Omarchy" + reset, cols) + "\n") + tty.flush() + + if not _render_tte_logo(logo_path): + with open("/dev/tty", "w", encoding="utf-8") as tty: + tty.write("\033[?25h\033[H\033[2J\n") + _render_static_finish_logo(tty, logo_path, cols) + tty.flush() + + with open("/dev/tty", "w", encoding="utf-8") as tty: tty.write("\n") duration = _install_duration(ctx) message = f"Installed in {duration}" if duration else "Finished installing"