summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
authorsigoden <sigoden@gmail.com>2023-11-08 20:36:30 +0800
committerGitHub <noreply@github.com>2023-11-08 20:36:30 +0800
commitb40659613dcaf626ed8e47ad787bcc58e5ee48ab (patch)
tree2436ac07190886a6e6bdbba635c59b20c7cdbbd0 /src/render
parenteb30d90391ef73429589a98f34dfe4d3d88d0a38 (diff)
downloadaichat-b40659613dcaf626ed8e47ad787bcc58e5ee48ab.tar.gz
feat: add a spinner to indicate waiting for response (#236)
Diffstat (limited to 'src/render')
-rw-r--r--src/render/stream.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/render/stream.rs b/src/render/stream.rs
index 189862d..2e05c3a 100644
--- a/src/render/stream.rs
+++ b/src/render/stream.rs
@@ -64,14 +64,21 @@ fn markdown_stream_inner(
let columns = terminal::size()?.0;
+ let mut spinner = Spinner::new(" Generating");
+
loop {
if abort.aborted() {
return Ok(());
}
+ spinner.step(writer)?;
if let Ok(evt) = rx.try_recv() {
match evt {
ReplyEvent::Text(text) => {
+ if spinner.is_running() {
+ spinner.stop(writer)?;
+ }
+
let (col, mut row) = cursor::position()?;
// Fix unexpected duplicate lines on kitty, see https://github.com/sigoden/aichat/issues/105
@@ -155,6 +162,59 @@ fn markdown_stream_inner(
Ok(())
}
+struct Spinner {
+ index: usize,
+ message: String,
+ stopped: bool,
+}
+
+impl Spinner {
+ const DATA: [&str; 10] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
+
+ fn new(message: &str) -> Self {
+ Spinner {
+ index: 0,
+ message: message.to_string(),
+ stopped: false,
+ }
+ }
+
+ fn is_running(&self) -> bool {
+ !self.stopped
+ }
+
+ fn step(&mut self, writer: &mut Stdout) -> Result<()> {
+ if self.stopped {
+ return Ok(());
+ }
+ let frame = Self::DATA[self.index % Self::DATA.len()];
+ let dots = ".".repeat((self.index / 8) % 4);
+ let line = format!("{frame}{}{dots}", self.message);
+ queue!(writer, cursor::MoveToColumn(0), style::Print(line),)?;
+ if self.index == 0 {
+ queue!(writer, cursor::Hide)?;
+ }
+ writer.flush()?;
+ self.index += 1;
+ Ok(())
+ }
+
+ fn stop(&mut self, writer: &mut Stdout) -> Result<()> {
+ if self.stopped {
+ return Ok(());
+ }
+ self.stopped = true;
+ queue!(
+ writer,
+ cursor::MoveToColumn(0),
+ terminal::Clear(terminal::ClearType::FromCursorDown),
+ cursor::Show
+ )?;
+ writer.flush()?;
+ Ok(())
+ }
+}
+
fn print_block(writer: &mut Stdout, text: &str, columns: u16) -> Result<u16> {
let mut num = 0;
for line in text.split('\n') {