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

wallet: show unconf lines and disable timestamp correction for self messages

darkfi 1 год назад
Родитель
Сommit
6ef8ed23f4

+ 16 - 2
bin/darkwallet/src/app/schema/chat.rs

@@ -19,6 +19,7 @@
 use darkfi::system::msleep;
 use darkfi_serial::Encodable;
 use sled_overlay::sled;
+use std::time::UNIX_EPOCH;
 
 use crate::{
     app::{
@@ -32,6 +33,7 @@ use crate::{
     expr::{self, Compiler, Op},
     gfx::{GraphicsEventPublisherPtr, Point, Rectangle, RenderApi, Vertex},
     mesh::{Color, MeshBuilder},
+    plugin::darkirc,
     prop::{
         Property, PropertyBool, PropertyFloat32, PropertyStr, PropertySubType, PropertyType, Role,
     },
@@ -911,9 +913,21 @@ pub async fn make(
                 continue
             }
 
+            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 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![];
-            channel.encode(&mut data).unwrap();
-            text.encode(&mut data).unwrap();
+            timest.encode(&mut data).unwrap();
+            msg.channel.encode(&mut data).unwrap();
+            msg.msg.encode(&mut data).unwrap();
             darkirc.call_method("send", data).await.unwrap();
         }
     });

+ 77 - 33
bin/darkwallet/src/plugin/darkirc.rs

@@ -42,7 +42,10 @@ use crate::{
     error::{Error, Result},
     prop::{PropertyStr, Role},
     scene::{MethodCallSub, Pimpl, SceneNodePtr, SceneNodeWeak},
-    ui::{chatview::MessageId, OnModify},
+    ui::{
+        chatview::{MessageId, Timestamp},
+        OnModify,
+    },
     ExecutorPtr,
 };
 
@@ -90,6 +93,8 @@ impl Privmsg {
 
     pub fn msg_id(&self, timest: u64) -> MessageId {
         let mut hasher = blake3::Hasher::new();
+        0u8.encode(&mut hasher).unwrap();
+        0u8.encode(&mut hasher).unwrap();
         timest.encode(&mut hasher).unwrap();
         self.channel.encode(&mut hasher).unwrap();
         self.nick.encode(&mut hasher).unwrap();
@@ -98,6 +103,30 @@ impl Privmsg {
     }
 }
 
+struct SeenMsg {
+    id: MessageId,
+    is_self: bool,
+    seen_times: usize,
+}
+
+struct SeenMessages {
+    seen: Vec<SeenMsg>,
+}
+
+impl SeenMessages {
+    fn new() -> Self {
+        Self { seen: vec![] }
+    }
+
+    fn get_status(&self, id: &MessageId) -> Option<&SeenMsg> {
+        self.seen.iter().find(|s| s.id == *id)
+    }
+
+    fn push(&mut self, id: MessageId, is_self: bool) {
+        self.seen.push(SeenMsg { id, is_self, seen_times: 0 });
+    }
+}
+
 pub type DarkIrcPtr = Arc<DarkIrc>;
 
 pub struct DarkIrc {
@@ -108,7 +137,7 @@ pub struct DarkIrc {
     event_graph: EventGraphPtr,
     db: sled::Db,
 
-    seen_msgs: SyncMutex<Vec<MessageId>>,
+    seen_msgs: SyncMutex<SeenMessages>,
     nick: PropertyStr,
 }
 
@@ -169,7 +198,7 @@ impl DarkIrc {
             event_graph,
             db,
 
-            seen_msgs: SyncMutex::new(vec![]),
+            seen_msgs: SyncMutex::new(SeenMessages::new()),
             nick,
         });
         Ok(Pimpl::DarkIrc(self_))
@@ -221,31 +250,37 @@ impl DarkIrc {
                 }
             };
 
+            let mut timest = ev.timestamp;
+            let msg_id = privmsg.msg_id(timest);
             inf!(
-                "Relaying channel={}, ev_id={:?}, ev={:?}, privmsg={:?}",
-                privmsg.channel,
+                "Relaying ev_id={:?}, ev={ev:?}, msg_id={msg_id}, privmsg={privmsg:?}, timest={timest}",
                 ev.id(),
-                ev,
-                privmsg
             );
 
-            let timest = ev.timestamp;
+            let is_self = {
+                let mut is_self = false;
+                let mut seen = self.seen_msgs.lock().unwrap();
+                match seen.get_status(&msg_id) {
+                    Some(msg) => {
+                        is_self = msg.is_self;
+
+                        if !msg.is_self || msg.seen_times > 1 {
+                            warn!(target: "plugin::darkirc", "Skipping duplicate seen message: {msg_id}");
+                            continue
+                        }
+                    }
+                    None => {
+                        seen.push(msg_id.clone(), false);
+                    }
+                }
+                is_self
+            };
+
             // This is a hack to make messages appear sequentially in the UI
-            let mut adj_timest = timest;
             let now_timest = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
