summaryrefslogtreecommitdiffstats
path: root/zellij-client/src
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2022-12-07 15:03:58 +0100
committerGitHub <noreply@github.com>2022-12-07 15:03:58 +0100
commitf8a078c1a959ca7bb243bd9a86b3ddc392605c9c (patch)
treef3d120d900446ae03c1c27ccd1ff5c0f9b49efc9 /zellij-client/src
parent81287a276f62d4ca98c9fa1b76332db074a13cc5 (diff)
feat(ux): show loading screen (#1997)
* feat(ux): show loading prompt * style(fmt): rustfmt
Diffstat (limited to 'zellij-client/src')
-rw-r--r--zellij-client/src/input_handler.rs14
-rw-r--r--zellij-client/src/lib.rs50
-rw-r--r--zellij-client/src/stdin_ansi_parser.rs3
-rw-r--r--zellij-client/src/stdin_handler.rs19
4 files changed, 83 insertions, 3 deletions
diff --git a/zellij-client/src/input_handler.rs b/zellij-client/src/input_handler.rs
index 801ff0951..bf3bcc006 100644
--- a/zellij-client/src/input_handler.rs
+++ b/zellij-client/src/input_handler.rs
@@ -147,6 +147,20 @@ impl InputHandler {
self.handle_stdin_ansi_instruction(ansi_instruction);
}
},
+ Ok((InputInstruction::StartedParsing, _error_context)) => {
+ log::info!("sending done loading");
+ self.send_client_instructions
+ .send(ClientInstruction::StartedParsingStdinQuery)
+ .unwrap();
+ log::info!("done sent done loading");
+ },
+ Ok((InputInstruction::DoneParsing, _error_context)) => {
+ log::info!("sending done loading");
+ self.send_client_instructions
+ .send(ClientInstruction::DoneParsingStdinQuery)
+ .unwrap();
+ log::info!("done sent done loading");
+ },
Err(err) => panic!("Encountered read error: {:?}", err),
}
}
diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs
index 0fd549ab4..51d6c99d6 100644
--- a/zellij-client/src/lib.rs
+++ b/zellij-client/src/lib.rs
@@ -43,6 +43,8 @@ pub(crate) enum ClientInstruction {
SwitchToMode(InputMode),
Connected,
ActiveClients(Vec<ClientId>),
+ StartedParsingStdinQuery,
+ DoneParsingStdinQuery,
}
impl From<ServerToClientMsg> for ClientInstruction {
@@ -70,6 +72,8 @@ impl From<&ClientInstruction> for ClientContext {
ClientInstruction::SwitchToMode(_) => ClientContext::SwitchToMode,
ClientInstruction::Connected => ClientContext::Connected,
ClientInstruction::ActiveClients(_) => ClientContext::ActiveClients,
+ ClientInstruction::StartedParsingStdinQuery => ClientContext::StartedParsingStdinQuery,
+ ClientInstruction::DoneParsingStdinQuery => ClientContext::DoneParsingStdinQuery,
}
}
}
@@ -121,6 +125,8 @@ pub(crate) enum InputInstruction {
KeyEvent(InputEvent, Vec<u8>),
SwitchToMode(InputMode),
AnsiStdinInstructions(Vec<AnsiStdinInstruction>),
+ StartedParsing,
+ DoneParsing,
}
pub fn start_client(
@@ -337,13 +343,51 @@ pub fn start_client(
};
let exit_msg: String;
+ let mut loading = true;
+ let mut pending_instructions = vec![];
+
+ let mut stdout = os_input.get_stdout_writer();
+ stdout
+ .write_all("\u{1b}[1mLoading Zellij\u{1b}[m".as_bytes())
+ .expect("cannot write to stdout");
+ stdout.flush().expect("could not flush");
loop {
- let (client_instruction, mut err_ctx) = receive_client_instructions
- .recv()
- .expect("failed to receive app instruction on channel");
+ let (client_instruction, mut err_ctx) = if !loading && !pending_instructions.is_empty() {
+ // there are buffered instructions, we need to go through them before processing the
+ // new ones
+ pending_instructions.remove(0)
+ } else {
+ receive_client_instructions
+ .recv()
+ .expect("failed to receive app instruction on channel")
+ };
+
+ if loading {
+ // when the app is still loading, we buffer instructions and show a loading screen
+ match client_instruction {
+ ClientInstruction::StartedParsingStdinQuery => {
+ stdout
+ .write_all("\n\rQuerying terminal emulator for \u{1b}[32;1mdefault colors\u{1b}[m and \u{1b}[32;1mpixel/cell\u{1b}[m ratio...".as_bytes())
+ .expect("cannot write to stdout");
+ stdout.flush().expect("could not flush");
+ },
+ ClientInstruction::DoneParsingStdinQuery => {
+ stdout
+ .write_all("done".as_bytes())
+ .expect("cannot write to stdout");
+ stdout.flush().expect("could not flush");
+ loading = false;
+ },
+ instruction => {
+ pending_instructions.push((instruction, err_ctx));
+ },
+ }
+ continue;
+ }
err_ctx.add_call(ContextType::Client((&client_instruction).into()));
+
match client_instruction {
ClientInstruction::Exit(reason) => {
os_input.send_to_server(ClientToServerMsg::ClientExited);
diff --git a/zellij-client/src/stdin_ansi_parser.rs b/zellij-client/src/stdin_ansi_parser.rs
index 09247bf9b..23e869b2b 100644
--- a/zellij-client/src/stdin_ansi_parser.rs
+++ b/zellij-client/src/stdin_ansi_parser.rs
@@ -73,6 +73,9 @@ impl StdinAnsiParser {
}
false
}
+ pub fn startup_query_duration(&self) -> u64 {
+ STARTUP_PARSE_DEADLINE_MS
+ }
pub fn parse(&mut self, mut raw_bytes: Vec<u8>) -> Vec<AnsiStdinInstruction> {
for byte in raw_bytes.drain(..) {
self.parse_byte(byte);
diff --git a/zellij-client/src/stdin_handler.rs b/zellij-client/src/stdin_handler.rs
index 8d6e51b0a..75634a05b 100644
--- a/zellij-client/src/stdin_handler.rs
+++ b/zellij-client/src/stdin_handler.rs
@@ -5,6 +5,20 @@ use std::sync::{Arc, Mutex};
use zellij_utils::channels::SenderWithContext;
use zellij_utils::termwiz::input::{InputEvent, InputParser, MouseButtons};
+fn send_done_parsing_after_query_timeout(
+ send_input_instructions: SenderWithContext<InputInstruction>,
+ query_duration: u64,
+) {
+ std::thread::spawn({
+ move || {
+ std::thread::sleep(std::time::Duration::from_millis(query_duration));
+ send_input_instructions
+ .send(InputInstruction::DoneParsing)
+ .unwrap();
+ }
+ });
+}
+
pub(crate) fn stdin_loop(
mut os_input: Box<dyn ClientOsApi>,
send_input_instructions: SenderWithContext<InputInstruction>,
@@ -15,6 +29,9 @@ pub(crate) fn stdin_loop(
let mut current_buffer = vec![];
// on startup we send a query to the terminal emulator for stuff like the pixel size and colors
// we get a response through STDIN, so it makes sense to do this here
+ send_input_instructions
+ .send(InputInstruction::StartedParsing)
+ .unwrap();
let terminal_emulator_query_string = stdin_ansi_parser
.lock()
.unwrap()
@@ -23,6 +40,8 @@ pub(crate) fn stdin_loop(
.get_stdout_writer()
.write(terminal_emulator_query_string.as_bytes())
.unwrap();
+ let query_duration = stdin_ansi_parser.lock().unwrap().startup_query_duration();
+ send_done_parsing_after_query_timeout(send_input_instructions.clone(), query_duration);
loop {
let buf = os_input.read_from_stdin();
{