Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

How to filter simpleChat messages (private chat)

Avatar

Former Community Member

So I tried to find the solution, but after several hours, I can't find how to do it.

My use case:

There is one host for a room. Others users in the room can only talk to the host, and the users can only see their private discussion with the host. Users can see the chat component only when the host is connected.

The host use another application in which he can see the list of users who are talking to him. He can select a user in the list, and he see a simple chat with only the messages between him and the selected user.

What I have completed (I think it can help others in the future, and maybe there are better way to do it):

* In the user application: use the userManager property of your ConnectSessionContainer. It has an arrayCollection named hostCollection concerning the hosts who are currently connected.

In my case, I put the chat components into a container, and use a binding to the visible property:

visible="{connectSession.userManager.hostCollection.length>0}"

You can also add an event listener to the userManager and listen for UserEvent.USER_CREATE and USER_REMOVE and check if event.userDescriptor.role==100  or checking the hostCollection.length of the userManager again.

* If you subclass simpleClass, you can access to the _toCombo which is the combo box of the chat.

You can set its visible property to false, and set its selectedItem to the first object in its dataprovider which role is equal to 100 in order to force the chat to be private with the host.

* In the host application, you can create a list that use the ConnectSessionContainer.userManager.audienceCollection as dataProvider to have a list of the users.

It's easy to set the combobox of the simple chat to speak only to the selected user, but what I haven't been able to do is to filter the history to only show the conversation with the selected user, and not other messages, without creating several rooms.

I looked into the source code, but the history property of the simpleChatModel is just a string, and haven't find an easy way to filter it.

I looked for an arrayCollection of the history nodes, because I could have use the filter property of the collection, but I haven't find it.

So, where should I look, and what is the best way to filter the history using the recipient_Id?

Thank you for your help...

Sorry for the long post, but maybe it will help someone in the future...

1 Accepted Solution

Avatar

Correct answer by
Former Community Member

Hi,

What other parts you have been doing is perfectly fine. So, I believe on

the host side you want to filter so that when as an host , you select an

user and click him, it should only show the chat between that user and

the host.

Though there is no direct way as by default, we show all messages to the

chat directed to a user, but still I can give some pointers.

What you need to do is either modify the formatMessageDescriptor method

in SimpleChatDescriptor or subsclass it .

Try to may be add another parameter to that function like

public function

formatMessageDescriptor(p_msgDesc:ChatMessageDescriptor,p_targetedUserID:String=null):String

and when you create a SimpleChat object, make sure that in the calls to

this method, you somehow pass the userID of only the user you want to

see the messages with. In a more generic way, this parameter could be an

array which contains the userIDs of only those users whose chat you want

to see in a window.

Then inside the function, make sure you filter it by doing something

like this

if ( p_msgDesc.recipientID == p_targetedUserID ) {

// you would only add those messages

}else {

// do nothing for that message i.e. return ""

}

If you are using an array of targetedUserIDs , then in a loop check if

it matches with the recipientID and if so, add that message.

This should work in your case. We are planning a complete chat redesign

in future( next year timeframe), at that point I will definitely keep in

mind your suggestion.

Let me know if it works for you.

Thanks

Hironmay Basu

View solution in original post

7 Replies

Avatar

Correct answer by
Former Community Member

Hi,

What other parts you have been doing is perfectly fine. So, I believe on

the host side you want to filter so that when as an host , you select an

user and click him, it should only show the chat between that user and

the host.

Though there is no direct way as by default, we show all messages to the

chat directed to a user, but still I can give some pointers.

What you need to do is either modify the formatMessageDescriptor method

in SimpleChatDescriptor or subsclass it .

Try to may be add another parameter to that function like

public function

formatMessageDescriptor(p_msgDesc:ChatMessageDescriptor,p_targetedUserID:String=null):String

and when you create a SimpleChat object, make sure that in the calls to

this method, you somehow pass the userID of only the user you want to

see the messages with. In a more generic way, this parameter could be an

array which contains the userIDs of only those users whose chat you want

to see in a window.

Then inside the function, make sure you filter it by doing something

like this

if ( p_msgDesc.recipientID == p_targetedUserID ) {

// you would only add those messages

}else {

// do nothing for that message i.e. return ""

}

If you are using an array of targetedUserIDs , then in a loop check if

it matches with the recipientID and if so, add that message.

This should work in your case. We are planning a complete chat redesign

in future( next year timeframe), at that point I will definitely keep in

mind your suggestion.

Let me know if it works for you.

Thanks

Hironmay Basu

Avatar

Former Community Member

A typo.. the formatMessageDecriptor method is in SimpleChatModel class.

Thanks

Hironmay Basu

Avatar

Former Community Member

Thank you for your response Hironmay,

I made some great progress by sub-classing both the simpleChat and simpleChatModel classes.

I read on Nigel twitter feed that he hates private, and I can thank him for his love of protected members, because it made my job so much easier!


I will explain what I did in the interest of other users, but I've got one last question:

In the Room Console AIR app, there is an "retract all items" in the node details of the explore tab.

I want to build the same button in my host chat application, but I haven't find a way to do it.

There is a retractItem method on the CollectionNode class, but it requires the itemID and I haven't find a way to access every item in the chat history in order to get their itemID.

