Skip to content

Commit

Permalink
feat: terminate containers on exit (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
therustmonk committed Aug 12, 2023
1 parent d4bb658 commit e3705ec
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 12 deletions.
9 changes: 9 additions & 0 deletions cli/src/component/main_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
Component,
ComponentEvent,
Input,
Pass,
},
state::{focus, AppState},
};
Expand All @@ -40,6 +41,14 @@ impl MainView {

impl Input for MainView {
fn on_event(&mut self, event: ComponentEvent, state: &mut AppState) {
if event.pass() == Pass::Quit {
let session = &mut state.state.config.session;
session.stop_all();
state.terminate();
state.focus_on(focus::TERMINATION);
state.update_state();
return;
}
self.header.on_event(event, state);
if state.focus_on == focus::ONBOARDING {
self.onboarding_scene.on_event(event, state);
Expand Down
4 changes: 4 additions & 0 deletions cli/src/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ mod normal;
mod onboarding;
mod settings;
mod tabs;
mod termination;
mod widgets;

use crossterm::event::{KeyCode, KeyEvent};
use derive_more::From;
pub use main_view::MainView;
pub use termination::TerminationView;
use tui::{backend::Backend, layout::Rect, Frame};

use crate::state::AppState;
Expand All @@ -37,6 +39,7 @@ pub enum Pass {
Next,
Other,
Tick,
Quit,
}

// impl Pass {
Expand Down Expand Up @@ -67,6 +70,7 @@ impl ComponentEvent {
KeyCode::Esc => Pass::Leave,
KeyCode::Enter => Pass::Enter,
KeyCode::Char(' ') => Pass::Space,
KeyCode::Char('q') => Pass::Quit,
KeyCode::Tab => Pass::Next,
_ => Pass::Other,
},
Expand Down
33 changes: 33 additions & 0 deletions cli/src/component/termination.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use tui::{
backend::Backend,
layout::{Alignment, Constraint, Direction, Layout, Rect},
widgets::Paragraph,
Frame,
};

use crate::component::{elements::block_with_title, AppState, Component};

pub struct TerminationView {}

impl TerminationView {
pub fn new() -> Self {
Self {}
}
}

impl<B: Backend> Component<B> for TerminationView {
type State = AppState;

fn draw(&self, f: &mut Frame<B>, rect: Rect, _state: &Self::State) {
let block = block_with_title(None, false);
let inner_rect = block.inner(rect);
f.render_widget(block, rect);
let constraints = [Constraint::Percentage(40), Constraint::Length(1)];
let v_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints(constraints)
.split(inner_rect);
let paragraph = Paragraph::new("Terminating...").alignment(Alignment::Center);
f.render_widget(paragraph, v_chunks[1]);
}
}
29 changes: 19 additions & 10 deletions cli/src/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{io::Stdout, time::Duration};
use anyhow::Error;
use async_trait::async_trait;
use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
event::{DisableMouseCapture, EnableMouseCapture, Event},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
Expand All @@ -14,9 +14,9 @@ use thiserror::Error;
use tui::{backend::CrosstermBackend, Terminal};

use crate::{
component::{Component, ComponentEvent, Input, MainView},
component::{Component, ComponentEvent, Input, MainView, TerminationView},
events::{EventHandle, TermEvent},
state::{bus::Bus, AppState},
state::{bus::Bus, focus, AppState},
};

type Term = Terminal<CrosstermBackend<Stdout>>;
Expand All @@ -39,6 +39,7 @@ pub struct Dashboard {
terminal: Option<Term>,
event_handle: Option<EventHandle>,
main_view: MainView,
termination_view: TerminationView,
// TODO: Get the state from a bus
state: Option<AppState>,
interval: Option<Interval>,
Expand All @@ -55,6 +56,7 @@ impl Dashboard {
terminal: None,
event_handle: None,
main_view: MainView::new(),
termination_view: TerminationView::new(),
state: None,
interval: None,
supervisor,
Expand Down Expand Up @@ -132,6 +134,11 @@ impl Dashboard {
tx.send(action)?;
Ok(())
}

fn stop_the_app(&mut self) -> Result<(), Error> {
self.event_handle.as_mut().ok_or(DashboardError::Events)?.interrupt();
Ok(())
}
}

#[async_trait]
Expand Down Expand Up @@ -168,12 +175,6 @@ impl Do<TermEvent> for Dashboard {
match event {
TermEvent::Event(event) => {
if let Event::Key(key) = event {
if let KeyCode::Char('q') = key.code {
self.event_handle
.as_mut()
.ok_or_else(|| DashboardError::Events)?
.interrupt();
}
let state = self.state.as_mut().ok_or_else(|| DashboardError::State)?;
self.main_view.on_event(key.into(), state);
let changed = state.process_events();
Expand Down Expand Up @@ -205,6 +206,9 @@ impl Do<Tick> for Dashboard {
if changed {
ctx.do_next(Redraw)?;
}
if state.is_terminated() {
self.stop_the_app()?;
}
Ok(())
}
}
Expand All @@ -220,7 +224,12 @@ impl Do<Redraw> for Dashboard {
let state = self.state.as_ref().ok_or_else(|| DashboardError::State)?;
let terminal = self.terminal.as_mut().ok_or_else(|| DashboardError::Terminal)?;
terminal.draw(|f| {
self.main_view.draw(f, f.size(), state);
let rect = f.size();
if state.focus_on == focus::TERMINATION {
self.termination_view.draw(f, rect, state);
} else {
self.main_view.draw(f, rect, state);
}
})?;
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions cli/src/state/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ macro_rules! focus {
}};
}

pub static TERMINATION: Focus = focus!();
pub static ONBOARDING: Focus = focus!();
pub static ROOT: Focus = focus!();
pub static TARI_MINING: Focus = focus!();
Expand Down
16 changes: 16 additions & 0 deletions cli/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct AppState {
pub bus: Bus,
pub bus_tx: BusTx,
pub state: LaunchpadState,
pub terminate: bool,
}

impl AppState {
Expand All @@ -32,14 +33,29 @@ impl AppState {
bus,
bus_tx,
state,
terminate: false,
}
}

pub fn is_terminated(&mut self) -> bool {
let has_active_task = self
.state
.containers
.values()
.filter(|state| !state.permanent)
.any(|state| state.status.is_started());
self.terminate && !has_active_task
}

pub fn focus_on(&mut self, value: Focus) {
let event = AppEvent::SetFocus(value);
self.events_queue.push_front(event);
}

pub fn terminate(&mut self) {
self.terminate = true;
}

pub fn redraw(&mut self) {
let event = AppEvent::Redraw;
self.events_queue.push_front(event);
Expand Down
4 changes: 2 additions & 2 deletions libs/protocol/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl TaskState {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct TaskProgress {
pub pct: u8,
pub stage: String,
Expand All @@ -123,7 +123,7 @@ impl TaskProgress {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TaskStatus {
Inactive,
/// Waiting for dependencies.
Expand Down

0 comments on commit e3705ec

Please sign in to comment.