feat: use gui_status for various gui states
This commit is contained in:
+1
-3
@@ -14,10 +14,8 @@ pub struct AppData {
|
|||||||
args: CliArgs,
|
args: CliArgs,
|
||||||
error: Option<AppError>,
|
error: Option<AppError>,
|
||||||
logs_parsed: bool,
|
logs_parsed: bool,
|
||||||
pub containers: StatefulList<ContainerItem>,
|
|
||||||
// pub init: bool,
|
|
||||||
// pub show_error: bool,
|
|
||||||
sorted_by: Option<(Header, SortedOrder)>,
|
sorted_by: Option<(Header, SortedOrder)>,
|
||||||
|
pub containers: StatefulList<ContainerItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
|
|||||||
+49
-38
@@ -3,7 +3,7 @@ use bollard::{
|
|||||||
service::ContainerSummary,
|
service::ContainerSummary,
|
||||||
Docker,
|
Docker,
|
||||||
};
|
};
|
||||||
use futures_util::StreamExt;
|
use futures_util::{Future, StreamExt};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@@ -318,6 +318,7 @@ impl DockerData {
|
|||||||
|
|
||||||
// Initialize docker container data, before any messages are received
|
// Initialize docker container data, before any messages are received
|
||||||
async fn initialise_container_data(&mut self) {
|
async fn initialise_container_data(&mut self) {
|
||||||
|
self.gui_state.lock().status_push(Status::Init);
|
||||||
let loading_uuid = Uuid::new_v4();
|
let loading_uuid = Uuid::new_v4();
|
||||||
let loading_spin = self.loading_spin(loading_uuid).await;
|
let loading_spin = self.loading_spin(loading_uuid).await;
|
||||||
|
|
||||||
@@ -336,8 +337,7 @@ 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.gui_state.lock().status_del(Status::Init);
|
||||||
self.gui_state.lock().set_status(Status::Normal);
|
|
||||||
self.stop_loading_spin(&loading_spin, loading_uuid);
|
self.stop_loading_spin(&loading_spin, loading_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,57 +346,68 @@ impl DockerData {
|
|||||||
self.app_data
|
self.app_data
|
||||||
.lock()
|
.lock()
|
||||||
.set_error(AppError::DockerCommand(error));
|
.set_error(AppError::DockerCommand(error));
|
||||||
self.gui_state.lock().set_status(Status::Error);
|
self.gui_state.lock().status_push(Status::Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Execute docker commands, will start and stop the loading spinner
|
||||||
|
async fn exec_docker(
|
||||||
|
&mut self,
|
||||||
|
docker_fn: impl Future<Output = Result<(), bollard::errors::Error>>,
|
||||||
|
uuid: Uuid,
|
||||||
|
control: DockerControls,
|
||||||
|
) {
|
||||||
|
let loading_spin = self.loading_spin(uuid).await;
|
||||||
|
if docker_fn.await.is_err() {
|
||||||
|
self.set_error(control);
|
||||||
|
};
|
||||||
|
self.stop_loading_spin(&loading_spin, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 loading_uuid = Uuid::new_v4();
|
let loading_uuid = Uuid::new_v4();
|
||||||
|
let docker = Arc::clone(&self.docker);
|
||||||
match message {
|
match message {
|
||||||
DockerMessage::Pause(id) => {
|
DockerMessage::Pause(id) => {
|
||||||
let loading_spin = self.loading_spin(loading_uuid).await;
|
self.exec_docker(
|
||||||
if docker.pause_container(id.get()).await.is_err() {
|
docker.pause_container(id.get()),
|
||||||
self.set_error(DockerControls::Pause);
|
loading_uuid,
|
||||||
};
|
DockerControls::Pause,
|
||||||
self.stop_loading_spin(&loading_spin, loading_uuid);
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
DockerMessage::Restart(id) => {
|
DockerMessage::Restart(id) => {
|
||||||
// DEBUG
|
self.exec_docker(
|
||||||
// self.set_error(DockerControls::Restart);
|
docker.restart_container(id.get(), None),
|
||||||
// DEBUG
|
loading_uuid,
|
||||||
|
DockerControls::Restart,
|
||||||
let loading_spin = self.loading_spin(loading_uuid).await;
|
)
|
||||||
if docker.restart_container(id.get(), None).await.is_err() {
|
.await;
|
||||||
self.set_error(DockerControls::Restart);
|
|
||||||
};
|
|
||||||
self.stop_loading_spin(&loading_spin, loading_uuid);
|
|
||||||
}
|
}
|
||||||
DockerMessage::Start(id) => {
|
DockerMessage::Start(id) => {
|
||||||
let loading_spin = self.loading_spin(loading_uuid).await;
|
self.exec_docker(
|
||||||
if docker
|
docker.start_container(id.get(), None::<StartContainerOptions<String>>),
|
||||||
.start_container(id.get(), None::<StartContainerOptions<String>>)
|
loading_uuid,
|
||||||
.await
|
DockerControls::Start,
|
||||||
.is_err()
|
)
|
||||||
{
|
.await;
|
||||||
self.set_error(DockerControls::Start);
|
|
||||||
};
|
|
||||||
self.stop_loading_spin(&loading_spin, loading_uuid);
|
|
||||||
}
|
}
|
||||||
DockerMessage::Stop(id) => {
|
DockerMessage::Stop(id) => {
|
||||||
let loading_spin = self.loading_spin(loading_uuid).await;
|
self.exec_docker(
|
||||||
if docker.stop_container(id.get(), None).await.is_err() {
|
docker.stop_container(id.get(), None),
|
||||||
self.set_error(DockerControls::Stop);
|
loading_uuid,
|
||||||
};
|
DockerControls::Stop,
|
||||||
self.stop_loading_spin(&loading_spin, loading_uuid);
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
DockerMessage::Unpause(id) => {
|
DockerMessage::Unpause(id) => {
|
||||||
let loading_spin = self.loading_spin(loading_uuid).await;
|
self.exec_docker(
|
||||||
if docker.unpause_container(id.get()).await.is_err() {
|
docker.unpause_container(id.get()),
|
||||||
self.set_error(DockerControls::Unpause);
|
loading_uuid,
|
||||||
};
|
DockerControls::Unpause,
|
||||||
self.stop_loading_spin(&loading_spin, loading_uuid);
|
)
|
||||||
|
.await;
|
||||||
self.update_everything().await;
|
self.update_everything().await;
|
||||||
}
|
}
|
||||||
DockerMessage::Update => self.update_everything().await,
|
DockerMessage::Update => self.update_everything().await,
|
||||||
|
|||||||
+127
-129
@@ -64,11 +64,12 @@ 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 error_or_help = self
|
||||||
let status = self.gui_state.lock().get_status();
|
.gui_state
|
||||||
match status {
|
.lock()
|
||||||
Status::Error | Status::Help => (),
|
.status_contains(&[Status::Error, Status::Help]);
|
||||||
_ => self.mouse_press(mouse_event),
|
if !error_or_help {
|
||||||
|
self.mouse_press(mouse_event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,155 +134,152 @@ 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, status: Status) {
|
async fn quit(&self) {
|
||||||
match status {
|
let error_init = self
|
||||||
Status::Error | Status::Init => self.is_running.store(false, Ordering::SeqCst),
|
.gui_state
|
||||||
_ => {
|
.lock()
|
||||||
if self.docker_sender.send(DockerMessage::Quit).await.is_err() {
|
.status_contains(&[Status::Error, Status::Init]);
|
||||||
self.is_running.store(false, Ordering::SeqCst)
|
if error_init {
|
||||||
}
|
self.is_running.store(false, Ordering::SeqCst);
|
||||||
}
|
} else 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 status = self.gui_state.lock().get_status();
|
let contains_error = self.gui_state.lock().status_contains(&[Status::Error]);
|
||||||
|
let contains_help = self.gui_state.lock().status_contains(&[Status::Help]);
|
||||||
|
|
||||||
match status {
|
if contains_error {
|
||||||
Status::Error => match key_code {
|
match key_code {
|
||||||
KeyCode::Char('q' | 'Q') => self.quit(status).await,
|
KeyCode::Char('q' | 'Q') => self.quit().await,
|
||||||
KeyCode::Char('c' | 'C') => {
|
KeyCode::Char('c' | 'C') => {
|
||||||
self.app_data.lock().remove_error();
|
self.app_data.lock().remove_error();
|
||||||
self.gui_state.lock().set_status(Status::Normal);
|
self.gui_state.lock().status_del(Status::Error);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
}
|
||||||
Status::Help => match key_code {
|
} else if contains_help {
|
||||||
KeyCode::Char('q' | 'Q') => self.quit(status).await,
|
match key_code {
|
||||||
KeyCode::Char('h' | 'H') => self.gui_state.lock().set_status(Status::Help),
|
KeyCode::Char('q' | 'Q') => self.quit().await,
|
||||||
|
KeyCode::Char('h' | 'H') => self.gui_state.lock().status_del(Status::Help),
|
||||||
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(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().status_push(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 => {
|
}
|
||||||
// Skip control panel if no containers, could be refactored
|
KeyCode::BackTab => {
|
||||||
let has_containers = self.app_data.lock().get_container_len() == 0;
|
// Skip control panel if no containers, could be refactored
|
||||||
let is_containers =
|
let has_containers = self.app_data.lock().get_container_len() == 0;
|
||||||
self.gui_state.lock().selected_panel == SelectablePanel::Logs;
|
let is_containers =
|
||||||
let count = if has_containers && is_containers {
|
self.gui_state.lock().selected_panel == SelectablePanel::Logs;
|
||||||
2
|
let count = if has_containers && is_containers {
|
||||||
} else {
|
2
|
||||||
1
|
} else {
|
||||||
};
|
1
|
||||||
for _ in 0..count {
|
};
|
||||||
self.gui_state.lock().previous_panel();
|
for _ in 0..count {
|
||||||
}
|
self.gui_state.lock().previous_panel();
|
||||||
}
|
}
|
||||||
KeyCode::Home => {
|
}
|
||||||
let mut locked_data = self.app_data.lock();
|
KeyCode::Home => {
|
||||||
match self.gui_state.lock().selected_panel {
|
let mut locked_data = self.app_data.lock();
|
||||||
SelectablePanel::Containers => locked_data.containers.start(),
|
match self.gui_state.lock().selected_panel {
|
||||||
SelectablePanel::Logs => locked_data.log_start(),
|
SelectablePanel::Containers => locked_data.containers.start(),
|
||||||
SelectablePanel::Commands => locked_data.docker_command_start(),
|
SelectablePanel::Logs => locked_data.log_start(),
|
||||||
}
|
SelectablePanel::Commands => locked_data.docker_command_start(),
|
||||||
}
|
}
|
||||||
KeyCode::End => {
|
}
|
||||||
let mut locked_data = self.app_data.lock();
|
KeyCode::End => {
|
||||||
match self.gui_state.lock().selected_panel {
|
let mut locked_data = self.app_data.lock();
|
||||||
SelectablePanel::Containers => locked_data.containers.end(),
|
match self.gui_state.lock().selected_panel {
|
||||||
SelectablePanel::Logs => locked_data.log_end(),
|
SelectablePanel::Containers => locked_data.containers.end(),
|
||||||
SelectablePanel::Commands => locked_data.docker_command_end(),
|
SelectablePanel::Logs => locked_data.log_end(),
|
||||||
}
|
SelectablePanel::Commands => locked_data.docker_command_end(),
|
||||||
}
|
}
|
||||||
KeyCode::Up | KeyCode::Char('k' | 'K') => self.previous(),
|
}
|
||||||
KeyCode::PageUp => {
|
KeyCode::Up | KeyCode::Char('k' | 'K') => self.previous(),
|
||||||
for _ in 0..=6 {
|
KeyCode::PageUp => {
|
||||||
self.previous();
|
for _ in 0..=6 {
|
||||||
}
|
self.previous();
|
||||||
}
|
}
|
||||||
KeyCode::Down | KeyCode::Char('j' | 'J') => self.next(),
|
}
|
||||||
KeyCode::PageDown => {
|
KeyCode::Down | KeyCode::Char('j' | 'J') => self.next(),
|
||||||
for _ in 0..=6 {
|
KeyCode::PageDown => {
|
||||||
self.next();
|
for _ in 0..=6 {
|
||||||
}
|
self.next();
|
||||||
}
|
}
|
||||||
KeyCode::Enter => {
|
}
|
||||||
// This isn't great, just means you can't send docker commands before full initialization of the program
|
KeyCode::Enter => {
|
||||||
let panel = self.gui_state.lock().selected_panel;
|
// This isn't great, just means you can't send docker commands before full initialization of the program
|
||||||
if panel == SelectablePanel::Commands {
|
let panel = self.gui_state.lock().selected_panel;
|
||||||
let option_command = self.app_data.lock().get_docker_command();
|
if panel == SelectablePanel::Commands {
|
||||||
|
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(()),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -61,12 +61,12 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
app_data.lock().set_error(AppError::DockerConnect);
|
app_data.lock().set_error(AppError::DockerConnect);
|
||||||
docker_gui_state.lock().set_status(Status::DockerConnect)
|
docker_gui_state.lock().status_push(Status::DockerConnect)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
app_data.lock().set_error(AppError::DockerConnect);
|
app_data.lock().set_error(AppError::DockerConnect);
|
||||||
docker_gui_state.lock().set_status(Status::DockerConnect)
|
docker_gui_state.lock().status_push(Status::DockerConnect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let input_app_data = Arc::clone(&app_data);
|
let input_app_data = Arc::clone(&app_data);
|
||||||
|
|||||||
+35
-47
@@ -216,43 +216,36 @@ 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();
|
let contains_init = gui_state.lock().status_contains(&[Status::Init]);
|
||||||
match status {
|
if contains_init {
|
||||||
Status::Init => {
|
let paragraph = Paragraph::new(format!("parsing logs {}", loading_icon))
|
||||||
let paragraph = Paragraph::new(format!("parsing logs {}", loading_icon))
|
.style(Style::default())
|
||||||
.style(Style::default())
|
.block(block)
|
||||||
.block(block)
|
.alignment(Alignment::Center);
|
||||||
.alignment(Alignment::Center);
|
f.render_widget(paragraph, area);
|
||||||
f.render_widget(paragraph, area);
|
} else if let Some(index) = index {
|
||||||
}
|
let items = app_data.lock().containers.items[index]
|
||||||
|
.logs
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|i| i.1.clone())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
_ => {
|
let items = List::new(items)
|
||||||
if let Some(index) = index {
|
.block(block)
|
||||||
let items = app_data.lock().containers.items[index]
|
.highlight_symbol(ARROW)
|
||||||
.logs
|
.highlight_style(Style::default().add_modifier(Modifier::BOLD));
|
||||||
.items
|
f.render_stateful_widget(
|
||||||
.iter()
|
items,
|
||||||
.enumerate()
|
area,
|
||||||
.map(|i| i.1.clone())
|
&mut app_data.lock().containers.items[index].logs.state,
|
||||||
.collect::<Vec<_>>();
|
);
|
||||||
|
} else {
|
||||||
let items = List::new(items)
|
let paragraph = Paragraph::new("no logs found")
|
||||||
.block(block)
|
.block(block)
|
||||||
.highlight_symbol(ARROW)
|
.alignment(Alignment::Center);
|
||||||
.highlight_style(Style::default().add_modifier(Modifier::BOLD));
|
f.render_widget(paragraph, area);
|
||||||
f.render_stateful_widget(
|
|
||||||
items,
|
|
||||||
area,
|
|
||||||
&mut app_data.lock().containers.items[index].logs.state,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let paragraph = Paragraph::new("no logs found")
|
|
||||||
.block(block)
|
|
||||||
.alignment(Alignment::Center);
|
|
||||||
f.render_widget(paragraph, area);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +349,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().get_status() == Status::Help;
|
let help_visible = gui_state.lock().status_contains(&[Status::Help]);
|
||||||
|
|
||||||
f.render_widget(block(Color::Black), area);
|
f.render_widget(block(Color::Black), area);
|
||||||
|
|
||||||
@@ -436,13 +429,8 @@ pub fn heading_bar<B: Backend>(
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let suffix = if info_visible { "exit" } else { "show" };
|
let suffix = if help_visible { "exit" } else { "show" };
|
||||||
let info_text = format!(
|
let info_text = format!("( h ) {} help {}", suffix, MARGIN,);
|
||||||
"( 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;
|
||||||
@@ -484,10 +472,10 @@ pub fn heading_bar<B: Backend>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show/hide help
|
// show/hide help
|
||||||
let color = if info_visible {
|
let color = if help_visible {
|
||||||
Color::White
|
|
||||||
} else {
|
|
||||||
Color::Black
|
Color::Black
|
||||||
|
} else {
|
||||||
|
Color::White
|
||||||
};
|
};
|
||||||
let help_paragraph = Paragraph::new(info_text)
|
let help_paragraph = Paragraph::new(info_text)
|
||||||
.block(block(color))
|
.block(block(color))
|
||||||
|
|||||||
+10
-7
@@ -181,7 +181,6 @@ pub enum Status {
|
|||||||
Help,
|
Help,
|
||||||
DockerConnect,
|
DockerConnect,
|
||||||
Error,
|
Error,
|
||||||
Normal,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Global gui_state, stored in an Arc<Mutex>
|
/// Global gui_state, stored in an Arc<Mutex>
|
||||||
@@ -191,7 +190,7 @@ 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,
|
status: HashSet<Status>,
|
||||||
pub selected_panel: SelectablePanel,
|
pub selected_panel: SelectablePanel,
|
||||||
pub info_box_text: Option<String>,
|
pub info_box_text: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -205,7 +204,7 @@ impl GuiState {
|
|||||||
selected_panel: SelectablePanel::Containers,
|
selected_panel: SelectablePanel::Containers,
|
||||||
is_loading: HashSet::new(),
|
is_loading: HashSet::new(),
|
||||||
info_box_text: None,
|
info_box_text: None,
|
||||||
status: Status::Init,
|
status: HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,12 +252,16 @@ impl GuiState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_status(&mut self, status: Status) {
|
pub fn status_push(&mut self, status: Status) {
|
||||||
self.status = status
|
self.status.insert(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_status(&self) -> Status {
|
pub fn status_del(&mut self, status: Status) {
|
||||||
self.status
|
self.status.remove(&status);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status_contains(&self, status: &[Status]) -> bool {
|
||||||
|
status.iter().any(|i| self.status.contains(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change to next selectable panel
|
/// Change to next selectable panel
|
||||||
|
|||||||
+3
-3
@@ -85,9 +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 status = gui_state.lock().get_status();
|
let status_dockerconnect = gui_state.lock().status_contains(&[Status::DockerConnect]);
|
||||||
|
|
||||||
if status == Status::DockerConnect {
|
if status_dockerconnect {
|
||||||
let mut seconds = 5;
|
let mut seconds = 5;
|
||||||
loop {
|
loop {
|
||||||
if seconds < 1 {
|
if seconds < 1 {
|
||||||
@@ -159,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().get_status() == Status::Help;
|
let show_help = gui_state.lock().status_contains(&[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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user