Not logged in. · Lost password · Register
Forum: agsXMPP RSS
How to implement this feature?
Page:  1  2  3  next
Avatar
c3csystems #1
User title: Anshuman
Member since Jun 2006 · 6 posts · Location: Kharagpur, India
Group memberships: Members
Show profile · Link to this post
Subject: User is typing...
Hi all,

This is not exactly a agsXMPP library related...but you all must have seen this feature in many messengers. When you are chatting with a person, if the other guy types in his IM window, the title or status bar of your IM window displays text like "<nick of user you are chatting with> is typing a message" and so on.

How should I implement this feature?

One option is (a very lousy one :( ) that when the focus of my IM window is the text entry area, I should send a custom message to server to be delivered to the user I am chatting with and interpret it client side. But this would be too cumbersome and bandwidth consuming.

Is there any such feature already implemented? If not, please suggest some ideas.

Thank you again,

Anshuman
I believe we should all pay our taxes with smile; I tried, but they only accept cash!
Avatar
Alex #2
Member since Feb 2003 · 4317 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hello,

what you wanna do are message events. There are currently 2 JEP's.

The most current clients use JEP-0022 because its there for many years now. It also has a diplayed feature.
JEP-0085 is newer, which is the reason why not many clients support it today. But for only typing notifications i would prefer JEP-0085.
Both JEP's are supported in the agsXMPP SDK.


Alex
Avatar
c3csystems #3
User title: Anshuman
Member since Jun 2006 · 6 posts · Location: Kharagpur, India
Group memberships: Members
Show profile · Link to this post
Subject: What could I do without you...
Thanks Alex,

I am going through the links you provided. Thank you very much.
I believe we should all pay our taxes with smile; I tried, but they only accept cash!
Avatar
yeawsing #4
Member since Jul 2006 · 33 posts · Location: South Korea
Group memberships: Members
Show profile · Link to this post
Hi, c3csystems

This is my first attempt on ChatState but I still got some problem with ChatState.gone and I am not sure am I right or wrong using KeyDown and KeyUp.

  1. public void IncomingMessage(agsXMPP.protocol.client.Message msg)
  2. {
  3.             #region JEP-0085 Contact's Client Sends Content Message Reply With <active/> Notification
  4.             /*
  5.                 <message
  6.                     from='juliet@capulet.com/balcony'
  7.                     to='romeo@shakespeare.lit/orchard'
  8.                     type='chat'>
  9.                   <thread>act2scene2chat1</thread>
  10.                   <body>
  11.                     What man art thou that thus bescreen'd in night
  12.                     So stumblest on my counsel?
  13.                   </body>
  14.                   <active xmlns='http://jabber.org/protocol/chatstates'/>
  15.                 </message>
  16.             */
  17.             #endregion
  18.  
  19.             MsgThreadID = msg.Thread;
  20.  
  21.             // Once receive message from Contact Client we set ChatState Active
  22.             if (msg.Chatstate == Chatstate.active)
  23.             {
  24.                 IsChatStateActive = true;
  25.                 _HasReceiveChatStateActivation = HasReceiveChatStateActivation;
  26.             }
  27.             //else
  28.             //    MessageBox.Show("Contact Client Chat State is not actived");
  29.  
  30.             rtfChat.SelectionColor = Color.Red;
  31.             rtfChat.AppendText(_nickname + " said: ");
  32.             rtfChat.SelectionColor = Color.Black;
  33.             rtfChat.AppendText(msg.Body);
  34.             rtfChat.AppendText("\r\n");
  35.  
  36.             this.chatstatemsg.Text = StatusMessage;
  37. }
  38.  
  39. private void cmdSend_Click(object sender, System.EventArgs e)
  40. {
  41.     agsXMPP.protocol.client.Message msg = new agsXMPP.protocol.client.Message();
  42.  
  43.             if (!IsChatStateActive)
  44.             {
  45.                 _messageThreadID = Hash.Sha1Hash(Id.GetNextId() + _connection.MyJID.ToString() + m_Jid.ToString());
  46.             }
  47.  
  48.             IsChatStateActive = true;
  49.             _HasReceiveChatStateActivation = HasReceiveChatStateActivation;
  50.  
  51.             msg.Type = MessageType.chat;
  52.             msg.To = m_Jid;
  53.             msg.From = _connection.MyJID;
  54.             msg.Thread = MsgThreadID;
  55.             msg.Body = rtfSend.Text;
  56.             msg.Chatstate = Chatstate.active;
  57.            
  58.     _connection.Send(msg);
  59.     OutgoingMessage(msg);
  60.     rtfSend.Text = "";
  61. }
  62.  
  63. private void MessageCallback(object sender, agsXMPP.protocol.client.Message msg, object data)
  64. {
  65.             if (InvokeRequired)
  66.             {
  67.                 // Windows Forms are not Thread Safe, we need to invoke this :(
  68.                 // We're not in the UI thread, so we need to call BeginInvoke            
  69.                 BeginInvoke(new MessageCB(MessageCallback), new object[] { sender, msg, data });
  70.                 return;
  71.             }
  72.  
  73.             if (msg.Body != null)
  74.             {
  75.                 DateTime dt = DateTime.Now;
  76.                 ReceiveLastMessageDate = dt.ToString("D", DateTimeFormatInfo.InvariantInfo);
  77.                 ReceiveLastMessageTime = dt.ToString("T", DateTimeFormatInfo.InvariantInfo);
  78.  
  79.                 this.chatstatemsg.Text = "Last message received at " + ReceiveLastMessageTime + " on " + ReceiveLastMessageDate;
  80.                 IncomingMessage(msg);
  81.             }
  82.             else if (msg.Body == null && msg.Chatstate == Chatstate.composing)
  83.             {
  84.                 this.chatstatemsg.Text = _nickname + " is writing a message";
  85.             }
  86.             else if (msg.Body == null && msg.Chatstate == Chatstate.gone)
  87.             {
  88.                 IsChatStateActive = false;
  89.                 _isChatStateGone = true;
  90.             }
  91.             else if (msg.Body == null && msg.Chatstate == Chatstate.paused)
  92.             {
  93.                 timerChatStatePause.Enabled = true;
  94.             }
  95.             else if (msg.Body == null && msg.Chatstate == Chatstate.inactive)
  96.             {
  97.                 HasReceiveChatStateActivation = false;
  98.             }
  99.             else if (msg.Body == null && msg.Chatstate == Chatstate.active)
  100.             {
  101.                 HasReceiveChatStateActivation = true;
  102.             }
  103. }
  104.  
  105.         private void timerChatStatePause_Tick(object sender, EventArgs e)
  106.         {
  107.             this.chatstatemsg.Text = String.Empty;
  108.             timerChatStatePause.Enabled = false;
  109.  
  110.         }
  111.  
  112.         private void rtfSend_TextChanged(object sender, EventArgs e)
  113.         {
  114.             this.chatstatemsg.Text = String.Empty;
  115.  
  116.         }
  117.  
  118.         private void frmChat_KeyUp(object sender, KeyEventArgs e)
  119.         {
  120.             if (IsChatStateActive)
  121.             {
  122.                 #region JEP-0085 Example 10. User's Client Sends Standalone <paused/> Notification
  123.                 /*
  124.                    <message
  125.                         from='romeo@montague.net/orchard'
  126.                         to='juliet@capulet.com/balcony'
  127.                         type='chat'>
  128.                       <thread>act2scene2chat1</thread>
  129.                       <paused xmlns='http://jabber.org/protocol/chatstates'/>
  130.                     </message>
  131.                 */
  132.                 #endregion
  133.  
  134.                 if (HasReceiveChatStateActivation)
  135.                 {
  136.                     SendChatState(Chatstate.paused);
  137.                 }
  138.             }
  139.         }
  140.  
  141.         private void frmChat_KeyDown(object sender, KeyEventArgs e)
  142.         {
  143.             if (IsChatStateActive)
  144.             {
  145.                 #region JEP-0085 Example 9. User's Client Sends Standalone <composing/> Notification
  146.                 /*
  147.                     <message
  148.                         from='romeo@montague.net/orchard'
  149.                         to='juliet@capulet.com/balcony'
  150.                         type='chat'>
  151.                       <thread>act2scene2chat1</thread>
  152.                       <composing xmlns='http://jabber.org/protocol/chatstates'/>
  153.                     </message>
  154.                 */
  155.                 #endregion
  156.  
  157.                 if (HasReceiveChatStateActivation)
  158.                 {
  159.                     SendChatState(Chatstate.composing);
  160.                 }
  161.             }
  162.         }
  163.  
  164.         private void frmChat_FormClosing(object sender, FormClosingEventArgs e)
  165.         {
  166.             #region JEP-0085 Example 17. Contact's Client Sends Standalone <gone/> Notification
  167.             /*
  168.                 <message
  169.                     from='juliet@capulet.com/balcony'
  170.                     to='romeo@shakespeare.lit/orchard'
  171.                     type='chat'>
  172.                   <thread>act2scene2chat1</thread>
  173.                   <gone xmlns='http://jabber.org/protocol/chatstates'/>
  174.                 </message>
  175.             */
  176.             #endregion
  177.  
  178.             if (_isChatStateGone)
  179.             {
  180.                 return;
  181.             }
  182.  
  183.             SendChatState(Chatstate.gone);
  184.         }
  185.  
  186.         private void frmChat_Resize(object sender, EventArgs e)
  187.         {
  188.             if (IsChatStateActive)
  189.             {
  190.                 if (this.WindowState == FormWindowState.Minimized)
  191.                 {
  192.                     #region JEP-0085 Example 14. Contact's Client Sends Standalone <inactive/> Notification
  193.                     /*
  194.                     <message
  195.                         from='juliet@capulet.com/balcony'
  196.                         to='romeo@shakespeare.lit/orchard'
  197.                         type='chat'>
  198.                       <thread>act2scene2chat1</thread>
  199.                       <inactive xmlns='http://jabber.org/protocol/chatstates'/>
  200.                     </message>
  201.                     */
  202.                     #endregion
  203.  
  204.                     SendChatState(Chatstate.inactive);
  205.                     _isMinimize = true;
  206.                     HasReceiveChatStateActivation = false;
  207.                     return;
  208.                 }
  209.  
  210.                 if (this.WindowState == FormWindowState.Normal)
  211.                 {
  212.                     #region JEP-0085 Example 15. Contact's Client Sends Standalone <active/> Notification
  213.                     /*
  214.                     <message
  215.                         from='juliet@capulet.com/balcony'
  216.                         to='romeo@shakespeare.lit/orchard'
  217.                         type='chat'>
  218.                       <thread>act2scene2chat1</thread>
  219.                       <active xmlns='http://jabber.org/protocol/chatstates'/>
  220.                     </message>
  221.                     */
  222.                     #endregion
  223.  
  224.                     if (_isMinimize)
  225.                     {
  226.                         SendChatState(Chatstate.active);
  227.                         HasReceiveChatStateActivation = true;
  228.                         _isMinimize = false;
  229.                         return;
  230.                     }
  231.                     else
  232.                         return;
  233.                 }
  234.             }
  235.         }
  236.  
  237.         private void SendChatState(Chatstate chatStateEnum)
  238.         {
  239.             agsXMPP.protocol.client.Message msg = new agsXMPP.protocol.client.Message();
  240.  
  241.             msg.Type = MessageType.chat;
  242.             msg.To = m_Jid;
  243.             msg.From = _connection.MyJID;
  244.             msg.Thread = MsgThreadID;
  245.             msg.Chatstate = chatStateEnum;
  246.             _connection.Send(msg);
  247.         }

Hope someone can corrrect me.
I am still learning..., hope I can contribute back.
YS
Avatar
Alex #5
Member since Feb 2003 · 4317 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hello,

The gone chatstate is normally sent when you close the chat window and close the conversation.

I don't understand your code in the KeyUp and KeyDown events. For me it looks like you send a Chatstate on every KeyDown and KeyUp. If this is true then you are totally wrong. This would also result in tremendous c2s traffic and breaks the servers neck if some clients do something like that.

Alex
Avatar
yeawsing #6
Member since Jul 2006 · 33 posts · Location: South Korea
Group memberships: Members
Show profile · Link to this post
Hi Alex,

Thanks for the comment and you are right about the KeyDown and KeyUp.  So do u think if I use a timer for ChatState.composing and ChatState.paused is a better approach or if u have a good solution, can you please show me how.  Thanks

YS
I am still learning..., hope I can contribute back.
YS
Avatar
Alex #7
Member since Feb 2003 · 4317 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hello,

yes a timer would solve the problem. You send the paused if you stop typing.
Some reason could be:
  • if somebody started to compose a message then stops typing to think about the message he/she is actually composing
  • you could also stop typing because you leave your desk or get a phone call
  • or you decice not to send this message at all and clear the composing window

You can use a timer which run e.g. every 500ms in your chatwindow. Then have a local variable which stores the timestamp of the last input or last text change event of your composing control. When the timer runs compare DateTime.Now with the timestamp for the last input. If there was no input for some seconds then the user stopped typing. I would start with a tmespan of 3-5 seconds and see how it works. If you have sent the paused then you can send the composing again when the user starts typing (but only once).
Would be cool if you can post a reply how this works for you.

Alex
Avatar
yeawsing #8
Member since Jul 2006 · 33 posts · Location: South Korea
Group memberships: Members
Show profile · Link to this post
Hi, Alex I am not sure have I follow all your step.  But here is my new approach according to your idea.

I have added a timer to the frmChat constructor:

  1. public frmChat(Jid jid, XmppClientConnection con, string nickname)
  2. {
  3.     m_Jid      = jid;
  4.     _connection = con;
  5.     _nickname   = nickname;
  6.        
  7.     InitializeComponent();
  8.            
  9.     this.Text = "Chat with " + nickname;
  10.    
  11.     Util.ChatForms.Add(m_Jid.Bare.ToLower(), this);
  12.  
  13.             IsChatStateActive = false;
  14.             _HasReceiveChatStateActivation = true;
  15.  
  16.             this.chatstatemsg.Text = String.Empty;
  17.             ReceiveLastMessageDate = dt.ToString("D", DateTimeFormatInfo.InvariantInfo);
  18.             ReceiveLastMessageTime = dt.ToString("T", DateTimeFormatInfo.InvariantInfo);
  19.             SendLastMessageDate = dt.ToString("D", DateTimeFormatInfo.InvariantInfo);
  20.             SendLastMessageTime = dt.ToString("T", DateTimeFormatInfo.InvariantInfo);
  21.  
  22.             // Start timer every 500ms in ChatWindow
  23.             this.timerChat.Enabled = true;
  24.             this.timerChat.Start();
  25.  
  26.  
  27.     // Setup new Message Callback
  28.     con.MesagageGrabber.Add(jid, new BareJidComparer(), new MessageCB(MessageCallback), null);
  29. }

I have remove the KeyUp and KeyDown.  My current code now is:

  1. private void MessageCallback(object sender, agsXMPP.protocol.client.Message msg, object data)
  2. {
  3.             if (InvokeRequired)
  4.             {
  5.                 // Windows Forms are not Thread Safe, we need to invoke this :(
  6.                 // We're not in the UI thread, so we need to call BeginInvoke            
  7.                 BeginInvoke(new MessageCB(MessageCallback), new object[] { sender, msg, data });
  8.                 return;
  9.             }
  10.  
  11.             if (msg.Body != null)
  12.             {
  13.                 DateTime dt = DateTime.Now;
  14.                 ReceiveLastMessageDate = dt.ToString("D", DateTimeFormatInfo.InvariantInfo);
  15.                 ReceiveLastMessageTime = dt.ToString("T", DateTimeFormatInfo.InvariantInfo);
  16.  
  17.                 this.chatstatemsg.Text = "Last message received at " + ReceiveLastMessageTime + " on " + ReceiveLastMessageDate;
  18.                 IncomingMessage(msg);
  19.             }
  20.             else if (msg.Body == null && msg.Chatstate == Chatstate.composing)
  21.             {
  22.                 this.chatstatemsg.Text = _nickname + " is writing a message";
  23.             }
  24.             else if (msg.Body == null && msg.Chatstate == Chatstate.gone)
  25.             {
  26.                 IsChatStateActive = false;
  27.                 _isChatStateGone = true;
  28.             }
  29.             else if (msg.Body == null && msg.Chatstate == Chatstate.paused)
  30.             {
  31.                 this.chatstatemsg.Text = "Last message received at " + ReceiveLastMessageTime + " on " + ReceiveLastMessageDate;
  32.             }
  33.             else if (msg.Body == null && msg.Chatstate == Chatstate.inactive)
  34.             {
  35.                 HasReceiveChatStateActivation = false;
  36.             }
  37.             else if (msg.Body == null && msg.Chatstate == Chatstate.active)
  38.             {
  39.                 HasReceiveChatStateActivation = true;
  40.             }
  41. }
  42.  
  43.        private bool isComposing = false;
  44.        public bool IsComposing
  45.        {
  46.             get { return isComposing; }
  47.             set { isComposing = value; }
  48.         }
  49.  
  50.         private void rtfSend_TextChanged(object sender, EventArgs e)
  51.         {
  52.             DtLastInputText = DateTime.Now;
  53.             Debug.WriteLine("Current DateTime TexTChange: " + DtLastInputText.ToString());
  54.         }
  55.  
  56.         private DateTime dtLastInputText;
  57.         public DateTime DtLastInputText
  58.         {
  59.             get { return dtLastInputText; }
  60.             set { dtLastInputText = value; }
  61.         }
  62.    
  63.         private void frmChat_FormClosing(object sender, FormClosingEventArgs e)
  64.         {
  65.             #region JEP-0085 Example 17. Contact's Client Sends Standalone <gone/> Notification
  66.             /*
  67.                 <message
  68.                     from='juliet@capulet.com/balcony'
  69.                     to='romeo@shakespeare.lit/orchard'
  70.                     type='chat'>
  71.                   <thread>act2scene2chat1</thread>
  72.                   <gone xmlns='http://jabber.org/protocol/chatstates'/>
  73.                 </message>
  74.             */
  75.             #endregion
  76.  
  77.             if (_isChatStateGone)
  78.             {
  79.                 return;
  80.             }
  81.  
  82.             SendChatState(Chatstate.gone);
  83.         }
  84.  
  85.         private void frmChat_Resize(object sender, EventArgs e)
  86.         {
  87.             if (IsChatStateActive)
  88.             {
  89.                 if (this.WindowState == FormWindowState.Minimized)
  90.                 {
  91.                     #region JEP-0085 Example 14. Contact's Client Sends Standalone <inactive/> Notification
  92.                     /*
  93.                     <message
  94.                         from='juliet@capulet.com/balcony'
  95.                         to='romeo@shakespeare.lit/orchard'
  96.                         type='chat'>
  97.                       <thread>act2scene2chat1</thread>
  98.                       <inactive xmlns='http://jabber.org/protocol/chatstates'/>
  99.                     </message>
  100.                     */
  101.                     #endregion
  102.  
  103.                     SendChatState(Chatstate.inactive);
  104.                     _isMinimize = true;
  105.                     HasReceiveChatStateActivation = false;
  106.                     return;
  107.                 }
  108.  
  109.                 if (this.WindowState == FormWindowState.Normal)
  110.                 {
  111.                     #region JEP-0085 Example 15. Contact's Client Sends Standalone <active/> Notification
  112.                     /*
  113.                     <message
  114.                         from='juliet@capulet.com/balcony'
  115.                         to='romeo@shakespeare.lit/orchard'
  116.                         type='chat'>
  117.                       <thread>act2scene2chat1</thread>
  118.                       <active xmlns='http://jabber.org/protocol/chatstates'/>
  119.                     </message>
  120.                     */
  121.                     #endregion
  122.  
  123.                     if (_isMinimize)
  124.                     {
  125.                         SendChatState(Chatstate.active);
  126.                         HasReceiveChatStateActivation = true;
  127.                         _isMinimize = false;
  128.                         return;
  129.                     }
  130.                     else
  131.                         return;
  132.                 }
  133.             }
  134.         }
  135.  
  136.         private void SendChatState(Chatstate chatStateEnum)
  137.         {
  138.             agsXMPP.protocol.client.Message msg = new agsXMPP.protocol.client.Message();
  139.  
  140.             msg.Type = MessageType.chat;
  141.             msg.To = m_Jid;
  142.             msg.From = _connection.MyJID;
  143.             msg.Thread = MsgThreadID;
  144.             msg.Chatstate = chatStateEnum;
  145.             _connection.Send(msg);
  146.         }

At the begining, I tried to use the compareTimeStamp.Seconds but the problem was it will reset back to 0 after reach 60 sec.  Then I tried to use the
compareTimeStamp.TotalSeconds but it give me a decimal value.  I have tried to use the Math.abs(...) but still not working.  So I decide to cast it into Int.

Another thing I am not, do I need to check for the overflow on the Timer because eventually the timer is keep on running until the form is close.

  1.         private void timerChat_Tick(object sender, EventArgs e)
  2.         {
  3.             if (IsChatStateActive)
  4.             {
  5.                 if (HasReceiveChatStateActivation)
  6.                 {
  7.                     DateTime dt = DateTime.Now;
  8.                     TimeSpan compareTimeStamp = dt.Subtract(DtLastInputText);
  9.  
  10.                     if ((int)compareTimeStamp.TotalSeconds == 3)
  11.                     {
  12.                         #region JEP-0085 Example 10. User's Client Sends Standalone <paused/> Notification
  13.                         /*
  14.                         <message
  15.                             from='romeo@montague.net/orchard'
  16.                             to='juliet@capulet.com/balcony'
  17.                             type='chat'>
  18.                             <thread>act2scene2chat1</thread>
  19.                             <paused xmlns='http://jabber.org/protocol/chatstates'/>
  20.                         </message>
  21.                         */
  22.                         #endregion
  23.  
  24.                         SendChatState(Chatstate.paused);
  25.                         IsComposing = false;
  26.                     }
  27.                     else if ((int)compareTimeStamp.TotalSeconds == 0)
  28.                     {
  29.                         if (!IsComposing)
  30.                         {
  31.                             #region JEP-0085 Example 9. User's Client Sends Standalone <composing/> Notification
  32.                             /*
  33.                             <message
  34.                                 from='romeo@montague.net/orchard'
  35.                                 to='juliet@capulet.com/balcony'
  36.                                 type='chat'>
  37.                                 <thread>act2scene2chat1</thread>
  38.                                 <composing xmlns='http://jabber.org/protocol/chatstates'/>
  39.                             </message>
  40.                             */
  41.                             #endregion
  42.  
  43.                             SendChatState(Chatstate.composing);
  44.                             IsComposing = true;
  45.                         }
  46.                         else
  47.                             return;
  48.                     }
  49.                 }
  50.             }
  51.         }

Please guide me more and correct me if I am wrong... thanks
I am still learning..., hope I can contribute back.
YS
Avatar
Jabberer #9
Member since Feb 2006 · 249 posts
Group memberships: Members
Show profile · Link to this post
this looks good now.

2 small comments:

  1. ...
  2. if ((int)compareTimeStamp.TotalSeconds == 3)
  3. {
  4. ...

i would use >= 3 here. The timer could have some delay if your system is under very high cpu load for a while.

  1. ...
  2. else if ((int)compareTimeStamp.TotalSeconds == 0)
  3. {
  4.      if (!IsComposing)
  5.      {
  6. ...
i don't understand this exactly. In which case is the timepan 0?
Software Developer
AG-Software
Avatar
yeawsing #10
Member since Jul 2006 · 33 posts · Location: South Korea
Group memberships: Members
Show profile · Link to this post
Hi, Jabberer thanks for the comment.

When I did a Debug

  1.         private void timerChat_Tick(object sender, EventArgs e)
  2.         {
  3.             if (IsChatStateActive)
  4.             {
  5.                 if (HasReceiveChatStateActivation)
  6.                 {
  7.                     DateTime dt = DateTime.Now;
  8.                     TimeSpan compareTimeStamp = dt.Subtract(DtLastInputText);
  9.                     Debug.WriteLine("Compare Time: " + (int)compareTimeStamp.TotalSeconds.ToString());
  10.  
  11.            if ((int)compareTimeStamp.TotalSeconds >= 3)
  12.                     {
  13.                         SendChatState(Chatstate.paused);
  14.                         IsComposing = false;
  15.                     }
  16.                     else if ((int)compareTimeStamp.TotalSeconds == 0)
  17.                     {
  18.                         if (!IsComposing)
  19.                         {
  20.                             if (this.rtfSend.Text.Length == 0)
  21.                                 return;
  22.  
  23.                             SendChatState(Chatstate.composing);
  24.                             IsComposing = true;
  25.                         }
  26.                         else
  27.                             return;
  28.                     }
  29.                 }
  30.             }
  31.         }
Sorry for my bad explanation.  Hope you understand.
When the dt.Subtract(DtLastInputText), it always show 0(zero) when the rtfSend_TextChanged(object sender, EventArgs e).  Therefore I assume :(

And in the
  1.  
  2.         private bool isComposing = false;
  3.         public bool IsComposing
  4.         {
  5.             get { return isComposing; }
  6.             set { isComposing = value; }
  7.         }
  8.  
  9.         private void cmdSend_Click(object sender, System.EventArgs e)
  10.        {
  11.             ...
  12.             IsComposing = false;
  13.             ...
  14.        }
I am still learning..., hope I can contribute back.
YS
Avatar
Jabberer #11
Member since Feb 2006 · 249 posts
Group memberships: Members
Show profile · Link to this post
sorry i don't understand what you mean, but make sure that:
  • you send the composing only once until the message is sent.
  • If the message is sent and the user is typing a new message then of course you send it once again.
  • If the user stopped typing and you have sent the paused, and starts typing again now then sent it once again
Software Developer
AG-Software
Avatar
yeawsing #12
Member since Jul 2006 · 33 posts · Location: South Korea
Group memberships: Members
Show profile · Link to this post
Thanks again.

I will have it check and debug more on this matter again.  If I get a better result, I will post it again for u guys to review. :)
  • you send the composing only once until the message is sent.
  • If the message is sent and the user is typing a new message then of course you send it once again.
  • If the user stopped typing and you have sent the paused, and starts typing again now then sent it once again
I am still learning..., hope I can contribute back.
YS
Avatar
Jabberer #13
Member since Feb 2006 · 249 posts
Group memberships: Members
Show profile · Link to this post
to clarify again.
The timer should be used only to detect inactivity of the user and send the paused event.
Software Developer
AG-Software
Avatar
yeawsing #14
Member since Jul 2006 · 33 posts · Location: South Korea
Group memberships: Members
Show profile · Link to this post
Hi Jabberer,

After reading your last two post I rethink again:

to clarify again.
The timer should be used only to detect inactivity of the user and send the paused event.

i don't understand this exactly. In which case is the timepan 0?

I have made the following changes and it work great now for composing and paused.

  1.         private void cmdSend_Click(object sender, System.EventArgs e)
  2.         {
  3.             ...
  4.             ...
  5.             // After we send a message, send a Chatstate.paused and stop the timerChat
  6.             if (IsComposing)
  7.             {
  8.                 SendChatState(Chatstate.paused);
  9.                 IsComposing = false;
  10.                 timerChat.Stop();
  11.                 Debug.WriteLine("Send Paused");
  12.             }
  13.         }
  14.  
  15.         private bool isComposing = false;
  16.         public bool IsComposing
  17.         {
  18.             get { return isComposing; }
  19.             set { isComposing = value; }
  20.         }
  21.  
  22.         private DateTime dtLastInputText;
  23.         public DateTime DtLastInputText
  24.         {
  25.             get { return dtLastInputText; }
  26.             set { dtLastInputText = value; }
  27.         }
  28.  
  29.         private void rtfSend_TextChanged(object sender, EventArgs e)
  30.         {
  31.             DtLastInputText = DateTime.Now;
  32.             Debug.WriteLine("Current DateTime TexTChange: " + DtLastInputText.ToString());
  33.             timerChat.Enabled = true;
  34.             if (!IsComposing)
  35.             {
  36.                 #region JEP-0085 Example 9. User's Client Sends Standalone <composing/> Notification
  37.                 /*
  38.                             <message
  39.                                 from='romeo@montague.net/orchard'
  40.                                 to='juliet@capulet.com/balcony'
  41.                                 type='chat'>
  42.                                 <thread>act2scene2chat1</thread>
  43.                                 <composing xmlns='http://jabber.org/protocol/chatstates'/>
  44.                             </message>
  45.                             */
  46.                 #endregion
  47.                
  48.                 // Start or Restart composing
  49.                 SendChatState(Chatstate.composing);
  50.                 IsComposing = true;
  51.                 Debug.WriteLine("Send Composing");
  52.             }
  53.             else
  54.             {
  55.                 Debug.WriteLine("Still Composing: " + rtfSend.Text);
  56.                 return;
  57.             }
  58.         }
  59.  
  60.         private void timerChat_Tick(object sender, EventArgs e)
  61.         {
  62.             if (IsChatStateActive)
  63.             {
  64.                 if (HasReceiveChatStateActivation)
  65.                 {
  66.                     DateTime dt = DateTime.Now;
  67.                     TimeSpan compareTimeStamp = dt.Subtract(DtLastInputText);
  68.                    
  69.                     // After some period of time user didn't type anything, we send a Chatstate.paused
  70.                     if ((int)compareTimeStamp.TotalSeconds >= 3)
  71.                     {
  72.                         #region JEP-0085 Example 10. User's Client Sends Standalone <paused/> Notification
  73.                         /*
  74.                         <message
  75.                             from='romeo@montague.net/orchard'
  76.                             to='juliet@capulet.com/balcony'
  77.                             type='chat'>
  78.                             <thread>act2scene2chat1</thread>
  79.                             <paused xmlns='http://jabber.org/protocol/chatstates'/>
  80.                         </message>
  81.                         */
  82.                         #endregion
  83.  
  84.                         SendChatState(Chatstate.paused);
  85.                         IsComposing = false;
  86.                         timerChat.Stop();
  87.                         Debug.WriteLine("Send Paused");
  88.                     }
  89.                 }
  90.             }
  91.         }

Please correct me again, if I am still missing something here.
I am still learning..., hope I can contribute back.
YS
Avatar
yeawsing #15
Member since Jul 2006 · 33 posts · Location: South Korea
Group memberships: Members
Show profile · Link to this post
One thing I am not sure about was the cmdSend_Click.  When this cmdSend_Click event execute, it will send a message which include Chatstate.active

  1. private void cmdSend_Click(object sender, System.EventArgs e)
  2. {
  3.     agsXMPP.protocol.client.Message msg = new agsXMPP.protocol.client.Message();
  4.     ...
  5.     msg.Type = MessageType.chat;
  6.     msg.To = m_Jid;
  7.     msg.From = _connection.MyJID;
  8.     msg.Thread = MsgThreadID;
  9.     msg.Body = rtfSend.Text;
  10.     msg.Chatstate = Chatstate.active;
  11.  
  12.     _connection.Send(msg);
  13.     if (IsComposing)
  14.     {
  15.         SendChatState(Chatstate.paused); // Do I need to send this mesg?
  16.         IsComposing = false;
  17.         timerChat.Stop();
  18.         Debug.WriteLine("Send Paused");
  19.     }

So, do I need to send that Chatstate.paused again?
I am still learning..., hope I can contribute back.
YS
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Page:  1  2  3  next
Forum: agsXMPP RSS