Browse Source

wallet: design tweaks and minor fixes.

darkfi 1 year ago
parent
commit
ae66029902

+ 6 - 0
bin/darkwallet/src/app/node.rs

@@ -283,6 +283,12 @@ pub fn create_chatedit(name: &str) -> SceneNode {
     prop.set_defaults_f32(vec![4.]).unwrap();
     node.add_property(prop).unwrap();
 
+    let mut prop = Property::new("padding", PropertyType::Float32, PropertySubType::Pixel);
+    prop.set_ui_text("Inner Padding", "Top and bottom padding inside");
+    prop.set_range_f32(0., f32::MAX);
+    prop.set_array_len(2);
+    node.add_property(prop).unwrap();
+
     let mut prop = Property::new("cursor_pos", PropertyType::Uint32, PropertySubType::Pixel);
     prop.set_range_u32(0, u32::MAX);
     node.add_property(prop).unwrap();

+ 40 - 7
bin/darkwallet/src/app/schema/chat.rs

@@ -68,6 +68,7 @@ mod android_ui_consts {
     pub const EMOJI_BG_W: f32 = 120.;
     pub const EMOJI_SCALE: f32 = 40.;
     pub const EMOJI_NEG_Y: f32 = 85.;
+    pub const EMOJIBTN_BOX: [f32; 4] = [20., 118., 80., 75.];
     pub const SENDARROW_NEG_X: f32 = 50.;
     pub const SENDARROW_NEG_Y: f32 = 80.;
     pub const SENDBTN_BOX: [f32; 4] = [86., 120., 80., 70.];
@@ -126,6 +127,7 @@ mod ui_consts {
     pub const EMOJI_BG_W: f32 = 80.;
     pub const EMOJI_SCALE: f32 = 20.;
     pub const EMOJI_NEG_Y: f32 = 34.;
+    pub const EMOJIBTN_BOX: [f32; 4] = [16., 50., 44., 36.];
     pub const SENDARROW_NEG_X: f32 = 50.;
     pub const SENDARROW_NEG_Y: f32 = 32.;
     pub const SENDBTN_BOX: [f32; 4] = [72., 50., 45., 34.];
@@ -152,6 +154,7 @@ pub async fn make(app: &App, window: SceneNodePtr, channel: &str, db: &sled::Db)
     cc.add_const_f32("SENDARROW_NEG_X", SENDARROW_NEG_X);
     cc.add_const_f32("SENDARROW_NEG_Y", SENDARROW_NEG_Y);
     cc.add_const_f32("EMOJI_NEG_Y", EMOJI_NEG_Y);
+    cc.add_const_f32("EMOJIBTN_BOX_1", EMOJIBTN_BOX[1]);
     cc.add_const_f32("SENDBTN_BOX_0", SENDBTN_BOX[0]);
     cc.add_const_f32("SENDBTN_BOX_1", SENDBTN_BOX[1]);
 
@@ -507,6 +510,10 @@ pub async fn make(app: &App, window: SceneNodePtr, channel: &str, db: &sled::Db)
     chatview_rect_prop.add_depend(&prop, 3, "editz_h");
     editbox_bg_rect_prop.add_depend(&prop, 3, "editz_h");
 
+    let prop = node.get_property("padding").unwrap();
+    prop.set_f32(Role::App, 0, 0.).unwrap();
+    prop.set_f32(Role::App, 1, TEXTBAR_BASELINE / 2.).unwrap();
+
     node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
     node.set_property_f32(Role::App, "linespacing", CHATEDIT_LINESPACING).unwrap();
     node.set_property_f32(Role::App, "descent", TEXT_DESCENT).unwrap();
@@ -613,16 +620,42 @@ pub async fn make(app: &App, window: SceneNodePtr, channel: &str, db: &sled::Db)
     let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
     layer_node.clone().link(node);
 
-    /*
+    // Create the emoji button
+    let node = create_button("emoji_btn");
+    node.set_property_bool(Role::App, "is_active", true).unwrap();
+    let prop = node.get_property("rect").unwrap();
+    prop.set_f32(Role::App, 0, EMOJIBTN_BOX[0]).unwrap();
+    let code = cc.compile("h - EMOJIBTN_BOX_1").unwrap();
+    prop.set_expr(Role::App, 1, code).unwrap();
+    prop.set_f32(Role::App, 2, EMOJIBTN_BOX[2]).unwrap();
+    prop.set_f32(Role::App, 3, EMOJIBTN_BOX[3]).unwrap();
+
+    let (slot, recvr) = Slot::new("emoji_clicked");
+    node.register("click", slot).unwrap();
+    let listen_click = app.ex.spawn(async move {
+        while let Ok(_) = recvr.recv().await {
+            info!(target: "app::chat", "clicked emoji");
+        }
+    });
+    app.tasks.lock().unwrap().push(listen_click);
+
+    let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
+    layer_node.clone().link(node);
+
     // Create debug box
-    let node = create_vector_art("debugtool");
+    /*
+    let mut node = create_vector_art("debugtool");
+    let mut prop = Property::new("hoff", PropertyType::Float32, PropertySubType::Pixel);
+    node.add_property(prop).unwrap();
+    node.set_property_f32(Role::App, "hoff", 40.).unwrap();
     let prop = node.get_property("rect").unwrap();
-    let code = cc.compile("w - 86").unwrap();
-    prop.set_expr(Role::App, 0, code).unwrap();
-    let code = cc.compile("h - 120").unwrap();
+    prop.set_f32(Role::App, 0, EMOJIBTN_BOX[0]).unwrap();
+    let code = cc.compile("h - EMOJIBTN_BOX_1").unwrap();
     prop.set_expr(Role::App, 1, code).unwrap();
-    prop.set_f32(Role::App, 2, 80.).unwrap();
-    prop.set_f32(Role::App, 3, 70.).unwrap();
+    prop.set_f32(Role::App, 2, EMOJIBTN_BOX[2]).unwrap();
+    prop.set_f32(Role::App, 3, EMOJIBTN_BOX[3]).unwrap();
+    let hoff_prop = node.get_property("hoff").unwrap();
+    prop.add_depend(&hoff_prop, 0, "hoff");
     node.set_property_u32(Role::App, "z_index", 6).unwrap();
     let mut shape = VectorShape::new();
     shape.add_outline(

+ 5 - 0
bin/darkwallet/src/app/schema/mod.rs

@@ -155,4 +155,9 @@ pub async fn make(app: &App, window: SceneNodePtr) {
         chat::make(app, window.clone(), channel, &db).await;
     }
     menu::make(app, window.clone()).await;
+
+    let chatview_node = app.sg_root.clone().lookup_node("/window/dev_chat_layer").unwrap();
+    chatview_node.set_property_bool(Role::App, "is_visible", true).unwrap();
+    let menu_node = app.sg_root.clone().lookup_node("/window/menu_layer").unwrap();
+    menu_node.set_property_bool(Role::App, "is_visible", false).unwrap();
 }

+ 23 - 13
bin/darkwallet/src/ui/chatedit.rs

@@ -113,6 +113,7 @@ impl TextWrap {
     }
     fn get_render(&mut self) -> &RenderedEditable {
         if self.rendered.is_none() {
+            //debug!(target: "ui::chatedit::text_wrap", "Regenerating render cache");
             self.rendered = Some(self.editable.render());
         }
         self.rendered.as_ref().unwrap()
@@ -159,7 +160,7 @@ impl TextWrap {
         let cidx = rendered.pos_to_idx(cursor_pos);
         self.editable.set_cursor_idx(cidx);
 
-        debug!(target: "ui::chatedit::text_wrap", "set_cursor_with_point() -> {cursor_pos} / {glyphs_len}");
+        //debug!(target: "ui::chatedit::text_wrap", "set_cursor_with_point() -> {cursor_pos} / {glyphs_len}");
         cursor_pos
     }
 
@@ -462,6 +463,7 @@ pub struct ChatEdit {
     descent: PropertyFloat32,
     scroll: PropertyFloat32,
     scroll_speed: PropertyFloat32,
+    padding: PropertyPtr,
     cursor_pos: PropertyUint32,
     font_size: PropertyFloat32,
     text: PropertyStr,
@@ -520,6 +522,7 @@ impl ChatEdit {
         let scroll = PropertyFloat32::wrap(node_ref, Role::Internal, "scroll", 0).unwrap();
         let scroll_speed =
             PropertyFloat32::wrap(node_ref, Role::Internal, "scroll_speed", 0).unwrap();
+        let padding = node_ref.get_property("padding").unwrap();
         let cursor_pos = PropertyUint32::wrap(node_ref, Role::Internal, "cursor_pos", 0).unwrap();
         let font_size = PropertyFloat32::wrap(node_ref, Role::Internal, "font_size", 0).unwrap();
         let text = PropertyStr::wrap(node_ref, Role::Internal, "text", 0).unwrap();
@@ -575,6 +578,7 @@ impl ChatEdit {
             descent,
             scroll: scroll.clone(),
             scroll_speed,
+            padding,
             cursor_pos,
             font_size: font_size.clone(),
             text,
@@ -616,10 +620,10 @@ impl ChatEdit {
             is_mouse_hover: AtomicBool::new(false),
         });
 
-        //self_.text_wrap.lock().editable.set_text(
-        //    "".to_string(),
-        //    "A berry is a small, pulpy, and often edible fruit. Typically, berries are juicy, rounded, brightly colored, sweet, sour or tart, and do not have a stone or pit, although many pips or seeds may be present. Common examples of berries in the culinary sense are strawberries, raspberries, blueberries, blackberries, white currants, blackcurrants, and redcurrants. In Britain, soft fruit is a horticultural term for such fruits.".to_string()
-        //);
+        self_.text_wrap.lock().editable.set_text(
+            "".to_string(),
+            "A berry is a small, pulpy, and often edible fruit. Typically, berries are juicy, rounded, brightly colored, sweet, sour or tart, and do not have a stone or pit, although many pips or seeds may be present. Common examples of berries in the culinary sense are strawberries, raspberries, blueberries, blackberries, white currants, blackcurrants, and redcurrants. In Britain, soft fruit is a horticultural term for such fruits.".to_string()
+        );
         //self_
         //    .text_wrap
         //    .lock()
@@ -672,6 +676,10 @@ impl ChatEdit {
 
         let (atlas, wrapped_lines, selections) = {
             let mut text_wrap = self.text_wrap.lock();
+            // Must happen after rect eval, which is inside regen_text_mesh
+            // Maybe we should take the eval out of here.
+            self.clamp_scroll(&mut text_wrap);
+
             let rendered_glyphs = &text_wrap.get_render().glyphs;
             let atlas = text::make_texture_atlas(&self.render_api, rendered_glyphs);
             let wrapped_lines = text_wrap.wrap(width);
@@ -1494,20 +1502,22 @@ impl ChatEdit {
         let width = self.wrap_width();
         let wrapped_lines = text_wrap.wrap(width);
         let rect_h = self.rect.get().h;
-        let max_scroll = wrapped_lines.height() - rect_h;
+        let mut max_scroll = wrapped_lines.height() - rect_h;
+        // Top padding
+        max_scroll += self.padding.get_f32(0).unwrap();
+        // Bottom padding
+        max_scroll += self.padding.get_f32(1).unwrap();
         max_scroll.clamp(0., f32::MAX)
     }
 
     /// When we resize the screen, the rect changes so we may need to alter the scroll.
     /// Or if we delete text.
     fn clamp_scroll(&self, text_wrap: &mut TextWrap) {
-        let width = self.wrap_width();
-        let wrapped_lines = text_wrap.wrap(width);
-        let max_scroll = wrapped_lines.height();
-
+        let max_scroll = self.max_scroll(text_wrap);
         let mut scroll = self.scroll.get();
-        scroll = scroll.clamp(0., wrapped_lines.height());
-        self.scroll.set(scroll);
+        if scroll > max_scroll {
+            self.scroll.set(max_scroll);
+        }
     }
 
     fn pause_blinking(&self) {
@@ -1643,6 +1653,7 @@ impl UIObject for ChatEdit {
         on_modify.when_change(self.select_ascent.prop(), redraw);
         on_modify.when_change(self.select_descent.prop(), redraw);
         on_modify.when_change(self.handle_descent.prop(), redraw);
+        on_modify.when_change(self.padding.clone(), redraw);
         // The commented properties are modified on input events
         // So then redraw() will get repeatedly triggered when these properties
         // are changed. We should find a solution. For now the hooks are disabled.
@@ -1698,7 +1709,6 @@ impl UIObject for ChatEdit {
         debug!(target: "ui::chatedit", "EditBox::draw()");
         *self.parent_rect.lock() = Some(parent_rect);
 
-        //self.clamp_scroll();
         self.make_draw_calls()
     }
 

+ 4 - 1
bin/darkwallet/src/ui/vector_art/mod.rs

@@ -100,7 +100,10 @@ impl VectorArt {
 
     async fn get_draw_calls(&self, parent_rect: Rectangle) -> Option<DrawUpdate> {
         //debug!(target: "ui::vector_art", "VectorArt::draw_cached()");
-        self.rect.eval(&parent_rect).ok()?;
+        if let Err(e) = self.rect.eval(&parent_rect) {
+            warn!(target: "ui::vector_art", "Rect eval failure: {e}");
+            return None
+        }
         let rect = self.rect.get();
         let verts = self.shape.eval(rect.w, rect.h).expect("bad shape");