Skip to content

Commit

Permalink
wallet: make paste popup work properly by hiding itself whenever chat…
Browse files Browse the repository at this point in the history
…edit changes
  • Loading branch information
darkfi committed Jan 11, 2025
1 parent 13597c5 commit f0a2ce1
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 49 deletions.
2 changes: 2 additions & 0 deletions bin/darkwallet/src/app/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ pub fn create_chatedit(name: &str) -> SceneNode {
node.add_property(prop).unwrap();

let mut prop = Property::new("cursor_pos", PropertyType::Uint32, PropertySubType::Pixel);
prop.set_ui_text("Cursor Pos", "Cursor position within the text");
prop.set_range_u32(0, u32::MAX);
node.add_property(prop).unwrap();

Expand Down Expand Up @@ -404,6 +405,7 @@ pub fn create_chatedit(name: &str) -> SceneNode {

node.add_signal("enter_pressed", "Enter key pressed", vec![]).unwrap();
node.add_signal("keyboard_request", "Request to show keyboard", vec![]).unwrap();
node.add_signal("paste_request", "Request to show paste dialog", vec![]).unwrap();

// Used by emoji_picker
node.add_method("insert_text", vec![("text", "Text", CallArgType::Str)], None).unwrap();
Expand Down
205 changes: 178 additions & 27 deletions bin/darkwallet/src/app/schema/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ pub async fn make(

let editz_text = PropertyStr::wrap(&node, Role::App, "text", 0).unwrap();
let editz_select_text = node.get_property("select_text").unwrap();
let editz_cursor_pos = node.get_property("cursor_pos").unwrap();

//let editbox_focus = PropertyBool::wrap(node, Role::App, "is_focused", 0).unwrap();
//let darkirc_backend = app.darkirc_backend.clone();
Expand Down Expand Up @@ -992,31 +993,6 @@ pub async fn make(

let cmd_hint_is_visible =
PropertyBool::wrap(&cmd_layer_node, Role::App, "is_visible", 0).unwrap();
let editz_text_sub = editz_text.prop().subscribe_modify();
let editz_text_task = app.ex.spawn(async move {
while let Ok(_) = editz_text_sub.receive().await {
let text = editz_text.get();
info!(target: "app::chat", "text changed: {text}");
// We want to avoid setting the property multiple times to the same value
// because then it triggers unnecessary redraw work.
if let Some(first_char) = text.chars().next() {
if first_char == '/' {
if !cmd_hint_is_visible.get() {
cmd_hint_is_visible.set(true);
}
} else {
if cmd_hint_is_visible.get() {
cmd_hint_is_visible.set(false);
}
}
} else {
if cmd_hint_is_visible.get() {
cmd_hint_is_visible.set(false);
}
}
}
});
app.tasks.lock().unwrap().push(editz_text_task);

// Create the actionbar bg
let node = create_vector_art("cmd_hint_bg");
Expand Down Expand Up @@ -1173,7 +1149,7 @@ pub async fn make(
layer_node.set_property_u32(Role::App, "priority", 1).unwrap();
let layer_node =
layer_node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
content_layer_node.link(layer_node.clone());
content_layer_node.clone().link(layer_node.clone());

let actions_is_visible = PropertyBool::wrap(&layer_node, Role::App, "is_visible", 0).unwrap();

Expand Down Expand Up @@ -1325,14 +1301,15 @@ pub async fn make(
let (slot, recvr) = Slot::new("paste_clicked");
node.register("click", slot).unwrap();
let actions_is_visible2 = actions_is_visible.clone();
let chatedit_node2 = chatedit_node.clone();
let listen_click = app.ex.spawn(async move {
let mut clip = Clipboard::new();
while let Ok(_) = recvr.recv().await {
if let Some(text) = clip.get() {
info!(target: "app::chat", "clicked paste: {text}");
let mut data = vec![];
text.encode(&mut data).unwrap();
chatedit_node.call_method("insert_text", data).await.unwrap();
chatedit_node2.call_method("insert_text", data).await.unwrap();
} else {
info!(target: "app::chat", "clicked paste but clip is empty");
}
Expand Down Expand Up @@ -1366,18 +1343,192 @@ pub async fn make(
let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
layer_node.clone().link(node);

// Paste overlay popup
let layer_node = create_layer("paste_layer");
let prop = layer_node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, 40.).unwrap();
let code = cc.compile("editz_bg_top_y - ACTION_POPUP_Y_OFF").unwrap();
//let code = cc.compile("h - 60 - 80").unwrap();
//let code = cc.compile("h - 60 - 300").unwrap();
prop.set_expr(Role::App, 1, code).unwrap();
prop.set_f32(Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
prop.set_f32(Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
prop.add_depend(&editbox_bg_rect_prop, 1, "editz_bg_top_y");
layer_node.set_property_bool(Role::App, "is_visible", false).unwrap();
layer_node.set_property_u32(Role::App, "z_index", 8).unwrap();
// Priority higher than chatview but lower than chatedit
layer_node.set_property_u32(Role::App, "priority", 1).unwrap();
let layer_node =
layer_node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
content_layer_node.link(layer_node.clone());

let pasta_is_visible = PropertyBool::wrap(&layer_node, Role::App, "is_visible", 0).unwrap();

let (slot, recvr) = Slot::new("reqpasta");
chatedit_node.register("paste_request", slot).unwrap();
let pasta_is_visible2 = pasta_is_visible.clone();
let listen_click = app.ex.spawn(async move {
while let Ok(_) = recvr.recv().await {
pasta_is_visible2.set(true);
}
});
app.tasks.lock().unwrap().push(listen_click);

// Create the paste bg
let node = create_vector_art("paste_bg");
let prop = node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, 0.).unwrap();
prop.set_f32(Role::App, 1, 0.).unwrap();
prop.set_f32(Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
prop.set_f32(Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
node.set_property_u32(Role::App, "z_index", 0).unwrap();

let mut shape = VectorShape::new();

let color1 = [0., 0.13, 0.08, 0.75];
let color2 = [0., 0., 0., 1.];
let gradient = [color1.clone(), color1, color2.clone(), color2];
let hicolor = [0., 0.94, 1., 1.];

// Paste box
shape.add_gradient_box(
expr::const_f32(0.),
expr::const_f32(0.),
expr::const_f32(ACTION_PASTE_RECT.w),
expr::const_f32(ACTION_PASTE_RECT.h),
gradient.clone(),
);

// Paste outline
shape.add_outline(
expr::const_f32(0.),
expr::const_f32(0.),
expr::const_f32(ACTION_PASTE_RECT.w),
expr::const_f32(ACTION_PASTE_RECT.h),
1.,
hicolor.clone(),
);

let node =
node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
layer_node.clone().link(node);

// Create some text
let node = create_text("paste_label");
let prop = node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, ACTION_LABEL_POS.x).unwrap();
prop.set_f32(Role::App, 1, ACTION_LABEL_POS.y).unwrap();
prop.set_f32(Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
prop.set_f32(Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
node.set_property_f32(Role::App, "baseline", 0.).unwrap();
node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap();
node.set_property_str(Role::App, "text", "paste").unwrap();
//node.set_property_bool(Role::App, "debug", true).unwrap();
//node.set_property_str(Role::App, "text", "anon1").unwrap();
let prop = node.get_property("text_color").unwrap();
prop.set_f32(Role::App, 0, 0.).unwrap();
prop.set_f32(Role::App, 1, 0.94).unwrap();
prop.set_f32(Role::App, 2, 1.).unwrap();
prop.set_f32(Role::App, 3, 1.).unwrap();
node.set_property_u32(Role::App, "z_index", 1).unwrap();

let node = node
.setup(|me| {
Text::new(
me,
window_scale.clone(),
app.render_api.clone(),
app.text_shaper.clone(),
app.ex.clone(),
)
})
.await;
layer_node.clone().link(node);

// Paste button
let node = create_button("paste_btn");
node.set_property_bool(Role::App, "is_active", true).unwrap();
let prop = node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, 0.).unwrap();
prop.set_f32(Role::App, 1, 0.).unwrap();
prop.set_f32(Role::App, 2, ACTION_PASTE_RECT.w).unwrap();
prop.set_f32(Role::App, 3, ACTION_PASTE_RECT.h).unwrap();

let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
layer_node.clone().link(node.clone());

let (slot, recvr) = Slot::new("paste_clicked");
node.register("click", slot).unwrap();
let chatedit_node2 = chatedit_node.clone();
let pasta_is_visible2 = pasta_is_visible.clone();
let listen_click = app.ex.spawn(async move {
let mut clip = Clipboard::new();
while let Ok(_) = recvr.recv().await {
if let Some(text) = clip.get() {
info!(target: "app::chat", "clicked paste: {text}");
let mut data = vec![];
text.encode(&mut data).unwrap();
chatedit_node2.call_method("insert_text", data).await.unwrap();
} else {
info!(target: "app::chat", "clicked paste but clip is empty");
}
pasta_is_visible2.set(false);
}
});
app.tasks.lock().unwrap().push(listen_click);

let editz_cpos_sub = editz_cursor_pos.subscribe_modify();
let pasta_is_visible2 = pasta_is_visible.clone();
let editz_cpos_task = app.ex.spawn(async move {
while let Ok(_) = editz_cpos_sub.receive().await {
pasta_is_visible2.set(false);
}
});
app.tasks.lock().unwrap().push(editz_cpos_task);

let editz_select_sub = editz_select_text.subscribe_modify();
let pasta_is_visible2 = pasta_is_visible.clone();
let editz_select_task = app.ex.spawn(async move {
while let Ok(_) = editz_select_sub.receive().await {
if editz_select_text.is_null(0).unwrap() {
info!(target: "app::chat", "selection changed: null");
actions_is_visible.set(false);
pasta_is_visible2.set(false);
} else {
let select_text = editz_select_text.get_str(0).unwrap();
info!(target: "app::chat", "selection changed: {select_text}");
actions_is_visible.set(true);
pasta_is_visible2.set(false);
}
}
});
app.tasks.lock().unwrap().push(editz_select_task);

let editz_text_sub = editz_text.prop().subscribe_modify();
let editz_text_task = app.ex.spawn(async move {
while let Ok(_) = editz_text_sub.receive().await {
pasta_is_visible.set(false);

let text = editz_text.get();
info!(target: "app::chat", "text changed: {text}");
// We want to avoid setting the property multiple times to the same value
// because then it triggers unnecessary redraw work.
if let Some(first_char) = text.chars().next() {
if first_char == '/' {
if !cmd_hint_is_visible.get() {
cmd_hint_is_visible.set(true);
}
} else {
if cmd_hint_is_visible.get() {
cmd_hint_is_visible.set(false);
}
}
} else {
if cmd_hint_is_visible.get() {
cmd_hint_is_visible.set(false);
}
}
}
});
app.tasks.lock().unwrap().push(editz_text_task);
}
Loading

0 comments on commit f0a2ce1

Please sign in to comment.