powered by Jive Software

Chat markers support in smack (xep-0333)


#1

Hello,

I am working on a xmpp client application for android. the ios version will have support for chat markers through xmpp framework (xmpp framework implements xep-0333)

it would be great if the android version had the same feature.

I was wondering if there was any plan to support chat markers in smack. otherwise, any hint on how to implement it ?

thank you for your help.


#2

Hi there,

At this moment Smack has support for this extension in experimental but I couldn’t finde snippet of code, examples or javadoc to understand how to use it, I tried reading the source code but I couldn’t understand how to use it.

I create a question about this in SO hoping find some help.
@Paul_Schaub do you know how to do it? or do know someone that can give me a hand with this?


#3

The code is very basic, but should nevertheless be easy to use.

Basically you use the ChatMarkersManager to announce support to the server and contacts.

In order to signal that you for example displayed a message, you have to send another message which contains a DisplayedExtension with the ID of the displayed message.

In order to determine if a contact displayed a message, you have to keep listening for messages that contain a DisplayedExtension.

Other events like Acknowledgement of messages are done analogue.

As I said, that’s a little bit of manual work, but definitely doable. If you come up with an automated, more convenient solution, please feel free to contribute back to Smack :slight_smile:


#4

Thank you for that @Paul_Schaub ,

It seems like I will contribute to Smack because what I found:
I tried what you said and it works only for sending ChatMarkersElements.MarkableExtension in a Message.
It only works with that cuz I didn’t wanna touch low layers of Smack and I tried with IncomingChatMessageListener and OutgoingChatMessageListener. What I found is that inside of ChatManager when a new stanza of type message arrives, it checks if it has body, if the message has no body, the stanza is ignored by ChatManager and never reach the newIncomingMessage() from IncomingChatMessageListener.

This is the code I’m talking about in ChatManager:

connection.addSyncStanzaListener(new StanzaListener() {
            @Override
            public void processStanza(Stanza stanza) {
                final Message message = (Message) stanza;
                if (!shouldAcceptMessage(message)) {
                    return;
                }

                final Jid from = message.getFrom();
                final EntityFullJid fullFrom = from.asEntityFullJidOrThrow();
                final EntityBareJid bareFrom = fullFrom.asEntityBareJid();
                final Chat chat = chatWith(bareFrom);
                chat.lockedResource = fullFrom;

                asyncButOrdered.performAsyncButOrdered(chat, new Runnable() {
                    @Override
                    public void run() {
                        for (IncomingChatMessageListener listener : incomingListeners) {
                            listener.newIncomingMessage(bareFrom, message, chat);
                        }
                    }
                });

            }
        }, INCOMING_MESSAGE_FILTER);

And that is a problem in my case because xep-0333 says:

When the recipient sends a Chat Marker, it SHOULD ensure that the message stanza contains only the Chat Marker child element and optionally (when appropriate) a thread child element. Naturally, intermediate entities might add other extension elements to the message when routing or delivering the receipt message, e.g., a delay…

So, I’m thinking in add something very similar to ChatStateManager and its interface ChatStateListener.

What do you thing about this?


#5

That sounds perfectly reasonable to me :slight_smile:


#6

Ok, I developed what I said but I’m not sure if it meets what it needs to be part of the library :sweat_smile: and I have some questions. Should I create a PR or just post the code in stackoverflow question @Paul_Schaub.

This is the current code


#7

I think it can’t hurt to open a PR :wink: The worst thing that might happen is, that the PR is not accepted, but my first impression (looked briefly over the code) is positive :slight_smile:


#8

ok! I will do it today


#9

hi @Paul_Schaub,
can you take a look https://github.com/igniterealtime/Smack/pull/256 and tell me what do you think? :slight_smile:


#10

I really like it. There are some minor things I’d change, but all in all its nice :slight_smile:


#11

I have updated the PR, can you take a look at it? @Paul_Schaub. Thx


#12

I’m fine with your PR, but I don’t have the last word in this :smiley:. Better ask @Flow :slight_smile:.


#13

Now that we have a merge, I think we can mark as resolved this post right?


#14

I don’t know, the unit test coverage is basically not existent.

I also had to remove some flawed methods in https://github.com/igniterealtime/Smack/commit/0fa6fb946c3fda93ccec3bd01f810025306248b3. Smack should provide an easy to use high level API. What I had expected are convinience methods that are passed a Message, which would check if the message is markable, and if so, sends the displayed and acknowledged marker. Note that I deliberately omitted the received chat marker, as those could probably be send automatically by Smack.

I think this is far from finished.


#15

Ok, I’m going to work on missing methods as you explain.


#16

A new PR XEP-0333 improvement part 2
we have those changes running in an app working like a charm :smiley: .

If that PR is ok, I think we only are missing the testing part right? so can I have some advice to do it? example or something like that? because I saw a little bit and the testing code for Smack library isn’t easy to read.


#17

Sorry for the late answer.

There are two kinds of tests in Smack. There are JUnit tests, which test basic stuff like the elements and providers and methods that are not depending on a state too much. Those tests are used to calculate code coverage.

Secondly there are integration tests, which are run on a life connection. Those are used to validate, that the codes functionality is working as intended. For example you could use that to verify, if your listeners are working by simulating simple scenarios the way a user would do (A sends a message to B, B then marks the message as read, A receives the read maker…). It is also not uncommon, that those tests uncover bugs in the server :wink: There is some documentation about integration tests, but its probably a good idea to look into the other integration tests to figure out how they work :slight_smile:

JUnit tests are placed in the same module as the code you wrote, but in the test package.

Integration tests are normally placed in the smack-integration-test module.


#18

Ideally the unit tests are not only testing basic stuff, but also high level APIs like the Managers. It is sadly just not often done because it is much more effort. But you could look for example at Henning’s legacy file transfer unit tests, which do also test non-basic high level API.

It is easier to write integration tests for high level API. The downside is, of course, that those require a real server to run against. That is why unit tests are preferable over integration tests.