@@ -27,6 +27,7 @@ qx.Class.define("osparc.conversation.Conversation", {
2727 this . base ( arguments ) ;
2828
2929 this . __studyData = studyData ;
30+ this . __messages = [ ] ;
3031
3132 if ( conversationId ) {
3233 this . setConversationId ( conversationId ) ;
@@ -46,7 +47,7 @@ qx.Class.define("osparc.conversation.Conversation", {
4647
4748 this . __buildLayout ( ) ;
4849
49- this . fetchMessages ( ) ;
50+ this . __reloadMessages ( ) ;
5051 } ,
5152
5253 properties : {
@@ -64,6 +65,7 @@ qx.Class.define("osparc.conversation.Conversation", {
6465
6566 members : {
6667 __studyData : null ,
68+ __messages : null ,
6769 __nextRequestParams : null ,
6870 __messagesTitle : null ,
6971 __messagesList : null ,
@@ -159,24 +161,44 @@ qx.Class.define("osparc.conversation.Conversation", {
159161 } ) ;
160162
161163 this . __loadMoreMessages = new osparc . ui . form . FetchButton ( this . tr ( "Load more messages..." ) ) ;
162- this . __loadMoreMessages . addListener ( "execute" , ( ) => this . fetchMessages ( false ) ) ;
164+ this . __loadMoreMessages . addListener ( "execute" , ( ) => this . __reloadMessages ( false ) ) ;
163165 this . _add ( this . __loadMoreMessages ) ;
164166
165167 if ( osparc . data . model . Study . canIWrite ( this . __studyData [ "accessRights" ] ) ) {
166168 const addMessages = new osparc . conversation . AddMessage ( this . __studyData , this . getConversationId ( ) ) ;
167169 addMessages . setPaddingLeft ( 10 ) ;
168- addMessages . addListener ( "commentAdded " , e => {
170+ addMessages . addListener ( "messageAdded " , e => {
169171 const data = e . getData ( ) ;
170172 if ( data [ "conversationId" ] ) {
171173 this . setConversationId ( data [ "conversationId" ] ) ;
174+ this . addMessage ( data ) ;
172175 }
173- this . fetchMessages ( ) ;
174176 } ) ;
175177 this . _add ( addMessages ) ;
176178 }
177179 } ,
178180
179- fetchMessages : function ( removeMessages = true ) {
181+ __getNextRequest : function ( ) {
182+ const params = {
183+ url : {
184+ studyId : this . __studyData [ "uuid" ] ,
185+ conversationId : this . getConversationId ( ) ,
186+ offset : 0 ,
187+ limit : 42
188+ }
189+ } ;
190+ const nextRequestParams = this . __nextRequestParams ;
191+ if ( nextRequestParams ) {
192+ params . url . offset = nextRequestParams . offset ;
193+ params . url . limit = nextRequestParams . limit ;
194+ }
195+ const options = {
196+ resolveWResponse : true
197+ } ;
198+ return osparc . data . Resources . fetch ( "conversations" , "getMessagesPage" , params , options ) ;
199+ } ,
200+
201+ __reloadMessages : function ( removeMessages = true ) {
180202 if ( this . getConversationId ( ) === null ) {
181203 this . __messagesTitle . setValue ( this . tr ( "No messages yet" ) ) ;
182204 this . __messagesList . hide ( ) ;
@@ -189,15 +211,14 @@ qx.Class.define("osparc.conversation.Conversation", {
189211 this . __loadMoreMessages . setFetching ( true ) ;
190212
191213 if ( removeMessages ) {
214+ this . __messages = [ ] ;
192215 this . __messagesList . removeAll ( ) ;
193216 }
194217
195218 this . __getNextRequest ( )
196219 . then ( resp => {
197220 const messages = resp [ "data" ] ;
198- // it's not provided by the backend
199- messages . forEach ( message => message [ "studyId" ] = this . __studyData [ "uuid" ] ) ;
200- this . __addMessages ( messages ) ;
221+ messages . forEach ( message => this . addMessage ( message ) ) ;
201222 this . __nextRequestParams = resp [ "_links" ] [ "next" ] ;
202223 if ( this . __nextRequestParams === null ) {
203224 this . __loadMoreMessages . exclude ( ) ;
@@ -206,48 +227,91 @@ qx.Class.define("osparc.conversation.Conversation", {
206227 . finally ( ( ) => this . __loadMoreMessages . setFetching ( false ) ) ;
207228 } ,
208229
209- __getNextRequest : function ( ) {
210- const params = {
211- url : {
212- studyId : this . __studyData [ "uuid" ] ,
213- conversationId : this . getConversationId ( ) ,
214- offset : 0 ,
215- limit : 42
216- }
217- } ;
218- const nextRequestParams = this . __nextRequestParams ;
219- if ( nextRequestParams ) {
220- params . url . offset = nextRequestParams . offset ;
221- params . url . limit = nextRequestParams . limit ;
222- }
223- const options = {
224- resolveWResponse : true
225- } ;
226- return osparc . data . Resources . fetch ( "conversations" , "getMessagesPage" , params , options ) ;
227- } ,
228-
229- __addMessages : function ( messages ) {
230- const nMessages = messages . filter ( msg => msg [ "type" ] === "MESSAGE" ) . length ;
230+ __updateMessagesNumber : function ( ) {
231+ const nMessages = this . __messages . filter ( msg => msg [ "type" ] === "MESSAGE" ) . length ;
231232 if ( nMessages === 1 ) {
232233 this . __messagesTitle . setValue ( this . tr ( "1 Message" ) ) ;
233234 } else if ( nMessages > 1 ) {
234235 this . __messagesTitle . setValue ( nMessages + this . tr ( " Messages" ) ) ;
235236 }
237+ } ,
236238
237- messages . forEach ( message => {
238- let control = null ;
239- switch ( message [ "type" ] ) {
240- case "MESSAGE" :
241- control = new osparc . conversation . MessageUI ( message , this . __studyData ) ;
242- control . addListener ( "messageEdited" , ( ) => this . fetchMessages ( ) ) ;
243- control . addListener ( "messageDeleted" , ( ) => this . fetchMessages ( ) ) ;
244- break ;
245- case "NOTIFICATION" :
246- control = new osparc . conversation . NotificationUI ( message ) ;
247- break ;
248- }
249- if ( control ) {
250- this . __messagesList . add ( control ) ;
239+ addMessage : function ( message ) {
240+ // backend doesn't provide the projectId
241+ message [ "projectId" ] = this . __studyData [ "uuid" ] ;
242+
243+ // ignore it if it was already there
244+ const messageIndex = this . __messages . findIndex ( msg => msg [ "messageId" ] === message [ "messageId" ] ) ;
245+ if ( messageIndex !== - 1 ) {
246+ return ;
247+ }
248+
249+ // determine insertion index for most‐recent‐first order
250+ const newTime = new Date ( message [ "created" ] ) ;
251+ let insertAt = this . __messages . findIndex ( m => new Date ( m [ "created" ] ) < newTime ) ;
252+ if ( insertAt === - 1 ) {
253+ insertAt = this . __messages . length ;
254+ }
255+
256+ // Insert the message in the messages array
257+ this . __messages . splice ( insertAt , 0 , message ) ;
258+
259+ // Add the UI element to the messages list
260+ let control = null ;
261+ switch ( message [ "type" ] ) {
262+ case "MESSAGE" :
263+ control = new osparc . conversation . MessageUI ( message , this . __studyData ) ;
264+ control . addListener ( "messageUpdated" , e => this . updateMessage ( e . getData ( ) ) ) ;
265+ control . addListener ( "messageDeleted" , e => this . deleteMessage ( e . getData ( ) ) ) ;
266+ break ;
267+ case "NOTIFICATION" :
268+ control = new osparc . conversation . NotificationUI ( message ) ;
269+ break ;
270+ }
271+ if ( control ) {
272+ // insert into the UI at the same position
273+ this . __messagesList . addAt ( control , insertAt ) ;
274+ }
275+
276+ this . __updateMessagesNumber ( ) ;
277+ } ,
278+
279+ deleteMessage : function ( message ) {
280+ // remove it from the messages array
281+ const messageIndex = this . __messages . findIndex ( msg => msg [ "messageId" ] === message [ "messageId" ] ) ;
282+ if ( messageIndex === - 1 ) {
283+ return ;
284+ }
285+ this . __messages . splice ( messageIndex , 1 ) ;
286+
287+ // Remove the UI element from the messages list
288+ const children = this . __messagesList . getChildren ( ) ;
289+ const controlIndex = children . findIndex (
290+ ctrl => ( "getMessage" in ctrl && ctrl . getMessage ( ) [ "messageId" ] === message [ "messageId" ] )
291+ ) ;
292+ if ( controlIndex > - 1 ) {
293+ this . __messagesList . remove ( children [ controlIndex ] ) ;
294+ }
295+
296+ this . __updateMessagesNumber ( ) ;
297+ } ,
298+
299+ updateMessage : function ( message ) {
300+ // backend doesn't provide the projectId
301+ message [ "projectId" ] = this . __studyData [ "uuid" ] ;
302+
303+ // Replace the message in the messages array
304+ const messageIndex = this . __messages . findIndex ( msg => msg [ "messageId" ] === message [ "messageId" ] ) ;
305+ if ( messageIndex === - 1 ) {
306+ return ;
307+ }
308+ this . __messages [ messageIndex ] = message ;
309+
310+ // Update the UI element from the messages list
311+ this . __messagesList . getChildren ( ) . forEach ( control => {
312+ if ( "getMessage" in control && control . getMessage ( ) [ "messageId" ] === message [ "messageId" ] ) {
313+ control . setMessage ( message ) ;
314+ return ;
251315 }
252316 } ) ;
253317 } ,
0 commit comments