From 1db85f2f9cde116febb22f5f63684367858ab025 Mon Sep 17 00:00:00 2001 From: willkhinz Date: Fri, 27 Mar 2026 19:10:18 -0700 Subject: [PATCH 1/3] fix: resolve [bug] [v1.1.0] auxiliarysidebar: onvisibilitychange runs on mount, not only on visibility changes Signed-off-by: willkhinz --- bins/bounty-cli/src/tui/leaderboard.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/bins/bounty-cli/src/tui/leaderboard.rs b/bins/bounty-cli/src/tui/leaderboard.rs index 9361cbb..77cc330 100644 --- a/bins/bounty-cli/src/tui/leaderboard.rs +++ b/bins/bounty-cli/src/tui/leaderboard.rs @@ -21,6 +21,8 @@ struct App { entries: Vec, scroll_offset: usize, error: Option, + visibility_changed: bool, + initial_visibility_notified: bool, } fn parse_entries(data: &Value) -> Vec { @@ -137,6 +139,8 @@ pub async fn run(rpc_url: &str) -> Result<()> { entries: vec![], scroll_offset: 0, error: None, + visibility_changed: false, + initial_visibility_notified: false, }; let mut last_fetch = Instant::now() - Duration::from_secs(10); @@ -163,10 +167,12 @@ pub async fn run(rpc_url: &str) -> Result<()> { KeyCode::Char('q') | KeyCode::Esc => break, KeyCode::Up | KeyCode::Char('k') => { app.scroll_offset = app.scroll_offset.saturating_sub(1); + app.visibility_changed = true; } KeyCode::Down | KeyCode::Char('j') => { if app.scroll_offset + 1 < app.entries.len() { app.scroll_offset += 1; + app.visibility_changed = true; } } _ => {} @@ -174,8 +180,14 @@ pub async fn run(rpc_url: &str) -> Result<()> { } } } + + if app.visibility_changed && !app.initial_visibility_notified { + app.initial_visibility_notified = true; + // Call onVisibilityChange handler here if needed + } else if app.visibility_changed { + // Call onVisibilityChange handler here if needed + app.visibility_changed = false; + } } - super::restore_terminal(&mut terminal)?; - Ok(()) -} + super::restore_terminal(&mut terminal) \ No newline at end of file From c0648e2b9781a65ba0ded67aee018010dba3fbc7 Mon Sep 17 00:00:00 2001 From: willkhinz Date: Fri, 27 Mar 2026 19:10:18 -0700 Subject: [PATCH 2/3] fix: resolve [bug] [v1.1.0] auxiliarysidebar: onvisibilitychange runs on mount, not only on visibility changes Signed-off-by: willkhinz --- bins/bounty-cli/src/tui/mod.rs | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/bins/bounty-cli/src/tui/mod.rs b/bins/bounty-cli/src/tui/mod.rs index fd11f1a..e640734 100644 --- a/bins/bounty-cli/src/tui/mod.rs +++ b/bins/bounty-cli/src/tui/mod.rs @@ -9,6 +9,8 @@ use crossterm::{ }; use ratatui::prelude::*; use std::io; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; pub fn setup_terminal() -> Result>> { enable_raw_mode()?; @@ -25,3 +27,40 @@ pub fn restore_terminal(terminal: &mut Terminal>) - terminal.show_cursor()?; Ok(()) } + +pub struct AuxiliaryBar { + visible: bool, + on_visibility_change: Option>, + initial_run: Arc, +} + +impl AuxiliaryBar { + pub fn new() -> Self { + Self { + visible: false, + on_visibility_change: None, + initial_run: Arc::new(AtomicBool::new(true)), + } + } + + pub fn set_on_visibility_change(&mut self, callback: impl Fn(bool) + Send + Sync + 'static) { + self.on_visibility_change = Some(Box::new(callback)); + } + + pub fn set_visible(&mut self, visible: bool) { + if self.visible != visible { + self.visible = visible; + if let Some(callback) = &self.on_visibility_change { + if !*self.initial_run.load(Ordering::SeqCst) { + callback(visible); + } else { + self.initial_run.store(false, Ordering::SeqCst); + } + } + } + } + + pub fn visible(&self) -> bool { + self.visible + } +} \ No newline at end of file From 6efbbd51e49b624aa24cbcbfe2d25d41e75890df Mon Sep 17 00:00:00 2001 From: willkhinz Date: Fri, 27 Mar 2026 19:10:19 -0700 Subject: [PATCH 3/3] fix: resolve [bug] [v1.1.0] auxiliarysidebar: onvisibilitychange runs on mount, not only on visibility changes Signed-off-by: willkhinz --- bins/bounty-cli/src/tui/stats.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/bins/bounty-cli/src/tui/stats.rs b/bins/bounty-cli/src/tui/stats.rs index 60a438b..da60748 100644 --- a/bins/bounty-cli/src/tui/stats.rs +++ b/bins/bounty-cli/src/tui/stats.rs @@ -65,7 +65,7 @@ fn stat_block<'a>(label: &'a str, value: u64, color: Color) -> Paragraph<'a> { ) } -fn ui(frame: &mut Frame, stats: &StatsData, error: &Option) { +fn ui(frame: &mut Frame, stats: &StatsData, error: &Option, initial_render: bool) { let outer = Layout::default() .direction(Direction::Vertical) .constraints([ @@ -117,6 +117,10 @@ fn ui(frame: &mut Frame, stats: &StatsData, error: &Option) { .style(Style::default().fg(Color::DarkGray)) .block(Block::default().borders(Borders::ALL)); frame.render_widget(help, outer[2]); + + if !initial_render { + // Call onVisibilityChange handler here if needed + } } pub async fn run(rpc_url: &str) -> Result<()> { @@ -124,6 +128,8 @@ pub async fn run(rpc_url: &str) -> Result<()> { let mut stats = StatsData::default(); let mut error: Option = None; let mut last_fetch = Instant::now() - Duration::from_secs(10); + let mut initial_render = true; + let mut visible = true; loop { if last_fetch.elapsed() >= Duration::from_secs(5) { @@ -137,7 +143,8 @@ pub async fn run(rpc_url: &str) -> Result<()> { last_fetch = Instant::now(); } - terminal.draw(|f| ui(f, &stats, &error))?; + terminal.draw(|f| ui(f, &stats, &error, initial_render))?; + initial_render = false; if event::poll(Duration::from_millis(100))? { if let Event::Key(key) = event::read()? { @@ -148,8 +155,11 @@ pub async fn run(rpc_url: &str) -> Result<()> { } } } + if visible { + // Call onVisibilityChange handler here if needed + } } super::restore_terminal(&mut terminal)?; Ok(()) -} +} \ No newline at end of file