Browse Source

app: add down arrow to chat when scrolling up to jump to the bottom

x 1 day ago
parent
commit
e79b899de4

+ 68 - 0
bin/app/src/app/schema/chat.rs

@@ -673,6 +673,74 @@ pub async fn make(
     });
     });
     layer_node.push_task(listen_file_download);
     layer_node.push_task(listen_file_download);
 
 
+    // Root content layer
+    let down_layer = create_layer("chat_down_arrow");
+    let prop = down_layer.get_property("rect").unwrap();
+    let code = cc.compile("w - 120").unwrap();
+    prop.set_expr(atom, Role::App, 0, code).unwrap();
+    let code = cc.compile("h / 2").unwrap();
+    prop.set_expr(atom, Role::App, 1, code).unwrap();
+    prop.set_f32(atom, Role::App, 2, 100.).unwrap();
+    prop.set_f32(atom, Role::App, 3, 100.).unwrap();
+    down_layer.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
+    down_layer.set_property_u32(atom, Role::App, "z_index", 3).unwrap();
+    let down_layer = down_layer.setup(|me| Layer::new(me, renderer.clone(), redraw.clone())).await;
+    layer_node.link(down_layer.clone());
+
+    let down_layer_is_visible =
+        PropertyBool::wrap(&down_layer, Role::App, "is_visible", 0).unwrap();
+    let chatview_scroll = PropertyFloat32::wrap(&chatview_node, Role::App, "scroll", 0).unwrap();
+    let chatview_scroll_sub = chatview_scroll.prop().subscribe_modify();
+    let redraw2 = redraw.clone();
+    let chatview_scroll2 = chatview_scroll.clone();
+    let monitor_scroll_task = ex.spawn(async move {
+        while let Ok(_) = chatview_scroll_sub.receive().await {
+            let scroll = chatview_scroll2.get();
+            let atom = &mut redraw2.make_guard(gfxtag!("down arrow visibility change"));
+            if scroll > 0. {
+                down_layer_is_visible.set(atom, true);
+            } else {
+                down_layer_is_visible.set(atom, false);
+            }
+        }
+    });
+    down_layer.push_task(monitor_scroll_task);
+
+    // Placeholder single-color background filling the whole overlay
+    let node = create_vector_art("downbg");
+    let prop = node.get_property("rect").unwrap();
+    prop.set_f32(atom, Role::App, 0, 50.).unwrap();
+    prop.set_f32(atom, Role::App, 1, 50.).unwrap();
+    prop.set_f32(atom, Role::App, 2, 100.).unwrap();
+    prop.set_f32(atom, Role::App, 3, 100.).unwrap();
+    node.set_property_bool(atom, Role::App, "is_visible", true).unwrap();
+    node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+    let mut shape = shape::create_down_bgtab(rgba!(0x003232ff), rgba!(0x294f60ff), 0.1).scaled(50.);
+    shape.join(shape::create_down_arrow(rgba!(0x00f0ffff), 1.));
+    let node = node.setup(|me| VectorArt::new(me, shape, renderer.clone(), redraw.clone())).await;
+    down_layer.link(node);
+
+    // Create the p2p toggle button
+    let node = create_button("scroll_bottom_btn");
+    node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
+    let prop = node.get_property("rect").unwrap();
+    prop.set_f32(atom, Role::App, 0, 0.).unwrap();
+    prop.set_f32(atom, Role::App, 1, 0.).unwrap();
+    prop.set_f32(atom, Role::App, 2, 100.).unwrap();
+    prop.set_f32(atom, Role::App, 3, 100.).unwrap();
+    let (slot, recvr) = Slot::new("scroll_bottom");
+    node.register("click", slot).unwrap();
+    let redraw2 = redraw.clone();
+    let listen_click = ex.spawn(async move {
+        while let Ok(_) = recvr.recv().await {
+            let atom = &mut redraw2.make_guard(gfxtag!("down arrow clicked"));
+            chatview_scroll.set(atom, 0.);
+        }
+    });
+    down_layer.push_task(listen_click);
+    let node = node.setup(|me| Button::new(me, renderer.clone(), redraw.clone())).await;
+    down_layer.link(node);
+
     // Selection overlay: shown only while the chatview has selected lines. It's
     // Selection overlay: shown only while the chatview has selected lines. It's
     // a child of `content` (not the chat layer) with z_index and priority above
     // a child of `content` (not the chat layer) with z_index and priority above
     // the netstatus layer, so its single background box draws over the netstatus
     // the netstatus layer, so its single background box draws over the netstatus

+ 37 - 0
bin/app/src/shape/down_arrow.rs

@@ -0,0 +1,37 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2026 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use crate::{
+    gfx::Point,
+    mesh::Color,
+    ui::{ShapeVertex, VectorShape},
+};
+
+pub fn create_down_arrow(color: Color, thickness: f32) -> VectorShape {
+    let verts = vec![
+        Point::new(-0., -22.5),
+        Point::new(-0.0, 12.),
+        Point::new(-15., -7.5),
+        Point::new(15., -7.5),
+    ];
+    let mut shape = VectorShape::new();
+    shape.add_line(verts[0], verts[1], thickness, color);
+    shape.add_line(verts[1], verts[2], thickness, color);
+    shape.add_line(verts[1], verts[3], thickness, color);
+    shape
+}

+ 50 - 0
bin/app/src/shape/down_bgtab.rs

@@ -0,0 +1,50 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2026 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use crate::{
+    gfx::Point,
+    mesh::Color,
+    ui::{ShapeVertex, VectorShape},
+};
+
+pub fn create_down_bgtab(color1: Color, color2: Color, border_thickness: f32) -> VectorShape {
+    let verts = vec![
+        Point::new(-0.926801, -0.067501),
+        Point::new(0.926801, -0.067501),
+        Point::new(-0.56229, -0.885142),
+        Point::new(0.56229, -0.885142),
+        Point::new(-0.912444, 0.0406),
+        Point::new(0.912444, 0.0406),
+        Point::new(-0.089009, 0.868252),
+        Point::new(0.082253, 0.868252),
+    ];
+    let mut shape = VectorShape::new();
+    shape.add_line(verts[0], verts[2], border_thickness, color2);
+    shape.add_line(verts[2], verts[3], border_thickness, color2);
+    shape.add_line(verts[3], verts[1], border_thickness, color2);
+    shape.add_line(verts[1], verts[5], border_thickness, color2);
+    shape.add_line(verts[5], verts[7], border_thickness, color2);
+    shape.add_line(verts[7], verts[6], border_thickness, color2);
+    shape.add_line(verts[6], verts[4], border_thickness, color2);
+    shape.add_line(verts[4], verts[0], border_thickness, color2);
+    shape.join(VectorShape {
+        verts: verts.iter().map(|v| ShapeVertex::from_xy(v.x, v.y, color1)).collect(),
+        indices: vec![1, 2, 0, 0, 5, 1, 4, 7, 5, 1, 3, 2, 0, 4, 5, 4, 6, 7],
+    });
+    shape
+}

+ 5 - 0
bin/app/src/shape/mod.rs

@@ -61,6 +61,11 @@ pub use blockchain_netlogo4::create_blockchain_netlogo4;
 mod x;
 mod x;
 pub use x::create_x;
 pub use x::create_x;
 
 
+mod down_bgtab;
+pub use down_bgtab::create_down_bgtab;
+mod down_arrow;
+pub use down_arrow::create_down_arrow;
+
 //mod settings;
 //mod settings;
 //pub use settings::{create_right_border, create_settings};
 //pub use settings::{create_right_border, create_settings};