Преглед изворни кода

ref(chat): create web MessageContainer component

master
Leonard Kim пре 6 година
родитељ
комит
0e8b0a9c5c

+ 2
- 77
react/features/chat/components/web/Chat.js Прегледај датотеку

@@ -12,8 +12,8 @@ import AbstractChat, {
12 12
     type Props
13 13
 } from '../AbstractChat';
14 14
 import ChatInput from './ChatInput';
15
-import ChatMessageGroup from './ChatMessageGroup';
16 15
 import DisplayNameForm from './DisplayNameForm';
16
+import MessageContainer from './MessageContainer';
17 17
 
18 18
 /**
19 19
  * React Component for holding the chat feature in a side panel that slides in
@@ -27,12 +27,6 @@ class Chat extends AbstractChat<Props> {
27 27
      */
28 28
     _isExited: boolean;
29 29
 
30
-    /**
31
-     * Reference to the HTML element at the end of the list of displayed chat
32
-     * messages. Used for scrolling to the end of the chat messages.
33
-     */
34
-    _messagesListEnd: ?HTMLElement;
35
-
36 30
     /**
37 31
      * Initializes a new {@code Chat} instance.
38 32
      *
@@ -43,32 +37,9 @@ class Chat extends AbstractChat<Props> {
43 37
         super(props);
44 38
 
45 39
         this._isExited = true;
46
-        this._messagesListEnd = null;
47 40
 
48 41
         // Bind event handlers so they are only bound once for every instance.
49 42
         this._renderPanelContent = this._renderPanelContent.bind(this);
50
-        this._setMessageListEndRef = this._setMessageListEndRef.bind(this);
51
-    }
52
-
53
-    /**
54
-     * Implements React's {@link Component#componentDidMount()}.
55
-     *
56
-     * @inheritdoc
57
-     */
58
-    componentDidMount() {
59
-        this._scrollMessagesToBottom();
60
-    }
61
-
62
-    /**
63
-     * Updates chat input focus.
64
-     *
65
-     * @inheritdoc
66
-     */
67
-    componentDidUpdate(prevProps) {
68
-        if (this.props._messages !== prevProps._messages) {
69
-            this._scrollMessagesToBottom();
70
-
71
-        }
72 43
     }
73 44
 
74 45
     /**
@@ -126,28 +97,9 @@ class Chat extends AbstractChat<Props> {
126 97
      * @returns {ReactElement}
127 98
      */
128 99
     _renderChat() {
129
-        const groupedMessages = this._getMessagesGroupedBySender();
130
-
131
-        const messages = groupedMessages.map((group, index) => {
132
-            const messageType = group[0] && group[0].messageType;
133
-
134
-            return (
135
-                <ChatMessageGroup
136
-                    className = { messageType || 'remote' }
137
-                    key = { index }
138
-                    messages = { group } />
139
-            );
140
-        });
141
-
142
-        messages.push(<div
143
-            key = 'end-marker'
144
-            ref = { this._setMessageListEndRef } />);
145
-
146 100
         return (
147 101
             <>
148
-                <div id = 'chatconversation'>
149
-                    { messages }
150
-                </div>
102
+                <MessageContainer messages = { this.props._messages } />
151 103
                 <ChatInput />
152 104
             </>
153 105
         );
@@ -210,33 +162,6 @@ class Chat extends AbstractChat<Props> {
210 162
             </div>
211 163
         );
212 164
     }
213
-
214
-    /**
215
-     * Automatically scrolls the displayed chat messages down to the latest.
216
-     *
217
-     * @private
218
-     * @returns {void}
219
-     */
220
-    _scrollMessagesToBottom() {
221
-        if (this._messagesListEnd) {
222
-            this._messagesListEnd.scrollIntoView({
223
-                behavior: this._isExited ? 'auto' : 'smooth'
224
-            });
225
-        }
226
-    }
227
-
228
-    _setMessageListEndRef: (?HTMLElement) => void;
229
-
230
-    /**
231
-     * Sets a reference to the HTML element at the bottom of the message list.
232
-     *
233
-     * @param {Object} messageListEnd - The HTML element.
234
-     * @private
235
-     * @returns {void}
236
-     */
237
-    _setMessageListEndRef(messageListEnd: ?HTMLElement) {
238
-        this._messagesListEnd = messageListEnd;
239
-    }
240 165
 }
