feat: docker_recv for all docker commands
This commit is contained in:
+14
-6
@@ -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
@@ -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
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user