Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: investigate crossterm windows 10 #17

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions applications/minotari_console_wallet/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use crate::utils::events::{Event, EventStream};

pub const MAX_WIDTH: u16 = 167;

pub fn run(app: App<CrosstermBackend<Stdout>>) -> Result<(), ExitError> {
pub fn run(app: App<CrosstermBackend<Stdout>>) -> Result<bool, ExitError> {
let mut app = app;
Handle::current()
.block_on(async {
Expand All @@ -75,7 +75,7 @@ pub fn run(app: App<CrosstermBackend<Stdout>>) -> Result<(), ExitError> {
crossterm_loop(app)
}
/// This is the main loop of the application UI using Crossterm based events
fn crossterm_loop(mut app: App<CrosstermBackend<Stdout>>) -> Result<(), ExitError> {
fn crossterm_loop(mut app: App<CrosstermBackend<Stdout>>) -> Result<bool, ExitError> {
let events = CrosstermEvents::new();
enable_raw_mode().map_err(|e| {
error!(target: LOG_TARGET, "Error enabling Raw Mode {}", e);
Expand Down Expand Up @@ -103,16 +103,19 @@ fn crossterm_loop(mut app: App<CrosstermBackend<Stdout>>) -> Result<(), ExitErro
ExitCode::InterfaceError
})?;

let mut all_ok = true;
loop {
terminal.draw(|f| app.draw(f)).map_err(|e| {
error!(target: LOG_TARGET, "Error drawing interface. {}", e);
ExitCode::InterfaceError
})?;
#[allow(clippy::blocks_in_conditions)]
match events.next().map_err(|e| {
let key_event = events.next().map_err(|e| {
error!(target: LOG_TARGET, "Error reading input event: {}", e);
ExitCode::InterfaceError
})? {
})?;
trace!(target: LOG_TARGET, "Key event: {:?}", key_event);
#[allow(clippy::blocks_in_conditions)]
match key_event {
Event::Input(event) => match (event.code, event.modifiers) {
(KeyCode::Char(c), KeyModifiers::CONTROL) => app.on_control_key(c),
(KeyCode::Char(c), _) => app.on_key(c),
Expand All @@ -131,12 +134,21 @@ fn crossterm_loop(mut app: App<CrosstermBackend<Stdout>>) -> Result<(), ExitErro
Event::Tick => {
app.on_tick();
},
Event::RestartCrosstermLoop => {
if let Err(e) = terminal.clear() {
error!(target: LOG_TARGET, "Error clearing interface. {}", e);
} else if let Err(e) = disable_raw_mode() {
error!(target: LOG_TARGET, "Error disabling Raw Mode {}", e);
}
all_ok = false;
return Ok(all_ok);
},
}
if app.should_quit {
trace!(target: LOG_TARGET, "CrosstermBackend should quit");
break;
}
}

terminal.clear().map_err(|e| {
error!(target: LOG_TARGET, "Error clearing interface. {}", e);
ExitCode::InterfaceError
Expand All @@ -155,5 +167,5 @@ fn crossterm_loop(mut app: App<CrosstermBackend<Stdout>>) -> Result<(), ExitErro
ExitCode::InterfaceError
})?;

Ok(())
Ok(all_ok)
}
45 changes: 34 additions & 11 deletions applications/minotari_console_wallet/src/utils/crossterm_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,29 +64,52 @@ impl CrosstermEvents {
let mut last_tick = Instant::now();
loop {
// poll for tick rate duration, if no events, sent tick event.
match event::poll(
config
.tick_rate
.checked_sub(last_tick.elapsed())
.unwrap_or_else(|| Duration::from_millis(1)),
) {
let effective_tick_rate = config
.tick_rate
.checked_sub(last_tick.elapsed())
.unwrap_or_else(|| Duration::from_millis(1));
match event::poll(effective_tick_rate.clone()) {
Ok(true) => {
if let Ok(CEvent::Key(key)) = event::read() {
if tx.send(Event::Input(key)).is_err() {
info!(target: LOG_TARGET, "Tick event channel shutting down");
if let Err(e) = tx.send(Event::Input(key)) {
info!(
target: LOG_TARGET,
"Tick event channel shutting down, key: {:?}, tick rate: {:?}, err: {}",
key, effective_tick_rate, e
);
// A send operation can only fail if the receiving end of a channel is disconnected.
break;
}
}
},
Ok(false) => {},
Err(e) => {
error!(target: LOG_TARGET, "Internal error in crossterm events: {}", e);
error!(
target: LOG_TARGET,
"Internal error in crossterm events, tick rate: {:?}, err: {}",
effective_tick_rate, e
);
// // Wait a bit before trying again
thread::sleep(Duration::from_millis(1000));
if e.to_string().contains("No process is on the other end of the pipe") {
if let Err(e) = tx.send(Event::RestartCrosstermLoop) {
info!(
target: LOG_TARGET,
"Tick event channel error 'Event::RestartCrosstermLoop', tick rate: {:?}, err: {})",
effective_tick_rate, e
);
}
break;
}
},
}
if last_tick.elapsed() >= config.tick_rate {
if tx.send(Event::Tick).is_err() {
info!(target: LOG_TARGET, "Tick event channel shutting down");
if let Err(e) = tx.send(Event::Tick) {
info!(
target: LOG_TARGET,
"Tick event channel shutting down 'Event::Tick', tick rate: {:?}, err: {})",
effective_tick_rate, e
);
// A send operation can only fail if the receiving end of a channel is disconnected.
break;
}
Expand Down
2 changes: 2 additions & 0 deletions applications/minotari_console_wallet/src/utils/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@

use std::sync::mpsc;

#[derive(Debug)]
pub enum Event<I> {
Input(I),
Tick,
RestartCrosstermLoop,
}

pub trait EventStream<I> {
Expand Down
42 changes: 26 additions & 16 deletions applications/minotari_console_wallet/src/wallet_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@

#![allow(dead_code, unused)]

use std::{fs, io::Stdout, path::PathBuf};
use std::{
fs,
io::{stdout, Stdout},
path::PathBuf,
};

use clap::Parser;
use log::*;
Expand Down Expand Up @@ -374,24 +378,30 @@ pub fn tui_mode(
return Err(ExitError::new(ExitCode::WalletError, "Could not select a base node"));
}

let app = handle.block_on(App::<CrosstermBackend<Stdout>>::new(
"Minotari Wallet".into(),
wallet,
config.clone(),
base_node_selected,
base_node_config.clone(),
notifier,
))?;
loop {
info!(target: LOG_TARGET, "Starting app");

info!(target: LOG_TARGET, "Starting app");
let app = handle.block_on(App::<CrosstermBackend<Stdout>>::new(
"Minotari Wallet".into(),
wallet.clone(),
config.clone(),
base_node_selected.clone(),
base_node_config.clone(),
notifier.clone(),
))?;

// Do not remove this println!
const CUCUMBER_TEST_MARKER: &str = "Minotari Console Wallet running... (TUI mode started)";
println!("{}", CUCUMBER_TEST_MARKER);
// Do not remove this println!
const CUCUMBER_TEST_MARKER: &str = "Minotari Console Wallet running... (TUI mode started)";
println!("{}", CUCUMBER_TEST_MARKER);

{
let _enter = handle.enter();
ui::run(app)?;
{
let _enter = handle.enter();
if ui::run(app)? {
break;
} else {
trace!(target: LOG_TARGET, "Re-starting app required");
}
}
}

info!(
Expand Down
Loading