-            if timest.abs_diff(now_timest) < RECENT_TIME_DIST {
+            if !is_self && timest.abs_diff(now_timest) < RECENT_TIME_DIST {
                 d!("Applied timestamp correction: <{timest}> => <{now_timest}>");
-                adj_timest = now_timest;
-            }
-
-            let msg_id = privmsg.msg_id(timest);
-            {
-                let mut seen = self.seen_msgs.lock().unwrap();
-                if seen.contains(&msg_id) {
-                    warn!(target: "plugin::darkirc", "Skipping duplicate seen message: {msg_id}");
-                    continue
-                }
-                seen.push(msg_id.clone());
+                timest = now_timest;
             }
 
             // Strip off starting #
@@ -268,8 +303,8 @@ impl DarkIrc {
 
             let mut arg_data = vec![];
             channel.encode(&mut arg_data).unwrap();
-            ev.timestamp.encode(&mut arg_data).unwrap();
-            ev.id().as_bytes().encode(&mut arg_data).unwrap();
+            timest.encode(&mut arg_data).unwrap();
+            msg_id.encode(&mut arg_data).unwrap();
             nick.encode(&mut arg_data).unwrap();
             privmsg.msg.encode(&mut arg_data).unwrap();
 
@@ -287,14 +322,15 @@ impl DarkIrc {
         d!("method called: send({method_call:?})");
         assert!(method_call.send_res.is_none());
 
-        fn decode_data(data: &[u8]) -> std::io::Result<(String, String)> {
+        fn decode_data(data: &[u8]) -> std::io::Result<(Timestamp, String, String)> {
             let mut cur = Cursor::new(&data);
+            let timest = Timestamp::decode(&mut cur).unwrap();
             let channel = String::decode(&mut cur)?;
             let msg = String::decode(&mut cur)?;
-            Ok((channel, msg))
+            Ok((timest, channel, msg))
         }
 
-        let Ok((channel, msg)) = decode_data(&method_call.data) else {
+        let Ok((timest, channel, msg)) = decode_data(&method_call.data) else {
             err!("send() method invalid arg data");
             return true
         };
@@ -304,29 +340,37 @@ impl DarkIrc {
             panic!("self destroyed before send_method_task was stopped!");
         };
 
-        self_.handle_send(channel, msg).await;
+        self_.handle_send(timest, channel, msg).await;
 
         true
     }
 
-    async fn handle_send(&self, channel: String, msg: String) {
+    async fn handle_send(&self, timest: Timestamp, channel: String, msg: String) {
         let nick = self.nick.get();
 
         // Send text to channel
-        let timest = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
-        d!("Sending privmsg: {timest} #{channel}: <{nick}> {msg}");
+        d!("Sending privmsg: {timest} {channel}: <{nick}> {msg}");
         let msg = Privmsg::new(channel, nick, msg);
+        let evgr = self.event_graph.clone();
+        let mut event = event_graph::Event::new(serialize_async(&msg).await, &evgr).await;
+        event.timestamp = timest;
+        let msg_id = msg.msg_id(timest);
+
+        // Keep track of our own messages so we don't apply timestamp correction to them
+        // which messes up the msg id.
+        {
+            let mut seen = self.seen_msgs.lock().unwrap();
+            seen.push(msg_id.clone(), true);
+        }
 
         let mut arg_data = vec![];
         timest.encode_async(&mut arg_data).await.unwrap();
-        msg.msg_id(timest).encode_async(&mut arg_data).await.unwrap();
+        msg_id.encode_async(&mut arg_data).await.unwrap();
         msg.nick.encode_async(&mut arg_data).await.unwrap();
         msg.msg.encode_async(&mut arg_data).await.unwrap();
 
         // Broadcast the msg
 
-        let evgr = self.event_graph.clone();
-        let event = event_graph::Event::new(serialize_async(&msg).await, &evgr).await;
         if let Err(e) = evgr.dag_insert(&[event.clone()]).await {
             error!(target: "darkirc", "Failed inserting new event to DAG: {}", e);
         }

+ 1 - 1
bin/darkwallet/src/plugin/mod.rs

@@ -21,7 +21,7 @@ use std::sync::Arc;
 
 use crate::ExecutorPtr;
 
-mod darkirc;
+pub mod darkirc;
 pub use darkirc::{DarkIrc, DarkIrcPtr};
 
 #[async_trait]

+ 2 - 1
bin/darkwallet/src/ui/chatview/mod.rs

@@ -315,7 +315,7 @@ impl ChatView {
             return false
         };
 
-        //debug!(target: "ui::chatview", "method called: insert_line({method_call:?})");
+        //debug!(target: "ui::chatview", "method called: insert_unconf_line({method_call:?})");
         assert!(method_call.send_res.is_none());
 
         fn decode_data(data: &[u8]) -> std::io::Result<(Timestamp, MessageId, String, String)> {
@@ -445,6 +445,7 @@ impl ChatView {
             // Mark it as confirmed.
             debug!(target: "ui::chatview", "Mark sent message as confirmed");
         } else {
+            debug!(target: "ui::chatview", "Inserting new message");
             // Insert the privmsg since it doesn't already exist
             if msgbuf.insert_privmsg(timest, msg_id, nick, text).is_none() {
                 // Not visible so no need to redraw