I tried the clear() method of the chatModel, but it cleared only the current session, and leave the items in the server, and when the host logout, the items reappears when the host login again.

On the bright side, here is what I use for my applications:
- Subsclassed the simpleChat in hostChat and clientChat classes, and the simpleChatModel in HostChatModel and ClientChatModel
- subclass the ChatMessageDescriptor ==> PrivateChatMessageDescriptor with 2 properties: userConcernedId and fromHost (boolean)
- override in the HostChatmodel the addMessage function to obtain  PrivateChatMessageDescriptor instances, and I add them in an ArrayCollection
- When the host select a user in the RosterList, a filter is used on the ArrayCollection, and the HistoryTextArea is updated to show only the thread between the host and the user. The _toCombo is updated to send private message to this user.
- I override the updateTypingIfNeeded method of HostChat to use a SharedProperty which contains the userId of the selected user when the host is typing or an empty string. This way, in the clientChat, I only show for the user when the host is typing a message for him, and not when other users are typing.
- I replace the TextInput by a TextArea to enable multiline input (well, this one opened lots of problems to fix, but I have)
- A lots of other tweaks

So as you can see, I made it
But I look forward to a new set of sparks component, because it would have been much easier to extend the SimpleChat without rewritten half of it.

And here are some of my feature requests:

- In the SimpleChat class, add a protected getAndInitModel() , which would be called in the subscribe method. This way, one can switch the model without overriding the subscribe method of the Chat class.
- Have a "multilineInput" property in the SimpleChat class to chose a TextInput or a TextArea as the user input component.
- Provide a way to enable Host/Users interaction directly in the pods without having to create a new room for each user to "separate" them.
I think a lot of use cases for LCCS would be to implement solutions for Customer Experience, and that will need more focus on what the host can do (private chat, ...)

Thank you again for your help, and thank the entire teams for this incredible service.

Dimitri K.

Avatar

Former Community Member

Hi,

Excellent to see your progress and your effort. When we do a chat

redesign, we would definitely take your requests and if found

feasible, I will put some of these into our existing chat too.

Coming back to your retract item issue, there was a server side

problem which was preventing the items being actually retracted on

server while clearing chat. This has beenn fixed and will be

automatically there in our updates in next few days. That will solve

your chat issue.

As far as the generic retract item is concerned, you need to do a

bookeeping of all the itemIDs for a particular node and then in a loop

call retractitem on all those items. I do like that in devconsole. To

do bookkeeping, you can use itemReceive function for that model, check

for that node when you receive an item and store it.

Overall I liked the way you built and i will surely go into details of

your suggestions. Our primary aim is to provide the messaging

infrastructure and we appreciate when users customize the upper level

UI components such as chat to suit their requirements.

Hope this helps

Thanks

Hironmay Basu

Sent from my iPhone

Avatar

Former Community Member

Thank you again for your response Hironmay, and also for your nice comments

One thing I seem to understand now: the data items of a collectionNode is not stored by default in the models you provide. Am I wrong?

I'm so used to the usual "invoke a service => get data from a server ==> put the data in the model and store it ==> update the views" that I kept looking for an arrayCollection of items in the collection node.

If I understand correctly, the collectionNode on our application only store their configuration, and are only responsible to publish new item and receive one from the server, but they don't store them. The items of the nodeCollection are only stored on the server, and the model of the application only store data created according to the items, but not the items itself.

In the simple chat example, the SimpleChatModel subscribe/listen to the chat history collectionNode, then each time a chat history item is received, the chatModel update create a ChatMessageDescriptor and dispatch an event with this descriptor as payload.

The important thing is: after the items have been received, there is no way of looping through each node items, because there are not stored  in the application.

The only way would be to implement your suggestion and to keep your own arrayCollection of collectionNode items.

I don't know if it was because I didn't read the doc carefully enough (or by poor english to french mental translation) but I found this point really confusing.

I'll try to read the doc again to see if you could put some some emphasis on this point, because it it could be really confusing for devs not used to this way of dealing with server data.

Avatar

Former Community Member

And one last thing: concerning the update with the item retracted fix, will I have to update the .swc or is it only server side and I won't have to do anything?

Avatar

Former Community Member

Hi,

Our update will include both. You will get a updated swc that has many

other fixes too and there will be also a server update that will contain

the chat model fix.

And yes, you are right, we don't store all the items locally as many

times it's not required and would provide an overhead. So, if you need,

you can just create an ArrayCollection of itemIDs( only itemIDs is

sufficient since you can get the actual items using fetchItems API in

collectionNode). Also in your case , since you only want to retract, you

can just store the itemIDs in an Array/ArrayCollection when you get the

items in onItemReceive, be it in the beginning or while you are in the

session.

In devconsole too, i do a bookkeeping of itemIDs locally so that i can

use them when I want to retract those items.

Hope this helps

Thanks

Hironmay Basu

The following has evaluated to null or missing: ==> liqladmin("SELECT id, value FROM metrics WHERE id = 'net_accepted_solutions' and user.id = '${acceptedAnswer.author.id}'").data.items [in template "analytics-container" at line 83, column 41] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: #assign answerAuthorNetSolutions = li... [in template "analytics-container" at line 83, column 5] ----