Ver código fonte

wallet: chatview store properties directly in MessageBuffer which simplifies function signatures

darkfi 1 ano atrás
pai
commit
8265976cfc

+ 5 - 0
bin/darkwallet/src/prop/wrap.rs

@@ -22,6 +22,7 @@ use crate::{
     scene::SceneNode,
     scene::SceneNode,
 };
 };
 
 
+#[derive(Clone)]
 pub struct PropertyBool {
 pub struct PropertyBool {
     prop: PropertyPtr,
     prop: PropertyPtr,
     role: Role,
     role: Role,
@@ -51,6 +52,7 @@ impl PropertyBool {
     }
     }
 }
 }
 
 
+#[derive(Clone)]
 pub struct PropertyUint32 {
 pub struct PropertyUint32 {
     prop: PropertyPtr,
     prop: PropertyPtr,
     role: Role,
     role: Role,
@@ -87,6 +89,7 @@ impl PropertyUint32 {
     }
     }
 }
 }
 
 
+#[derive(Clone)]
 pub struct PropertyFloat32 {
 pub struct PropertyFloat32 {
     prop: PropertyPtr,
     prop: PropertyPtr,
     role: Role,
     role: Role,
@@ -116,6 +119,7 @@ impl PropertyFloat32 {
     }
     }
 }
 }
 
 
+#[derive(Clone)]
 pub struct PropertyStr {
 pub struct PropertyStr {
     prop: PropertyPtr,
     prop: PropertyPtr,
     role: Role,
     role: Role,
@@ -145,6 +149,7 @@ impl PropertyStr {
     }
     }
 }
 }
 
 
+#[derive(Clone)]
 pub struct PropertyColor {
 pub struct PropertyColor {
     prop: PropertyPtr,
     prop: PropertyPtr,
     role: Role,
     role: Role,

+ 49 - 81
bin/darkwallet/src/ui/chatview/mod.rs

@@ -143,6 +143,9 @@ pub struct ChatView {
     accel: AtomicF32,
     accel: AtomicF32,
     speed: AtomicF32,
     speed: AtomicF32,
 
 
+    // Triggers the background loading task to wake up
+    bgload_cv: Arc<CondVar>,
+
     /// Used for correct converting input event pos from screen to widget space.
     /// 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.
     /// We also use it when we re-eval rect when its changed via property.
     parent_rect: SyncMutex<Option<Rectangle>>,
     parent_rect: SyncMutex<Option<Rectangle>>,
@@ -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());
             let mut on_modify = OnModify::new(ex, node_name, node_id, me.clone());
 
 
             async fn reload_view(self_: Arc<ChatView>) {
             async fn reload_view(self_: Arc<ChatView>) {
@@ -245,6 +263,7 @@ impl ChatView {
                 key_down_task,
                 key_down_task,
                 insert_line_method_task,
                 insert_line_method_task,
                 motion_task,
                 motion_task,
+                bgload_task,
             ];
             ];
             tasks.append(&mut on_modify.tasks);
             tasks.append(&mut on_modify.tasks);
 
 
@@ -256,7 +275,17 @@ impl ChatView {
                 text_shaper: text_shaper.clone(),
                 text_shaper: text_shaper.clone(),
                 tree,
                 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(),
                 dc_key: OsRng.gen(),
 
 
                 mouse_pos: SyncMutex::new(Point::from([0., 0.])),
                 mouse_pos: SyncMutex::new(Point::from([0., 0.])),
@@ -282,6 +311,8 @@ impl ChatView {
                 accel: AtomicF32::new(0.),
                 accel: AtomicF32::new(0.),
                 speed: AtomicF32::new(0.),
                 speed: AtomicF32::new(0.),
 
 
+                bgload_cv,
+
                 parent_rect: SyncMutex::new(None),
                 parent_rect: SyncMutex::new(None),
             }
             }
         });
         });
