(
terminal: &mut Terminal<ratatui::backend::CrosstermBackend<io::Stdout>>,
server: &str,
)
| 894 | } |
| 895 | |
| 896 | async fn run_app( |
| 897 | terminal: &mut Terminal<ratatui::backend::CrosstermBackend<io::Stdout>>, |
| 898 | server: &str, |
| 899 | ) -> Result<()> { |
| 900 | let mut app = App::new(server); |
| 901 | let client = Client::new(); |
| 902 | let mut response_rx: Option<tokio::sync::mpsc::UnboundedReceiver<Option<String>>> = None; |
| 903 | let mut gen_start: Option<Instant> = None; |
| 904 | let mut token_count: usize = 0; |
| 905 | let mut last_topology_fetch = Instant::now() - std::time::Duration::from_secs(60); |
| 906 | |
| 907 | loop { |
| 908 | // Fetch topology periodically (every 10s) or on first switch to cluster tab |
| 909 | if app.tab == Tab::Cluster |
| 910 | && last_topology_fetch.elapsed() > std::time::Duration::from_secs(10) |
| 911 | { |
| 912 | if let Ok(topo) = fetch_topology(&client, server).await { |
| 913 | app.topology = Some(topo); |
| 914 | } |
| 915 | last_topology_fetch = Instant::now(); |
| 916 | } |
| 917 | |
| 918 | terminal.draw(|f| draw(f, &mut app))?; |
| 919 | |
| 920 | if app.should_quit { |
| 921 | break; |
| 922 | } |
| 923 | |
| 924 | let timeout = std::time::Duration::from_millis(16); |
| 925 | |
| 926 | tokio::select! { |
| 927 | _ = tokio::time::sleep(timeout) => { |
| 928 | while event::poll(std::time::Duration::ZERO)? { |
| 929 | if let Event::Key(key) = event::read()? { |
| 930 | if key.kind != KeyEventKind::Press { |
| 931 | continue; |
| 932 | } |
| 933 | match key.code { |
| 934 | KeyCode::Esc => { |
| 935 | app.should_quit = true; |
| 936 | } |
| 937 | KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { |
| 938 | app.should_quit = true; |
| 939 | } |
| 940 | // Tab switching |
| 941 | KeyCode::Char('1') if !app.streaming => { |
| 942 | app.tab = Tab::Chat; |
| 943 | } |
| 944 | KeyCode::Char('2') if !app.streaming => { |
| 945 | app.tab = Tab::Cluster; |
| 946 | // Force immediate fetch |
| 947 | if app.topology.is_none() { |
| 948 | last_topology_fetch = Instant::now() - std::time::Duration::from_secs(60); |
| 949 | } |
| 950 | } |
| 951 | KeyCode::Tab if !app.streaming => { |
| 952 | app.tab = match app.tab { |
| 953 | Tab::Chat => Tab::Cluster, |
no test coverage detected