magi-code 0.102.1

Repository-aware CLI coding agent for terminal work
Documentation
use super::MissionControlApp;
use crate::tui::state::MissionControlState;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use std::time::{Duration, Instant};

impl MissionControlApp {
    pub(super) fn open_background_jobs(&mut self, ui: &mut MissionControlState) {
        ui.modals.background_jobs = Some(Default::default());
        ui.hide_autocomplete();
        self.background_jobs_refresh = None;
        self.refresh_background_jobs(ui);
    }

    pub(super) fn refresh_background_jobs(&mut self, ui: &mut MissionControlState) -> bool {
        let Some(modal) = ui.modals.background_jobs.as_mut() else {
            return false;
        };
        if self
            .background_jobs_refresh
            .is_some_and(|last| last.elapsed() < Duration::from_millis(250))
        {
            return false;
        }
        self.background_jobs_refresh = Some(Instant::now());
        let Some(jobs) = self.state.bash_jobs.running_snapshot() else {
            return false;
        };
        let changed = modal.jobs != jobs || !modal.loaded;
        let selected_id = modal.jobs.get(modal.selected).map(|job| job.id.as_str());
        modal.selected = selected_id
            .and_then(|id| jobs.iter().position(|job| job.id == id))
            .unwrap_or_else(|| modal.selected.min(jobs.len().saturating_sub(1)));
        modal.jobs = jobs;
        modal.loaded = true;
        changed
    }

    pub(super) fn handle_background_jobs_key(
        &mut self,
        key: KeyEvent,
        ui: &mut MissionControlState,
    ) {
        if key.modifiers != KeyModifiers::NONE {
            return;
        }
        if key.code == KeyCode::Esc {
            ui.modals.background_jobs = None;
            return;
        }
        let Some(modal) = ui.modals.background_jobs.as_mut() else {
            return;
        };
        match key.code {
            KeyCode::Up => modal.selected = modal.selected.saturating_sub(1),
            KeyCode::Down => {
                modal.selected = (modal.selected + 1).min(modal.jobs.len().saturating_sub(1))
            }
            crate::tui::input::BACKGROUND_JOB_KILL_KEY => {
                if let Some(job) = modal.jobs.get(modal.selected) {
                    modal.notice = match self.state.bash_jobs.request_stop(&job.id) {
                        Ok(()) => format!("Stop requested for PID {}", job.pid),
                        Err(error) => error.to_string(),
                    };
                    self.background_jobs_refresh = None;
                    self.refresh_background_jobs(ui);
                }
            }
            _ => {}
        }
    }
}