@@ -536,11 +567,7 @@ impl ChatView {
         }
         }
 
 
         // Add message to page
         // 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
         // This will refresh the view, so we just use this
         let scroll = self.scroll.get();
         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
         // Get the current earliest timestamp
         let iter = match msgbuf.oldest_timestamp() {
         let iter = match msgbuf.oldest_timestamp() {
             Some(oldest_timest) => {
             Some(oldest_timest) => {
@@ -611,17 +637,6 @@ impl ChatView {
             None => self.tree.iter().rev(),
             None => self.tree.iter().rev(),
         };
         };
 
 
-        self.load_n_msgs(msgbuf, iter, PRELOAD_PAGES).await
-    }
-
-    async fn load_n_msgs<I: Iterator<Item = sled::Result<(sled::IVec, sled::IVec)>>>(
-        &self,
-        msgbuf: &mut MessageBuffer,
-        iter: I,
-        n: usize,
-    ) -> usize {
-        let mut msgs_len = 0;
-
         for entry in iter {
         for entry in iter {
             let Ok((k, v)) = entry else { break };
             let Ok((k, v)) = entry else { break };
             assert_eq!(k.len(), 8 + 32);
             assert_eq!(k.len(), 8 + 32);
@@ -631,28 +646,13 @@ impl ChatView {
             let chatmsg: ChatMsg = deserialize(&v).unwrap();
             let chatmsg: ChatMsg = deserialize(&v).unwrap();
             debug!(target: "ui::chatview", "{timest:?} {chatmsg:?}");
             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<Color> {
-        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
     /// Invalidates cache and redraws everything
@@ -723,27 +723,15 @@ impl ChatView {
         mut scroll: f32,
         mut scroll: f32,
         rect_h: f32,
         rect_h: f32,
     ) -> Option<f32> {
     ) -> Option<f32> {
-        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.
         // 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 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. {
         if scroll < 0. {
             return Some(0.)
             return Some(0.)
@@ -768,35 +756,15 @@ impl ChatView {
         rect: &Rectangle,
         rect: &Rectangle,
     ) -> (Vec<DrawInstruction>, FreedData) {
     ) -> (Vec<DrawInstruction>, FreedData) {
         let scroll = self.scroll.get();
         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
         // 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 start_pos = if total_height < rect.h { total_height } else { rect.h };
 
 
         let mut instrs = vec![];
         let mut instrs = vec![];
         //let mut old_drawmesh = 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.;
         let mut current_height = 0.;
         for (i, (y_pos, mesh)) in enumerate(meshes) {
         for (i, (y_pos, mesh)) in enumerate(meshes) {

+ 68 - 24
bin/darkwallet/src/ui/chatview/page.rs

@@ -436,17 +436,45 @@ pub struct MessageBuffer {
     date_msgs: HashMap<NaiveDate, Message>,
     date_msgs: HashMap<NaiveDate, Message>,
     pub(super) freed: FreedData,
     pub(super) freed: FreedData,
     pub(super) line_width: f32,
     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,
     render_api: RenderApiPtr,
     text_shaper: TextShaperPtr,
     text_shaper: TextShaperPtr,
 }
 }
 
 
 impl MessageBuffer {
 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 {
         Self {
             msgs: vec![],
             msgs: vec![],
             date_msgs: HashMap::new(),
             date_msgs: HashMap::new(),
             freed: Default::default(),
             freed: Default::default(),
             line_width: 0.,
             line_width: 0.,
+
+            font_size,
+            line_height,
+            baseline,
+            timestamp_color,
+            text_color,
+            nick_colors,
+            debug,
+
             render_api,
             render_api,
             text_shaper,
             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 mut height = 0.;
 
 
-        let msgs = self.msgs_with_date(font_size);
+        let msgs = self.msgs_with_date();
         let mut msgs = pin!(msgs);
         let mut msgs = pin!(msgs);
 
 
         while let Some(msg) = msgs.next().await {
         while let Some(msg) = msgs.next().await {
@@ -500,12 +524,13 @@ impl MessageBuffer {
 
 
     pub(super) async fn insert_privmsg(
     pub(super) async fn insert_privmsg(
         &mut self,
         &mut self,
-        font_size: f32,
         timest: Timestamp,
         timest: Timestamp,
         message_id: MessageId,
         message_id: MessageId,
         nick: String,
         nick: String,
         text: String,
         text: String,
     ) {
     ) {
+        let font_size = self.font_size.get();
+
         let msg = PrivMessage::new(
         let msg = PrivMessage::new(
             font_size,
             font_size,
             timest,
             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(
     pub(super) async fn push_privmsg(
         &mut self,
         &mut self,
-        font_size: f32,
         timest: Timestamp,
         timest: Timestamp,
         message_id: MessageId,
         message_id: MessageId,
         nick: String,
         nick: String,
         text: String,
         text: String,
     ) {
     ) {
+        let font_size = self.font_size.get();
+
         let msg = PrivMessage::new(
         let msg = PrivMessage::new(
             font_size,
             font_size,
             timest,
             timest,
@@ -578,10 +604,12 @@ impl MessageBuffer {
         }
         }
 
 
         let idx = self.msgs.len() - 1;
         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 timest = msg.timestamp();
         let msg_is_date = msg.is_date();
         let msg_is_date = msg.is_date();
 
 
@@ -600,17 +628,18 @@ impl MessageBuffer {
         &mut self,
         &mut self,
         rect: &Rectangle,
         rect: &Rectangle,
         scroll: f32,
         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)> {
     ) -> 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 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 msgs = pin!(msgs);
 
 
         let mut meshes = vec![];
         let mut meshes = vec![];
@@ -633,8 +662,8 @@ impl MessageBuffer {
                     rect,
                     rect,
                     line_height,
                     line_height,
                     baseline,
                     baseline,
-                    nick_colors,
-                    timestamp_color,
+                    &nick_colors,
+                    timest_color,
                     text_color,
                     text_color,
                     debug_render,
                     debug_render,
                     &render_api,
                     &render_api,
@@ -650,7 +679,8 @@ impl MessageBuffer {
     }
     }
 
 
     /// Gets around borrow checker with unsafe
     /// Gets around borrow checker with unsafe
-    fn msgs_with_date(&mut self, font_size: f32) -> impl Stream<Item = &mut Message> {
+    fn msgs_with_date(&mut self) -> impl Stream<Item = &mut Message> {
+        let font_size = self.font_size.get();
         AsyncIter::from(async_gen! {
         AsyncIter::from(async_gen! {
             let mut last_date = None;
             let mut last_date = None;
 
 
@@ -705,4 +735,18 @@ impl MessageBuffer {
         let first_msg = &self.msgs.first()?;
         let first_msg = &self.msgs.first()?;
         Some(first_msg.timestamp())
         Some(first_msg.timestamp())
     }
     }
+
+    fn read_nick_colors(&self) -> Vec<Color> {
+        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
+    }
 }
 }