241 166
 
242 167
 export default translate(connect(_mapStateToProps, _mapDispatchToProps)(Chat));

+ 129
- 0
react/features/chat/components/web/MessageContainer.js Прегледај датотеку

@@ -0,0 +1,129 @@
1
+// @flow
2
+
3
+import React, { PureComponent } from 'react';
4
+
5
+import ChatMessageGroup from './ChatMessageGroup';
6
+
7
+type Props = {
8
+
9
+    /**
10
+     * The messages array to render.
11
+     */
12
+    messages: Array<Object>
13
+}
14
+
15
+/**
16
+ * Displays all received chat messages, grouped by sender.
17
+ *
18
+ * @extends PureComponent
19
+ */
20
+export default class MessageContainer extends PureComponent<Props> {
21
+    static defaultProps = {
22
+        messages: []
23
+    };
24
+
25
+    /**
26
+     * Reference to the HTML element at the end of the list of displayed chat
27
+     * messages. Used for scrolling to the end of the chat messages.
28
+     */
29
+    _messagesListEndRef: Object;
30
+
31
+    /**
32
+     * Initializes a new {@code MessageContainer} instance.
33
+     *
34
+     * @param {Props} props - The React {@code Component} props to initialize
35
+     * the new {@code MessageContainer} instance with.
36
+     */
37
+    constructor(props: Props) {
38
+        super(props);
39
+
40
+        this._messagesListEndRef = React.createRef();
41
+    }
42
+
43
+    /**
44
+     * Implements React's {@link Component#componentDidMount()}.
45
+     *
46
+     * @inheritdoc
47
+     */
48
+    componentDidMount() {
49
+        this._scrollMessagesToBottom();
50
+    }
51
+
52
+    /**
53
+     * Updates chat input focus.
54
+     *
55
+     * @inheritdoc
56
+     */
57
+    componentDidUpdate() {
58
+        this._scrollMessagesToBottom();
59
+    }
60
+
61
+    /**
62
+     * Implements {@code Component#render}.
63
+     *
64
+     * @inheritdoc
65
+     */
66
+    render() {
67
+        const groupedMessages = this._getMessagesGroupedBySender();
68
+        const messages = groupedMessages.map((group, index) => {
69
+            const messageType = group[0] && group[0].messageType;
70
+
71
+            return (
72
+                <ChatMessageGroup
73
+                    className = { messageType || 'remote' }
74
+                    key = { index }
75
+                    messages = { group } />
76
+            );
77
+        });
78
+
79
+        return (
80
+            <div id = 'chatconversation'>
81
+                { messages }
82
+                <div ref = { this._messagesListEndRef } />
83
+            </div>
84
+        );
85
+    }
86
+
87
+    /**
88
+     * Iterates over all the messages and creates nested arrays which hold
89
+     * consecutive messages sent by the same participant.
90
+     *
91
+     * @private
92
+     * @returns {Array<Array<Object>>}
93
+     */
94
+    _getMessagesGroupedBySender() {
95
+        const messagesCount = this.props.messages.length;
96
+        const groups = [];
97
+        let currentGrouping = [];
98
+        let currentGroupParticipantId;
99
+
100
+        for (let i = 0; i < messagesCount; i++) {
101
+            const message = this.props.messages[i];
102
+
103
+            if (message.id === currentGroupParticipantId) {
104
+                currentGrouping.push(message);
105
+            } else {
106
+                groups.push(currentGrouping);
107
+
108
+                currentGrouping = [ message ];
109
+                currentGroupParticipantId = message.id;
110
+            }
111
+        }
112
+
113
+        groups.push(currentGrouping);
114
+
115
+        return groups;
116
+    }
117
+
118
+    /**
119
+     * Automatically scrolls the displayed chat messages down to the latest.
120
+     *
121
+     * @private
122
+     * @returns {void}
123
+     */
124
+    _scrollMessagesToBottom() {
125
+        this._messagesListEndRef.current.scrollIntoView({
126
+            behavior: 'smooth'
127
+        });
128
+    }
129
+}

Loading…
Откажи
Сачувај