diff --git a/src/action.rs b/src/action.rs index 04671ad..71c9d2b 100644 --- a/src/action.rs +++ b/src/action.rs @@ -8,7 +8,10 @@ use serde::{ #[derive(Debug, Clone, PartialEq, Eq)] pub enum Action { Tick, + /// Apply any pending update to the screen Render, + /// Notify there is a pending update + ShouldRender, Resize(u16, u16), Suspend, Resume, diff --git a/src/app.rs b/src/app.rs index 6fb1276..a776c35 100644 --- a/src/app.rs +++ b/src/app.rs @@ -205,7 +205,22 @@ impl App { })); } + let mut changes_since_last_render = true; loop { + if changes_since_last_render { + tui.draw(|f| { + for component in self.components.iter_mut() { + let r = component.draw(f, f.size(), &self.buffers); + if let Err(e) = r { + action_tx + .send(Action::Error(format!("Failed to draw: {:?}", e))) + .unwrap(); + } + } + })?; + changes_since_last_render = false; + } + tokio::select! { e = tui.next() => { if let Some(e) = e { @@ -221,9 +236,9 @@ impl App { let (client, sync_response) = sync_response.expect("sync_responses_rx unexpectedly closed"); self.handle_sync_response(&action_tx, client, sync_response).await.context("Error while handling sync response")?; } - poll_updates = futures::future::join_all( - self.buffers.iter_mut().map(|buf| buf.poll_updates()) - ) => {} + poll_updates = self.buffers.poll_updates() => { + changes_since_last_render = true; + } sync_result = sync_results.next() => { if !self.should_quit.load(Ordering::Acquire) { panic!("Sync ended unexpected: {:?}", sync_result); @@ -243,18 +258,21 @@ impl App { Action::Suspend => self.should_suspend = true, Action::Resume => self.should_suspend = false, Action::NextBuffer => { + changes_since_last_render = true; // self.buffer implements wrap-around itself self .buffers .set_active_index(self.buffers.active_index() as isize + 1) }, Action::PreviousBuffer => { + changes_since_last_render = true; // self.buffer implements wrap-around itself self .buffers .set_active_index(self.buffers.active_index() as isize - 1) }, Action::Resize(w, h) => { + changes_since_last_render = true; tui.resize(Rect::new(0, 0, w, h))?; tui.draw(|f| { for component in self.components.iter_mut() { @@ -267,19 +285,14 @@ impl App { } })?; }, + Action::ShouldRender => { + changes_since_last_render = true; + }, Action::Render => { - tui.draw(|f| { - for component in self.components.iter_mut() { - let r = component.draw(f, f.size(), &self.buffers); - if let Err(e) = r { - action_tx - .send(Action::Error(format!("Failed to draw: {:?}", e))) - .unwrap(); - } - } - })?; + // Merely used as a way to signify it's time to render any pending update }, Action::RunCommand(ref command_line) => { + changes_since_last_render = true; log::info!("Got command: {command_line}"); crate::commands::run_command(&command_line, &self, &action_tx)?; }, @@ -291,6 +304,7 @@ impl App { }; } } + if self.should_suspend { tui.suspend()?; action_tx.send(Action::Resume)?; diff --git a/src/buffers/mod.rs b/src/buffers/mod.rs index 6974a0c..af5d9e2 100644 --- a/src/buffers/mod.rs +++ b/src/buffers/mod.rs @@ -14,6 +14,8 @@ * along with this program. If not, see . */ +use futures::stream::FuturesUnordered; +use futures::StreamExt; use matrix_sdk::async_trait; use nonempty::NonEmpty; @@ -23,10 +25,13 @@ mod room; pub use room::RoomBuffer; #[async_trait] -pub trait Buffer: Send { +pub trait Buffer: Send + Sync { /// A short human-readable name for the room, eg. to show in compact buflist fn short_name(&self) -> String; - async fn poll_updates(&mut self) {} + /// Returns if there are any updates to apply. + async fn poll_updates(&mut self) { + std::future::pending().await + } fn content(&self) -> Vec; // TODO: make this lazy, only the last few are used /// Called when the user is being showned the oldest items this buffer returned. /// @@ -47,6 +52,16 @@ impl Buffers { } } + pub async fn poll_updates(&mut self) { + self + .iter_mut() + .map(|buf| buf.poll_updates()) + .collect::>() + .next() + .await + .expect("poll_updates reached the end of the never-ending stream"); + } + pub fn iter(&self) -> impl Iterator { self.buffers.iter().map(|buffer_box| &**buffer_box) } diff --git a/src/components/home.rs b/src/components/home.rs index b3fc4de..9d50f98 100644 --- a/src/components/home.rs +++ b/src/components/home.rs @@ -96,7 +96,7 @@ impl Component for Home { // Shift-Enter events (at least on Foot via SSH). // However, tui-textarea implements Alt-Tab to insert a newline, so it's okay. self.textarea.insert_newline(); - Ok(Some(Action::Render)) + Ok(Some(Action::ShouldRender)) }, _ => { assert!( @@ -104,7 +104,7 @@ impl Component for Home { "backlog.handle_key_events returned Some" ); self.textarea.input(key); - Ok(Some(Action::Render)) + Ok(Some(Action::ShouldRender)) }, } }