notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 9cbba37507b60ffc6a57098fcafdf76272330034
parent b94e715539b2251626d568f518a62e7ec355d811
Author: William Casarin <jb55@jb55.com>
Date:   Mon,  4 Aug 2025 11:29:54 -0700

debug: add repaint causes debug tool

enable with --debug, click on fps/frame time counter

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
MCargo.lock | 1+
Mcrates/notedeck/src/media/gif.rs | 11+++++------
Mcrates/notedeck_chrome/src/chrome.rs | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mcrates/notedeck_columns/src/app.rs | 3+--
Mcrates/notedeck_dave/Cargo.toml | 1+
Mcrates/notedeck_dave/src/lib.rs | 5-----
6 files changed, 83 insertions(+), 21 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -3622,6 +3622,7 @@ dependencies = [ "eframe", "egui", "egui-wgpu", + "egui_extras", "enostr", "futures", "hex", diff --git a/crates/notedeck/src/media/gif.rs b/crates/notedeck/src/media/gif.rs @@ -151,12 +151,11 @@ pub fn ensure_latest_texture( gifs.insert(url.to_owned(), new_state); } - if let Some(req) = next_state.repaint_at { - // TODO(jb55): make a continuous gif rendering setting - // 24fps for gif is fine - tracing::trace!("requesting repaint for {url} after {req:?}"); - ui.ctx() - .request_repaint_after(std::time::Duration::from_millis(41)); + if let Some(repaint) = next_state.repaint_at { + tracing::trace!("requesting repaint for {url} after {repaint:?}"); + if let Ok(dur) = repaint.duration_since(SystemTime::now()) { + ui.ctx().request_repaint_after(dur); + } } next_state.texture diff --git a/crates/notedeck_chrome/src/chrome.rs b/crates/notedeck_chrome/src/chrome.rs @@ -19,6 +19,7 @@ use notedeck_columns::{ use notedeck_dave::{Dave, DaveAvatar}; use notedeck_notebook::Notebook; use notedeck_ui::{app_images, AnimationHelper, ProfilePic}; +use std::collections::HashMap; static ICON_WIDTH: f32 = 40.0; pub static ICON_EXPANSION_MULTIPLE: f32 = 1.2; @@ -28,15 +29,18 @@ pub struct Chrome { open: bool, tab_selected: i32, apps: Vec<NotedeckApp>, + pub repaint_causes: HashMap<egui::RepaintCause, u64>, #[cfg(feature = "memory")] show_memory_debug: bool, + show_repaint_debug: bool, } impl Default for Chrome { fn default() -> Self { Self { active: 0, + repaint_causes: Default::default(), tab_selected: 0, // sidemenu is not open by default on mobile/narrow uis open: !notedeck::ui::is_compiled_as_mobile(), @@ -44,6 +48,7 @@ impl Default for Chrome { #[cfg(feature = "memory")] show_memory_debug: false, + show_repaint_debug: false, } } } @@ -959,7 +964,7 @@ fn pfp_button(ctx: &mut AppContext, ui: &mut egui::Ui) -> egui::Response { /// The section of the chrome sidebar that starts at the /// bottom and goes up fn bottomup_sidebar( - _chrome: &mut Chrome, + chrome: &mut Chrome, ctx: &mut AppContext, ui: &mut egui::Ui, ) -> Option<ChromePanelAction> { @@ -1009,11 +1014,30 @@ fn bottomup_sidebar( .on_hover_cursor(egui::CursorIcon::PointingHand); if ctx.args.options.contains(NotedeckOptions::Debug) { - ui.weak(format!("{}", ctx.frame_history.fps() as i32)); - ui.weak(format!( - "{:10.1}", - ctx.frame_history.mean_frame_time() * 1e3 - )); + let r = ui + .weak(format!("{}", ctx.frame_history.fps() as i32)) + .union(ui.weak(format!( + "{:10.1}", + ctx.frame_history.mean_frame_time() * 1e3 + ))) + .on_hover_cursor(egui::CursorIcon::PointingHand); + + if r.clicked() { + chrome.show_repaint_debug = !chrome.show_repaint_debug; + } + + if chrome.show_repaint_debug { + for cause in ui.ctx().repaint_causes() { + chrome + .repaint_causes + .entry(cause) + .and_modify(|rc| { + *rc += 1; + }) + .or_insert(1); + } + repaint_causes_window(ui, &chrome.repaint_causes) + } #[cfg(feature = "memory")] { @@ -1024,14 +1048,14 @@ fn bottomup_sidebar( .on_hover_cursor(egui::CursorIcon::PointingHand) .clicked() { - _chrome.show_memory_debug = !_chrome.show_memory_debug; + chrome.show_memory_debug = !chrome.show_memory_debug; } } if let Some(resident) = mem_use.resident { ui.weak(format!("{}", format_bytes(resident as f64))); } - if _chrome.show_memory_debug { + if chrome.show_memory_debug { egui::Window::new("Memory Debug").show(ui.ctx(), memory_debug_ui); } } @@ -1151,3 +1175,46 @@ pub fn format_bytes(number_of_bytes: f64) -> String { format!("{:.*} GiB", decimals, number_of_bytes / 30.0_f64.exp2()) } } + +fn repaint_causes_window(ui: &mut egui::Ui, causes: &HashMap<egui::RepaintCause, u64>) { + egui::Window::new("Repaint Causes").show(ui.ctx(), |ui| { + use egui_extras::{Column, TableBuilder}; + TableBuilder::new(ui) + .column(Column::auto().at_least(600.0).resizable(true)) + .column(Column::auto().at_least(50.0).resizable(true)) + .column(Column::auto().at_least(50.0).resizable(true)) + .column(Column::remainder()) + .header(20.0, |mut header| { + header.col(|ui| { + ui.heading("file"); + }); + header.col(|ui| { + ui.heading("line"); + }); + header.col(|ui| { + ui.heading("count"); + }); + header.col(|ui| { + ui.heading("reason"); + }); + }) + .body(|mut body| { + for (cause, hits) in causes.iter() { + body.row(30.0, |mut row| { + row.col(|ui| { + ui.label(cause.file.to_string()); + }); + row.col(|ui| { + ui.label(format!("{}", cause.line)); + }); + row.col(|ui| { + ui.label(format!("{hits}")); + }); + row.col(|ui| { + ui.label(format!("{}", &cause.reason)); + }); + }); + } + }); + }); +} diff --git a/crates/notedeck_columns/src/app.rs b/crates/notedeck_columns/src/app.rs @@ -27,7 +27,6 @@ use notedeck_ui::{ }; use std::collections::{BTreeSet, HashMap}; use std::path::Path; -use std::time::Duration; use tracing::{debug, error, info, trace, warn}; use uuid::Uuid; @@ -374,7 +373,7 @@ fn render_damus( fullscreen_media_viewer_ui(ui, &mut damus.view_state.media_viewer, app_ctx.img_cache); // We use this for keeping timestamps and things up to date - ui.ctx().request_repaint_after(Duration::from_secs(5)); + //ui.ctx().request_repaint_after(Duration::from_secs(5)); app_action } diff --git a/crates/notedeck_dave/Cargo.toml b/crates/notedeck_dave/Cargo.toml @@ -23,3 +23,4 @@ rand = "0.9.0" bytemuck = "1.22.0" futures = "0.3.31" #reqwest = "0.12.15" +egui_extras = { workspace = true } diff --git a/crates/notedeck_dave/src/lib.rs b/crates/notedeck_dave/src/lib.rs @@ -344,11 +344,6 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr impl notedeck::App for Dave { fn update(&mut self, ctx: &mut AppContext<'_>, ui: &mut egui::Ui) -> Option<AppAction> { - /* - self.app - .frame_history - .on_new_frame(ctx.input(|i| i.time), frame.info().cpu_usage); - */ let mut app_action: Option<AppAction> = None; // always insert system prompt if we have no context