Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * This module operates on the view states from the message_drawer_view_conversation module.
18
 * It exposes functions that can be used to generate new version of the state.
19
 *
20
 * Important notes for this module:
21
 * 1.) The existing state is always immutable. It should never be modified.
22
 * 2.) All functions that operate on the state should always clone the state and
23
 *     modify the cloned state before returning it.
24
 *
25
 * It's important that the states remain immutable because they are diff'd in
26
 * the message_drawer_view_conversation_patcher module in order to work out what
27
 * has changed.
28
 *
29
 * @module     core_message/message_drawer_view_conversation_state_manager
30
 * @copyright  2018 Ryan Wyllie <ryan@moodle.com>
31
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32
 */
33
define(['jquery'], function($) {
34
 
35
    /**
36
     * Clone a state, a state is a collection of information about the variables required to build
37
     * the conversation user interface.
38
     *
39
     * @param  {Object} state State to clone
40
     * @return {Object} newstate A copy of the state to clone.
41
     */
42
    var cloneState = function(state) {
43
        // Do a deep extend to make sure we recursively copy objects and
44
        // arrays so that the new state doesn't contain any references to
45
        // the old state, e.g. adding a value to an array in the new state
46
        // shouldn't also add it to the old state.
47
        return $.extend(true, {}, state);
48
    };
49
 
50
    /**
51
     * Format messages to be used in a state.
52
     *
53
     * @param  {Array} messages The messages to format.
54
     * @param  {Number} loggedInUserId The logged in user id.
55
     * @param  {Array} members The converstation members.
56
     * @return {Array} Formatted messages.
57
     */
58
    var formatMessages = function(messages, loggedInUserId, members) {
59
        return messages.map(function(message) {
60
            var fromLoggedInUser = message.useridfrom == loggedInUserId;
61
            return {
62
                // Stringify the id.
63
                id: "" + message.id,
64
                fromLoggedInUser: fromLoggedInUser,
65
                userFrom: members[message.useridfrom],
66
                text: message.text,
67
                timeCreated: message.timecreated ? parseInt(message.timecreated, 10) : null
68
            };
69
        });
70
    };
71
 
72
    /**
73
     * Format members to be used in a state.
74
     *
75
     * @param  {Array} members The messages to format.
76
     * @return {Array} Formatted members.
77
     */
78
    var formatMembers = function(members) {
79
        return members.map(function(member) {
80
            return {
81
                id: member.id,
82
                fullname: member.fullname,
83
                profileurl: member.profileurl,
84
                profileimageurl: member.profileimageurl,
85
                profileimageurlsmall: member.profileimageurlsmall,
86
                isonline:  member.isonline,
87
                showonlinestatus: member.showonlinestatus,
88
                isblocked: member.isblocked,
89
                iscontact: member.iscontact,
90
                isdeleted: member.isdeleted,
91
                canmessage: member.canmessage,
92
                canmessageevenifblocked: member.canmessageevenifblocked,
93
                requirescontact: member.requirescontact,
1441 ariadna 94
                contactrequests: member.contactrequests || [],
95
                cancreatecontact: member.cancreatecontact,
1 efrain 96
            };
97
        });
98
    };
99
 
100
    /**
101
     * Create an initial (blank) state.
102
     *
103
     * @param  {Number} midnight Midnight time.
104
     * @param  {Number} loggedInUserId The logged in user id.
105
     * @param  {Number} id The conversation id.
106
     * @param  {Number} messagePollMin The message poll start timeout in seconds.
107
     * @param  {Number} messagePollMax The message poll max timeout limit in seconds.
108
     * @param  {Number} messagePollAfterMax The message poll frequency in seconds to reset to after max limit is reached.
109
     * @return {Object} Initial state.
110
     */
111
    var buildInitialState = function(
112
        midnight,
113
        loggedInUserId,
114
        id,
115
        messagePollMin,
116
        messagePollMax,
117
        messagePollAfterMax
118
    ) {
119
        return {
120
            midnight: midnight,
121
            loggedInUserId: loggedInUserId,
122
            id: id,
123
            messagePollMin: messagePollMin,
124
            messagePollMax: messagePollMax,
125
            messagePollAfterMax: messagePollAfterMax,
126
            name: null,
127
            subname: null,
128
            type: null,
129
            totalMemberCount: null,
130
            imageUrl: null,
131
            isFavourite: null,
132
            isMuted: null,
133
            canDeleteMessagesForAllUsers: false,
134
            deleteMessagesForAllUsers: false,
135
            members: {},
136
            messages: [],
137
            hasTriedToLoadMessages: false,
138
            loadingMessages: true,
139
            loadingMembers: true,
140
            loadingConfirmAction: false,
141
            pendingBlockUserIds: [],
142
            pendingUnblockUserIds: [],
143
            pendingRemoveContactIds: [],
144
            pendingAddContactIds: [],
145
            pendingDeleteMessageIds: [],
146
            pendingSendMessageIds: [],
147
            pendingDeleteConversation: false,
148
            selectedMessageIds: [],
149
            showEmojiAutoComplete: false,
150
            showEmojiPicker: false
151
        };
152
    };
153
 
154
    /**
155
     * Add messages to a state and sort them by timecreated.
156
     *
157
     * @param  {Object} state Current state.
158
     * @param  {Array} messages Messages to add to state.
159
     * @return {Object} state New state with added messages.
160
     */
161
    var addMessages = function(state, messages) {
162
        var newState = cloneState(state);
163
        var formattedMessages = formatMessages(messages, state.loggedInUserId, state.members);
164
        formattedMessages = formattedMessages.map(function(message) {
165
            message.sendState = null;
166
            message.timeAdded = Date.now();
167
            message.errorMessage = null;
168
            return message;
169
        });
170
        var allMessages = state.messages.concat(formattedMessages);
171
        // Sort the messages. Oldest to newest.
172
        allMessages.sort(function(a, b) {
173
            if (a.timeCreated === null && b.timeCreated === null) {
174
                if (a.timeAdded < b.timeAdded) {
175
                    return -1;
176
                } else if (a.timeAdded > b.timeAdded) {
177
                    return 1;
178
                }
179
            }
180
 
181
            if (a.timeCreated === null && b.timeCreated !== null) {
182
                // A comes after b.
183
                return 1;
184
            } else if (a.timeCreated !== null && b.timeCreated === null) {
185
                // A comes before b.
186
                return -1;
187
            } else if (a.timeCreated < b.timeCreated) {
188
                // A comes before b.
189
                return -1;
190
            } else if (a.timeCreated > b.timeCreated) {
191
                // A comes after b.
192
                return 1;
193
            } else if (a.id < b.id) {
194
                return -1;
195
            } else if (a.id > b.id) {
196
                return 1;
197
            } else {
198
                return 0;
199
            }
200
        });
201
 
202
        // Filter out any duplicate messages.
203
        newState.messages = allMessages.filter(function(message, index, sortedMessages) {
204
            return !index || message.id != sortedMessages[index - 1].id;
205
        });
206
 
207
        return newState;
208
    };
209
 
210
    /**
211
     * Update existing messages.
212
     *
213
     * @param  {Object} state Current state.
214
     * @param  {Array} data 2D array of old and new messages
215
     * @return {Object} state.
216
     */
217
    var updateMessages = function(state, data) {
218
        var newState = cloneState(state);
219
        var updatesById = data.reduce(function(carry, messageData) {
220
            var oldMessage = messageData[0];
221
            var newMessage = messageData[1];
222
            var formattedMessages = formatMessages([newMessage], state.loggedInUserId, state.members);
223
            var formattedMessage = formattedMessages[0];
224
 
225
            carry[oldMessage.id] = formattedMessage;
226
            return carry;
227
        }, {});
228
 
229
        newState.messages = newState.messages.map(function(message) {
230
            if (message.id in updatesById) {
231
                return $.extend(message, updatesById[message.id]);
232
            } else {
233
                return message;
234
            }
235
        });
236
 
237
        return newState;
238
    };
239
 
240
    /**
241
     * Remove messages from state.
242
     *
243
     * @param  {Object} state Current state.
244
     * @param  {Array} messages Messages to remove from state.
245
     * @return {Object} state New state with removed messages.
246
     */
247
    var removeMessages = function(state, messages) {
248
        var newState = cloneState(state);
249
        var removeMessageIds = messages.map(function(message) {
250
            return "" + message.id;
251
        });
252
        newState.messages = newState.messages.filter(function(message) {
253
            return removeMessageIds.indexOf(message.id) < 0;
254
        });
255
 
256
        return newState;
257
    };
258
 
259
    /**
260
     * Remove messages from state by message id.
261
     *
262
     * @param  {Object} state Current state.
263
     * @param  {Array} messageIds Message ids to remove from state.
264
     * @return {Object} state New state with removed messages.
265
     */
266
    var removeMessagesById = function(state, messageIds) {
267
        var newState = cloneState(state);
268
        messageIds = messageIds.map(function(id) {
269
            return "" + id;
270
        });
271
        newState.messages = newState.messages.filter(function(message) {
272
            return messageIds.indexOf(message.id) < 0;
273
        });
274
 
275
        return newState;
276
    };
277
 
278
    /**
279
     * Add conversation member to state.
280
     *
281
     * @param  {Object} state Current state.
282
     * @param  {Array} members Conversation members to be added to state.
283
     * @return {Object} New state with added members.
284
     */
285
    var addMembers = function(state, members) {
286
        var newState = cloneState(state);
287
        var formattedMembers = formatMembers(members);
288
        formattedMembers.forEach(function(member) {
289
            newState.members[member.id] = member;
290
        });
291
        return newState;
292
    };
293
 
294
    /**
295
     * Remove members from state.
296
     *
297
     * @param  {Object} state Current state.
298
     * @param  {Array} members Members to be removed from state.
299
     * @return {Object} New state with removed members.
300
     */
301
    var removeMembers = function(state, members) {
302
        var newState = cloneState(state);
303
        members.forEach(function(member) {
304
            delete newState.members[member.id];
305
        });
306
        return newState;
307
    };
308
 
309
    /**
310
     * Set the state loading messages attribute.
311
     *
312
     * @param  {Object} state Current state.
313
     * @param  {Bool} value New loading messages value.
314
     * @return {Object} New state with loading messages attribute.
315
     */
316
    var setLoadingMessages = function(state, value) {
317
        var newState = cloneState(state);
318
        newState.loadingMessages = value;
319
        if (state.loadingMessages && !value) {
320
            // If we're going from loading to not loading then
321
            // it means we've tried to load.
322
            newState.hasTriedToLoadMessages = true;
323
        }
324
        return newState;
325
    };
326
 
327
    /**
328
     * Set the state loading members attribute.
329
     *
330
     * @param  {Object} state Current state.
331
     * @param  {Bool} value New loading members value.
332
     * @return {Object} New state with loading members attribute.
333
     */
334
    var setLoadingMembers = function(state, value) {
335
        var newState = cloneState(state);
336
        newState.loadingMembers = value;
337
        return newState;
338
    };
339
 
340
    /**
341
     * Set the conversation id.
342
     *
343
     * @param  {Object} state Current state.
344
     * @param  {String} value The ID.
345
     * @return {Object} New state.
346
     */
347
    var setId = function(state, value) {
348
        var newState = cloneState(state);
349
        newState.id = value;
350
        return newState;
351
    };
352
 
353
    /**
354
     * Set the state name attribute.
355
     *
356
     * @param  {Object} state Current state.
357
     * @param  {String} value New name value.
358
     * @return {Object} New state with name attribute.
359
     */
360
    var setName = function(state, value) {
361
        var newState = cloneState(state);
362
        newState.name = value;
363
        return newState;
364
    };
365
 
366
    /**
367
     * Set the state subname attribute.
368
     *
369
     * @param  {Object} state Current state.
370
     * @param  {String} value New subname value.
371
     * @return {Object} New state.
372
     */
373
    var setSubname = function(state, value) {
374
        var newState = cloneState(state);
375
        newState.subname = value;
376
        return newState;
377
    };
378
 
379
    /**
380
     * Set the conversation type.
381
     *
382
     * @param  {Object} state Current state.
383
     * @param  {Int} type Conversation type.
384
     * @return {Object} New state.
385
     */
386
    var setType = function(state, type) {
387
        var newState = cloneState(state);
388
        newState.type = type;
389
        return newState;
390
    };
391
 
392
    /**
393
     * Set whether the conversation is a favourite conversation.
394
     *
395
     * @param  {Object} state Current state.
396
     * @param  {Bool} isFavourite If it's a favourite.
397
     * @return {Object} New state.
398
     */
399
    var setIsFavourite = function(state, isFavourite) {
400
        var newState = cloneState(state);
401
        newState.isFavourite = isFavourite;
402
        return newState;
403
    };
404
 
405
    /**
406
     * Set whether the conversation is a muted conversation.
407
     *
408
     * @param  {Object} state Current state.
409
     * @param  {bool} isMuted If it's muted.
410
     * @return {Object} New state.
411
     */
412
    var setIsMuted = function(state, isMuted) {
413
        var newState = cloneState(state);
414
        newState.isMuted = isMuted;
415
        return newState;
416
    };
417
 
418
    /**
419
     * Set the total member count.
420
     *
421
     * @param  {Object} state Current state.
422
     * @param  {String} count The count.
423
     * @return {Object} New state.
424
     */
425
    var setTotalMemberCount = function(state, count) {
426
        var newState = cloneState(state);
427
        newState.totalMemberCount = count;
428
        return newState;
429
    };
430
 
431
    /**
432
     * Set the conversation image url.
433
     *
434
     * @param  {Object} state Current state.
435
     * @param  {String} url The url to the image.
436
     * @return {Object} New state.
437
     */
438
    var setImageUrl = function(state, url) {
439
        var newState = cloneState(state);
440
        newState.imageUrl = url;
441
        return newState;
442
    };
443
 
444
    /**
445
     * Set the state loading confirm action attribute.
446
     *
447
     * @param  {Object} state Current state.
448
     * @param  {Bool} value New loading confirm action value.
449
     * @return {Object} New state with loading confirm action attribute.
450
     */
451
    var setLoadingConfirmAction = function(state, value) {
452
        var newState = cloneState(state);
453
        newState.loadingConfirmAction = value;
454
        return newState;
455
    };
456
 
457
    /**
458
     * Set the state pending delete conversation attribute.
459
     *
460
     * @param  {Object} state Current state.
461
     * @param  {Bool} value New pending delete conversation value.
462
     * @return {Object} New state with pending delete conversation attribute.
463
     */
464
    var setPendingDeleteConversation = function(state, value) {
465
        var newState = cloneState(state);
466
        newState.pendingDeleteConversation = value;
467
        return newState;
468
    };
469
 
470
    /**
471
     * Set the state of message to pending.
472
     *
473
     * @param  {Object} state Current state.
474
     * @param  {Array} messageIds Messages to delete.
475
     * @return {Object} New state with array of pending delete message ids.
476
     */
477
    var setMessagesSendPendingById = function(state, messageIds) {
478
        var newState = cloneState(state);
479
        messageIds = messageIds.map(function(id) {
480
            return "" + id;
481
        });
482
        newState.messages.forEach(function(message) {
483
            if (messageIds.indexOf(message.id) >= 0) {
484
                message.sendState = 'pending';
485
                message.errorMessage = null;
486
            }
487
        });
488
        return newState;
489
    };
490
 
491
    /**
492
     * Set the state of message to sent.
493
     *
494
     * @param  {Object} state Current state.
495
     * @param  {Array} messageIds Messages to delete.
496
     * @return {Object} New state with array of pending delete message ids.
497
     */
498
    var setMessagesSendSuccessById = function(state, messageIds) {
499
        var newState = cloneState(state);
500
        messageIds = messageIds.map(function(id) {
501
            return "" + id;
502
        });
503
        newState.messages.forEach(function(message) {
504
            if (messageIds.indexOf(message.id) >= 0) {
505
                message.sendState = 'sent';
506
                message.errorMessage = null;
507
            }
508
        });
509
        return newState;
510
    };
511
 
512
    /**
513
     * Set the state of messages to error.
514
     *
515
     * @param  {Object} state Current state.
516
     * @param  {Array} messageIds Messages to delete.
517
     * @param  {string} errorMessage
518
     * @return {Object} New state with array of pending delete message ids.
519
     */
520
    var setMessagesSendFailById = function(state, messageIds, errorMessage) {
521
        var newState = cloneState(state);
522
        messageIds = messageIds.map(function(id) {
523
            return "" + id;
524
        });
525
        newState.messages.forEach(function(message) {
526
            if (messageIds.indexOf(message.id) >= 0) {
527
                message.sendState = 'error';
528
                message.errorMessage = errorMessage;
529
            }
530
        });
531
        return newState;
532
    };
533
 
534
    /**
535
     * Set the visibility of the emoji picker.
536
     *
537
     * @param  {Object} state Current state.
538
     * @param  {Bool} show Should the emoji picker be shown.
539
     * @return {Object} New state with array of pending delete message ids.
540
     */
541
    var setShowEmojiPicker = function(state, show) {
542
        var newState = cloneState(state);
543
        newState.showEmojiPicker = show;
544
        return newState;
545
    };
546
 
547
    /**
548
     * Set whether emojis auto complete suggestions should be shown.
549
     *
550
     * @param  {Object} state Current state.
551
     * @param  {Bool} show Show the autocomplete
552
     * @return {Object} New state with array of pending delete message ids.
553
     */
554
    var setShowEmojiAutoComplete = function(state, show) {
555
        var newState = cloneState(state);
556
        newState.showEmojiAutoComplete = show;
557
        return newState;
558
    };
559
 
560
    /**
561
     * Set the state pending block userids.
562
     *
563
     * @param  {Object} state Current state.
564
     * @param  {Array} userIds User ids to block.
565
     * @return {Object} New state with array of pending block userids.
566
     */
567
    var addPendingBlockUsersById = function(state, userIds) {
568
        var newState = cloneState(state);
569
        userIds.forEach(function(id) {
570
            newState.pendingBlockUserIds.push(id);
571
        });
572
        return newState;
573
    };
574
 
575
    /**
576
     * Set the state pending remove userids.
577
     *
578
     * @param  {Object} state Current state.
579
     * @param  {Array} userIds User ids to remove.
580
     * @return {Object} New state with array of pending remove userids.
581
     */
582
    var addPendingRemoveContactsById = function(state, userIds) {
583
        var newState = cloneState(state);
584
        userIds.forEach(function(id) {
585
            newState.pendingRemoveContactIds.push(id);
586
        });
587
        return newState;
588
    };
589
 
590
    /**
591
     * Set the state pending unblock userids.
592
     *
593
     * @param  {Object} state Current state.
594
     * @param  {Array} userIds User ids to unblock.
595
     * @return {Object} New state with array of pending unblock userids.
596
     */
597
    var addPendingUnblockUsersById = function(state, userIds) {
598
        var newState = cloneState(state);
599
        userIds.forEach(function(id) {
600
            newState.pendingUnblockUserIds.push(id);
601
        });
602
        return newState;
603
    };
604
 
605
    /**
606
     * Set the state pending add users to contacts userids.
607
     *
608
     * @param  {Object} state Current state.
609
     * @param  {Array} userIds User ids to add users to contacts.
610
     * @return {Object} New state with array of pending add users to contacts userids.
611
     */
612
    var addPendingAddContactsById = function(state, userIds) {
613
        var newState = cloneState(state);
614
        userIds.forEach(function(id) {
615
            newState.pendingAddContactIds.push(id);
616
        });
617
        return newState;
618
    };
619
 
620
    /**
621
     * Set the state pending delete messages.
622
     *
623
     * @param  {Object} state Current state.
624
     * @param  {Array} messageIds Messages to delete.
625
     * @return {Object} New state with array of pending delete message ids.
626
     */
627
    var addPendingDeleteMessagesById = function(state, messageIds) {
628
        var newState = cloneState(state);
629
        messageIds.forEach(function(id) {
630
            newState.pendingDeleteMessageIds.push(id);
631
        });
632
        return newState;
633
    };
634
 
635
    /**
636
     * Update the state pending block userids.
637
     *
638
     * @param  {Object} state Current state.
639
     * @param  {Array} userIds User ids to remove from the list of user ids to block.
640
     * @return {Object} New state with array of pending block userids.
641
     */
642
    var removePendingBlockUsersById = function(state, userIds) {
643
        var newState = cloneState(state);
644
        newState.pendingBlockUserIds = newState.pendingBlockUserIds.filter(function(id) {
645
            return userIds.indexOf(id) < 0;
646
        });
647
        return newState;
648
    };
649
 
650
    /**
651
     * Update the state pending remove userids.
652
     *
653
     * @param  {Object} state Current state.
654
     * @param  {Array} userIds User ids to remove from the list of user ids to remove.
655
     * @return {Object} New state with array of pending remove userids.
656
     */
657
    var removePendingRemoveContactsById = function(state, userIds) {
658
        var newState = cloneState(state);
659
        newState.pendingRemoveContactIds = newState.pendingRemoveContactIds.filter(function(id) {
660
            return userIds.indexOf(id) < 0;
661
        });
662
        return newState;
663
    };
664
 
665
    /**
666
     * Update the state pending unblock userids.
667
     *
668
     * @param  {Object} state Current state.
669
     * @param  {Array} userIds User ids to remove from the list of user ids to unblock.
670
     * @return {Object} New state with array of pending unblock userids.
671
     */
672
    var removePendingUnblockUsersById = function(state, userIds) {
673
        var newState = cloneState(state);
674
        newState.pendingUnblockUserIds = newState.pendingUnblockUserIds.filter(function(id) {
675
            return userIds.indexOf(id) < 0;
676
        });
677
        return newState;
678
    };
679
 
680
    /**
681
     * Update the state pending add to contacts userids.
682
     *
683
     * @param  {Object} state Current state.
684
     * @param  {Array} userIds User ids to remove from the list of user ids to add to contacts.
685
     * @return {Object} New state with array of pending add to contacts userids.
686
     */
687
    var removePendingAddContactsById = function(state, userIds) {
688
        var newState = cloneState(state);
689
        newState.pendingAddContactIds = newState.pendingAddContactIds.filter(function(id) {
690
            return userIds.indexOf(id) < 0;
691
        });
692
        return newState;
693
    };
694
 
695
    /**
696
     * Update the state pending delete messages userids.
697
     *
698
     * @param  {Object} state Current state.
699
     * @param  {Array} messageIds Message ids to remove from the list of messages to delete.
700
     * @return {Object} New state with array of messages to delete.
701
     */
702
    var removePendingDeleteMessagesById = function(state, messageIds) {
703
        var newState = cloneState(state);
704
        messageIds = messageIds.map(function(id) {
705
            return "" + id;
706
        });
707
        newState.pendingDeleteMessageIds = newState.pendingDeleteMessageIds.filter(function(id) {
708
            return messageIds.indexOf(id) < 0;
709
        });
710
        return newState;
711
    };
712
 
713
    /**
714
     * Add messages to state selected messages.
715
     *
716
     * @param  {Object} state Current state.
717
     * @param  {Array} messageIds Messages that are selected.
718
     * @return {Object} New state with array of not blocked members.
719
     */
720
    var addSelectedMessagesById = function(state, messageIds) {
721
        var newState = cloneState(state);
722
        messageIds = messageIds.map(function(id) {
723
            return "" + id;
724
        });
725
        newState.selectedMessageIds = newState.selectedMessageIds.concat(messageIds);
726
        return newState;
727
    };
728
 
729
    /**
730
     * Remove messages from the state selected messages.
731
     *
732
     * @param  {Object} state Current state.
733
     * @param  {Array} messageIds Messages to remove from selected messages.
734
     * @return {Object} New state with array of selected messages.
735
     */
736
    var removeSelectedMessagesById = function(state, messageIds) {
737
        var newState = cloneState(state);
738
        messageIds = messageIds.map(function(id) {
739
            return "" + id;
740
        });
741
        newState.selectedMessageIds = newState.selectedMessageIds.filter(function(id) {
742
            return messageIds.indexOf(id) < 0;
743
        });
744
        return newState;
745
    };
746
 
747
    /**
748
     * Mark messages as read.
749
     *
750
     * @param  {Object} state Current state.
751
     * @param  {Array} readMessages Messages that are read.
752
     * @return {Object} New state with array of messages that have the isread attribute set.
753
     */
754
    var markMessagesAsRead = function(state, readMessages) {
755
        var newState = cloneState(state);
756
        var readMessageIds = readMessages.map(function(message) {
757
            return message.id;
758
        });
759
        newState.messages = newState.messages.map(function(message) {
760
            if (readMessageIds.indexOf(message.id) >= 0) {
761
                message.isRead = true;
762
            }
763
 
764
            return message;
765
        });
766
        return newState;
767
    };
768
 
769
    /**
770
     * Add a contact request to each of the members that the request is for.
771
     *
772
     * @param  {Object} state Current state.
773
     * @param  {Array} requests The contact requests
774
     * @return {Object} New state
775
     */
776
    var addContactRequests = function(state, requests) {
777
        var newState = cloneState(state);
778
 
779
        requests.forEach(function(request) {
780
            var fromUserId = request.userid;
781
            var toUserId = request.requesteduserid;
782
            newState.members[fromUserId].contactrequests.push(request);
783
            newState.members[toUserId].contactrequests.push(request);
784
        });
785
 
786
        return newState;
787
    };
788
 
789
    /**
790
     * Remove a contact request from the members of that request.
791
     *
792
     * @param  {Object} state Current state.
793
     * @param  {Array} requests The contact requests
794
     * @return {Object} New state
795
     */
796
    var removeContactRequests = function(state, requests) {
797
        var newState = cloneState(state);
798
        requests.forEach(function(request) {
799
            var fromUserId = request.userid;
800
            var toUserId = request.requesteduserid;
801
 
802
            newState.members[fromUserId].contactrequests = newState.members[fromUserId].contactrequests.filter(function(existing) {
803
                return existing.userid != fromUserId;
804
            });
805
            newState.members[toUserId].contactrequests = newState.members[toUserId].contactrequests.filter(function(existing) {
806
                return existing.requesteduserid != toUserId;
807
            });
808
        });
809
 
810
        return newState;
811
    };
812
 
813
    /**
814
     * Set wheter the message of the conversation can delete for all users.
815
     *
816
     * @param  {Object} state Current state.
817
     * @param  {Bool} value If it can delete for all users.
818
     * @return {Object} New state.
819
     */
820
    var setCanDeleteMessagesForAllUsers = function(state, value) {
821
        var newState = cloneState(state);
822
        newState.canDeleteMessagesForAllUsers = value;
823
        return newState;
824
    };
825
 
826
    /**
827
     * Set wheter the messages of the conversation delete for all users.
828
     *
829
     * @param  {Object} state Current state.
830
     * @param  {Bool} value Delete messages for all users.
831
     * @return {Object} New state.
832
     */
833
    var setDeleteMessagesForAllUsers = function(state, value) {
834
        var newState = cloneState(state);
835
        newState.deleteMessagesForAllUsers = value;
836
        return newState;
837
    };
838
 
839
    return {
840
        buildInitialState: buildInitialState,
841
        addMessages: addMessages,
842
        updateMessages: updateMessages,
843
        removeMessages: removeMessages,
844
        removeMessagesById: removeMessagesById,
845
        addMembers: addMembers,
846
        removeMembers: removeMembers,
847
        setLoadingMessages: setLoadingMessages,
848
        setLoadingMembers: setLoadingMembers,
849
        setId: setId,
850
        setName: setName,
851
        setSubname: setSubname,
852
        setType: setType,
853
        setIsFavourite: setIsFavourite,
854
        setIsMuted: setIsMuted,
855
        setCanDeleteMessagesForAllUsers: setCanDeleteMessagesForAllUsers,
856
        setDeleteMessagesForAllUsers: setDeleteMessagesForAllUsers,
857
        setTotalMemberCount: setTotalMemberCount,
858
        setImageUrl: setImageUrl,
859
        setLoadingConfirmAction: setLoadingConfirmAction,
860
        setPendingDeleteConversation: setPendingDeleteConversation,
861
        setMessagesSendPendingById: setMessagesSendPendingById,
862
        setMessagesSendSuccessById: setMessagesSendSuccessById,
863
        setMessagesSendFailById: setMessagesSendFailById,
864
        setShowEmojiAutoComplete: setShowEmojiAutoComplete,
865
        setShowEmojiPicker: setShowEmojiPicker,
866
        addPendingBlockUsersById: addPendingBlockUsersById,
867
        addPendingRemoveContactsById: addPendingRemoveContactsById,
868
        addPendingUnblockUsersById: addPendingUnblockUsersById,
869
        addPendingAddContactsById: addPendingAddContactsById,
870
        addPendingDeleteMessagesById: addPendingDeleteMessagesById,
871
        removePendingBlockUsersById: removePendingBlockUsersById,
872
        removePendingRemoveContactsById: removePendingRemoveContactsById,
873
        removePendingUnblockUsersById: removePendingUnblockUsersById,
874
        removePendingAddContactsById: removePendingAddContactsById,
875
        removePendingDeleteMessagesById: removePendingDeleteMessagesById,
876
        addSelectedMessagesById: addSelectedMessagesById,
877
        removeSelectedMessagesById: removeSelectedMessagesById,
878
        markMessagesAsRead: markMessagesAsRead,
879
        addContactRequests: addContactRequests,
880
        removeContactRequests: removeContactRequests
881
    };
882
});