Просмотр исходного кода

app/chatview: fix crash when selecting lines

darkfi 5 дней назад
Родитель
Сommit
23cf2d82e1
3 измененных файлов с 40 добавлено и 22 удалено
  1. 3 3
      bin/app/Makefile
  2. 13 10
      bin/app/src/ui/chatview/mod.rs
  3. 24 9
      bin/app/src/ui/chatview/page.rs

+ 3 - 3
bin/app/Makefile

@@ -100,11 +100,11 @@ assets/forest_720x1280.mp4:
 
 compile-dev: $(SRC) fonts assets/forest_1920x1080.ivf
 	$(CARGO) lbuild --no-default-features $(DEV_FEATURES)
+	-mv target/debug/darkfi-app .
 
 dev:
 	$(MAKE) compile-dev
-	-mv target/debug/darkfi-app .
-	./darkfi-app
+	./darkfi-app 2>&1 | tee app.log
 
 # Users should use the android-release and android-debug targets instead.
 apk:
@@ -114,9 +114,9 @@ apk:
 
 compile-apk: $(SRC) fonts assets/forest_720x1280.mp4
 	cargo quad-apk build --no-default-features $(DEV_FEATURES)
+	-mv $(DEBUG_APK) .
 
 install-apk:
-	-mv $(DEBUG_APK) .
 	-adb $(ADB_DEVICE_INST) uninstall darkfi.darkfi_app
 	adb $(ADB_DEVICE_INST) install -r darkfi-app.apk
 

+ 13 - 10
bin/app/src/ui/chatview/mod.rs

