zilliz 1.4.3

TUI and CLI tool for managing Zilliz Cloud clusters and Milvus operations
Documentation
pub mod app;
pub mod event;
pub mod handler;
pub mod home_fetch;
pub mod render;
pub mod views;
pub mod widgets;
pub mod wizard;

use anyhow::Result;
use crossterm::{
    event::{DisableMouseCapture, EnableMouseCapture},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::prelude::*;

use crate::config::manager::ConfigManager;
use crate::model::loader::Models;

use self::app::App;
use self::event::{Event, EventLoop};

/// Restores the terminal (raw mode, alternate screen, mouse capture) on every
/// exit path — including an error return or a panic inside the render/event
/// loop — so the user is never left with a corrupted terminal.
struct TerminalGuard;

impl Drop for TerminalGuard {
    fn drop(&mut self) {
        let _ = disable_raw_mode();
        let _ = execute!(std::io::stdout(), LeaveAlternateScreen, DisableMouseCapture);
    }
}

/// Main entry point for TUI mode.
pub async fn run(models: Models, config_mgr: ConfigManager) -> Result<()> {
    enable_raw_mode()?;
    let mut stdout = std::io::stdout();
    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
    // Past this point the guard owns terminal teardown; it runs on normal
    // return, `?` early-return, and unwinding panics alike.
    let _guard = TerminalGuard;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    let mut app = App::new(models, config_mgr);
    if app.auth.is_signed_in() {
        app.spawn_home_counts_fetch();
    }
    let event_loop = EventLoop::new(250);

    let result = run_loop(&mut terminal, &mut app, &event_loop);

    let _ = terminal.show_cursor();

    result
}

fn run_loop(
    terminal: &mut Terminal<CrosstermBackend<std::io::Stdout>>,
    app: &mut App,
    event_loop: &EventLoop,
) -> Result<()> {
    loop {
        terminal.draw(|frame| render::render(frame, app))?;

        // Drain any wizard messages (device-code ready, token received, errors)
        // before blocking on the next crossterm event so the UI updates promptly.
        while let Ok(msg) = app.msg_rx.try_recv() {
            handler::handle_wizard_msg(app, msg);
        }
        // Same for home-counts background updates.
        while let Ok(msg) = app.home_rx.try_recv() {
            app.apply_home_msg(msg);
        }

        match event_loop.next()? {
            Event::Key(key) => {
                handler::handle_key(app, key);
            }
            Event::Tick | Event::Resize(_, _) => {
                if app.auth.is_signed_in() && app.home_counts_refresh_due() {
                    app.spawn_home_counts_fetch();
                }
            }
        }

        if app.should_quit {
            // Cancel any in-flight wizard tasks so they don't run past quit.
            handler::cancel_wizard(app);
            app.abort_home_counts_fetch();
            break;
        }
    }

    Ok(())
}