Skip to content

Commit

Permalink
wallet: add configurable shortcuts and make enter send the text loool
Browse files Browse the repository at this point in the history
  • Loading branch information
darkfi committed Jan 12, 2025
1 parent 877cf88 commit 3edeafc
Show file tree
Hide file tree
Showing 8 changed files with 392 additions and 46 deletions.
6 changes: 6 additions & 0 deletions bin/darkwallet/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ mod node;
use node::create_darkirc;
mod schema;

const PLUGINS_ENABLED: bool = true;

//fn print_type_of<T>(_: &T) {
// println!("{}", std::any::type_name::<T>())
//}
Expand Down Expand Up @@ -169,6 +171,10 @@ impl App {
let plugin = Arc::new(SceneNode3::new("plugin", SceneNodeType3::PluginRoot));
self.sg_root.clone().link(plugin.clone());

if !PLUGINS_ENABLED {
return
}

let darkirc = create_darkirc("darkirc");
let darkirc = darkirc
.setup(|me| async {
Expand Down
18 changes: 16 additions & 2 deletions bin/darkwallet/src/app/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ pub fn create_button(name: &str) -> SceneNode {
node
}

pub fn create_shortcut(name: &str) -> SceneNode {
debug!(target: "app", "create_shortcut({name})");
let mut node = SceneNode::new(name, SceneNodeType::Shortcut);

let mut prop = Property::new("key", PropertyType::Str, PropertySubType::Null);
prop.allow_null_values();
node.add_property(prop).unwrap();

let prop = Property::new("priority", PropertyType::Uint32, PropertySubType::Null);
node.add_property(prop).unwrap();

node.add_signal("shortcut", "Shortcut triggered", vec![]).unwrap();

node
}

pub fn create_image(name: &str) -> SceneNode {
debug!(target: "app", "create_image({name})");
let mut node = SceneNode::new(name, SceneNodeType::Image);
Expand Down Expand Up @@ -262,8 +278,6 @@ pub fn create_editbox(name: &str) -> SceneNode {
let prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
node.add_property(prop).unwrap();

node.add_signal("enter_pressed", "Enter key pressed", vec![]).unwrap();

node
}

Expand Down
83 changes: 60 additions & 23 deletions bin/darkwallet/src/app/schema/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
app::{
node::{
create_button, create_chatedit, create_chatview, create_editbox, create_emoji_picker,
create_image, create_layer, create_text, create_vector_art,
create_image, create_layer, create_shortcut, create_text, create_vector_art,
},
populate_tree, App,
},
Expand All @@ -42,7 +42,7 @@ use crate::{
text::TextShaperPtr,
ui::{
emoji_picker, Button, ChatEdit, ChatView, EditBox, EmojiPicker, Image, Layer, ShapeVertex,
Text, VectorArt, VectorShape, Window,
Shortcut, Text, VectorArt, VectorShape, Window,
},
util::unixtime,
ExecutorPtr,
Expand Down Expand Up @@ -881,19 +881,24 @@ pub async fn make(
prop.set_f32(Role::App, 2, SENDBTN_BOX[2]).unwrap();
prop.set_f32(Role::App, 3, SENDBTN_BOX[3]).unwrap();

let (slot, recvr) = Slot::new("send_clicked");
node.register("click", slot).unwrap();
let editz_text2 = editz_text.clone();
let channel2 = channel.to_string();
let sg_root2 = app.sg_root.clone();
let listen_click = app.ex.spawn(async move {
let channel = format!("#{channel2}");
while let Ok(_) = recvr.recv().await {
let text = editz_text2.get();
info!(target: "app::chat", "Send '{text}' to channel: #{channel2}");
editz_text2.set("");
#[derive(Clone)]
struct SendMsg {
channel: String,
editz_text: PropertyStr,
sg_root: SceneNodePtr,
chatview_node: SceneNodePtr,
}

impl SendMsg {
async fn send(&self) {
let text = self.editz_text.get();
info!(target: "app::chat", "Send '{text}' to channel: #{}", self.channel);
self.editz_text.set("");

let darkirc = sg_root2.clone().lookup_node("/plugin/darkirc").unwrap();
let Some(darkirc) = self.sg_root.clone().lookup_node("/plugin/darkirc") else {
error!(target: "app::chat", "DarkIrc plugin has not been loaded");
return
};

if text.starts_with("/nick") {
let nick = text.split_whitespace().nth(1).unwrap_or("anon");
Expand All @@ -908,34 +913,66 @@ pub async fn make(
id.encode(&mut data).unwrap();
"NOTICE".encode(&mut data).unwrap();
msg.encode(&mut data).unwrap();
chatview_node.call_method("insert_line", data).await.unwrap();
self.chatview_node.call_method("insert_line", data).await.unwrap();

continue
return
}

let timest = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
let nick = darkirc.get_property_str("nick").unwrap();
let msg = darkirc::Privmsg::new(channel.clone(), nick, text);
let msg = darkirc::Privmsg::new(self.channel.clone(), nick, text);

let mut data = vec![];
timest.encode(&mut data).unwrap();
msg.msg_id(timest).encode(&mut data).unwrap();
msg.nick.encode(&mut data).unwrap();
msg.msg.encode(&mut data).unwrap();
chatview_node.call_method("insert_unconf_line", data).await.unwrap();
//let mut data = vec![];
//timest.encode(&mut data).unwrap();
//msg.msg_id(timest).encode(&mut data).unwrap();
//msg.nick.encode(&mut data).unwrap();
//msg.msg.encode(&mut data).unwrap();
//chatview_node.call_method("insert_unconf_line", data).await.unwrap();

let mut data = vec![];
timest.encode(&mut data).unwrap();
msg.channel.encode(&mut data).unwrap();
msg.msg.encode(&mut data).unwrap();
darkirc.call_method("send", data).await.unwrap();
}
}

let sendmsg = SendMsg {
editz_text: editz_text.clone(),
channel: format!("#{channel}"),
sg_root: app.sg_root.clone(),
chatview_node,
};

let (slot, recvr) = Slot::new("send_clicked");
node.register("click", slot).unwrap();
let sendmsg2 = sendmsg.clone();
let listen_click = app.ex.spawn(async move {
while let Ok(_) = recvr.recv().await {
sendmsg2.send().await;
}
});
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 shortcut to send as well
let node = create_shortcut("send_shortcut");
node.set_property_str(Role::App, "key", "enter").unwrap();

let (slot, recvr) = Slot::new("enter_pressed");
node.register("shortcut", slot).unwrap();
let listen_enter = app.ex.spawn(async move {
while let Ok(_) = recvr.recv().await {
sendmsg.send().await;
}
});
app.tasks.lock().unwrap().push(listen_enter);

let node = node.setup(|me| Shortcut::new(me)).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();
Expand Down
8 changes: 6 additions & 2 deletions bin/darkwallet/src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use simplelog::{
};
use std::{path::PathBuf, thread::sleep, time::Duration};

const LOGS_ENABLED: bool = true;
const LOGS_ENABLED: bool = false;
// Measured in bytes
const LOGFILE_MAXSIZE: usize = 5_000_000;

Expand Down Expand Up @@ -43,7 +43,11 @@ mod android {
impl Log for AndroidLoggerWrapper {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
let target = metadata.target();
if target.starts_with("sled") || target.starts_with("rustls") {
if target.starts_with("sled") ||
target.starts_with("rustls") ||
target.starts_with("net::") ||
target.starts_with("event_graph")
{
return false
}
if metadata.level() > self.level {
Expand Down
4 changes: 3 additions & 1 deletion bin/darkwallet/src/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ pub enum SceneNodeType {
ChatEdit = 18,
Image = 19,
Button = 20,
EmojiPicker = 21,
Shortcut = 21,
EmojiPicker = 22,
PluginRoot = 100,
Plugin = 101,
}
Expand Down Expand Up @@ -476,6 +477,7 @@ pub enum Pimpl {
ChatView(ui::ChatViewPtr),
Image(ui::ImagePtr),
Button(ui::ButtonPtr),
Shortcut(ui::ShortcutPtr),
EmojiPicker(ui::EmojiPickerPtr),
DarkIrc(plugin::DarkIrcPtr),
}
76 changes: 60 additions & 16 deletions bin/darkwallet/src/ui/chatedit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,62 +1162,103 @@ impl ChatEdit {
false
}

async fn handle_key(&self, key: &KeyCode, mods: &KeyMods) {
async fn handle_key(&self, key: &KeyCode, mods: &KeyMods) -> bool {
debug!(target: "ui::chatedit", "handle_key({:?}, {:?})", key, mods);
match key {
KeyCode::Left => {
self.adjust_cursor(mods.shift, |editable| editable.move_cursor(-1));
self.pause_blinking();
//self.apply_cursor_scrolling();
self.redraw().await;
return true
}
KeyCode::Right => {
self.adjust_cursor(mods.shift, |editable| editable.move_cursor(1));
self.pause_blinking();
//self.apply_cursor_scrolling();
self.redraw().await;
return true
}
KeyCode::Kp0 => {
self.insert_char('0').await;
return true
}
KeyCode::Kp1 => {
self.insert_char('1').await;
return true
}
KeyCode::Kp2 => {
self.insert_char('2').await;
return true
}
KeyCode::Kp3 => {
self.insert_char('3').await;
return true
}
KeyCode::Kp4 => {
self.insert_char('4').await;
return true
}
KeyCode::Kp5 => {
self.insert_char('5').await;
return true
}
KeyCode::Kp6 => {
self.insert_char('6').await;
return true
}
KeyCode::Kp7 => {
self.insert_char('7').await;
return true
}
KeyCode::Kp8 => {
self.insert_char('8').await;
return true
}
KeyCode::Kp9 => {
self.insert_char('9').await;
return true
}
KeyCode::KpDecimal => {
self.insert_char('.').await;
return true
}
KeyCode::Kp0 => self.insert_char('0').await,
KeyCode::Kp1 => self.insert_char('1').await,
KeyCode::Kp2 => self.insert_char('2').await,
KeyCode::Kp3 => self.insert_char('3').await,
KeyCode::Kp4 => self.insert_char('4').await,
KeyCode::Kp5 => self.insert_char('5').await,
KeyCode::Kp6 => self.insert_char('6').await,
KeyCode::Kp7 => self.insert_char('7').await,
KeyCode::Kp8 => self.insert_char('8').await,
KeyCode::Kp9 => self.insert_char('9').await,
KeyCode::KpDecimal => self.insert_char('.').await,
KeyCode::Enter | KeyCode::KpEnter => {
let node = self.node.upgrade().unwrap();
node.trigger("enter_pressed", vec![]).await.unwrap();
if mods.shift {
// Does nothing for now. Later will enable multiline.
}
}
KeyCode::Delete => {
self.delete(0, 1);
self.clamp_scroll(&mut self.text_wrap.lock());
self.pause_blinking();
self.redraw().await;
return true
}
KeyCode::Backspace => {
self.delete(1, 0);
self.clamp_scroll(&mut self.text_wrap.lock());
self.pause_blinking();
self.redraw().await;
return true
}
KeyCode::Home => {
self.adjust_cursor(mods.shift, |editable| editable.move_start());
self.pause_blinking();
//self.apply_cursor_scrolling();
self.redraw().await;
return true
}
KeyCode::End => {
self.adjust_cursor(mods.shift, |editable| editable.move_end());
self.pause_blinking();
//self.apply_cursor_scrolling();
self.redraw().await;
return true
}
_ => {}
}
false
}

fn delete(&self, before: usize, after: usize) {
Expand Down Expand Up @@ -1946,10 +1987,13 @@ impl UIObject for ChatEdit {
/*if actions > 0 {
debug!(target: "ui::chatedit", "Key {:?} has {} actions", key, actions);
}*/
let mut is_handled = false;
for _ in 0..actions {
self.handle_key(&key, &mods).await;
if self.handle_key(&key, &mods).await {
is_handled = true;
}
}
true
is_handled
}

async fn handle_mouse_btn_down(&self, btn: MouseButton, mut mouse_pos: Point) -> bool {
Expand Down
8 changes: 6 additions & 2 deletions bin/darkwallet/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub use vector_art::{
};
mod layer;
pub use layer::{Layer, LayerPtr};
mod shortcut;
pub use shortcut::{Shortcut, ShortcutPtr};
mod text;
pub use text::{Text, TextPtr};
mod win;
Expand Down Expand Up @@ -188,7 +190,8 @@ pub fn get_ui_object_ptr(node: &SceneNode3) -> Arc<dyn UIObject + Send> {
Pimpl::Image(obj) => obj.clone(),
Pimpl::Button(obj) => obj.clone(),
Pimpl::EmojiPicker(obj) => obj.clone(),
_ => panic!("unhandled type for get_ui_object"),
Pimpl::Shortcut(obj) => obj.clone(),
_ => panic!("unhandled type for get_ui_object: {node:?}"),
}
}
pub fn get_ui_object3<'a>(node: &'a SceneNode3) -> &'a dyn UIObject {
Expand All @@ -202,7 +205,8 @@ pub fn get_ui_object3<'a>(node: &'a SceneNode3) -> &'a dyn UIObject {
Pimpl::Image(obj) => obj.as_ref(),
Pimpl::Button(obj) => obj.as_ref(),
Pimpl::EmojiPicker(obj) => obj.as_ref(),
_ => panic!("unhandled type for get_ui_object"),
Pimpl::Shortcut(obj) => obj.as_ref(),
_ => panic!("unhandled type for get_ui_object: {node:?}"),
}
}

Expand Down
Loading

0 comments on commit 3edeafc

Please sign in to comment.