@@ -586,7 +586,7 @@ impl ChatView {
 
         let mut msgbuf = self.msgbuf.lock().await;
         let had = msgbuf.has_selection();
-        msgbuf.select_line(y).await;
+        msgbuf.select_line(&rect, y).await;
         let has = msgbuf.has_selection();
         drop(msgbuf);
 
@@ -604,7 +604,7 @@ impl ChatView {
 
         let mut msgbuf = self.msgbuf.lock().await;
         let had = msgbuf.has_selection();
-        msgbuf.deselect_line(y).await;
+        msgbuf.deselect_line(&rect, y).await;
         let has = msgbuf.has_selection();
         drop(msgbuf);
 
@@ -614,9 +614,10 @@ impl ChatView {
 
     /// Query whether the line under screen y is currently selected.
     async fn is_line_selected(&self, screen_y: f32) -> bool {
+        let rect = self.rect.get();
         let y = self.to_msgbuf_pos(Point::new(0., screen_y)).y;
         let mut msgbuf = self.msgbuf.lock().await;
-        msgbuf.is_line_selected(y).await
+        msgbuf.is_line_selected(&rect, y).await
     }
 
     /// Emit `select_changed(true/false)` whenever the presence of any selected
@@ -1100,7 +1101,7 @@ impl ChatView {
         // URL under the finger takes priority: copy it, don't select.
         let msgbuf_pos = self.to_msgbuf_pos(start_pos);
         let mut msgbuf = self.msgbuf.lock().await;
-        let on_url = msgbuf.url_at(msgbuf_pos.x, msgbuf_pos.y).await;
+        let on_url = msgbuf.url_at(&rect, msgbuf_pos.x, msgbuf_pos.y).await;
         drop(msgbuf);
 
         if let Some(url) = on_url {
@@ -1289,7 +1290,7 @@ impl UIObject for ChatView {
         if rect.contains(mouse_pos) {
             let mut msgbuf = self.msgbuf.lock().await;
             let msgbuf_pos = self.to_msgbuf_pos(mouse_pos);
-            if let Some((msg, msg_top)) = msgbuf.get_line(msgbuf_pos.y).await {
+            if let Some((msg, msg_top)) = msgbuf.get_line(&rect, msgbuf_pos.y).await {
                 if msg
                     .handle_mouse_btn_down(btn, Point::new(msgbuf_pos.x, msg_top - msgbuf_pos.y))
                     .await
@@ -1303,7 +1304,7 @@ impl UIObject for ChatView {
         if btn == MouseButton::Right && rect.contains(mouse_pos) {
             let msgbuf_pos = self.to_msgbuf_pos(mouse_pos);
             let mut msgbuf = self.msgbuf.lock().await;
-            if let Some(url) = msgbuf.url_at(msgbuf_pos.x, msgbuf_pos.y).await {
+            if let Some(url) = msgbuf.url_at(&rect, msgbuf_pos.x, msgbuf_pos.y).await {
                 drop(msgbuf);
                 self.show_toast(&url, mouse_pos - rect.pos()).await;
                 return true
@@ -1315,7 +1316,7 @@ impl UIObject for ChatView {
         if btn == MouseButton::Left && rect.contains(mouse_pos) {
             let msgbuf_pos = self.to_msgbuf_pos(mouse_pos);
             let mut msgbuf = self.msgbuf.lock().await;
-            if msgbuf.url_at(msgbuf_pos.x, msgbuf_pos.y).await.is_some() {
+            if msgbuf.url_at(&rect, msgbuf_pos.x, msgbuf_pos.y).await.is_some() {
                 return true
             }
         }
@@ -1349,7 +1350,7 @@ impl UIObject for ChatView {
         if rect.contains(mouse_pos) {
             let mut msgbuf = self.msgbuf.lock().await;
             let msgbuf_pos = self.to_msgbuf_pos(mouse_pos);
-            if let Some((msg, msg_top)) = msgbuf.get_line(msgbuf_pos.y).await {
+            if let Some((msg, msg_top)) = msgbuf.get_line(&rect, msgbuf_pos.y).await {
                 if msg
                     .handle_mouse_btn_up(btn, Point::new(msgbuf_pos.x, msg_top - msgbuf_pos.y))
                     .await
@@ -1412,7 +1413,7 @@ impl UIObject for ChatView {
 
         let mut msgbuf = self.msgbuf.lock().await;
         let msgbuf_pos = self.to_msgbuf_pos(mouse_pos);
-        if let Some((msg, msg_top)) = msgbuf.get_line(msgbuf_pos.y).await {
+        if let Some((msg, msg_top)) = msgbuf.get_line(&rect, msgbuf_pos.y).await {
             msg.handle_mouse_move(Point::new(msgbuf_pos.x, msg_top - msgbuf_pos.y)).await;
         }
         false
@@ -1542,7 +1543,9 @@ impl UIObject for ChatView {
                     let mut msgbuf = self.msgbuf.lock().await;
                     let msgbuf_pos = self.to_msgbuf_pos(touch_pos);
                     let mut is_handled = false;
-                    if let Some((msg, msg_top)) = msgbuf.get_line(msgbuf_pos.y).await {
+                    if let Some((msg, msg_top)) =
+                        msgbuf.get_line(&self.rect.get(), msgbuf_pos.y).await
+                    {
                         is_handled = msg
                             .handle_touch(
                                 TouchPhase::Ended,

+ 24 - 9
bin/app/src/ui/chatview/page.rs

@@ -1506,15 +1506,30 @@ impl MessageBuffer {
         colors
     }
 
-    pub async fn get_line(&mut self, y: f32) -> Option<(&mut Message, f32)> {
+    pub async fn get_line(&mut self, rect: &Rectangle, y: f32) -> Option<(&mut Message, f32)> {
         let line_height = self.line_height.get();
         let msg_spacing = self.msg_spacing.get();
+        let timestamp_width = self.timestamp_width.get();
+        let text_color = self.text_color.get();
+        let url_text_color = self.url_text_color.get();
+        let nick_colors = self.read_nick_colors();
 
         let msgs = self.msgs_with_date();
         let mut msgs = pin!(msgs);
 
         let mut current_pos = 0.;
         while let Some(msg) = msgs.next().await {
+            // Messages can have their layout cache cleared at any time
+            // (e.g. by select/deselect), so make sure it exists before
+            // measuring, same as in calc_total_height().
+            msg.cache_txt_layout(
+                rect,
+                line_height,
+                timestamp_width,
+                &nick_colors,
+                text_color,
+                url_text_color,
+            );
             let mesh_height = msg.height(line_height);
             let msg_bottom = current_pos;
             let msg_top = current_pos + mesh_height + msg_spacing;
@@ -1530,13 +1545,13 @@ impl MessageBuffer {
         None
     }
 
-    pub async fn url_at(&mut self, x: f32, y: f32) -> Option<String> {
-        let (msg, msg_top) = self.get_line(y).await?;
+    pub async fn url_at(&mut self, rect: &Rectangle, x: f32, y: f32) -> Option<String> {
+        let (msg, msg_top) = self.get_line(rect, y).await?;
         msg.url_hit(Point::new(x, msg_top - y))
     }
 
-    pub async fn select_line(&mut self, y: f32) {
-        if let Some((msg, _)) = self.get_line(y).await {
+    pub async fn select_line(&mut self, rect: &Rectangle, y: f32) {
+        if let Some((msg, _)) = self.get_line(rect, y).await {
             // Do nothing
             if msg.is_date() {
                 return
@@ -1548,8 +1563,8 @@ impl MessageBuffer {
         }
     }
 
-    pub async fn deselect_line(&mut self, y: f32) {
-        if let Some((msg, _)) = self.get_line(y).await {
+    pub async fn deselect_line(&mut self, rect: &Rectangle, y: f32) {
+        if let Some((msg, _)) = self.get_line(rect, y).await {
             if msg.is_date() {
                 return
             }
@@ -1560,8 +1575,8 @@ impl MessageBuffer {
         }
     }
 
-    pub async fn is_line_selected(&mut self, y: f32) -> bool {
-        if let Some((msg, _)) = self.get_line(y).await {
+    pub async fn is_line_selected(&mut self, rect: &Rectangle, y: f32) -> bool {
+        if let Some((msg, _)) = self.get_line(rect, y).await {
             if msg.is_date() {
                 return false
             }