Przeglądaj źródła

wallet: chatview cleanup bg loader and make small fixes

darkfi 1 rok temu
rodzic
commit
2e4bdcd7e0

+ 72 - 61
bin/darkwallet/src/ui/chatview/mod.rs

@@ -79,8 +79,7 @@ pub struct ChatMsg {
 type Timestamp = u64;
 type Timestamp = u64;
 type MessageId = [u8; 32];
 type MessageId = [u8; 32];
 
 
-const PAGE_SIZE: usize = 10;
-const PRELOAD_PAGES: usize = 10;
+const PRELOAD_PAGES: usize = 1;
 
 
 #[derive(Clone)]
 #[derive(Clone)]
 struct TouchInfo {
 struct TouchInfo {
@@ -233,13 +232,13 @@ impl ChatView {
             let cv = bgload_cv.clone();
             let cv = bgload_cv.clone();
             let bgload_task = ex.spawn(async move {
             let bgload_task = ex.spawn(async move {
                 loop {
                 loop {
+                    cv.wait().await;
                     let Some(self_) = me2.upgrade() else {
                     let Some(self_) = me2.upgrade() else {
                         // Should not happen
                         // Should not happen
-                        panic!("self destroyed before motion_task was stopped!");
+                        panic!("self destroyed before bgload_task was stopped!");
                     };
                     };
-                    cv.reset();
                     self_.handle_bgload().await;
                     self_.handle_bgload().await;
-                    cv.wait().await;
+                    cv.reset();
                 }
                 }
             });
             });
 
 
@@ -567,11 +566,9 @@ impl ChatView {
         }
         }
 
 
         // Add message to page
         // Add message to page
+        let mut msgbuf = self.msgbuf.lock().await;
         self.msgbuf.lock().await.insert_privmsg(timest, message_id, nick, text).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();
-        self.scrollview(scroll).await;
+        self.bgload_cv.notify();
     }
     }
 
 
     async fn handle_movement(&self) {
     async fn handle_movement(&self) {
@@ -617,11 +614,27 @@ impl ChatView {
     }
     }
 
 
     async fn handle_bgload(&self) {
     async fn handle_bgload(&self) {
+        //debug!(target: "ui::chatview", "ChatView::handle_bgload()");
         // Do we need to load some more?
         // Do we need to load some more?
         let scroll = self.scroll.get();
         let scroll = self.scroll.get();
+        let mut rect = read_rect(self.rect.clone()).expect("bad rect property");
+        let top = scroll + rect.h;
+
+        let preload_height = PRELOAD_PAGES as f32 * rect.h;
 
 
         let mut msgbuf = self.msgbuf.lock().await;
         let mut msgbuf = self.msgbuf.lock().await;
 
 
+        let total_height = msgbuf.calc_total_height().await;
+        if total_height > top + preload_height {
+            // Nothing to do here
+            //debug!(target: "ui::chatview", "bgloader: buffer is sufficient");
+            return
+        }
+
+        // Keep loading until this is below 0
+        let mut remaining_load_height = top + preload_height - total_height;
+        debug!(target: "ui::chatview", "bgloader: remaining px = {remaining_load_height}");
+
         // 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) => {
@@ -634,7 +647,10 @@ impl ChatView {
                 let iter = self.tree.range(..key).rev();
                 let iter = self.tree.range(..key).rev();
                 iter
                 iter
             }
             }
-            None => self.tree.iter().rev(),
+            None => {
+                debug!(target: "ui::chatview", "initial load");
+                self.tree.iter().rev()
+            }
         };
         };
 
 
         for entry in iter {
         for entry in iter {
@@ -646,7 +662,17 @@ 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(timest, message_id, chatmsg.nick, chatmsg.text).await;
+            let msg_height =
+                msgbuf.push_privmsg(timest, message_id, chatmsg.nick, chatmsg.text).await;
+
+            remaining_load_height -= msg_height;
+            if remaining_load_height <= 0. {
+                break
+            }
+
+            // todo: if msg is visible {
+            self.redraw_cached(&mut msgbuf).await;
+            // }
         }
         }
     }
     }
 
 
