Просмотр исходного кода

wallet: UI working with darkirc 🔥🔥🔥

darkfi 2 лет назад
Родитель
Сommit
e7eb633916

+ 11 - 11
bin/darkwallet/src/app.rs

@@ -20,17 +20,20 @@ use async_recursion::async_recursion;
 use chrono::{NaiveDate, NaiveDateTime};
 use darkfi_serial::Encodable;
 use futures::{stream::FuturesUnordered, StreamExt};
-use std::{sync::{Arc, Mutex as SyncMutex}, thread};
 use smol::Task;
+use std::{
+    sync::{Arc, Mutex as SyncMutex},
+    thread,
+};
 
 use crate::{
     error::Error,
     expr::Op,
     gfx2::{GraphicsEventPublisherPtr, RenderApiPtr, Vertex},
-    prop::{Property, PropertySubType, PropertyType, Role, PropertyStr, PropertyBool},
+    prop::{Property, PropertyBool, PropertyStr, PropertySubType, PropertyType, Role},
     scene::{
         CallArgType, MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId,
-        SceneNodeType, Slot
+        SceneNodeType, Slot,
     },
     text2::TextShaperPtr,
     ui::{chatview, Button, ChatView, EditBox, Image, Mesh, RenderLayer, Stoppable, Text, Window},
@@ -362,10 +365,7 @@ impl App {
         prop.set_f32(Role::App, 3, 60.).unwrap();
 
         let (sender, btn_click_recvr) = async_channel::unbounded();
-        let slot_click = Slot {
-            name: "button_clicked".to_string(),
-            notify: sender
-        };
+        let slot_click = Slot { name: "button_clicked".to_string(), notify: sender };
         node.register("click", slot_click).unwrap();
 
         drop(sg);
@@ -641,7 +641,7 @@ impl App {
         let task = self.ex.spawn(async move {
             while let Ok(_) = btn_click_recvr.recv().await {
                 let text = editbox_text.get();
-                editbox_text.prop().unset(Role::App, 0);
+                editbox_text.prop().unset(Role::App, 0).unwrap();
                 // Clicking outside the editbox makes it lose focus
                 // So lets focus it again
                 editbox_focus.set(true);
@@ -729,9 +729,9 @@ impl App {
         drop(sg);
         let db = sled::open(CHATDB_PATH).expect("cannot open sleddb");
         let chat_tree = db.open_tree(b"chat").unwrap();
-        if chat_tree.is_empty() {
-            populate_tree(&chat_tree);
-        }
+        //if chat_tree.is_empty() {
+        //    populate_tree(&chat_tree);
+        //}
         debug!(target: "app", "db has {} lines", chat_tree.len());
         let pimpl = ChatView::new(
             self.ex.clone(),

+ 1 - 1
bin/darkwallet/src/gfx2.rs

@@ -33,7 +33,7 @@ use std::{
 };
 
 use crate::{
-    app::{AsyncRuntime, AppPtr},
+    app::{AppPtr, AsyncRuntime},
     error::{Error, Result},
     pubsub::{Publisher, PublisherPtr, Subscription, SubscriptionId},
     shader,

+ 52 - 13
bin/darkwallet/src/main.rs

@@ -35,12 +35,12 @@ use darkfi::{
         jsonrpc::JsonSubscriber,
         server::{listen_and_serve, RequestHandler},
     },
-    system::{sleep, sleep_forever, StoppableTask, StoppableTaskPtr, Subscription},
+    system::{sleep, sleep_forever, CondVar, StoppableTask, StoppableTaskPtr, Subscription},
     util::path::{expand_path, get_config_path},
     Error, Result,
 };
 use darkfi_serial::{
-    async_trait, deserialize_async, AsyncDecodable, SerialDecodable, SerialEncodable,
+    async_trait, deserialize_async, AsyncDecodable, Encodable, SerialDecodable, SerialEncodable,
 };
 
 #[macro_use]
@@ -71,7 +71,11 @@ mod text2;
 mod ui;
 mod util;
 
-use crate::{net::ZeroMQAdapter, scene::SceneGraph, text2::TextShaper};
+use crate::{
+    net::ZeroMQAdapter,
+    scene::{SceneGraph, SceneGraphPtr2},
+    text2::TextShaper,
+};
 
 pub type ExecutorPtr = Arc<smol::Executor<'static>>;
 
@@ -88,7 +92,7 @@ pub struct Privmsg {
     pub msg: String,
 }
 
-async fn print_evs(ev_sub: Subscription<event_graph::Event>) {
+async fn relay_darkirc_events(sg: SceneGraphPtr2, ev_sub: Subscription<event_graph::Event>) {
     loop {
         let ev = ev_sub.receive().await;
 
@@ -101,14 +105,31 @@ async fn print_evs(ev_sub: Subscription<event_graph::Event>) {
             }
         };
 
-        info!("ev_id={:?}", ev.id());
-        info!("ev: {:?}", ev);
-        info!("privmsg: {:?}", privmsg);
-        info!("");
+        if privmsg.channel != "#random" {
+            continue
+        }
+
+        info!(target: "main", "ev_id={:?}", ev.id());
+        info!(target: "main", "ev: {:?}", ev);
+        info!(target: "main", "privmsg: {:?}", privmsg);
+        info!(target: "main", "");
+
+        let response_fn = Box::new(|_| {});
+
+        let mut arg_data = vec![];
+        ev.timestamp.encode(&mut arg_data);
+        ev.id().as_bytes().encode(&mut arg_data);
+        privmsg.nick.encode(&mut arg_data);
+        privmsg.msg.encode(&mut arg_data);
+
+        let mut sg = sg.lock().await;
+        let chatview_node = sg.lookup_node_mut("/window/view/chatty").unwrap();
+        chatview_node.call_method("insert_line", arg_data, response_fn).unwrap();
+        drop(sg);
     }
 }
 
-async fn realmain(ex: ExecutorPtr) -> darkfi::Result<()> {
+async fn run_darkirc_backend(sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Result<()> {
     let sled_db = sled::open("evgrdb")?;
 
     let mut p2p_settings: NetSettings = Default::default();
@@ -141,7 +162,7 @@ async fn realmain(ex: ExecutorPtr) -> darkfi::Result<()> {
         .await;
 
     let ev_sub = event_graph.event_pub.clone().subscribe().await;
-    let ev_task = ex.spawn(print_evs(ev_sub));
+    let ev_task = ex.spawn(relay_darkirc_events(sg, ev_sub));
 
     info!("Starting P2P network");
     p2p.clone().start().await?;
@@ -191,6 +212,7 @@ async fn realmain(ex: ExecutorPtr) -> darkfi::Result<()> {
     Ok(())
 }
 
+/*
 fn newmain() {
     simplelog::TermLogger::init(
         simplelog::LevelFilter::Info,
@@ -210,12 +232,13 @@ fn newmain() {
         // Run the main future on the current thread.
         .finish(|| {
             smol::future::block_on(async {
-                realmain(ex.clone()).await?;
+                run_darkirc_backend(ex.clone()).await?;
                 drop(signal);
                 Ok::<(), darkfi::Error>(())
             })
         });
 }
+*/
 
 fn main() {
     // Exit the application on panic right away
@@ -271,9 +294,14 @@ fn main() {
 
     let app =
         app::App::new(sg.clone(), ex.clone(), render_api.clone(), event_pub.clone(), text_shaper);
-    let app_task = ex.spawn(app.clone().start());
+    let app_cv = Arc::new(CondVar::new());
+    let app2 = app.clone();
+    let app_cv2 = app_cv.clone();
+    let app_task = ex.spawn(async move {
+        app2.start().await;
+        app_cv2.notify();
+    });
     async_runtime.push_task(app_task);
-    //app.clone().start();
 
     // Nice to see which events exist
     let ev_sub = event_pub.subscribe_key_down();
@@ -325,6 +353,17 @@ fn main() {
     });
     async_runtime.push_task(ev_relay_task);
 
+    let ex2 = ex.clone();
+    let darkirc_task = ex.spawn(async move {
+        // Wait for app to finish starting
+        app_cv.wait().await;
+
+        if let Err(e) = run_darkirc_backend(sg, ex2).await {
+            error!(target: "main", "darkirc backend failed: {e}");
+        }
+    });
+    async_runtime.push_task(darkirc_task);
+
     //let stage = gfx2::Stage::new(method_rep, event_pub);
     gfx2::run_gui(app, async_runtime, method_rep, event_pub);
     debug!(target: "main", "Started GFX backend");

+ 1 - 3
bin/darkwallet/src/scene.rs

@@ -541,9 +541,7 @@ impl SceneNode {
         for (_, slot) in sig.get_slots() {
             debug!(target: "scene", "triggering {}", slot.name);
             // Trigger the slot
-            futures.push(async {
-                slot.notify.send(data.clone()).await.is_ok()
-            });
+            futures.push(async { slot.notify.send(data.clone()).await.is_ok() });
         }
         let success: Vec<_> = futures.collect().await;
         debug!(target: "scene", "trigger success: {success:?}");

+ 20 - 3
bin/darkwallet/src/ui/chatview.rs

@@ -668,6 +668,18 @@ impl ChatView {
             }
         };
 
+        // Maybe we can write this code below better
+        if pages.is_empty() {
+            let msgs = vec![Message { timest, id: message_id, chatmsg, glyphs }];
+            let page = Page2::new(msgs, &self.render_api).await;
+            pages.push(page);
+            drop(pages);
+
+            let mut scroll = self.scroll.get();
+            self.scrollview(scroll).await;
+            return;
+        }
+
         let page = &mut pages[idx];
         let mut msgs = page.msgs.clone();
         msgs.push(Message { timest, id: message_id, chatmsg, glyphs });
@@ -917,7 +929,11 @@ impl ChatView {
                 // No more pages available to load
                 pages = self.pages2.lock().await.clone();
                 let new_height = self.get_total_height(&rect, &pages).await;
-                *scroll = new_height - rect.h;
+                if new_height > rect.h {
+                    *scroll = new_height - rect.h;
+                } else {
+                    *scroll = 0.;
+                }
                 break
             }
         }
@@ -955,7 +971,7 @@ impl ChatView {
     /// Basically a version of redraw() where regen_mesh() is never called.
     /// Instead we use the cached version.
     async fn scrollview(&self, mut scroll: f32) -> f32 {
-        //debug!(target: "ui::chatview", "scrollview()");
+        debug!(target: "ui::chatview", "scrollview()");
         let old_scroll = self.scroll.get();
 
         let sg = self.sg.lock().await;
@@ -1062,13 +1078,14 @@ impl ChatView {
         let mut scroll = self.scroll.get();
         assert!(scroll >= 0.);
         // For when we resize the window and scroll is no longer valid
-        let max_allowed_scroll = total_height - rect.h;
+        let max_allowed_scroll = if total_height > rect.h { total_height - rect.h } else { 0. };
         debug!(
             "max_allowed_scroll = {max_allowed_scroll} = total_height={total_height} - rect.h={}",
             rect.h
         );
         if scroll > max_allowed_scroll {
             scroll = max_allowed_scroll;
+            assert!(scroll >= 0.);
             self.scroll.set(scroll);
         }
 

+ 1 - 1
src/event_graph/event.rs

@@ -32,7 +32,7 @@ use super::{
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 pub struct Event {
     /// Timestamp of the event in whole seconds
-    pub(crate) timestamp: u64,
+    pub timestamp: u64,
     /// Content of the event
     pub(crate) content: Vec<u8>,
     /// Parent nodes in the event DAG