Explorar o código

wallet: add a network status indicator

darkfi hai 1 ano
pai
achega
d1db976c21

+ 50 - 2
bin/darkwallet/src/app/mod.rs

@@ -19,7 +19,7 @@
 use async_recursion::async_recursion;
 use chrono::{Local, NaiveDate, NaiveDateTime, TimeZone};
 use darkfi::system::CondVar;
-use darkfi_serial::{Decodable, Encodable};
+use darkfi_serial::{deserialize, Decodable, Encodable};
 use futures::{stream::FuturesUnordered, StreamExt};
 use sled_overlay::sled;
 use smol::Task;
@@ -52,7 +52,7 @@ macro_rules! d { ($($arg:tt)*) => { debug!(target: "app", $($arg)*); } }
 macro_rules! t { ($($arg:tt)*) => { trace!(target: "app", $($arg)*); } }
 macro_rules! i { ($($arg:tt)*) => { info!(target: "app", $($arg)*); } }
 
-const PLUGINS_ENABLED: bool = true;
+const PLUGINS_ENABLED: bool = false;
 
 //fn print_type_of<T>(_: &T) {
 //    println!("{}", std::any::type_name::<T>())
@@ -253,6 +253,54 @@ impl App {
         });
         self.tasks.lock().unwrap().push(listen_recv);
 
+        let (slot, recvr) = Slot::new("connect");
+        darkirc.register("connect", slot).unwrap();
+        let sg_root2 = self.sg_root.clone();
+        let listen_connect = self.ex.spawn(async move {
+            let net0 = sg_root2.clone().lookup_node("/window/netstatus_layer/net0").unwrap();
+            let net1 = sg_root2.clone().lookup_node("/window/netstatus_layer/net1").unwrap();
+            let net2 = sg_root2.clone().lookup_node("/window/netstatus_layer/net2").unwrap();
+            let net3 = sg_root2.clone().lookup_node("/window/netstatus_layer/net3").unwrap();
+
+            let net0_is_visible = PropertyBool::wrap(&net0, Role::App, "is_visible", 0).unwrap();
+            let net1_is_visible = PropertyBool::wrap(&net1, Role::App, "is_visible", 0).unwrap();
+            let net2_is_visible = PropertyBool::wrap(&net2, Role::App, "is_visible", 0).unwrap();
+            let net3_is_visible = PropertyBool::wrap(&net3, Role::App, "is_visible", 0).unwrap();
+
+            while let Ok(data) = recvr.recv().await {
+                let peers_count: u32 = deserialize(&data).unwrap();
+
+                let atom = &mut PropertyAtomicGuard::new();
+                match peers_count {
+                    0 => {
+                        net0_is_visible.set(atom, true);
+                        net1_is_visible.set(atom, false);
+                        net2_is_visible.set(atom, false);
+                        net3_is_visible.set(atom, false);
+                    }
+                    1 => {
+                        net0_is_visible.set(atom, false);
+                        net1_is_visible.set(atom, true);
+                        net2_is_visible.set(atom, false);
+                        net3_is_visible.set(atom, false);
+                    }
+                    2 => {
+                        net0_is_visible.set(atom, false);
+                        net1_is_visible.set(atom, false);
+                        net2_is_visible.set(atom, true);
+                        net3_is_visible.set(atom, false);
+                    }
+                    _ => {
+                        net0_is_visible.set(atom, false);
+                        net1_is_visible.set(atom, false);
+                        net2_is_visible.set(atom, false);
+                        net3_is_visible.set(atom, true);
+                    }
+                }
+            }
+        });
+        self.tasks.lock().unwrap().push(listen_connect);
+
         plugin.link(darkirc);
 
         i!("Plugins loaded");

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

@@ -601,6 +601,13 @@ pub fn create_darkirc(name: &str) -> SceneNode {
     )
     .unwrap();
 
+    node.add_signal(
+        "connect",
+        "Connections and disconnects",
+        vec![("peers_count", "Peers count", CallArgType::Uint32)],
+    )
+    .unwrap();
+
     node.add_method(
         "send",
         vec![("channel", "Channel", CallArgType::Str), ("msg", "Message", CallArgType::Str)],

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

@@ -53,6 +53,7 @@ pub const COLOR_SCHEME: ColorScheme = ColorScheme::DarkMode;
 //pub const COLOR_SCHEME: ColorScheme = ColorScheme::PaperLight;
 
 mod android_ui_consts {
+    pub const NETSTATUS_ICON_SIZE: f32 = 140.;
     pub const EMOJI_PICKER_ICON_SIZE: f32 = 100.;
 }
 
@@ -96,6 +97,7 @@ mod ui_consts {
     not(feature = "emulate-android")
 ))]
 mod ui_consts {
+    pub const NETSTATUS_ICON_SIZE: f32 = 60.;
     pub const EMOJI_PICKER_ICON_SIZE: f32 = 40.;
     pub use super::desktop_paths::*;
 }
