Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

Conversation

@Edgpaez
Copy link
Contributor

@Edgpaez Edgpaez commented Nov 23, 2025

Thanks again for the time and effort you've put into lazyjj !

This implements a simple loader that looks like this:
output

and uses it when doing git push or fetch

I used throbber-widgets-tui for the loader animation.

I had to move input handling in main to use poll instead of blocking on read. Without this the loader would not move. However, I am only polling if there is a popup (presumably the LoaderPopup), otherwise we just block waiting for an input event as we are doing right now.

Happy to change based on feedback :)

@dotdash
Copy link
Collaborator

dotdash commented Dec 7, 2025

I didn't look for why it happens, but if the lazyjj window loses focus after the popup appears and then immediately regains focus, the popup stays frozen and doesn't disappear until your press a key, scroll or toggle focus again.

@dotdash
Copy link
Collaborator

dotdash commented Dec 7, 2025

Otherwise, very nice!

@Edgpaez
Copy link
Contributor Author

Edgpaez commented Dec 9, 2025

Thank you for testing and reviewing my PR @dotdash !
I could not replicate the issue you are seeing. I have tried this in my usual setup (Zellij + Wezterm) and in Ghostty and the pop up always goes away.

Are you sure this is not related to lazyjj not receiving the focus event? I have had that problem in the past using Zellij maybe it also happens in your setup?

@dotdash
Copy link
Collaborator

dotdash commented Dec 24, 2025

The focus event at least definitely makes it into lazyjj.

lazyjj_fetch.mp4

src/main.rs Outdated
Comment on lines 214 to 223
let event = loop {
match event::read()? {
event::Event::FocusLost => continue,
Event::Mouse(MouseEvent {
kind: MouseEventKind::Moved,
..
}) => continue,
event => break event,
}
};
Copy link
Collaborator

@dotdash dotdash Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issues lies here. The events we get can look like this:

read(0, "\33[O", 1024)                  = 3
read(0, "\33[I", 1024)                  = 3
read(0, "\33[<35;120;27M", 1024)        = 13

That's: Focus lost, Focus gained, Mouse moved

In the Focus lost case, event::poll reports that there's an event, so we enter the inner loop, where the first match case is taken and we loop here, and then wait for another event from event::read. That's why the animation stops.

When focus is gained, that event is read and breaks us out of the loop, so we see one increment in the animation loop.

But then we get the event for the mouse movement, and again, event::poll reports an available event, and then we hit the second match arm, loop and wait in event::read for another event to come in, and we freeze again.

So the continues need to be fixed to refer to the outer loop.

diff --git a/src/main.rs b/src/main.rs
index 30f20e2..c962aea 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -155,7 +155,7 @@ fn run_app<B: Backend>(
 ) -> Result<()> {
     let mut start_time = Instant::now();
     let mut drawing_popup = false;
-    loop {
+    'main: loop {
         // Draw
         let mut terminal_draw_res = Ok(());
         terminal.draw(|f| {
@@ -213,11 +213,11 @@ fn run_app<B: Backend>(
         if !drawing_popup || event::poll(std::time::Duration::from_millis(100))? {
             let event = loop {
                 match event::read()? {
-                    event::Event::FocusLost => continue,
+                    event::Event::FocusLost => continue 'main,
                     Event::Mouse(MouseEvent {
                         kind: MouseEventKind::Moved,
                         ..
-                    }) => continue,
+                    }) => continue 'main,
                     event => break event,
                 }
             };

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, the issue is even easier to reproduce. Just move the mouse while the popup is shown and it will freeze and not disappear until you generate an event other than FocusLost and mouse movements.

Copy link
Collaborator

@dotdash dotdash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the loop issue and maybe unify the util functions.

note that my suggested fix leaves an issue open: the animation plays fast if you produce event, e.g. by moving the mouse. I'd be fine with accepting that for now though.

@Edgpaez
Copy link
Contributor Author

Edgpaez commented Jan 10, 2026

Thanks again for the review @dotdash. You were correct. When applying your patch I noticed the loop was not necessary, so I moved the code a bit. Hopefully now it is clear that when we're not drawing the loader, we block waiting for an event. When we're drawing the loader, we wait for events for 100ms or just render again.

@dotdash
Copy link
Collaborator

dotdash commented Jan 10, 2026

Thanks for the update. Note that I'll be moving my work over to https://github.com/blazingjj/blazingjj. See #166. I'll test your PRs there and integrate them if they work and then merge them here as we're still close enough code wise.

@dotdash dotdash merged commit f72c980 into Cretezy:main Jan 11, 2026
16 of 20 checks passed
@Edgpaez Edgpaez deleted the loader branch January 13, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants