Procházet zdrojové kódy

wallet: chatview correct scroll clamping calcs

darkfi před 2 roky
rodič
revize
6c7e190a0e

+ 18 - 7
bin/darkwallet/insert_line.py

@@ -1,12 +1,23 @@
+#!/usr/bin/python
 from gui import *
 from gui import *
+import time
 
 
-node_id = api.lookup_node_id("/window/view/chatty")
+def send(timest, nick, msg):
+    node_id = api.lookup_node_id("/window/view/chatty")
 
 
-arg_data = bytearray()
-serial.write_u64(arg_data, 1722944340005)
-arg_data += bytes(32)
-serial.encode_str(arg_data, "nick")
-serial.encode_str(arg_data, "hello1234")
+    arg_data = bytearray()
+    serial.write_u64(arg_data, timest)
+    arg_data += bytes(32)
+    serial.encode_str(arg_data, nick)
+    serial.encode_str(arg_data, msg)
 
 
-api.call_method(node_id, "insert_line", arg_data)
+    api.call_method(node_id, "insert_line", arg_data)
 
 
+#for i in range(28):
+for i in range(27):
+    send(1722944640000 + i, "hhi12", "hello 123")
+    time.sleep(0.1)
+time.sleep(0.5)
+send(1722944641015, "john", "hpqjyzzxxdhio")
+time.sleep(1)
+send(1722944642015, "clr", "hello1234ppjjh")

+ 3 - 0
bin/darkwallet/src/app.rs

@@ -928,9 +928,11 @@ fn create_editbox(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
     node.add_property(prop).unwrap();
     node.add_property(prop).unwrap();
 
 
     let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
     let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
+    prop.set_range_f32(0., f32::MAX);
     node.add_property(prop).unwrap();
     node.add_property(prop).unwrap();
 
 
     let mut prop = Property::new("cursor_pos", PropertyType::Uint32, PropertySubType::Pixel);
     let mut prop = Property::new("cursor_pos", PropertyType::Uint32, PropertySubType::Pixel);
+    prop.set_range_u32(0, u32::MAX);
     node.add_property(prop).unwrap();
     node.add_property(prop).unwrap();
 
 
     let mut prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
     let mut prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
@@ -982,6 +984,7 @@ fn create_chatview(
 
 
     let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Null);
     let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Null);
     prop.set_ui_text("Scroll", "Scroll up from the bottom");
     prop.set_ui_text("Scroll", "Scroll up from the bottom");
+    prop.set_range_f32(0., f32::MAX);
     node.add_property(prop).unwrap();
     node.add_property(prop).unwrap();
 
 
     let prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
     let prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);

+ 20 - 11
bin/darkwallet/src/main.rs

@@ -77,6 +77,11 @@ use crate::{
     text2::TextShaper,
     text2::TextShaper,
 };
 };
 
 
