Hello. I'd like to commit chatstates_iris and maybe jabber_gone I'm posting here in order to ask for review because it may be considered as new feature. patches are quite small anyway.
BACKGROUND: Currently, Kopete uses JEP-0022 [1] for typing notification. Most of ancient client implement it. Anyway, new client now implement JEP-0085 [2] . Some client implement only it (gtalk, libgaim based clients, ...) PATCHES: the attached chatstates_iris.diff is a patch against libiris (in the 0.12 branch) to implement the new jep on the old one. I'd like to commit it, this is not really a new feature, since users may think typing notification are broken. (we received already a bug report [3]) The second patch (jabber_gone) is a patch to Kopete 0.12, that implement a new feature provided by JEP-0085: the ability to know when the user closes his window This is a new feature, should I commit ? PSI: the psi guys have also implemented the JEP-0085, but a bit differently: (see the chatstates_psi.diff patch) their way is more complex, but more low)level to the protocol itself. And it require much ore change in the client. We probably should go that way in KDE4 (i only had their patch after having implemented it) [1] http://www.jabber.org/jeps/jep-0022.html [2] http://www.jabber.org/jeps/jep-0085.html [3] https://bugs.kde.org/show_bug.cgi?id=121507 PS: i wanted to also implement the jep-0183 , but it's too late, i must have done that yesterday :-) .
Index: iris/include/im.h
===================================================================
--- iris/include/im.h (revision 525193)
+++ iris/include/im.h (working copy)
@@ -49,7 +49,7 @@
typedef QValueList<Url> UrlList;
typedef QMap<QString, QString> StringMap;
typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent,
- ComposingEvent, CancelEvent } MsgEvent;
+ ComposingEvent, CancelEvent, InactiveEvent, GoneEvent }
MsgEvent;
class Message
{
Index: iris/xmpp-im/types.cpp
===================================================================
--- iris/xmpp-im/types.cpp (revision 525193)
+++ iris/xmpp-im/types.cpp (working copy)
@@ -544,6 +544,8 @@
else
x.appendChild(s.createTextElement("jabber:x:event","id",d->eventId));
}
+ else
+ s.appendChild( s.createElement(NS_CHATSTATES ,
"active" ) );
for(QValueList<MsgEvent>::ConstIterator ev =
d->eventList.begin(); ev != d->eventList.end(); ++ev) {
switch (*ev) {
@@ -558,14 +560,26 @@
break;
case ComposingEvent:
x.appendChild(s.createElement("jabber:x:event", "composing"));
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "composing" ) );
break;
case CancelEvent:
- // Add nothing
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "paused" ) );
break;
+ case InactiveEvent:
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "inactive" ) );
+ break;
+ case GoneEvent:
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "gone" ) );
+ break;
}
}
s.appendChild(x);
- }
+ }
+
// xencrypted
if(!d->xencrypted.isEmpty())
@@ -595,6 +609,7 @@
d->subject.clear();
d->body.clear();
d->thread = QString();
+ d->eventList.clear();
QDomElement root = s.element();
@@ -631,6 +646,33 @@
}
}
}
+ else if (e.namespaceURI() == NS_CHATSTATES)
+ {
+ if(e.tagName() == "active")
+ {
+ //like in JEP-0022 we let the client
know that we can receive ComposingEvent
+ // (we can do that according to §4.6
of the JEP-0085)
+ d->eventList += ComposingEvent;
+ d->eventList += InactiveEvent;
+ d->eventList += GoneEvent;
+ }
+ else if (e.tagName() == "composing")
+ {
+ d->eventList += ComposingEvent;
+ }
+ else if (e.tagName() == "paused")
+ {
+ d->eventList += CancelEvent;
+ }
+ else if (e.tagName() == "inactive")
+ {
+ d->eventList += InactiveEvent;
+ }
+ else if (e.tagName() == "gone")
+ {
+ d->eventList += GoneEvent;
+ }
+ }
else {
//printf("extension element: [%s]\n",
e.tagName().latin1());
}
@@ -664,7 +706,6 @@
}
// events
- d->eventList.clear();
nl = root.elementsByTagNameNS("jabber:x:event", "x");
if (nl.count()) {
nl = nl.item(0).childNodes();
Index: iris/xmpp-core/protocol.h
===================================================================
--- iris/xmpp-core/protocol.h (revision 525193)
+++ iris/xmpp-core/protocol.h (working copy)
@@ -37,6 +37,7 @@
#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind"
#define NS_XHTML_IM "http://jabber.org/protocol/xhtml-im"
#define NS_XHTML "http://www.w3.org/1999/xhtml"
+#define NS_CHATSTATES "http://jabber.org/protocol/chatstates"
namespace XMPP
{
Index: jabbercontact.h
===================================================================
--- jabbercontact.h (revision 525193)
+++ jabbercontact.h (working copy)
@@ -255,16 +255,17 @@
* Indicates whether the vCard is currently
* being updated or not.
*/
- bool mVCardUpdateInProgress;
+ bool mVCardUpdateInProgress :1;
- bool mRequestComposingEvent;
- bool mRequestOfflineEvent;
- bool mRequestDisplayedEvent;
- bool mRequestDeliveredEvent;
+ bool mRequestComposingEvent :1;
+ bool mRequestOfflineEvent :1;
+ bool mRequestDisplayedEvent :1;
+ bool mRequestDeliveredEvent :1;
+ bool mRequestGoneEvent :1;
/**
* tell if the disco#info has been done for this contact.
*/
- bool mDiscoDone;
+ bool mDiscoDone :1;
QString mLastReceivedMessageId;
QTimer *m_syncTimer;
Index: libiris/iris/include/im.h
===================================================================
--- libiris/iris/include/im.h (revision 525193)
+++ libiris/iris/include/im.h (working copy)
@@ -49,7 +49,7 @@
typedef QValueList<Url> UrlList;
typedef QMap<QString, QString> StringMap;
typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent,
- ComposingEvent, CancelEvent } MsgEvent;
+ ComposingEvent, CancelEvent, InactiveEvent, GoneEvent }
MsgEvent;
class Message
{
Index: libiris/iris/xmpp-im/types.cpp
===================================================================
--- libiris/iris/xmpp-im/types.cpp (revision 525193)
+++ libiris/iris/xmpp-im/types.cpp (working copy)
@@ -544,6 +544,8 @@
else
x.appendChild(s.createTextElement("jabber:x:event","id",d->eventId));
}
+ else
+ s.appendChild( s.createElement(NS_CHATSTATES ,
"active" ) );
for(QValueList<MsgEvent>::ConstIterator ev =
d->eventList.begin(); ev != d->eventList.end(); ++ev) {
switch (*ev) {
@@ -558,14 +560,26 @@
break;
case ComposingEvent:
x.appendChild(s.createElement("jabber:x:event", "composing"));
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "composing" ) );
break;
case CancelEvent:
- // Add nothing
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "paused" ) );
break;
+ case InactiveEvent:
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "inactive" ) );
+ break;
+ case GoneEvent:
+ if (d->body.isEmpty())
+ s.appendChild(
s.createElement(NS_CHATSTATES , "gone" ) );
+ break;
}
}
s.appendChild(x);
- }
+ }
+
// xencrypted
if(!d->xencrypted.isEmpty())
@@ -595,6 +609,7 @@
d->subject.clear();
d->body.clear();
d->thread = QString();
+ d->eventList.clear();
QDomElement root = s.element();
@@ -631,6 +646,33 @@
}
}
}
+ else if (e.namespaceURI() == NS_CHATSTATES)
+ {
+ if(e.tagName() == "active")
+ {
+ //like in JEP-0022 we let the client
know that we can receive ComposingEvent
+ // (we can do that according to §4.6
of the JEP-0085)
+ d->eventList += ComposingEvent;
+ d->eventList += InactiveEvent;
+ d->eventList += GoneEvent;
+ }
+ else if (e.tagName() == "composing")
+ {
+ d->eventList += ComposingEvent;
+ }
+ else if (e.tagName() == "paused")
+ {
+ d->eventList += CancelEvent;
+ }
+ else if (e.tagName() == "inactive")
+ {
+ d->eventList += InactiveEvent;
+ }
+ else if (e.tagName() == "gone")
+ {
+ d->eventList += GoneEvent;
+ }
+ }
else {
//printf("extension element: [%s]\n",
e.tagName().latin1());
}
@@ -664,7 +706,6 @@
}
// events
- d->eventList.clear();
nl = root.elementsByTagNameNS("jabber:x:event", "x");
if (nl.count()) {
nl = nl.item(0).childNodes();
Index: libiris/iris/xmpp-core/protocol.h
===================================================================
--- libiris/iris/xmpp-core/protocol.h (revision 525193)
+++ libiris/iris/xmpp-core/protocol.h (working copy)
@@ -37,6 +37,7 @@
#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind"
#define NS_XHTML_IM "http://jabber.org/protocol/xhtml-im"
#define NS_XHTML "http://www.w3.org/1999/xhtml"
+#define NS_CHATSTATES "http://jabber.org/protocol/chatstates"
namespace XMPP
{
Index: jabberchatsession.h
===================================================================
--- jabberchatsession.h (revision 525193)
+++ jabberchatsession.h (working copy)
@@ -40,7 +40,9 @@
JabberChatSession ( JabberProtocol *protocol, const JabberBaseContact
*user,
Kopete::ContactPtrList
others, const QString &resource = "",
const char *name = 0 );
-
+
+ ~JabberChatSession();
+
/**
* @brief Get the local user in the session
* @return the local user in the session, same as account()->myself()
Index: jabbercontact.cpp
===================================================================
--- jabbercontact.cpp (revision 525193)
+++ jabbercontact.cpp (working copy)
@@ -117,6 +117,7 @@
mRequestDisplayedEvent = false;
mRequestDeliveredEvent = false;
mRequestComposingEvent = false;
+ mRequestGoneEvent = false;
mDiscoDone = false;
}
@@ -294,14 +295,25 @@
{
mManager->receivedEventNotification( i18n("Message
stored on the server, contact offline") );
}
+ else if (message.containsEvent ( XMPP::GoneEvent ) )
+ {
+ if(mManager->view(
Kopete::Contact::CannotCreate ))
+ { //show an internal message if the user has
not already closed his window
+ Kopete::Message m=Kopete::Message (
this, mManager->members(),
+ i18n("%1 has ended their
participation in the chat session.").arg(metaContact()->displayName()),
+ Kopete::Message::Internal );
+ mManager->appendMessage ( m,
message.from().resource () );
+ }
+ }
}
else
// Then here could be event notification requests
{
- mRequestComposingEvent = message.containsEvent (
XMPP::ComposingEvent ) ? true : false;
- mRequestOfflineEvent = message.containsEvent (
XMPP::OfflineEvent ) ? true : false;
- mRequestDeliveredEvent = message.containsEvent (
XMPP::DeliveredEvent ) ? true : false;
- mRequestDisplayedEvent = message.containsEvent (
XMPP::DisplayedEvent) ? true : false;
+ mRequestComposingEvent = message.containsEvent (
XMPP::ComposingEvent );
+ mRequestOfflineEvent = message.containsEvent (
XMPP::OfflineEvent );
+ mRequestDeliveredEvent = message.containsEvent (
XMPP::DeliveredEvent );
+ mRequestDisplayedEvent = message.containsEvent (
XMPP::DisplayedEvent);
+ mRequestGoneEvent= message.containsEvent (
XMPP::GoneEvent);
}
}
@@ -1463,6 +1475,8 @@
return mRequestComposingEvent;
else if ( event == CancelEvent )
return mRequestComposingEvent;
+ else if ( event == GoneEvent )
+ return mRequestGoneEvent;
else
return false;
}
Index: jabberchatsession.cpp
===================================================================
--- jabberchatsession.cpp (revision 525193)
+++ jabberchatsession.cpp (working copy)
@@ -74,6 +74,12 @@
}
+JabberChatSession::~JabberChatSession( )
+{
+ sendNotification( XMPP::GoneEvent );
+}
+
+
void JabberChatSession::slotUpdateDisplayName ()
{
kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << endl;
@@ -310,6 +316,7 @@
}
+
#include "jabberchatsession.moc"
// vim: set noet ts=4 sts=4 sw=4:
Sun Feb 26 22:20:50 CET 2006 Remko Troncon <[EMAIL PROTECTED]>
* Chat states.
diff -rN -u old-psi-mainline/iris/include/im.h new-psi-mainline/iris/include/im.h
--- old-psi-mainline/iris/include/im.h 2006-04-01 15:42:18.000000000 +0200
+++ new-psi-mainline/iris/include/im.h 2006-04-01 15:42:18.000000000 +0200
@@ -51,6 +51,8 @@
typedef QMap<QString, QString> StringMap;
typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent,
ComposingEvent, CancelEvent } MsgEvent;
+ typedef enum { StateNone, StateActive, StateComposing, StatePaused,
+ StateInactive, StateGone } ChatState;
class Message
{
@@ -96,6 +98,10 @@
bool containsEvents() const;
bool containsEvent(MsgEvent e) const;
void addEvent(MsgEvent e);
+
+ // JEP-0085
+ ChatState chatState() const;
+ void setChatState(ChatState);
// JEP-0027
QString xencrypted() const;
@@ -286,6 +292,7 @@
bool canGroupchat() const;
bool canVoice() const;
bool canDisco() const;
+ bool canChatState() const;
bool isGateway() const;
bool haveVCard() const;
diff -rN -u old-psi-mainline/iris/xmpp-im/types.cpp new-psi-mainline/iris/xmpp-im/types.cpp
--- old-psi-mainline/iris/xmpp-im/types.cpp 2006-04-01 15:42:18.000000000 +0200
+++ new-psi-mainline/iris/xmpp-im/types.cpp 2006-04-01 15:42:19.000000000 +0200
@@ -192,6 +192,7 @@
QList<MsgEvent> eventList;
QString eventId;
QString xencrypted, invite;
+ ChatState chatState;
bool spooled, wasEncrypted;
};
@@ -210,6 +211,7 @@
d->spooled = false;
d->wasEncrypted = false;
d->errorCode = -1;*/
+ d->chatState = StateNone;
}
//! \brief Constructs a copy of Message object
@@ -422,6 +424,16 @@
}
}
+ChatState Message::chatState() const
+{
+ return d->chatState;
+}
+
+void Message::setChatState(ChatState state)
+{
+ d->chatState = state;
+}
+
QString Message::xencrypted() const
{
return d->xencrypted;
@@ -544,6 +556,30 @@
s.appendChild(x);
}
+ // chat state
+ QString chatStateNS = "http://jabber.org/protocol/chatstates";
+ if (d->chatState != StateNone) {
+ switch(d->chatState) {
+ case StateActive:
+ s.appendChild(s.createElement(chatStateNS, "active"));
+ break;
+ case StateComposing:
+ s.appendChild(s.createElement(chatStateNS, "composing"));
+ break;
+ case StatePaused:
+ s.appendChild(s.createElement(chatStateNS, "paused"));
+ break;
+ case StateInactive:
+ s.appendChild(s.createElement(chatStateNS, "inactive"));
+ break;
+ case StateGone:
+ s.appendChild(s.createElement(chatStateNS, "gone"));
+ break;
+ default:
+ break;
+ }
+ }
+
// xencrypted
if(!d->xencrypted.isEmpty())
s.appendChild(s.createTextElement("jabber:x:encrypted", "x", d->xencrypted));
@@ -646,6 +682,25 @@
d->eventList += CancelEvent;
}
+ // Chat states
+ QString chatStateNS = "http://jabber.org/protocol/chatstates";
+ t = root.elementsByTagNameNS(chatStateNS, "active").item(0).toElement();
+ if(!t.isNull())
+ d->chatState = StateActive;
+ t = root.elementsByTagNameNS(chatStateNS, "composing").item(0).toElement();
+ if(!t.isNull())
+ d->chatState = StateComposing;
+ t = root.elementsByTagNameNS(chatStateNS, "paused").item(0).toElement();
+ if(!t.isNull())
+ d->chatState = StatePaused;
+ t = root.elementsByTagNameNS(chatStateNS, "inactive").item(0).toElement();
+ if(!t.isNull())
+ d->chatState = StateInactive;
+ t = root.elementsByTagNameNS(chatStateNS, "gone").item(0).toElement();
+ if(!t.isNull())
+ d->chatState = StateGone;
+
+
// xencrypted
t = root.elementsByTagNameNS("jabber:x:encrypted", "x").item(0).toElement();
if(!t.isNull())
@@ -1488,6 +1543,15 @@
return test(ns);
}
+#define FID_CHATSTATE "http://jabber.org/protocol/chatstates"
+bool Features::canChatState() const
+{
+ QStringList ns;
+ ns << FID_CHATSTATE;
+
+ return test(ns);
+}
+
#define FID_VCARD "vcard-temp"
bool Features::haveVCard() const
{
pgpMFYFEu2rpc.pgp
Description: PGP signature
_______________________________________________ kopete-devel mailing list [email protected] https://mail.kde.org/mailman/listinfo/kopete-devel