@@ -655,31 +681,6 @@ impl ChatView {
         self.line_height.get() - self.baseline.get()
         self.line_height.get() - self.baseline.get()
     }
     }
 
 
-    /// Invalidates cache and redraws everything
-    async fn redraw(&self) {
-        debug!(target: "ui::chatview", "redraw()");
-        let sg = self.sg.lock().await;
-        let node = sg.get_node(self.node_id).unwrap();
-
-        let Some(parent_rect) = get_parent_rect(&sg, node) else {
-            return;
-        };
-
-        let Some(draw_update) = self.draw(&sg, &parent_rect).await else {
-            error!(target: "ui::chatview", "ChatView {:?} failed to draw", node);
-            return;
-        };
-        self.render_api.replace_draw_calls(draw_update.draw_calls).await;
-        debug!(target: "ui::chatview", "replace draw calls done");
-        for buffer_id in draw_update.freed_buffers {
-            self.render_api.delete_buffer(buffer_id);
-        }
-        for texture_id in draw_update.freed_textures {
-            self.render_api.delete_texture(texture_id);
-        }
-    }
-
-    /// Basically a version of redraw() which doesn't invalidate the cache
     async fn scrollview(&self, mut scroll: f32) -> f32 {
     async fn scrollview(&self, mut scroll: f32) -> f32 {
         //debug!(target: "ui::chatview", "scrollview()");
         //debug!(target: "ui::chatview", "scrollview()");
         let old_scroll = self.scroll.get();
         let old_scroll = self.scroll.get();
@@ -692,25 +693,11 @@ impl ChatView {
             scroll = new_scroll;
             scroll = new_scroll;
         }
         }
 
 
-        let (mut mesh_instrs, freed) = self.get_meshes(&mut msgbuf, &rect).await;
-        drop(msgbuf);
-
-        let mut instrs = vec![DrawInstruction::ApplyViewport(rect)];
-        instrs.append(&mut mesh_instrs);
-
-        let draw_calls =
-            vec![(self.dc_key, DrawCall { instrs, dcs: vec![], z_index: self.z_index.get() })];
-
-        self.render_api.replace_draw_calls(draw_calls).await;
-
-        for buffer_id in freed.buffers {
-            self.render_api.delete_buffer(buffer_id);
-        }
-        for texture_id in freed.textures {
-            self.render_api.delete_texture(texture_id);
-        }
+        self.redraw_cached(&mut msgbuf).await;
 
 
         self.scroll.set(scroll);
         self.scroll.set(scroll);
+        self.bgload_cv.notify();
+
         scroll - old_scroll
         scroll - old_scroll
     }
     }
 
 
@@ -726,17 +713,11 @@ impl ChatView {
         // 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().await;
-
-        //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.)
         }
         }
 
 
+        let total_height = msgbuf.calc_total_height().await;
         let max_allowed_scroll = if total_height > rect_h { total_height - rect_h } else { 0. };
         let max_allowed_scroll = if total_height > rect_h { total_height - rect_h } else { 0. };
 
 
         if scroll > max_allowed_scroll {
         if scroll > max_allowed_scroll {
@@ -794,7 +775,6 @@ impl ChatView {
         debug!(target: "ui::chatview", "ChatView::draw()");
         debug!(target: "ui::chatview", "ChatView::draw()");
 
 
         *self.parent_rect.lock().unwrap() = Some(parent_rect.clone());
         *self.parent_rect.lock().unwrap() = Some(parent_rect.clone());
-
         let rect = eval_rect(self.rect.clone(), parent_rect).expect("bad rect property");
         let rect = eval_rect(self.rect.clone(), parent_rect).expect("bad rect property");
 
 
         let mut msgbuf = self.msgbuf.lock().await;
         let mut msgbuf = self.msgbuf.lock().await;
@@ -805,6 +785,10 @@ impl ChatView {
             self.scroll.set(scroll);
             self.scroll.set(scroll);
         }
         }
 
 
+        // We may need to load more messages since the screen size has changed.
+        // Now we have updated all the values so it's safe to wake up here.
+        self.bgload_cv.notify();
+
         let (mut mesh_instrs, freed) = self.get_meshes(&mut msgbuf, &rect).await;
         let (mut mesh_instrs, freed) = self.get_meshes(&mut msgbuf, &rect).await;
         drop(msgbuf);
         drop(msgbuf);
 
 
@@ -821,4 +805,31 @@ impl ChatView {
             freed_buffers: freed.buffers,
             freed_buffers: freed.buffers,
         })
         })
     }
     }
