wip: gui_status, should use a hashset?

This commit is contained in:
Jack Wills
2022-10-14 21:26:20 +00:00
parent 46ffbeef6a
commit 90e26c300e
7 changed files with 240 additions and 192 deletions
+2 -4
View File
@@ -15,8 +15,8 @@ pub struct AppData {
error: Option<AppError>, error: Option<AppError>,
logs_parsed: bool, logs_parsed: bool,
pub containers: StatefulList<ContainerItem>, pub containers: StatefulList<ContainerItem>,
pub init: bool, // pub init: bool,
pub show_error: bool, // pub show_error: bool,
sorted_by: Option<(Header, SortedOrder)>, sorted_by: Option<(Header, SortedOrder)>,
} }
@@ -79,9 +79,7 @@ impl AppData {
args, args,
containers: StatefulList::new(vec![]), containers: StatefulList::new(vec![]),
error: None, error: None,
init: false,
logs_parsed: false, logs_parsed: false,
show_error: false,
sorted_by: None, sorted_by: None,
} }
} }
+20 -18
View File
@@ -19,7 +19,7 @@ use crate::{
app_data::{AppData, ContainerId, DockerControls}, app_data::{AppData, ContainerId, DockerControls},
app_error::AppError, app_error::AppError,
parse_args::CliArgs, parse_args::CliArgs,
ui::GuiState, ui::{GuiState, Status},
}; };
mod message; mod message;
pub use message::DockerMessage; pub use message::DockerMessage;
@@ -336,32 +336,40 @@ impl DockerData {
tokio::time::sleep(std::time::Duration::from_millis(100)).await; tokio::time::sleep(std::time::Duration::from_millis(100)).await;
self.initialised = self.app_data.lock().initialised(&all_ids); self.initialised = self.app_data.lock().initialised(&all_ids);
} }
self.app_data.lock().init = true; // self.app_data.lock().init = true;
self.gui_state.lock().set_status(Status::Normal);
self.stop_loading_spin(&loading_spin, loading_uuid); self.stop_loading_spin(&loading_spin, loading_uuid);
} }
/// Set the global error as the dockererror, and set gui_state to errro
fn set_error(&mut self, error: DockerControls) {
self.app_data
.lock()
.set_error(AppError::DockerCommand(error));
self.gui_state.lock().set_status(Status::Error);
}
/// Handle incoming messages, container controls & all container information update /// Handle incoming messages, container controls & all container information update
async fn message_handler(&mut self) { async fn message_handler(&mut self) {
while let Some(message) = self.receiver.recv().await { while let Some(message) = self.receiver.recv().await {
let docker = Arc::clone(&self.docker); let docker = Arc::clone(&self.docker);
let app_data = Arc::clone(&self.app_data);
let loading_uuid = Uuid::new_v4(); let loading_uuid = Uuid::new_v4();
match message { match message {
DockerMessage::Pause(id) => { DockerMessage::Pause(id) => {
let loading_spin = self.loading_spin(loading_uuid).await; let loading_spin = self.loading_spin(loading_uuid).await;
if docker.pause_container(id.get()).await.is_err() { if docker.pause_container(id.get()).await.is_err() {
app_data self.set_error(DockerControls::Pause);
.lock()
.set_error(AppError::DockerCommand(DockerControls::Pause));
}; };
self.stop_loading_spin(&loading_spin, loading_uuid); self.stop_loading_spin(&loading_spin, loading_uuid);
} }
DockerMessage::Restart(id) => { DockerMessage::Restart(id) => {
// DEBUG
// self.set_error(DockerControls::Restart);
// DEBUG
let loading_spin = self.loading_spin(loading_uuid).await; let loading_spin = self.loading_spin(loading_uuid).await;
if docker.restart_container(id.get(), None).await.is_err() { if docker.restart_container(id.get(), None).await.is_err() {
app_data self.set_error(DockerControls::Restart);
.lock()
.set_error(AppError::DockerCommand(DockerControls::Restart));
}; };
self.stop_loading_spin(&loading_spin, loading_uuid); self.stop_loading_spin(&loading_spin, loading_uuid);
} }
@@ -372,27 +380,21 @@ impl DockerData {
.await .await
.is_err() .is_err()
{ {
app_data self.set_error(DockerControls::Start);
.lock()
.set_error(AppError::DockerCommand(DockerControls::Start));
}; };
self.stop_loading_spin(&loading_spin, loading_uuid); self.stop_loading_spin(&loading_spin, loading_uuid);
} }
DockerMessage::Stop(id) => { DockerMessage::Stop(id) => {
let loading_spin = self.loading_spin(loading_uuid).await; let loading_spin = self.loading_spin(loading_uuid).await;
if docker.stop_container(id.get(), None).await.is_err() { if docker.stop_container(id.get(), None).await.is_err() {
app_data self.set_error(DockerControls::Stop);
.lock()
.set_error(AppError::DockerCommand(DockerControls::Stop));
}; };
self.stop_loading_spin(&loading_spin, loading_uuid); self.stop_loading_spin(&loading_spin, loading_uuid);
} }
DockerMessage::Unpause(id) => { DockerMessage::Unpause(id) => {
let loading_spin = self.loading_spin(loading_uuid).await; let loading_spin = self.loading_spin(loading_uuid).await;
if docker.unpause_container(id.get()).await.is_err() { if docker.unpause_container(id.get()).await.is_err() {
app_data self.set_error(DockerControls::Unpause);
.lock()
.set_error(AppError::DockerCommand(DockerControls::Unpause));
}; };
self.stop_loading_spin(&loading_spin, loading_uuid); self.stop_loading_spin(&loading_spin, loading_uuid);
self.update_everything().await; self.update_everything().await;
+138 -126
View File
@@ -21,7 +21,7 @@ use crate::{
app_data::{AppData, DockerControls, Header, SortedOrder}, app_data::{AppData, DockerControls, Header, SortedOrder},
app_error::AppError, app_error::AppError,
docker_data::DockerMessage, docker_data::DockerMessage,
ui::{GuiState, SelectablePanel}, ui::{GuiState, SelectablePanel, Status},
}; };
pub use message::InputMessages; pub use message::InputMessages;
@@ -64,10 +64,11 @@ impl InputHandler {
match message { match message {
InputMessages::ButtonPress(key_code) => self.button_press(key_code).await, InputMessages::ButtonPress(key_code) => self.button_press(key_code).await,
InputMessages::MouseEvent(mouse_event) => { InputMessages::MouseEvent(mouse_event) => {
let show_error = self.app_data.lock().show_error; // let show_error = self.app_data.lock().show_error;
let show_info = self.gui_state.lock().show_help; let status = self.gui_state.lock().get_status();
if !show_error && !show_info { match status {
self.mouse_press(mouse_event); Status::Error | Status::Help => (),
_ => self.mouse_press(mouse_event),
} }
} }
} }
@@ -85,10 +86,11 @@ impl InputHandler {
.gui_state .gui_state
.lock() .lock()
.set_info_box("✖ mouse capture disabled".to_owned()), .set_info_box("✖ mouse capture disabled".to_owned()),
Err(_) => self Err(_) => {
.app_data self.app_data
.lock() .lock()
.set_error(AppError::MouseCapture(false)), .set_error(AppError::MouseCapture(false));
}
} }
} else { } else {
match execute!(std::io::stdout(), EnableMouseCapture) { match execute!(std::io::stdout(), EnableMouseCapture) {
@@ -96,7 +98,9 @@ impl InputHandler {
.gui_state .gui_state
.lock() .lock()
.set_info_box("✓ mouse capture enabled".to_owned()), .set_info_box("✓ mouse capture enabled".to_owned()),
Err(_) => self.app_data.lock().set_error(AppError::MouseCapture(true)), Err(_) => {
self.app_data.lock().set_error(AppError::MouseCapture(true));
}
} }
}; };
@@ -129,147 +133,155 @@ impl InputHandler {
} }
/// Send a quit message to docker, to abort all spawns, if an error is return, set is_running to false here instead /// Send a quit message to docker, to abort all spawns, if an error is return, set is_running to false here instead
async fn quit(&self) { async fn quit(&self, status: Status) {
match self.docker_sender.send(DockerMessage::Quit).await { match status {
Ok(_) => (), Status::Error | Status::Init => self.is_running.store(false, Ordering::SeqCst),
Err(_) => self.is_running.store(false, Ordering::SeqCst), _ => {
if self.docker_sender.send(DockerMessage::Quit).await.is_err() {
self.is_running.store(false, Ordering::SeqCst)
}
}
} }
// match self.docker_sender.send(DockerMessage::Quit).await {
// Ok(_) => (),
// Err(_) => self.is_running.store(false, Ordering::SeqCst),
// }
} }
/// Handle any keyboard button events /// Handle any keyboard button events
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
async fn button_press(&mut self, key_code: KeyCode) { async fn button_press(&mut self, key_code: KeyCode) {
let show_error = self.app_data.lock().show_error; let status = self.gui_state.lock().get_status();
let show_info = self.gui_state.lock().show_help;
if show_error { match status {
match key_code { Status::Error => match key_code {
KeyCode::Char('q' | 'Q') => self.quit().await, KeyCode::Char('q' | 'Q') => self.quit(status).await,
KeyCode::Char('c' | 'C') => { KeyCode::Char('c' | 'C') => {
self.app_data.lock().show_error = false;
self.app_data.lock().remove_error(); self.app_data.lock().remove_error();
self.gui_state.lock().set_status(Status::Normal);
} }
_ => (), _ => (),
} },
} else if show_info { Status::Help => match key_code {
match key_code { KeyCode::Char('q' | 'Q') => self.quit(status).await,
KeyCode::Char('q' | 'Q') => self.quit().await, KeyCode::Char('h' | 'H') => self.gui_state.lock().set_status(Status::Help),
KeyCode::Char('h' | 'H') => self.gui_state.lock().show_help = false,
KeyCode::Char('m' | 'M') => self.m_key(), KeyCode::Char('m' | 'M') => self.m_key(),
_ => (), _ => (),
} },
} else { _ => {
match key_code { match key_code {
KeyCode::Char('0') => self.app_data.lock().set_sorted(None), KeyCode::Char('0') => self.app_data.lock().set_sorted(None),
KeyCode::Char('1') => self.sort(Header::State), KeyCode::Char('1') => self.sort(Header::State),
KeyCode::Char('2') => self.sort(Header::Status), KeyCode::Char('2') => self.sort(Header::Status),
KeyCode::Char('3') => self.sort(Header::Cpu), KeyCode::Char('3') => self.sort(Header::Cpu),
KeyCode::Char('4') => self.sort(Header::Memory), KeyCode::Char('4') => self.sort(Header::Memory),
KeyCode::Char('5') => self.sort(Header::Id), KeyCode::Char('5') => self.sort(Header::Id),
KeyCode::Char('6') => self.sort(Header::Name), KeyCode::Char('6') => self.sort(Header::Name),
KeyCode::Char('7') => self.sort(Header::Image), KeyCode::Char('7') => self.sort(Header::Image),
KeyCode::Char('8') => self.sort(Header::Rx), KeyCode::Char('8') => self.sort(Header::Rx),
KeyCode::Char('9') => self.sort(Header::Tx), KeyCode::Char('9') => self.sort(Header::Tx),
KeyCode::Char('q' | 'Q') => self.quit().await, KeyCode::Char('q' | 'Q') => self.quit(status).await,
KeyCode::Char('h' | 'H') => self.gui_state.lock().show_help = true, KeyCode::Char('h' | 'H') => self.gui_state.lock().set_status(Status::Help),
KeyCode::Char('m' | 'M') => self.m_key(), KeyCode::Char('m' | 'M') => self.m_key(),
KeyCode::Tab => { KeyCode::Tab => {
// Skip control panel if no containers, could be refactored // Skip control panel if no containers, could be refactored
let has_containers = self.app_data.lock().get_container_len() == 0; let has_containers = self.app_data.lock().get_container_len() == 0;
let is_containers = let is_containers =
self.gui_state.lock().selected_panel == SelectablePanel::Containers; self.gui_state.lock().selected_panel == SelectablePanel::Containers;
let count = if has_containers && is_containers { let count = if has_containers && is_containers {
2 2
} else { } else {
1 1
}; };
for _ in 0..count { for _ in 0..count {
self.gui_state.lock().next_panel(); self.gui_state.lock().next_panel();
}
} }
} KeyCode::BackTab => {
KeyCode::BackTab => { // Skip control panel if no containers, could be refactored
// Skip control panel if no containers, could be refactored let has_containers = self.app_data.lock().get_container_len() == 0;
let has_containers = self.app_data.lock().get_container_len() == 0; let is_containers =
let is_containers = self.gui_state.lock().selected_panel == SelectablePanel::Logs;
self.gui_state.lock().selected_panel == SelectablePanel::Logs; let count = if has_containers && is_containers {
let count = if has_containers && is_containers { 2
2 } else {
} else { 1
1 };
}; for _ in 0..count {
for _ in 0..count { self.gui_state.lock().previous_panel();
self.gui_state.lock().previous_panel(); }
} }
} KeyCode::Home => {
KeyCode::Home => { let mut locked_data = self.app_data.lock();
let mut locked_data = self.app_data.lock(); match self.gui_state.lock().selected_panel {
match self.gui_state.lock().selected_panel { SelectablePanel::Containers => locked_data.containers.start(),
SelectablePanel::Containers => locked_data.containers.start(), SelectablePanel::Logs => locked_data.log_start(),
SelectablePanel::Logs => locked_data.log_start(), SelectablePanel::Commands => locked_data.docker_command_start(),
SelectablePanel::Commands => locked_data.docker_command_start(), }
} }
} KeyCode::End => {
KeyCode::End => { let mut locked_data = self.app_data.lock();
let mut locked_data = self.app_data.lock(); match self.gui_state.lock().selected_panel {
match self.gui_state.lock().selected_panel { SelectablePanel::Containers => locked_data.containers.end(),
SelectablePanel::Containers => locked_data.containers.end(), SelectablePanel::Logs => locked_data.log_end(),
SelectablePanel::Logs => locked_data.log_end(), SelectablePanel::Commands => locked_data.docker_command_end(),
SelectablePanel::Commands => locked_data.docker_command_end(), }
} }
} KeyCode::Up | KeyCode::Char('k' | 'K') => self.previous(),
KeyCode::Up | KeyCode::Char('k' | 'K') => self.previous(), KeyCode::PageUp => {
KeyCode::PageUp => { for _ in 0..=6 {
for _ in 0..=6 { self.previous();
self.previous(); }
} }
} KeyCode::Down | KeyCode::Char('j' | 'J') => self.next(),
KeyCode::Down | KeyCode::Char('j' | 'J') => self.next(), KeyCode::PageDown => {
KeyCode::PageDown => { for _ in 0..=6 {
for _ in 0..=6 { self.next();
self.next(); }
} }
} KeyCode::Enter => {
KeyCode::Enter => { // This isn't great, just means you can't send docker commands before full initialization of the program
// This isn't great, just means you can't send docker commands before full initialization of the program let panel = self.gui_state.lock().selected_panel;
let panel = self.gui_state.lock().selected_panel; if panel == SelectablePanel::Commands {
if panel == SelectablePanel::Commands { let option_command = self.app_data.lock().get_docker_command();
let option_command = self.app_data.lock().get_docker_command();
if let Some(command) = option_command { if let Some(command) = option_command {
let option_id = self.app_data.lock().get_selected_container_id(); let option_id = self.app_data.lock().get_selected_container_id();
if let Some(id) = option_id { if let Some(id) = option_id {
match command { match command {
DockerControls::Pause => self DockerControls::Pause => self
.docker_sender .docker_sender
.send(DockerMessage::Pause(id)) .send(DockerMessage::Pause(id))
.await .await
.unwrap_or(()), .unwrap_or(()),
DockerControls::Unpause => self DockerControls::Unpause => self
.docker_sender .docker_sender
.send(DockerMessage::Unpause(id)) .send(DockerMessage::Unpause(id))
.await .await
.unwrap_or(()), .unwrap_or(()),
DockerControls::Start => self DockerControls::Start => self
.docker_sender .docker_sender
.send(DockerMessage::Start(id)) .send(DockerMessage::Start(id))
.await .await
.unwrap_or(()), .unwrap_or(()),
DockerControls::Stop => self DockerControls::Stop => self
.docker_sender .docker_sender
.send(DockerMessage::Stop(id)) .send(DockerMessage::Stop(id))
.await .await
.unwrap_or(()), .unwrap_or(()),
DockerControls::Restart => self DockerControls::Restart => self
.docker_sender .docker_sender
.send(DockerMessage::Restart(id)) .send(DockerMessage::Restart(id))
.await .await
.unwrap_or(()), .unwrap_or(()),
}
} }
} }
} }
} }
_ => (),
} }
_ => (),
} }
} }
} }
+9 -3
View File
@@ -24,7 +24,7 @@ mod input_handler;
mod parse_args; mod parse_args;
mod ui; mod ui;
use ui::{create_ui, GuiState}; use ui::{create_ui, GuiState, Status};
fn setup_tracing() { fn setup_tracing() {
tracing_subscriber::fmt().with_max_level(Level::INFO).init(); tracing_subscriber::fmt().with_max_level(Level::INFO).init();
@@ -59,9 +59,15 @@ async fn main() {
is_running, is_running,
)); ));
} }
Err(_) => app_data.lock().set_error(AppError::DockerConnect), Err(_) => {
app_data.lock().set_error(AppError::DockerConnect);
docker_gui_state.lock().set_status(Status::DockerConnect)
}
}, },
Err(_) => app_data.lock().set_error(AppError::DockerConnect), Err(_) => {
app_data.lock().set_error(AppError::DockerConnect);
docker_gui_state.lock().set_status(Status::DockerConnect)
}
} }
let input_app_data = Arc::clone(&app_data); let input_app_data = Arc::clone(&app_data);
+43 -33
View File
@@ -15,6 +15,7 @@ use tui::{
}; };
use crate::app_data::{Header, SortedOrder}; use crate::app_data::{Header, SortedOrder};
use crate::ui::Status;
use crate::{ use crate::{
app_data::{AppData, ByteStats, Columns, CpuStats, State, Stats}, app_data::{AppData, ByteStats, Columns, CpuStats, State, Stats},
app_error::AppError, app_error::AppError,
@@ -215,37 +216,43 @@ pub fn logs<B: Backend>(
loading_icon: &str, loading_icon: &str,
) { ) {
let block = generate_block(app_data, area, gui_state, SelectablePanel::Logs); let block = generate_block(app_data, area, gui_state, SelectablePanel::Logs);
let status = gui_state.lock().get_status();
match status {
Status::Init => {
let paragraph = Paragraph::new(format!("parsing logs {}", loading_icon))
.style(Style::default())
.block(block)
.alignment(Alignment::Center);
f.render_widget(paragraph, area);
}
let init = app_data.lock().init; _ => {
if !init { if let Some(index) = index {
let paragraph = Paragraph::new(format!("parsing logs {}", loading_icon)) let items = app_data.lock().containers.items[index]
.style(Style::default()) .logs
.block(block) .items
.alignment(Alignment::Center); .iter()
f.render_widget(paragraph, area); .enumerate()
} else if let Some(index) = index { .map(|i| i.1.clone())
let items = app_data.lock().containers.items[index] .collect::<Vec<_>>();
.logs
.items
.iter()
.enumerate()
.map(|i| i.1.clone())
.collect::<Vec<_>>();
let items = List::new(items) let items = List::new(items)
.block(block) .block(block)
.highlight_symbol(ARROW) .highlight_symbol(ARROW)
.highlight_style(Style::default().add_modifier(Modifier::BOLD)); .highlight_style(Style::default().add_modifier(Modifier::BOLD));
f.render_stateful_widget( f.render_stateful_widget(
items, items,
area, area,
&mut app_data.lock().containers.items[index].logs.state, &mut app_data.lock().containers.items[index].logs.state,
); );
} else { } else {
let paragraph = Paragraph::new("no logs found") let paragraph = Paragraph::new("no logs found")
.block(block) .block(block)
.alignment(Alignment::Center); .alignment(Alignment::Center);
f.render_widget(paragraph, area); f.render_widget(paragraph, area);
// }
}
}
} }
} }
@@ -349,7 +356,7 @@ pub fn heading_bar<B: Backend>(
gui_state: &Arc<Mutex<GuiState>>, gui_state: &Arc<Mutex<GuiState>>,
) { ) {
let block = |fg: Color| Block::default().style(Style::default().bg(Color::Magenta).fg(fg)); let block = |fg: Color| Block::default().style(Style::default().bg(Color::Magenta).fg(fg));
let info_visible = gui_state.lock().show_help; let info_visible = gui_state.lock().get_status() == Status::Help;
f.render_widget(block(Color::Black), area); f.render_widget(block(Color::Black), area);
@@ -430,7 +437,12 @@ pub fn heading_bar<B: Backend>(
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let suffix = if info_visible { "exit" } else { "show" }; let suffix = if info_visible { "exit" } else { "show" };
let info_text = format!("( h ) {} help {}", suffix, MARGIN); let info_text = format!(
"( h ) {} help {} {:?}",
suffix,
MARGIN,
gui_state.lock().get_status()
);
let info_width = info_text.chars().count(); let info_width = info_text.chars().count();
let column_width = usize::from(area.width) - info_width; let column_width = usize::from(area.width) - info_width;
@@ -457,8 +469,6 @@ pub fn heading_bar<B: Backend>(
.alignment(Alignment::Center); .alignment(Alignment::Center);
f.render_widget(loading_paragraph, split_bar[0]); f.render_widget(loading_paragraph, split_bar[0]);
let container_splits = header_data.iter().map(|i| i.2).collect::<Vec<_>>(); let container_splits = header_data.iter().map(|i| i.2).collect::<Vec<_>>();
let headers_section = Layout::default() let headers_section = Layout::default()
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
+21 -2
View File
@@ -173,6 +173,17 @@ impl fmt::Display for Loading {
} }
} }
/// The application can be in these four states
/// Various functions (e.g input handler), operate differently depending upon current Status
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Status {
Init,
Help,
DockerConnect,
Error,
Normal,
}
/// Global gui_state, stored in an Arc<Mutex> /// Global gui_state, stored in an Arc<Mutex>
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct GuiState { pub struct GuiState {
@@ -180,8 +191,8 @@ pub struct GuiState {
heading_map: HashMap<Header, Rect>, heading_map: HashMap<Header, Rect>,
loading_icon: Loading, loading_icon: Loading,
is_loading: HashSet<Uuid>, is_loading: HashSet<Uuid>,
status: Status,
pub selected_panel: SelectablePanel, pub selected_panel: SelectablePanel,
pub show_help: bool,
pub info_box_text: Option<String>, pub info_box_text: Option<String>,
} }
impl GuiState { impl GuiState {
@@ -192,9 +203,9 @@ impl GuiState {
heading_map: HashMap::new(), heading_map: HashMap::new(),
loading_icon: Loading::One, loading_icon: Loading::One,
selected_panel: SelectablePanel::Containers, selected_panel: SelectablePanel::Containers,
show_help: false,
is_loading: HashSet::new(), is_loading: HashSet::new(),
info_box_text: None, info_box_text: None,
status: Status::Init,
} }
} }
@@ -242,6 +253,14 @@ impl GuiState {
}; };
} }
pub fn set_status(&mut self, status: Status) {
self.status = status
}
pub fn get_status(&self) -> Status {
self.status
}
/// Change to next selectable panel /// Change to next selectable panel
pub fn next_panel(&mut self) { pub fn next_panel(&mut self) {
self.selected_panel = self.selected_panel.next(); self.selected_panel = self.selected_panel.next();
+7 -6
View File
@@ -25,7 +25,7 @@ mod draw_blocks;
mod gui_state; mod gui_state;
pub use self::color_match::*; pub use self::color_match::*;
pub use self::gui_state::{GuiState, SelectablePanel}; pub use self::gui_state::{GuiState, SelectablePanel, Status};
use crate::{ use crate::{
app_data::AppData, app_error::AppError, docker_data::DockerMessage, app_data::AppData, app_error::AppError, docker_data::DockerMessage,
input_handler::InputMessages, input_handler::InputMessages,
@@ -56,7 +56,7 @@ pub async fn create_ui(
update_duration, update_duration,
) )
.await; .await;
terminal.clear()?; terminal.clear()?;
disable_raw_mode()?; disable_raw_mode()?;
execute!( execute!(
@@ -85,8 +85,9 @@ async fn run_app<B: Backend + Send>(
let input_poll_rate = std::time::Duration::from_millis(75); let input_poll_rate = std::time::Duration::from_millis(75);
// Check for docker connect errors before attempting to draw the gui // Check for docker connect errors before attempting to draw the gui
let e = app_data.lock().get_error(); let status = gui_state.lock().get_status();
if let Some(AppError::DockerConnect) = e {
if status == Status::DockerConnect {
let mut seconds = 5; let mut seconds = 5;
loop { loop {
if seconds < 1 { if seconds < 1 {
@@ -138,6 +139,7 @@ async fn run_app<B: Backend + Send>(
break; break;
} }
} }
// }
} }
Ok(()) Ok(())
} }
@@ -157,7 +159,7 @@ fn ui<B: Backend>(
let log_index = app_data.lock().get_selected_log_index(); let log_index = app_data.lock().get_selected_log_index();
let sorted_by = app_data.lock().get_sorted(); let sorted_by = app_data.lock().get_sorted();
let show_help = gui_state.lock().show_help; let show_help = gui_state.lock().get_status() == Status::Help;
let info_text = gui_state.lock().info_box_text.clone(); let info_text = gui_state.lock().info_box_text.clone();
let loading_icon = gui_state.lock().get_loading(); let loading_icon = gui_state.lock().get_loading();
@@ -241,7 +243,6 @@ fn ui<B: Backend>(
} }
if let Some(error) = has_error { if let Some(error) = has_error {
app_data.lock().show_error = true;
draw_blocks::error(f, error, None); draw_blocks::error(f, error, None);
} }
} }