feat: docker_recv for all docker commands

This commit is contained in:
Jack Wills
2022-04-29 16:10:14 +00:00
parent 9c85470bdc
commit 679203cf2d
7 changed files with 270 additions and 161 deletions
+14 -6
View File
@@ -223,6 +223,7 @@ pub fn draw_logs<B: Backend>(
f: &mut Frame<'_, B>,
gui_state: &Arc<Mutex<GuiState>>,
index: Option<usize>,
loading_icon: String,
selected_panel: &SelectablePanel,
) {
let panel = SelectablePanel::Logs;
@@ -233,8 +234,8 @@ pub fn draw_logs<B: Backend>(
let init = app_data.lock().init;
if !init {
let icon = gui_state.lock().get_loading();
let parsing_logs = format!("parsing logs {}", icon);
// let icon = gui_state.lock().get_loading();
let parsing_logs = format!("parsing logs {}", loading_icon);
let paragraph = Paragraph::new(parsing_logs)
.style(Style::default())
.block(block)
@@ -367,16 +368,22 @@ pub fn draw_heading_bar<B: Backend>(
columns: &Columns,
f: &mut Frame<'_, B>,
has_containers: bool,
loading_icon: String,
info_visible: bool,
) {
let block = || Block::default().style(Style::default().bg(Color::Magenta).fg(Color::Black));
f.render_widget(block(), area);
let mut column_headings = format!(" {:>width$}", columns.state.0, width = columns.state.1);
let mut column_headings = format!(
" {}{:>width$}",
loading_icon,
columns.state.0,
width = columns.state.1
);
column_headings.push_str(
format!(
"{} {:>width$}",
"{} {:>width$}",
MARGIN,
columns.status.0,
width = columns.status.1
@@ -471,7 +478,9 @@ pub fn draw_help_box<B: Backend>(f: &mut Frame<'_, B>) {
help_text.push_str("\n ( ↑ ↓ ← → ) to change selected line");
help_text.push_str("\n ( enter ) to send docker container commands");
help_text.push_str("\n ( h ) to toggle this help information");
help_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied");
help_text.push_str(
"\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied",
);
help_text.push_str("\n ( q ) to quit at any time");
help_text.push_str("\n mouse scrolling & clicking also available");
help_text.push_str("\n\n currenty an early work in progress, all and any input appreciated");
@@ -602,7 +611,6 @@ pub fn draw_info<B: Backend>(f: &mut Frame<'_, B>, text: String) {
.title_alignment(Alignment::Center)
.borders(Borders::NONE);
let mut max_line_width = 0;
text.lines().into_iter().for_each(|line| {
let width = line.chars().count();
+20 -13
View File
@@ -8,6 +8,7 @@ pub enum SelectablePanel {
Logs,
}
#[allow(unused)]
#[derive(Debug, Clone, Copy)]
pub enum BoxLocation {
TopLeft,
@@ -165,10 +166,12 @@ pub struct GuiState {
// Is an issue if two panels are in the same space, sush as a smaller panel embedded, yet infront of, a larger panel
// If a BMapTree think it would mean have to implement ordering for SelectablePanel
area_map: HashMap<SelectablePanel, Rect>,
loading: Loading,
loading_icon: Loading,
// Should be a vec, each time loading add a new to the vec, and reset remove from vec
// for for if is_loading just check if vec is empty or not
is_loading: bool,
pub selected_panel: SelectablePanel,
pub show_help: bool,
// show_info_panel: bool,
pub info_box_text: Option<String>,
}
@@ -177,10 +180,10 @@ impl GuiState {
pub fn default() -> Self {
Self {
area_map: HashMap::new(),
loading: Loading::One,
loading_icon: Loading::One,
selected_panel: SelectablePanel::Containers,
show_help: false,
// show_info_panel: false,
is_loading: false,
info_box_text: None,
}
}
@@ -218,29 +221,33 @@ impl GuiState {
self.selected_panel = self.selected_panel.prev();
}
/// Advance loading animation
pub fn next_loading(&mut self) {
self.loading = self.loading.next()
self.loading_icon = self.loading_icon.next();
self.is_loading = true;
}
/// if is_loading, return loading animation frame, else single space
pub fn get_loading(&mut self) -> String {
self.loading.to_string()
if self.is_loading {
self.loading_icon.to_string()
} else {
String::from(" ")
}
}
/// set is_loading to false, but keep animation frame at same state
pub fn reset_loading(&mut self) {
self.loading = Loading::One;
self.is_loading = false;
}
/// Set info box content
pub fn set_info_box(&mut self, text: String) {
self.info_box_text = Some(text);
// self.show_info_panel = true;
// Should spawn and after 10 seconds close?
// Need to copy whatever we're doing with parsing logs icon
}
/// Remove info box content
pub fn reset_info_box(&mut self) {
// self.loading = Loading::One;
self.info_box_text = None;
// self.show_info_panel = false;
}
}
+38 -6
View File
@@ -5,12 +5,15 @@ use crossterm::{
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use parking_lot::Mutex;
use std::sync::atomic::AtomicBool;
use std::{
io,
sync::{atomic::Ordering, Arc},
};
use tokio::sync::broadcast::Sender;
use std::{
sync::atomic::AtomicBool,
time::{Duration, Instant},
};
use tokio::sync::mpsc::Sender;
use tracing::error;
use tui::{
backend::{Backend, CrosstermBackend},
@@ -24,7 +27,10 @@ mod gui_state;
pub use self::color_match::*;
pub use self::gui_state::{GuiState, SelectablePanel};
use crate::{app_data::AppData, app_error::AppError, input_handler::InputMessages};
use crate::{
app_data::AppData, app_error::AppError, docker_data::DockerMessage,
input_handler::InputMessages,
};
use draw_blocks::*;
/// Take control of the terminal in order to draw gui
@@ -33,6 +39,8 @@ pub async fn create_ui(
sender: Sender<InputMessages>,
is_running: Arc<AtomicBool>,
gui_state: Arc<Mutex<GuiState>>,
docker_sx: Sender<DockerMessage>,
update_duration: Duration,
) -> Result<()> {
enable_raw_mode()?;
let mut stdout = io::stdout();
@@ -40,7 +48,16 @@ pub async fn create_ui(
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let res = run_app(&mut terminal, app_data, sender, is_running, gui_state).await;
let res = run_app(
&mut terminal,
app_data,
sender,
is_running,
gui_state,
docker_sx,
update_duration,
)
.await;
disable_raw_mode().unwrap();
execute!(
@@ -63,6 +80,8 @@ async fn run_app<B: Backend>(
sender: Sender<InputMessages>,
is_running: Arc<AtomicBool>,
gui_state: Arc<Mutex<GuiState>>,
docker_sx: Sender<DockerMessage>,
update_duration: Duration,
) -> Result<(), AppError> {
let input_poll_rate = std::time::Duration::from_millis(75);
@@ -84,6 +103,7 @@ async fn run_app<B: Backend>(
}
}
} else {
let mut now = Instant::now();
loop {
terminal.draw(|f| ui(f, &app_data, &gui_state)).unwrap();
if crossterm::event::poll(input_poll_rate).unwrap() {
@@ -91,15 +111,24 @@ async fn run_app<B: Backend>(
if let Event::Key(key) = event {
sender
.send(InputMessages::ButtonPress(key.code))
.unwrap_or(0);
.await
.unwrap_or(());
} else if let Event::Mouse(m) = event {
sender.send(InputMessages::MouseEvent(m)).unwrap_or(0);
sender
.send(InputMessages::MouseEvent(m))
.await
.unwrap_or(());
} else if let Event::Resize(_, _) = event {
gui_state.lock().clear_area_map();
terminal.autoresize().unwrap_or(());
}
}
if now.elapsed() >= update_duration {
docker_sx.send(DockerMessage::Update).await.unwrap();
now = Instant::now();
}
if !is_running.load(Ordering::SeqCst) {
break;
}
@@ -128,6 +157,7 @@ fn ui<B: Backend>(
let selected_panel = gui_state.lock().selected_panel;
let show_help = gui_state.lock().show_help;
let info_text = gui_state.lock().info_box_text.clone();
let loading_icon = gui_state.lock().get_loading();
let whole_layout = Layout::default()
.direction(Direction::Vertical)
@@ -189,6 +219,7 @@ fn ui<B: Backend>(
f,
gui_state,
log_index,
loading_icon.to_owned(),
&selected_panel,
);
@@ -197,6 +228,7 @@ fn ui<B: Backend>(
&column_widths,
f,
has_containers,
loading_icon,
show_help,
);