diff --git a/bin/darkwallet/src/prop/wrap.rs b/bin/darkwallet/src/prop/wrap.rs index c781c6230..f93d44211 100644 --- a/bin/darkwallet/src/prop/wrap.rs +++ b/bin/darkwallet/src/prop/wrap.rs @@ -22,6 +22,7 @@ use crate::{ scene::SceneNode, }; +#[derive(Clone)] pub struct PropertyBool { prop: PropertyPtr, role: Role, @@ -51,6 +52,7 @@ impl PropertyBool { } } +#[derive(Clone)] pub struct PropertyUint32 { prop: PropertyPtr, role: Role, @@ -87,6 +89,7 @@ impl PropertyUint32 { } } +#[derive(Clone)] pub struct PropertyFloat32 { prop: PropertyPtr, role: Role, @@ -116,6 +119,7 @@ impl PropertyFloat32 { } } +#[derive(Clone)] pub struct PropertyStr { prop: PropertyPtr, role: Role, @@ -145,6 +149,7 @@ impl PropertyStr { } } +#[derive(Clone)] pub struct PropertyColor { prop: PropertyPtr, role: Role, diff --git a/bin/darkwallet/src/ui/chatview/mod.rs b/bin/darkwallet/src/ui/chatview/mod.rs index 37badc69f..553857149 100644 --- a/bin/darkwallet/src/ui/chatview/mod.rs +++ b/bin/darkwallet/src/ui/chatview/mod.rs @@ -143,6 +143,9 @@ pub struct ChatView { accel: AtomicF32, speed: AtomicF32, + // Triggers the background loading task to wake up + bgload_cv: Arc, + /// Used for correct converting input event pos from screen to widget space. /// We also use it when we re-eval rect when its changed via property. parent_rect: SyncMutex>, @@ -225,6 +228,21 @@ impl ChatView { } }); + let me2 = me.clone(); + let bgload_cv = Arc::new(CondVar::new()); + let cv = bgload_cv.clone(); + let bgload_task = ex.spawn(async move { + loop { + let Some(self_) = me2.upgrade() else { + // Should not happen + panic!("self destroyed before motion_task was stopped!"); + }; + cv.reset(); + self_.handle_bgload().await; + cv.wait().await; + } + }); + let mut on_modify = OnModify::new(ex, node_name, node_id, me.clone()); async fn reload_view(self_: Arc) { @@ -245,6 +263,7 @@ impl ChatView { key_down_task, insert_line_method_task, motion_task, + bgload_task, ]; tasks.append(&mut on_modify.tasks); @@ -256,7 +275,17 @@ impl ChatView { text_shaper: text_shaper.clone(), tree, - msgbuf: AsyncMutex::new(MessageBuffer::new(render_api, text_shaper)), + msgbuf: AsyncMutex::new(MessageBuffer::new( + font_size.clone(), + line_height.clone(), + baseline.clone(), + timestamp_color.clone(), + text_color.clone(), + nick_colors.clone(), + debug.clone(), + render_api, + text_shaper, + )), dc_key: OsRng.gen(), mouse_pos: SyncMutex::new(Point::from([0., 0.])), @@ -282,6 +311,8 @@ impl ChatView { accel: AtomicF32::new(0.), speed: AtomicF32::new(0.), + bgload_cv, + parent_rect: SyncMutex::new(None), } }); @@ -536,11 +567,7 @@ impl ChatView { } // Add message to page - self.msgbuf - .lock() - .await - .insert_privmsg(self.font_size.get(), timest, message_id, nick.clone(), text.clone()) - .await; + self.msgbuf.lock().await.insert_privmsg(timest, message_id, nick, text).await; // This will refresh the view, so we just use this let scroll = self.scroll.get(); @@ -589,13 +616,12 @@ impl ChatView { } } - /// Descent = line height - baseline - fn descent(&self) -> f32 { - self.line_height.get() - self.baseline.get() - } + async fn handle_bgload(&self) { + // Do we need to load some more? + let scroll = self.scroll.get(); + + let mut msgbuf = self.msgbuf.lock().await; - /// Load extra msgs - async fn preload_msgs(&self, msgbuf: &mut MessageBuffer) -> usize { // Get the current earliest timestamp let iter = match msgbuf.oldest_timestamp() { Some(oldest_timest) => { @@ -611,17 +637,6 @@ impl ChatView { None => self.tree.iter().rev(), }; - self.load_n_msgs(msgbuf, iter, PRELOAD_PAGES).await - } - - async fn load_n_msgs>>( - &self, - msgbuf: &mut MessageBuffer, - iter: I, - n: usize, - ) -> usize { - let mut msgs_len = 0; - for entry in iter { let Ok((k, v)) = entry else { break }; assert_eq!(k.len(), 8 + 32); @@ -631,28 +646,13 @@ impl ChatView { let chatmsg: ChatMsg = deserialize(&v).unwrap(); debug!(target: "ui::chatview", "{timest:?} {chatmsg:?}"); - msgbuf - .push_privmsg(self.font_size.get(), timest, message_id, chatmsg.nick, chatmsg.text) - .await; - - msgs_len += 1; + msgbuf.push_privmsg(timest, message_id, chatmsg.nick, chatmsg.text).await; } - debug!(target: "ui::chatview", "populated {} messages", msgs_len); - msgs_len } - fn read_nick_colors(&self) -> Vec { - let mut colors = vec![]; - let mut color = [0f32; 4]; - for i in 0..self.nick_colors.get_len() { - color[i % 4] = self.nick_colors.get_f32(i).expect("prop logic err"); - - if i > 0 && i % 4 == 0 { - let color = std::mem::take(&mut color); - colors.push(color); - } - } - colors + /// Descent = line height - baseline + fn descent(&self) -> f32 { + self.line_height.get() - self.baseline.get() } /// Invalidates cache and redraws everything @@ -723,27 +723,15 @@ impl ChatView { mut scroll: f32, rect_h: f32, ) -> Option { - let line_height = self.line_height.get(); - let baseline = self.baseline.get(); - let font_size = self.font_size.get(); - // We still wish to preload pages to fill the screen, so we just adjust it up to 0. let nonneg_scroll = max(scroll, 0.); - let mut total_height = msgbuf.calc_total_height(line_height, baseline, font_size).await; - // Load pages until we run out or we have enough - while total_height < nonneg_scroll + rect_h { - let n_loaded_pages = self.preload_msgs(msgbuf).await; - debug!(target: "ui::chatview", "set_adjusted_scroll() loaded until {:?}", msgbuf.oldest_timestamp()); + let mut total_height = msgbuf.calc_total_height().await; - // We need this value after so first update it - total_height = msgbuf.calc_total_height(line_height, baseline, font_size).await; - - // No more pages available to load - if n_loaded_pages == 0 { - break - } - } + //if total_height < nonneg_scroll + rect_h { + // // Trigger loading + // self.bgload_cv.notify(); + //} if scroll < 0. { return Some(0.) @@ -768,35 +756,15 @@ impl ChatView { rect: &Rectangle, ) -> (Vec, FreedData) { let scroll = self.scroll.get(); - let font_size = self.font_size.get(); - let line_height = self.line_height.get(); - let baseline = self.baseline.get(); - let debug_render = self.debug.get(); - let total_height = msgbuf.calc_total_height(line_height, baseline, font_size).await; + let total_height = msgbuf.calc_total_height().await; // If lines aren't enough to fill the available buffer then start from the top let start_pos = if total_height < rect.h { total_height } else { rect.h }; let mut instrs = vec![]; //let mut old_drawmesh = vec![]; - let timest_color = self.timestamp_color.get(); - let text_color = self.text_color.get(); - let nick_colors = self.read_nick_colors(); - - let meshes = msgbuf - .gen_meshes( - rect, - scroll, - font_size, - line_height, - baseline, - &nick_colors, - timest_color.clone(), - text_color.clone(), - debug_render, - ) - .await; + let meshes = msgbuf.gen_meshes(rect, scroll).await; let mut current_height = 0.; for (i, (y_pos, mesh)) in enumerate(meshes) { diff --git a/bin/darkwallet/src/ui/chatview/page.rs b/bin/darkwallet/src/ui/chatview/page.rs index edb73cbe2..4cb7992a1 100644 --- a/bin/darkwallet/src/ui/chatview/page.rs +++ b/bin/darkwallet/src/ui/chatview/page.rs @@ -436,17 +436,45 @@ pub struct MessageBuffer { date_msgs: HashMap, pub(super) freed: FreedData, pub(super) line_width: f32, + + font_size: PropertyFloat32, + line_height: PropertyFloat32, + baseline: PropertyFloat32, + timestamp_color: PropertyColor, + text_color: PropertyColor, + nick_colors: PropertyPtr, + debug: PropertyBool, + render_api: RenderApiPtr, text_shaper: TextShaperPtr, } impl MessageBuffer { - pub(super) fn new(render_api: RenderApiPtr, text_shaper: TextShaperPtr) -> Self { + pub(super) fn new( + font_size: PropertyFloat32, + line_height: PropertyFloat32, + baseline: PropertyFloat32, + timestamp_color: PropertyColor, + text_color: PropertyColor, + nick_colors: PropertyPtr, + debug: PropertyBool, + render_api: RenderApiPtr, + text_shaper: TextShaperPtr, + ) -> Self { Self { msgs: vec![], date_msgs: HashMap::new(), freed: Default::default(), line_width: 0., + + font_size, + line_height, + baseline, + timestamp_color, + text_color, + nick_colors, + debug, + render_api, text_shaper, } @@ -480,15 +508,11 @@ impl MessageBuffer { } } - pub(super) async fn calc_total_height( - &mut self, - line_height: f32, - baseline: f32, - font_size: f32, - ) -> f32 { + pub(super) async fn calc_total_height(&mut self) -> f32 { + let line_height = self.line_height.get(); let mut height = 0.; - let msgs = self.msgs_with_date(font_size); + let msgs = self.msgs_with_date(); let mut msgs = pin!(msgs); while let Some(msg) = msgs.next().await { @@ -500,12 +524,13 @@ impl MessageBuffer { pub(super) async fn insert_privmsg( &mut self, - font_size: f32, timest: Timestamp, message_id: MessageId, nick: String, text: String, ) { + let font_size = self.font_size.get(); + let msg = PrivMessage::new( font_size, timest, @@ -549,17 +574,18 @@ impl MessageBuffer { } }; - self.insert_msg(msg, idx, font_size).await; + self.insert_msg(msg, idx).await; } pub(super) async fn push_privmsg( &mut self, - font_size: f32, timest: Timestamp, message_id: MessageId, nick: String, text: String, ) { + let font_size = self.font_size.get(); + let msg = PrivMessage::new( font_size, timest, @@ -578,10 +604,12 @@ impl MessageBuffer { } let idx = self.msgs.len() - 1; - self.insert_msg(msg, idx, font_size).await; + self.insert_msg(msg, idx).await; } - async fn insert_msg(&mut self, msg: Message, idx: usize, font_size: f32) { + async fn insert_msg(&mut self, msg: Message, idx: usize) { + let font_size = self.font_size.get(); + let timest = msg.timestamp(); let msg_is_date = msg.is_date(); @@ -600,17 +628,18 @@ impl MessageBuffer { &mut self, rect: &Rectangle, scroll: f32, - font_size: f32, - line_height: f32, - baseline: f32, - nick_colors: &[Color], - timestamp_color: Color, - text_color: Color, - debug_render: bool, ) -> Vec<(f32, DrawMesh)> { + let line_height = self.line_height.get(); + let baseline = self.baseline.get(); + let debug_render = self.debug.get(); + + let timest_color = self.timestamp_color.get(); + let text_color = self.text_color.get(); + let nick_colors = self.read_nick_colors(); + let render_api = self.render_api.clone(); - let msgs = self.msgs_with_date(font_size); + let msgs = self.msgs_with_date(); let mut msgs = pin!(msgs); let mut meshes = vec![]; @@ -633,8 +662,8 @@ impl MessageBuffer { rect, line_height, baseline, - nick_colors, - timestamp_color, + &nick_colors, + timest_color, text_color, debug_render, &render_api, @@ -650,7 +679,8 @@ impl MessageBuffer { } /// Gets around borrow checker with unsafe - fn msgs_with_date(&mut self, font_size: f32) -> impl Stream { + fn msgs_with_date(&mut self) -> impl Stream { + let font_size = self.font_size.get(); AsyncIter::from(async_gen! { let mut last_date = None; @@ -705,4 +735,18 @@ impl MessageBuffer { let first_msg = &self.msgs.first()?; Some(first_msg.timestamp()) } + + fn read_nick_colors(&self) -> Vec { + let mut colors = vec![]; + let mut color = [0f32; 4]; + for i in 0..self.nick_colors.get_len() { + color[i % 4] = self.nick_colors.get_f32(i).expect("prop logic err"); + + if i > 0 && i % 4 == 0 { + let color = std::mem::take(&mut color); + colors.push(color); + } + } + colors + } }