@@ -113,6 +115,8 @@ enum ColorScheme {
 
 pub async fn make(app: &App, window: SceneNodePtr) {
     let mut cc = Compiler::new();
+    cc.add_const_f32("NETSTATUS_ICON_SIZE", NETSTATUS_ICON_SIZE);
+
     let atom = &mut PropertyAtomicGuard::new();
 
     if COLOR_SCHEME == ColorScheme::DarkMode {
@@ -222,6 +226,99 @@ pub async fn make(app: &App, window: SceneNodePtr) {
         window.clone().link(node);
     }
 
+    let netlayer_node = create_layer("netstatus_layer");
+    let prop = netlayer_node.get_property("rect").unwrap();
+    let code = cc.compile("w - NETSTATUS_ICON_SIZE").unwrap();
+    prop.clone().set_expr(atom, Role::App, 0, code).unwrap();
+    prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+    prop.clone().set_f32(atom, Role::App, 2, NETSTATUS_ICON_SIZE).unwrap();
+    prop.clone().set_f32(atom, Role::App, 3, NETSTATUS_ICON_SIZE).unwrap();
+    netlayer_node.set_property_bool(atom, Role::App, "is_visible", true).unwrap();
+    netlayer_node.set_property_u32(atom, Role::App, "z_index", 2).unwrap();
+    let netlayer_node =
+        netlayer_node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
+    window.clone().link(netlayer_node.clone());
+
+    let node = create_vector_art("net0");
+    let prop = node.get_property("rect").unwrap();
+    prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+    prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+    prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+    prop.clone().set_expr(atom, Role::App, 3, expr::load_var("h")).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 = VectorShape::new();
+    shape.add_filled_box(
+        expr::const_f32(0.),
+        expr::const_f32(0.),
+        expr::load_var("w"),
+        expr::load_var("h"),
+        [1., 0., 0., 1.],
+    );
+    let net0_node =
+        node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+    netlayer_node.clone().link(net0_node);
+
+    let node = create_vector_art("net1");
+    let prop = node.get_property("rect").unwrap();
+    prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+    prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+    prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+    prop.clone().set_expr(atom, Role::App, 3, expr::load_var("h")).unwrap();
+    node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
+    node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+    let mut shape = VectorShape::new();
+    shape.add_filled_box(
+        expr::const_f32(0.),
+        expr::const_f32(0.),
+        expr::load_var("w"),
+        expr::load_var("h"),
+        [0., 0.3, 0., 1.],
+    );
+    let net1_node =
+        node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+    netlayer_node.clone().link(net1_node);
+
+    let node = create_vector_art("net2");
+    let prop = node.get_property("rect").unwrap();
+    prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+    prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+    prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+    prop.clone().set_expr(atom, Role::App, 3, expr::load_var("h")).unwrap();
+    node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
+    node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+    let mut shape = VectorShape::new();
+    shape.add_filled_box(
+        expr::const_f32(0.),
+        expr::const_f32(0.),
+        expr::load_var("w"),
+        expr::load_var("h"),
+        [0., 0.6, 0., 1.],
+    );
+    let net2_node =
+        node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+    netlayer_node.clone().link(net2_node);
+
+    let node = create_vector_art("net3");
+    let prop = node.get_property("rect").unwrap();
+    prop.clone().set_f32(atom, Role::App, 0, 0.).unwrap();
+    prop.clone().set_f32(atom, Role::App, 1, 0.).unwrap();
+    prop.clone().set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+    prop.clone().set_expr(atom, Role::App, 3, expr::load_var("h")).unwrap();
+    node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
+    node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+    let mut shape = VectorShape::new();
+    shape.add_filled_box(
+        expr::const_f32(0.),
+        expr::const_f32(0.),
+        expr::load_var("w"),
+        expr::load_var("h"),
+        [0., 1., 0., 1.],
+    );
+    let net3_node =
+        node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
+    netlayer_node.clone().link(net3_node);
+
     let emoji_meshes = emoji_picker::EmojiMeshes::new(
         app.render_api.clone(),
         app.text_shaper.clone(),

+ 21 - 3
bin/darkwallet/src/plugin/darkirc.rs

@@ -28,8 +28,8 @@ use darkfi::{
     Result as DarkFiResult,
 };
 use darkfi_serial::{
-    deserialize_async, serialize_async, AsyncEncodable, Decodable, Encodable, SerialDecodable,
-    SerialEncodable,
+    deserialize_async, serialize, serialize_async, AsyncEncodable, Decodable, Encodable,
+    SerialDecodable, SerialEncodable,
 };
 use sled_overlay::sled;
 use std::{
@@ -426,6 +426,21 @@ impl DarkIrc {
 
         self.p2p.broadcast(&EventPut(event)).await;
     }
+
+    async fn connect_notify(self: Arc<Self>, channel_sub: Subscription<DarkFiResult<ChannelPtr>>) {
+        loop {
+            // Wait for a channel
+            if let Err(_) = channel_sub.receive().await {
+                e!("There was an error listening for channels. The service closed unexpectedly.");
+                return
+            }
+
+            let peers_count = self.p2p.hosts().peers().len() as u32;
+
+            let node = self.node.upgrade().unwrap();
+            node.trigger("connect", serialize(&peers_count)).await.unwrap();
+        }
+    }
 }
 
 #[async_trait]
@@ -463,7 +478,10 @@ impl PluginObject for DarkIrc {
         let channel_sub = self.p2p.hosts().subscribe_channel().await;
         let dag_task = ex.spawn(self.clone().dag_sync(channel_sub));
 
-        let mut tasks = vec![send_method_task, ev_task, dag_task];
+        let channel_sub = self.p2p.hosts().subscribe_channel().await;
+        let connect_notify_task = ex.spawn(self.clone().connect_notify(channel_sub));
+
+        let mut tasks = vec![send_method_task, ev_task, dag_task, connect_notify_task];
         tasks.append(&mut on_modify.tasks);
         self.tasks.set(tasks);
     }