+
+    async fn redraw_cached(&self, msgbuf: &mut MessageBuffer) {
+        let rect = read_rect(self.rect.clone()).expect("bad rect property");
+
+        let (mut mesh_instrs, freed) = self.get_meshes(msgbuf, &rect).await;
+
+        let mut instrs = vec![DrawInstruction::ApplyViewport(rect)];
+        instrs.append(&mut mesh_instrs);
+
+        let draw_calls =
+            vec![(self.dc_key, DrawCall { instrs, dcs: vec![], z_index: self.z_index.get() })];
+
+        self.render_api.replace_draw_calls(draw_calls).await;
+
+        for buffer_id in freed.buffers {
+            self.render_api.delete_buffer(buffer_id);
+        }
+        for texture_id in freed.textures {
+            self.render_api.delete_texture(texture_id);
+        }
+    }
+
+    /// Invalidates cache and redraws everything
+    async fn redraw_all(&self) {
+        debug!(target: "ui::chatview", "redraw()");
+        // ... todo fin
+    }
 }
 }

+ 7 - 25
bin/darkwallet/src/ui/chatview/page.rs

@@ -480,10 +480,6 @@ impl MessageBuffer {
         }
         }
     }
     }
 
 
-    pub(super) fn push(&mut self, msg: Message) {
-        self.msgs.push(msg);
-    }
-
     /// For scrolling we want to be able to adjust and measure without
     /// For scrolling we want to be able to adjust and measure without
     /// explicitly rendering since it may be off screen.
     /// explicitly rendering since it may be off screen.
     pub(super) fn adjust_width(&mut self, line_width: f32) {
     pub(super) fn adjust_width(&mut self, line_width: f32) {
@@ -574,7 +570,7 @@ impl MessageBuffer {
             }
             }
         };
         };
 
 
-        self.insert_msg(msg, idx).await;
+        self.msgs.insert(idx, msg);
     }
     }
 
 
     pub(super) async fn push_privmsg(
     pub(super) async fn push_privmsg(
@@ -583,7 +579,7 @@ impl MessageBuffer {
         message_id: MessageId,
         message_id: MessageId,
         nick: String,
         nick: String,
         text: String,
         text: String,
-    ) {
+    ) -> f32 {
         let font_size = self.font_size.get();
         let font_size = self.font_size.get();
 
 
         let msg = PrivMessage::new(
         let msg = PrivMessage::new(
@@ -598,29 +594,15 @@ impl MessageBuffer {
         )
         )
         .await;
         .await;
 
 
+        let msg_height = msg.height(self.line_height.get());
+
         if self.msgs.is_empty() {
         if self.msgs.is_empty() {
             self.msgs.push(msg);
             self.msgs.push(msg);
-            return
+            return msg_height
         }
         }
 
 
-        let idx = self.msgs.len() - 1;
-        self.insert_msg(msg, idx).await;
-    }
-
-    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();
-
-        // Do we cross from a new day?
-        let prev_msg = &self.msgs[idx];
-        let prev_timest = prev_msg.timestamp();
-        let prev_is_date = prev_msg.is_date();
-        let prev_date = Local.timestamp_millis_opt(prev_timest as i64).unwrap().date_naive();
-        let curr_date = Local.timestamp_millis_opt(timest as i64).unwrap().date_naive();
-
-        self.msgs.insert(idx, msg);
+        self.msgs.push(msg);
+        msg_height
     }
     }
 
 
     /// Generate caches and return meshes
     /// Generate caches and return meshes