+#[cfg(target_os = "android")]
+const EVGRDB_PATH: &str = "/data/data/darkfi.darkwallet/evgrdb/";
+#[cfg(target_os = "linux")]
+const EVGRDB_PATH: &str = "evgrdb";
+
 pub type ExecutorPtr = Arc<smol::Executor<'static>>;
 pub type ExecutorPtr = Arc<smol::Executor<'static>>;
 
 
 fn panic_hook(panic_info: &std::panic::PanicInfo) {
 fn panic_hook(panic_info: &std::panic::PanicInfo) {
@@ -130,7 +135,8 @@ async fn relay_darkirc_events(sg: SceneGraphPtr2, ev_sub: Subscription<event_gra
 }
 }
 
 
 async fn run_darkirc_backend(sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Result<()> {
 async fn run_darkirc_backend(sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Result<()> {
-    let sled_db = sled::open("evgrdb")?;
+    info!(target: "main", "Starting DarkIRC backend");
+    let sled_db = sled::open(EVGRDB_PATH)?;
 
 
     let mut p2p_settings: NetSettings = Default::default();
     let mut p2p_settings: NetSettings = Default::default();
     p2p_settings.app_version = semver::Version::parse("0.5.0").unwrap();
     p2p_settings.app_version = semver::Version::parse("0.5.0").unwrap();
@@ -151,7 +157,7 @@ async fn run_darkirc_backend(sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Res
 
 
     let prune_task = event_graph.prune_task.get().unwrap();
     let prune_task = event_graph.prune_task.get().unwrap();
 
 
-    info!("Registering EventGraph P2P protocol");
+    info!(target: "main", "Registering EventGraph P2P protocol");
     let event_graph_ = Arc::clone(&event_graph);
     let event_graph_ = Arc::clone(&event_graph);
     let registry = p2p.protocol_registry();
     let registry = p2p.protocol_registry();
     registry
     registry
@@ -164,16 +170,16 @@ async fn run_darkirc_backend(sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Res
     let ev_sub = event_graph.event_pub.clone().subscribe().await;
     let ev_sub = event_graph.event_pub.clone().subscribe().await;
     let ev_task = ex.spawn(relay_darkirc_events(sg, ev_sub));
     let ev_task = ex.spawn(relay_darkirc_events(sg, ev_sub));
 
 
-    info!("Starting P2P network");
+    info!(target: "main", "Starting P2P network");
     p2p.clone().start().await?;
     p2p.clone().start().await?;
 
 
-    info!("Waiting for some P2P connections...");
+    info!(target: "main", "Waiting for some P2P connections...");
     sleep(5).await;
     sleep(5).await;
 
 
     // We'll attempt to sync {sync_attempts} times
     // We'll attempt to sync {sync_attempts} times
     let sync_attempts = 4;
     let sync_attempts = 4;
     for i in 1..=sync_attempts {
     for i in 1..=sync_attempts {
-        info!("Syncing event DAG (attempt #{})", i);
+        info!(target: "main", "Syncing event DAG (attempt #{})", i);
         match event_graph.dag_sync().await {
         match event_graph.dag_sync().await {
             Ok(()) => break,
             Ok(()) => break,
             Err(e) => {
             Err(e) => {
@@ -195,19 +201,19 @@ async fn run_darkirc_backend(sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Res
     // Signal handling for graceful termination.
     // Signal handling for graceful termination.
     //let (signals_handler, signals_task) = SignalHandler::new(ex)?;
     //let (signals_handler, signals_task) = SignalHandler::new(ex)?;
     //signals_handler.wait_termination(signals_task).await?;
     //signals_handler.wait_termination(signals_task).await?;
-    info!("Caught termination signal, cleaning up and exiting...");
+    info!(target: "main", "Caught termination signal, cleaning up and exiting...");
 
 
-    info!("Stopping P2P network");
+    info!(target: "main", "Stopping P2P network");
     p2p.stop().await;
     p2p.stop().await;
 
 
-    info!("Stopping IRC server");
+    info!(target: "main", "Stopping IRC server");
     prune_task.stop().await;
     prune_task.stop().await;
 
 
-    info!("Flushing sled database...");
+    info!(target: "main", "Flushing sled database...");
     let flushed_bytes = sled_db.flush_async().await?;
     let flushed_bytes = sled_db.flush_async().await?;
-    info!("Flushed {} bytes", flushed_bytes);
+    info!(target: "main", "Flushed {} bytes", flushed_bytes);
 
 
-    info!("Shut down successfully");
+    info!(target: "main", "Shut down successfully");
 
 
     Ok(())
     Ok(())
 }
 }
@@ -299,6 +305,7 @@ fn main() {
     let app_cv2 = app_cv.clone();
     let app_cv2 = app_cv.clone();
     let app_task = ex.spawn(async move {
     let app_task = ex.spawn(async move {
         app2.start().await;
         app2.start().await;
+        debug!(target: "main", "App started - sending wakeup notification to the backend");
         app_cv2.notify();
         app_cv2.notify();
     });
     });
     async_runtime.push_task(app_task);
     async_runtime.push_task(app_task);
@@ -353,6 +360,7 @@ fn main() {
     });
     });
     async_runtime.push_task(ev_relay_task);
     async_runtime.push_task(ev_relay_task);
 
 
+    /*
     let ex2 = ex.clone();
     let ex2 = ex.clone();
     let darkirc_task = ex.spawn(async move {
     let darkirc_task = ex.spawn(async move {
         // Wait for app to finish starting
         // Wait for app to finish starting
@@ -363,6 +371,7 @@ fn main() {
         }
         }
     });
     });
     async_runtime.push_task(darkirc_task);
     async_runtime.push_task(darkirc_task);
+    */
 
 
     //let stage = gfx2::Stage::new(method_rep, event_pub);
     //let stage = gfx2::Stage::new(method_rep, event_pub);
     gfx2::run_gui(app, async_runtime, method_rep, event_pub);
     gfx2::run_gui(app, async_runtime, method_rep, event_pub);

+ 42 - 25
bin/darkwallet/src/ui/chatview.rs

@@ -762,6 +762,27 @@ impl ChatView {
         self.line_height.get() - self.baseline.get()
         self.line_height.get() - self.baseline.get()
     }
     }
 
 
+    fn clamp_scroll(scroll: &mut f32, total_height: f32, rect_h: f32) -> bool {
+        assert!(*scroll >= 0.);
+
+        // For when we resize the window and scroll is no longer valid
+        let max_allowed_scroll = if total_height > rect_h { total_height - rect_h } else { 0. };
+        debug!(
+            target: "ui::chatview",
+            "max_allowed_scroll = {max_allowed_scroll} = total_height={total_height} - rect.h={}",
+            rect_h
+        );
+
+        if *scroll > max_allowed_scroll {
+            *scroll = max_allowed_scroll;
+            assert!(*scroll >= 0.);
+            return true
+        }
+
+        // Unchanged
+        false
+    }
+
     /// Beware of this method. Here be dragons.
     /// Beware of this method. Here be dragons.
     /// Possibly racy so we limit it just to mouse stuff (for now).
     /// Possibly racy so we limit it just to mouse stuff (for now).
     fn cached_rect(&self) -> Option<Rectangle> {
     fn cached_rect(&self) -> Option<Rectangle> {
@@ -915,6 +936,7 @@ impl ChatView {
     async fn draw_cached(&self, mut rect: Rectangle, scroll: &mut f32) -> Vec<DrawInstruction> {
     async fn draw_cached(&self, mut rect: Rectangle, scroll: &mut f32) -> Vec<DrawInstruction> {
         let mut instrs = vec![];
         let mut instrs = vec![];
 
 
+        // When scrolling it can go negative so clamp it here
         if *scroll < 0. {
         if *scroll < 0. {
             *scroll = 0.;
             *scroll = 0.;
         }
         }
@@ -922,23 +944,28 @@ impl ChatView {
         // Make sure we have enough pages loaded.
         // Make sure we have enough pages loaded.
         // If there's no more to load then adjust the scroll.
         // If there's no more to load then adjust the scroll.
         let mut pages = self.pages2.lock().await.clone();
         let mut pages = self.pages2.lock().await.clone();
-        while self.get_total_height(&rect, &pages).await < *scroll + rect.h {
+        let mut total_height = self.get_total_height(&rect, &pages).await;
+        while total_height < *scroll + rect.h {
             debug!(target: "ui::chatview", "draw_cached() loading more pages");
             debug!(target: "ui::chatview", "draw_cached() loading more pages");
 
 
-            if self.preload_pages().await == 0 {
-                // No more pages available to load
-                pages = self.pages2.lock().await.clone();
-                let new_height = self.get_total_height(&rect, &pages).await;
-                if new_height > rect.h {
-                    *scroll = new_height - rect.h;
-                } else {
-                    *scroll = 0.;
-                }
+            // No more pages available to load
+            let n_loaded_pages = self.preload_pages().await;
+
+            // We need this value after so first update it
+            total_height = self.get_total_height(&rect, &pages).await;
+
+            if n_loaded_pages == 0 {
                 break
                 break
             }
             }
+
+            pages = self.pages2.lock().await.clone();
         }
         }
 
 
-        let descent = self.descent();
+        // 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 };
+
+        Self::clamp_scroll(scroll, total_height, rect.h);
+
         let mut current_height = 0.;
         let mut current_height = 0.;
         for page in pages {
         for page in pages {
             if current_height > *scroll + rect.h {
             if current_height > *scroll + rect.h {
@@ -946,14 +973,14 @@ impl ChatView {
             }
             }
 
 
             let mesh_inf = page.mesh_inf.lock().unwrap().clone();
             let mesh_inf = page.mesh_inf.lock().unwrap().clone();
-            let mesh_inf = mesh_inf.expect("preload above should've regen_mesh()");
+            let mesh_inf = mesh_inf.expect("preload above should regen mesh");
 
 
             // Apply scroll and scissor
             // Apply scroll and scissor
             // We use the scissor for scrolling
             // We use the scissor for scrolling
             // Because we use the scissor, our actual rect is now rect instead of parent_rect
             // Because we use the scissor, our actual rect is now rect instead of parent_rect
             let off_x = 0.;
             let off_x = 0.;
             // This calc decides whether scroll is in terms of pages or pixels
             // This calc decides whether scroll is in terms of pages or pixels
-            let off_y = (*scroll - current_height + rect.h) / rect.h;
+            let off_y = (*scroll + start_pos - current_height) / rect.h;
             let scale_x = 1. / rect.w;
             let scale_x = 1. / rect.w;
             let scale_y = 1. / rect.h;
             let scale_y = 1. / rect.h;
             let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
             let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
@@ -1029,7 +1056,6 @@ impl ChatView {
         let font_size = self.font_size.get();
         let font_size = self.font_size.get();
         let line_height = self.line_height.get();
         let line_height = self.line_height.get();
         let baseline = self.baseline.get();
         let baseline = self.baseline.get();
-        let descent = self.descent();
         let debug_render = self.debug.get();
         let debug_render = self.debug.get();
 
 
         let mut instrs = vec![];
         let mut instrs = vec![];
@@ -1070,22 +1096,13 @@ impl ChatView {
             mesh_infs.push(mesh_inf);
             mesh_infs.push(mesh_inf);
         }
         }
 
 
-        let total_height = current_height + descent;
+        let total_height = current_height;
 
 
         // 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 scroll = self.scroll.get();
         let mut scroll = self.scroll.get();
-        assert!(scroll >= 0.);
-        // For when we resize the window and scroll is no longer valid
-        let max_allowed_scroll = if total_height > rect.h { total_height - rect.h } else { 0. };
-        debug!(
-            "max_allowed_scroll = {max_allowed_scroll} = total_height={total_height} - rect.h={}",
-            rect.h
-        );
-        if scroll > max_allowed_scroll {
-            scroll = max_allowed_scroll;
-            assert!(scroll >= 0.);
+        if Self::clamp_scroll(&mut scroll, total_height, rect.h) {
             self.scroll.set(scroll);
             self.scroll.set(scroll);
         }
         }