浏览代码

feat: add chat color scheming

master
Bettenbuk Zoltan 6 年前
父节点
当前提交
a35099f949

+ 2
- 0
react/features/base/color-scheme/ColorSchemeRegistry.js 查看文件

153
         const colorScheme = toState(stateful)['features/base/color-scheme'];
153
         const colorScheme = toState(stateful)['features/base/color-scheme'];
154
 
154
 
155
         return {
155
         return {
156
+            ...defaultScheme._defaultTheme,
157
+            ...colorScheme._defaultTheme,
156
             ...defaultScheme[componentName],
158
             ...defaultScheme[componentName],
157
             ...colorScheme[componentName]
159
             ...colorScheme[componentName]
158
         }[colorDefinition];
160
         }[colorDefinition];

+ 16
- 9
react/features/base/color-scheme/defaultScheme.js 查看文件

6
  * The default color scheme of the application.
6
  * The default color scheme of the application.
7
  */
7
  */
8
 export default {
8
 export default {
9
-    'BottomSheet': {
9
+    '_defaultTheme': {
10
+        // Generic app theme colors that are used accross the entire app.
11
+        // All scheme definitions below inherit these values.
10
         background: 'rgb(255, 255, 255)',
12
         background: 'rgb(255, 255, 255)',
11
-        icon: '#1c2025',
12
-        label: '#1c2025'
13
+        icon: 'rgb(28, 32, 37)',
14
+        text: 'rgb(28, 32, 37)'
15
+    },
16
+    'Chat': {
17
+        displayName: 'rgb(94, 109, 121)',
18
+        localMsgBackground: 'rgb(215, 230, 249)',
19
+        privateMsgBackground: 'rgb(250, 219, 219)',
20
+        privateMsgNotice: 'rgb(186, 39, 58)',
21
+        remoteMsgBackground: 'rgb(241, 242, 246)',
22
+        replyBorder: 'rgb(219, 197, 200)',
23
+        replyIcon: 'rgb(94, 109, 121)'
13
     },
24
     },
14
     'Dialog': {
25
     'Dialog': {
15
-        background: 'rgb(255, 255, 255)',
16
         border: 'rgba(0, 3, 6, 0.6)',
26
         border: 'rgba(0, 3, 6, 0.6)',
17
         buttonBackground: ColorPalette.blue,
27
         buttonBackground: ColorPalette.blue,
18
-        buttonLabel: ColorPalette.white,
19
-        icon: '#1c2025',
20
-        text: '#1c2025'
28
+        buttonLabel: ColorPalette.white
21
     },
29
     },
22
     'Header': {
30
     'Header': {
23
         background: ColorPalette.blue,
31
         background: ColorPalette.blue,
30
         background: 'rgb(42, 58, 75)'
38
         background: 'rgb(42, 58, 75)'
31
     },
39
     },
32
     'LoadConfigOverlay': {
40
     'LoadConfigOverlay': {
33
-        background: 'rgb(249, 249, 249)',
34
-        text: 'rgb(28, 32, 37)'
41
+        background: 'rgb(249, 249, 249)'
35
     },
42
     },
36
     'Thumbnail': {
43
     'Thumbnail': {
37
         activeParticipantHighlight: 'rgb(81, 214, 170)',
44
         activeParticipantHighlight: 'rgb(81, 214, 170)',

+ 1
- 1
react/features/base/dialog/components/native/styles.js 查看文件

147
      * Style for the label in a generic item rendered in the menu.
147
      * Style for the label in a generic item rendered in the menu.
148
      */
148
      */
149
     labelStyle: {
149
     labelStyle: {
150
-        color: schemeColor('label'),
150
+        color: schemeColor('text'),
151
         flexShrink: 1,
151
         flexShrink: 1,
152
         fontSize: MD_FONT_SIZE,
152
         fontSize: MD_FONT_SIZE,
153
         marginLeft: 32,
153
         marginLeft: 32,

+ 4
- 2
react/features/chat/components/AbstractChatMessage.js 查看文件

4
 
4
 
5
 import { getLocalizedDateFormatter } from '../../base/i18n';
5
 import { getLocalizedDateFormatter } from '../../base/i18n';
6
 
6
 
7
+import { MESSAGE_TYPE_ERROR, MESSAGE_TYPE_LOCAL } from '../constants';
8
+
7
 /**
9
 /**
8
  * Formatter string to display the message timestamp.
10
  * Formatter string to display the message timestamp.
9
  */
11
  */
65
     _getMessageText() {
67
     _getMessageText() {
66
         const { message } = this.props;
68
         const { message } = this.props;
67
 
69
 
68
-        return message.messageType === 'error'
70
+        return message.messageType === MESSAGE_TYPE_ERROR
69
             ? this.props.t('chat.error', {
71
             ? this.props.t('chat.error', {
70
                 error: message.message
72
                 error: message.message
71
             })
73
             })
81
         const { message, t } = this.props;
83
         const { message, t } = this.props;
82
 
84
 
83
         return t('chat.privateNotice', {
85
         return t('chat.privateNotice', {
84
-            recipient: message.messageType === 'local' ? message.recipient : t('chat.you')
86
+            recipient: message.messageType === MESSAGE_TYPE_LOCAL ? message.recipient : t('chat.you')
85
         });
87
         });
86
     }
88
     }
87
 }
89
 }

+ 2
- 2
react/features/chat/components/AbstractMessageRecipient.js 查看文件

6
 
6
 
7
 import { setPrivateMessageRecipient } from '../actions';
7
 import { setPrivateMessageRecipient } from '../actions';
8
 
8
 
9
-type Props = {
9
+export type Props = {
10
 
10
 
11
     /**
11
     /**
12
      * Function used to translate i18n labels.
12
      * Function used to translate i18n labels.
27
 /**
27
 /**
28
  * Abstract class for the {@code MessageRecipient} component.
28
  * Abstract class for the {@code MessageRecipient} component.
29
  */
29
  */
30
-export default class AbstractMessageRecipient extends PureComponent<Props> {
30
+export default class AbstractMessageRecipient<P: Props> extends PureComponent<P> {
31
 
31
 
32
 }
32
 }
33
 
33
 

+ 28
- 4
react/features/chat/components/native/Chat.js 查看文件

3
 import React from 'react';
3
 import React from 'react';
4
 import { KeyboardAvoidingView, SafeAreaView } from 'react-native';
4
 import { KeyboardAvoidingView, SafeAreaView } from 'react-native';
5
 
5
 
6
+import { ColorSchemeRegistry } from '../../../base/color-scheme';
6
 import { translate } from '../../../base/i18n';
7
 import { translate } from '../../../base/i18n';
7
-
8
 import { HeaderWithNavigation, SlidingView } from '../../../base/react';
8
 import { HeaderWithNavigation, SlidingView } from '../../../base/react';
9
 import { connect } from '../../../base/redux';
9
 import { connect } from '../../../base/redux';
10
+import { StyleType } from '../../../base/styles';
10
 
11
 
11
 import AbstractChat, {
12
 import AbstractChat, {
12
     _mapDispatchToProps,
13
     _mapDispatchToProps,
13
-    _mapStateToProps,
14
-    type Props
14
+    _mapStateToProps as _abstractMapStateToProps,
15
+    type Props as AbstractProps
15
 } from '../AbstractChat';
16
 } from '../AbstractChat';
16
 
17
 
17
 import ChatInputBar from './ChatInputBar';
18
 import ChatInputBar from './ChatInputBar';
19
 import MessageRecipient from './MessageRecipient';
20
 import MessageRecipient from './MessageRecipient';
20
 import styles from './styles';
21
 import styles from './styles';
21
 
22
 
23
+type Props = AbstractProps & {
24
+
25
+    /**
26
+     * The color-schemed stylesheet of the feature.
27
+     */
28
+    _styles: StyleType
29
+};
30
+
22
 /**
31
 /**
23
  * Implements a React native component that renders the chat window (modal) of
32
  * Implements a React native component that renders the chat window (modal) of
24
  * the mobile client.
33
  * the mobile client.
41
      * @inheritdoc
50
      * @inheritdoc
42
      */
51
      */
43
     render() {
52
     render() {
53
+        const { _styles } = this.props;
54
+
44
         return (
55
         return (
45
             <SlidingView
56
             <SlidingView
46
                 onHide = { this._onClose }
57
                 onHide = { this._onClose }
52
                     <HeaderWithNavigation
63
                     <HeaderWithNavigation
53
                         headerLabelKey = 'chat.title'
64
                         headerLabelKey = 'chat.title'
54
                         onPressBack = { this._onClose } />
65
                         onPressBack = { this._onClose } />
55
-                    <SafeAreaView style = { styles.backdrop }>
66
+                    <SafeAreaView style = { _styles.backdrop }>
56
                         <MessageContainer messages = { this.props._messages } />
67
                         <MessageContainer messages = { this.props._messages } />
57
                         <MessageRecipient />
68
                         <MessageRecipient />
58
                         <ChatInputBar onSend = { this.props._onSendMessage } />
69
                         <ChatInputBar onSend = { this.props._onSendMessage } />
80
     }
91
     }
81
 }
92
 }
82
 
93
 
94
+/**
95
+ * Maps part of the redux state to the props of this component.
96
+ *
97
+ * @param {Object} state - The Redux state.
98
+ * @returns {Props}
99
+ */
100
+function _mapStateToProps(state) {
101
+    return {
102
+        ..._abstractMapStateToProps(state),
103
+        _styles: ColorSchemeRegistry.get(state, 'Chat')
104
+    };
105
+}
106
+
83
 export default translate(connect(_mapStateToProps, _mapDispatchToProps)(Chat));
107
 export default translate(connect(_mapStateToProps, _mapDispatchToProps)(Chat));

+ 104
- 37
react/features/chat/components/native/ChatMessage.js 查看文件

4
 import { Text, View } from 'react-native';
4
 import { Text, View } from 'react-native';
5
 
5
 
6
 import { Avatar } from '../../../base/avatar';
6
 import { Avatar } from '../../../base/avatar';
7
+import { ColorSchemeRegistry } from '../../../base/color-scheme';
7
 import { translate } from '../../../base/i18n';
8
 import { translate } from '../../../base/i18n';
8
 import { Linkify } from '../../../base/react';
9
 import { Linkify } from '../../../base/react';
10
+import { connect } from '../../../base/redux';
11
+import { type StyleType } from '../../../base/styles';
9
 
12
 
13
+import { MESSAGE_TYPE_ERROR, MESSAGE_TYPE_LOCAL } from '../../constants';
10
 import { replaceNonUnicodeEmojis } from '../../functions';
14
 import { replaceNonUnicodeEmojis } from '../../functions';
11
 
15
 
12
-import AbstractChatMessage, { type Props } from '../AbstractChatMessage';
16
+import AbstractChatMessage, { type Props as AbstractProps } from '../AbstractChatMessage';
13
 import PrivateMessageButton from '../PrivateMessageButton';
17
 import PrivateMessageButton from '../PrivateMessageButton';
14
 
18
 
15
 import styles from './styles';
19
 import styles from './styles';
16
 
20
 
21
+type Props = AbstractProps & {
22
+
23
+    /**
24
+     * The color-schemed stylesheet of the feature.
25
+     */
26
+    _styles: StyleType
27
+};
28
+
17
 /**
29
 /**
18
  * Renders a single chat message.
30
  * Renders a single chat message.
19
  */
31
  */
24
      * @inheritdoc
36
      * @inheritdoc
25
      */
37
      */
26
     render() {
38
     render() {
27
-        const { message } = this.props;
28
-        const localMessage = message.messageType === 'local';
39
+        const { _styles, message } = this.props;
40
+        const localMessage = message.messageType === MESSAGE_TYPE_LOCAL;
41
+        const { privateMessage } = message;
29
 
42
 
30
         // Style arrays that need to be updated in various scenarios, such as
43
         // Style arrays that need to be updated in various scenarios, such as
31
         // error messages or others.
44
         // error messages or others.
32
         const detailsWrapperStyle = [
45
         const detailsWrapperStyle = [
33
             styles.detailsWrapper
46
             styles.detailsWrapper
34
         ];
47
         ];
35
-        const textWrapperStyle = [
36
-            styles.textWrapper
48
+        const messageBubbleStyle = [
49
+            styles.messageBubble
37
         ];
50
         ];
38
 
51
 
39
         if (localMessage) {
52
         if (localMessage) {
53
+            // This is a message sent by the local participant.
54
+
40
             // The wrapper needs to be aligned to the right.
55
             // The wrapper needs to be aligned to the right.
41
             detailsWrapperStyle.push(styles.ownMessageDetailsWrapper);
56
             detailsWrapperStyle.push(styles.ownMessageDetailsWrapper);
42
 
57
 
43
-            // The bubble needs to be differently styled.
44
-            textWrapperStyle.push(styles.ownTextWrapper);
45
-        } else if (message.messageType === 'error') {
46
-            // The bubble needs to be differently styled.
47
-            textWrapperStyle.push(styles.systemTextWrapper);
58
+            // The bubble needs some additional styling
59
+            messageBubbleStyle.push(_styles.localMessageBubble);
60
+        } else if (message.messageType === MESSAGE_TYPE_ERROR) {
61
+            // This is a system message.
62
+
63
+            // The bubble needs some additional styling
64
+            messageBubbleStyle.push(styles.systemMessageBubble);
65
+        } else {
66
+            // This is a remote message sent by a remote participant.
67
+
68
+            // The bubble needs some additional styling
69
+            messageBubbleStyle.push(_styles.remoteMessageBubble);
70
+        }
71
+
72
+        if (privateMessage) {
73
+            messageBubbleStyle.push(_styles.privateMessageBubble);
48
         }
74
         }
49
 
75
 
50
         return (
76
         return (
51
             <View style = { styles.messageWrapper } >
77
             <View style = { styles.messageWrapper } >
52
                 { this._renderAvatar() }
78
                 { this._renderAvatar() }
53
                 <View style = { detailsWrapperStyle }>
79
                 <View style = { detailsWrapperStyle }>
54
-                    <View style = { styles.replyWrapper }>
55
-                        <View style = { textWrapperStyle } >
56
-                            {
57
-                                this.props.showDisplayName
58
-                                    && this._renderDisplayName()
59
-                            }
80
+                    <View style = { messageBubbleStyle }>
81
+                        <View style = { styles.textWrapper } >
82
+                            { this._renderDisplayName() }
60
                             <Linkify linkStyle = { styles.chatLink }>
83
                             <Linkify linkStyle = { styles.chatLink }>
61
                                 { replaceNonUnicodeEmojis(this._getMessageText()) }
84
                                 { replaceNonUnicodeEmojis(this._getMessageText()) }
62
                             </Linkify>
85
                             </Linkify>
63
-                            {
64
-                                message.privateMessage
65
-                                    && this._renderPrivateNotice()
66
-                            }
86
+                            { this._renderPrivateNotice() }
67
                         </View>
87
                         </View>
68
-                        { message.privateMessage && !localMessage
69
-                            && <PrivateMessageButton
70
-                                participantID = { message.id }
71
-                                reply = { true }
72
-                                showLabel = { false }
73
-                                toggledStyles = { styles.replyStyles } /> }
88
+                        { this._renderPrivateReplyButton() }
74
                     </View>
89
                     </View>
75
-                    { this.props.showTimestamp && this._renderTimestamp() }
90
+                    { this._renderTimestamp() }
76
                 </View>
91
                 </View>
77
             </View>
92
             </View>
78
         );
93
         );
104
     }
119
     }
105
 
120
 
106
     /**
121
     /**
107
-     * Renders the display name of the sender.
122
+     * Renders the display name of the sender if necessary.
108
      *
123
      *
109
-     * @returns {React$Element<*>}
124
+     * @returns {React$Element<*> | null}
110
      */
125
      */
111
     _renderDisplayName() {
126
     _renderDisplayName() {
127
+        const { _styles, message, showDisplayName } = this.props;
128
+
129
+        if (!showDisplayName) {
130
+            return null;
131
+        }
132
+
112
         return (
133
         return (
113
-            <Text style = { styles.displayName }>
114
-                { this.props.message.displayName }
134
+            <Text style = { _styles.displayName }>
135
+                { message.displayName }
115
             </Text>
136
             </Text>
116
         );
137
         );
117
     }
138
     }
118
 
139
 
119
     /**
140
     /**
120
-     * Renders the message privacy notice.
141
+     * Renders the message privacy notice, if necessary.
121
      *
142
      *
122
-     * @returns {React$Element<*>}
143
+     * @returns {React$Element<*> | null}
123
      */
144
      */
124
     _renderPrivateNotice() {
145
     _renderPrivateNotice() {
146
+        const { _styles, message } = this.props;
147
+
148
+        if (!message.privateMessage) {
149
+            return null;
150
+        }
151
+
125
         return (
152
         return (
126
-            <Text style = { styles.privateNotice }>
153
+            <Text style = { _styles.privateNotice }>
127
                 { this._getPrivateNoticeMessage() }
154
                 { this._getPrivateNoticeMessage() }
128
             </Text>
155
             </Text>
129
         );
156
         );
130
     }
157
     }
131
 
158
 
132
     /**
159
     /**
133
-     * Renders the time at which the message was sent.
160
+     * Renders the private reply button, if necessary.
134
      *
161
      *
135
-     * @returns {React$Element<*>}
162
+     * @returns {React$Element<*> | null}
163
+     */
164
+    _renderPrivateReplyButton() {
165
+        const { _styles, message } = this.props;
166
+        const { messageType, privateMessage } = message;
167
+
168
+        if (!privateMessage || messageType === MESSAGE_TYPE_LOCAL) {
169
+            return null;
170
+        }
171
+
172
+        return (
173
+            <View style = { _styles.replyContainer }>
174
+                <PrivateMessageButton
175
+                    participantID = { message.id }
176
+                    reply = { true }
177
+                    showLabel = { false }
178
+                    toggledStyles = { _styles.replyStyles } />
179
+            </View>
180
+        );
181
+    }
182
+
183
+    /**
184
+     * Renders the time at which the message was sent, if necessary.
185
+     *
186
+     * @returns {React$Element<*> | null}
136
      */
187
      */
137
     _renderTimestamp() {
188
     _renderTimestamp() {
189
+        if (!this.props.showTimestamp) {
190
+            return null;
191
+        }
192
+
138
         return (
193
         return (
139
             <Text style = { styles.timeText }>
194
             <Text style = { styles.timeText }>
140
                 { this._getFormattedTimestamp() }
195
                 { this._getFormattedTimestamp() }
143
     }
198
     }
144
 }
199
 }
145
 
200
 
146
-export default translate(ChatMessage);
201
+/**
202
+ * Maps part of the redux state to the props of this component.
203
+ *
204
+ * @param {Object} state - The Redux state.
205
+ * @returns {Props}
206
+ */
207
+function _mapStateToProps(state) {
208
+    return {
209
+        _styles: ColorSchemeRegistry.get(state, 'Chat')
210
+    };
211
+}
212
+
213
+export default translate(connect(_mapStateToProps)(ChatMessage));

+ 4
- 2
react/features/chat/components/native/ChatMessageGroup.js 查看文件

3
 import React, { Component } from 'react';
3
 import React, { Component } from 'react';
4
 import { FlatList } from 'react-native';
4
 import { FlatList } from 'react-native';
5
 
5
 
6
+import { MESSAGE_TYPE_LOCAL, MESSAGE_TYPE_REMOTE } from '../../constants';
7
+
6
 import ChatMessage from './ChatMessage';
8
 import ChatMessage from './ChatMessage';
7
 import styles from './styles';
9
 import styles from './styles';
8
 
10
 
73
             <ChatMessage
75
             <ChatMessage
74
                 message = { message }
76
                 message = { message }
75
                 showAvatar = {
77
                 showAvatar = {
76
-                    this.props.messages[0].messageType !== 'local'
78
+                    this.props.messages[0].messageType !== MESSAGE_TYPE_LOCAL
77
                         && index === this.props.messages.length - 1
79
                         && index === this.props.messages.length - 1
78
                 }
80
                 }
79
                 showDisplayName = {
81
                 showDisplayName = {
80
-                    this.props.messages[0].messageType === 'remote'
82
+                    this.props.messages[0].messageType === MESSAGE_TYPE_REMOTE
81
                         && index === this.props.messages.length - 1
83
                         && index === this.props.messages.length - 1
82
                 }
84
                 }
83
                 showTimestamp = { index === 0 } />
85
                 showTimestamp = { index === 0 } />

+ 29
- 7
react/features/chat/components/native/MessageRecipient.js 查看文件

3
 import React from 'react';
3
 import React from 'react';
4
 import { Text, TouchableHighlight, View } from 'react-native';
4
 import { Text, TouchableHighlight, View } from 'react-native';
5
 
5
 
6
+import { ColorSchemeRegistry } from '../../../base/color-scheme';
6
 import { translate } from '../../../base/i18n';
7
 import { translate } from '../../../base/i18n';
7
 import { Icon, IconCancelSelection } from '../../../base/icons';
8
 import { Icon, IconCancelSelection } from '../../../base/icons';
8
 import { connect } from '../../../base/redux';
9
 import { connect } from '../../../base/redux';
10
+import { type StyleType } from '../../../base/styles';
9
 
11
 
10
 import AbstractMessageRecipient, {
12
 import AbstractMessageRecipient, {
11
     _mapDispatchToProps,
13
     _mapDispatchToProps,
12
-    _mapStateToProps
14
+    _mapStateToProps as _abstractMapStateToProps,
15
+    type Props as AbstractProps
13
 } from '../AbstractMessageRecipient';
16
 } from '../AbstractMessageRecipient';
14
 
17
 
15
-import styles from './styles';
18
+type Props = AbstractProps & {
19
+
20
+    /**
21
+     * The color-schemed stylesheet of the feature.
22
+     */
23
+    _styles: StyleType
24
+};
16
 
25
 
17
 /**
26
 /**
18
  * Class to implement the displaying of the recipient of the next message.
27
  * Class to implement the displaying of the recipient of the next message.
19
  */
28
  */
20
-class MessageRecipient extends AbstractMessageRecipient {
29
+class MessageRecipient extends AbstractMessageRecipient<Props> {
21
     /**
30
     /**
22
      * Implements {@code PureComponent#render}.
31
      * Implements {@code PureComponent#render}.
23
      *
32
      *
24
      * @inheritdoc
33
      * @inheritdoc
25
      */
34
      */
26
     render() {
35
     render() {
27
-        const { _privateMessageRecipient } = this.props;
36
+        const { _privateMessageRecipient, _styles } = this.props;
28
 
37
 
29
         if (!_privateMessageRecipient) {
38
         if (!_privateMessageRecipient) {
30
             return null;
39
             return null;
33
         const { t } = this.props;
42
         const { t } = this.props;
34
 
43
 
35
         return (
44
         return (
36
-            <View style = { styles.messageRecipientContainer }>
37
-                <Text style = { styles.messageRecipientText }>
45
+            <View style = { _styles.messageRecipientContainer }>
46
+                <Text style = { _styles.messageRecipientText }>
38
                     { t('chat.messageTo', {
47
                     { t('chat.messageTo', {
39
                         recipient: _privateMessageRecipient
48
                         recipient: _privateMessageRecipient
40
                     }) }
49
                     }) }
42
                 <TouchableHighlight onPress = { this.props._onRemovePrivateMessageRecipient }>
51
                 <TouchableHighlight onPress = { this.props._onRemovePrivateMessageRecipient }>
43
                     <Icon
52
                     <Icon
44
                         src = { IconCancelSelection }
53
                         src = { IconCancelSelection }
45
-                        style = { styles.messageRecipientCancelIcon } />
54
+                        style = { _styles.messageRecipientCancelIcon } />
46
                 </TouchableHighlight>
55
                 </TouchableHighlight>
47
             </View>
56
             </View>
48
         );
57
         );
49
     }
58
     }
50
 }
59
 }
51
 
60
 
61
+/**
62
+ * Maps part of the redux state to the props of this component.
63
+ *
64
+ * @param {Object} state - The Redux state.
65
+ * @returns {Props}
66
+ */
67
+function _mapStateToProps(state) {
68
+    return {
69
+        ..._abstractMapStateToProps(state),
70
+        _styles: ColorSchemeRegistry.get(state, 'Chat')
71
+    };
72
+}
73
+
52
 export default translate(connect(_mapStateToProps, _mapDispatchToProps)(MessageRecipient));
74
 export default translate(connect(_mapStateToProps, _mapDispatchToProps)(MessageRecipient));

+ 78
- 66
react/features/chat/components/native/styles.js 查看文件

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
3
 import { BoxModel, ColorPalette } from '../../../base/styles';
4
 import { BoxModel, ColorPalette } from '../../../base/styles';
4
 
5
 
6
+const BUBBLE_RADIUS = 8;
7
+
5
 /**
8
 /**
6
  * The styles of the feature chat.
9
  * The styles of the feature chat.
7
  *
10
  *
20
         width: 32
23
         width: 32
21
     },
24
     },
22
 
25
 
23
-    /**
24
-     * Background of the chat screen.
25
-     */
26
-    backdrop: {
27
-        backgroundColor: ColorPalette.white,
28
-        flex: 1
29
-    },
30
-
31
     chatContainer: {
26
     chatContainer: {
32
         alignItems: 'stretch',
27
         alignItems: 'stretch',
33
         flex: 1,
28
         flex: 1,
47
         flexDirection: 'column'
42
         flexDirection: 'column'
48
     },
43
     },
49
 
44
 
50
-    /**
51
-     * The text node for the display name.
52
-     */
53
-    displayName: {
54
-        color: 'rgb(118, 136, 152)',
55
-        fontSize: 13
56
-    },
57
-
58
     /**
45
     /**
59
      * A special padding to avoid issues on some devices (such as Android devices with custom suggestions bar).
46
      * A special padding to avoid issues on some devices (such as Android devices with custom suggestions bar).
60
      */
47
      */
76
         height: 48
63
         height: 48
77
     },
64
     },
78
 
65
 
79
-    messageContainer: {
80
-        flex: 1
81
-    },
82
-
83
-    messageRecipientCancelIcon: {
84
-        color: ColorPalette.white,
85
-        fontSize: 18
86
-    },
87
-
88
-    messageRecipientContainer: {
66
+    messageBubble: {
89
         alignItems: 'center',
67
         alignItems: 'center',
90
-        backgroundColor: ColorPalette.warning,
91
-        flexDirection: 'row',
92
-        padding: BoxModel.padding
68
+        borderRadius: BUBBLE_RADIUS,
69
+        flexDirection: 'row'
93
     },
70
     },
94
 
71
 
95
-    messageRecipientText: {
96
-        color: ColorPalette.white,
72
+    messageContainer: {
97
         flex: 1
73
         flex: 1
98
     },
74
     },
99
 
75
 
100
-    /**
101
-     * The message text itself.
102
-     */
103
-    messageText: {
104
-        color: 'rgb(28, 32, 37)',
105
-        fontSize: 15
106
-    },
107
-
108
     /**
76
     /**
109
      * Wrapper View for the entire block.
77
      * Wrapper View for the entire block.
110
      */
78
      */
123
         alignItems: 'flex-end'
91
         alignItems: 'flex-end'
124
     },
92
     },
125
 
93
 
126
-    /**
127
-     * Style modifier for the {@code textWrapper} for own messages.
128
-     */
129
-    ownTextWrapper: {
130
-        backgroundColor: 'rgb(210, 231, 249)',
131
-        borderTopLeftRadius: 8,
132
-        borderTopRightRadius: 0
133
-    },
134
-
135
     replyWrapper: {
94
     replyWrapper: {
136
         alignItems: 'center',
95
         alignItems: 'center',
137
         flexDirection: 'row'
96
         flexDirection: 'row'
138
     },
97
     },
139
 
98
 
140
-    replyStyles: {
141
-        iconStyle: {
142
-            color: 'rgb(118, 136, 152)',
143
-            fontSize: 22,
144
-            margin: BoxModel.margin / 2
145
-        }
146
-    },
147
-
148
-    privateNotice: {
149
-        color: ColorPalette.warning,
150
-        fontSize: 13,
151
-        fontStyle: 'italic'
152
-    },
153
-
154
     sendButtonIcon: {
99
     sendButtonIcon: {
155
         color: ColorPalette.darkGrey,
100
         color: ColorPalette.darkGrey,
156
         fontSize: 22
101
         fontSize: 22
159
     /**
104
     /**
160
      * Style modifier for system (error) messages.
105
      * Style modifier for system (error) messages.
161
      */
106
      */
162
-    systemTextWrapper: {
107
+    systemMessageBubble: {
163
         backgroundColor: 'rgb(247, 215, 215)'
108
         backgroundColor: 'rgb(247, 215, 215)'
164
     },
109
     },
165
 
110
 
168
      */
113
      */
169
     textWrapper: {
114
     textWrapper: {
170
         alignItems: 'flex-start',
115
         alignItems: 'flex-start',
171
-        backgroundColor: 'rgb(240, 243, 247)',
172
-        borderRadius: 8,
173
-        borderTopLeftRadius: 0,
174
         flexDirection: 'column',
116
         flexDirection: 'column',
175
         padding: 9
117
         padding: 9
176
     },
118
     },
183
         fontSize: 13
125
         fontSize: 13
184
     }
126
     }
185
 };
127
 };
128
+
129
+ColorSchemeRegistry.register('Chat', {
130
+    /**
131
+     * Background of the chat screen.
132
+     */
133
+    backdrop: {
134
+        backgroundColor: schemeColor('background'),
135
+        flex: 1
136
+    },
137
+
138
+    /**
139
+     * The text node for the display name.
140
+     */
141
+    displayName: {
142
+        color: schemeColor('displayName'),
143
+        fontSize: 13
144
+    },
145
+
146
+    localMessageBubble: {
147
+        backgroundColor: schemeColor('localMsgBackground'),
148
+        borderTopRightRadius: 0
149
+    },
150
+
151
+    messageRecipientCancelIcon: {
152
+        color: schemeColor('icon'),
153
+        fontSize: 18
154
+    },
155
+
156
+    messageRecipientContainer: {
157
+        alignItems: 'center',
158
+        backgroundColor: schemeColor('privateMsgBackground'),
159
+        flexDirection: 'row',
160
+        padding: BoxModel.padding
161
+    },
162
+
163
+    messageRecipientText: {
164
+        color: schemeColor('text'),
165
+        flex: 1
166
+    },
167
+
168
+    privateNotice: {
169
+        color: schemeColor('privateMsgNotice'),
170
+        fontSize: 11,
171
+        marginTop: 6
172
+    },
173
+
174
+    privateMessageBubble: {
175
+        backgroundColor: schemeColor('privateMsgBackground')
176
+    },
177
+
178
+    remoteMessageBubble: {
179
+        backgroundColor: schemeColor('remoteMsgBackground'),
180
+        borderTopLeftRadius: 0
181
+    },
182
+
183
+    replyContainer: {
184
+        alignSelf: 'stretch',
185
+        borderLeftColor: schemeColor('replyBorder'),
186
+        borderLeftWidth: 1,
187
+        justifyContent: 'center'
188
+    },
189
+
190
+    replyStyles: {
191
+        iconStyle: {
192
+            color: schemeColor('replyIcon'),
193
+            fontSize: 22,
194
+            padding: 8
195
+        }
196
+    }
197
+});

+ 3
- 1
react/features/chat/components/web/ChatMessage.js 查看文件

7
 import { translate } from '../../../base/i18n';
7
 import { translate } from '../../../base/i18n';
8
 import { Linkify } from '../../../base/react';
8
 import { Linkify } from '../../../base/react';
9
 
9
 
10
+import { MESSAGE_TYPE_LOCAL } from '../../constants';
11
+
10
 import AbstractChatMessage, {
12
 import AbstractChatMessage, {
11
     type Props
13
     type Props
12
 } from '../AbstractChatMessage';
14
 } from '../AbstractChatMessage';
47
                         </div>
49
                         </div>
48
                         { message.privateMessage && this._renderPrivateNotice() }
50
                         { message.privateMessage && this._renderPrivateNotice() }
49
                     </div>
51
                     </div>
50
-                    { message.privateMessage && message.messageType !== 'local'
52
+                    { message.privateMessage && message.messageType !== MESSAGE_TYPE_LOCAL
51
                     && <PrivateMessageButton
53
                     && <PrivateMessageButton
52
                         participantID = { message.id }
54
                         participantID = { message.id }
53
                         reply = { true }
55
                         reply = { true }

+ 3
- 1
react/features/chat/components/web/MessageContainer.js 查看文件

2
 
2
 
3
 import React from 'react';
3
 import React from 'react';
4
 
4
 
5
+import { MESSAGE_TYPE_REMOTE } from '../../constants';
6
+
5
 import AbstractMessageContainer, { type Props }
7
 import AbstractMessageContainer, { type Props }
6
     from '../AbstractMessageContainer';
8
     from '../AbstractMessageContainer';
7
 
9
 
61
 
63
 
62
             return (
64
             return (
63
                 <ChatMessageGroup
65
                 <ChatMessageGroup
64
-                    className = { messageType || 'remote' }
66
+                    className = { messageType || MESSAGE_TYPE_REMOTE }
65
                     key = { index }
67
                     key = { index }
66
                     messages = { group } />
68
                     messages = { group } />
67
             );
69
             );

+ 3
- 2
react/features/chat/components/web/MessageRecipient.js 查看文件

8
 
8
 
9
 import AbstractMessageRecipient, {
9
 import AbstractMessageRecipient, {
10
     _mapDispatchToProps,
10
     _mapDispatchToProps,
11
-    _mapStateToProps
11
+    _mapStateToProps,
12
+    type Props
12
 } from '../AbstractMessageRecipient';
13
 } from '../AbstractMessageRecipient';
13
 
14
 
14
 /**
15
 /**
15
  * Class to implement the displaying of the recipient of the next message.
16
  * Class to implement the displaying of the recipient of the next message.
16
  */
17
  */
17
-class MessageRecipient extends AbstractMessageRecipient {
18
+class MessageRecipient extends AbstractMessageRecipient<Props> {
18
     /**
19
     /**
19
      * Implements {@code PureComponent#render}.
20
      * Implements {@code PureComponent#render}.
20
      *
21
      *

+ 17
- 0
react/features/chat/constants.js 查看文件

1
+// @flow
2
+
1
 /**
3
 /**
2
  * The audio ID of the audio element for which the {@link playAudio} action is
4
  * The audio ID of the audio element for which the {@link playAudio} action is
3
  * triggered when new chat message is received.
5
  * triggered when new chat message is received.
5
  * @type {string}
7
  * @type {string}
6
  */
8
  */
7
 export const INCOMING_MSG_SOUND_ID = 'INCOMING_MSG_SOUND';
9
 export const INCOMING_MSG_SOUND_ID = 'INCOMING_MSG_SOUND';
10
+
11
+/**
12
+ * The {@code messageType} of error (system) messages.
13
+ */
14
+export const MESSAGE_TYPE_ERROR = 'error';
15
+
16
+/**
17
+ * The {@code messageType} of local messages.
18
+ */
19
+export const MESSAGE_TYPE_LOCAL = 'local';
20
+
21
+/**
22
+ * The {@code messageType} of remote messages.
23
+ */
24
+export const MESSAGE_TYPE_REMOTE = 'remote';

+ 6
- 6
react/features/chat/middleware.js 查看文件

22
 import { SEND_MESSAGE, SET_PRIVATE_MESSAGE_RECIPIENT } from './actionTypes';
22
 import { SEND_MESSAGE, SET_PRIVATE_MESSAGE_RECIPIENT } from './actionTypes';
23
 import { addMessage, clearMessages, toggleChat } from './actions';
23
 import { addMessage, clearMessages, toggleChat } from './actions';
24
 import { ChatPrivacyDialog } from './components';
24
 import { ChatPrivacyDialog } from './components';
25
-import { INCOMING_MSG_SOUND_ID } from './constants';
25
+import { INCOMING_MSG_SOUND_ID, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_LOCAL, MESSAGE_TYPE_REMOTE } from './constants';
26
 import { INCOMING_MSG_SOUND_FILE } from './sounds';
26
 import { INCOMING_MSG_SOUND_FILE } from './sounds';
27
 
27
 
28
 declare var APP: Object;
28
 declare var APP: Object;
194
 function _handleChatError({ dispatch }, error) {
194
 function _handleChatError({ dispatch }, error) {
195
     dispatch(addMessage({
195
     dispatch(addMessage({
196
         hasRead: true,
196
         hasRead: true,
197
-        messageType: 'error',
197
+        messageType: MESSAGE_TYPE_ERROR,
198
         message: error,
198
         message: error,
199
         privateMessage: false,
199
         privateMessage: false,
200
         timestamp: Date.now()
200
         timestamp: Date.now()
231
         displayName,
231
         displayName,
232
         hasRead,
232
         hasRead,
233
         id,
233
         id,
234
-        messageType: participant.local ? 'local' : 'remote',
234
+        messageType: participant.local ? MESSAGE_TYPE_LOCAL : MESSAGE_TYPE_REMOTE,
235
         message,
235
         message,
236
         privateMessage,
236
         privateMessage,
237
         recipient: getParticipantDisplayName(state, localParticipant.id),
237
         recipient: getParticipantDisplayName(state, localParticipant.id),
285
         displayName,
285
         displayName,
286
         hasRead: true,
286
         hasRead: true,
287
         id: localParticipant.id,
287
         id: localParticipant.id,
288
-        messageType: 'local',
288
+        messageType: MESSAGE_TYPE_LOCAL,
289
         message,
289
         message,
290
         privateMessage: true,
290
         privateMessage: true,
291
         recipient: getParticipantDisplayName(getState, recipientID),
291
         recipient: getParticipantDisplayName(getState, recipientID),
323
     const lastMessage = navigator.product === 'ReactNative'
323
     const lastMessage = navigator.product === 'ReactNative'
324
         ? messages[0] : messages[messages.length - 1];
324
         ? messages[0] : messages[messages.length - 1];
325
 
325
 
326
-    if (lastMessage.messageType === 'local') {
326
+    if (lastMessage.messageType === MESSAGE_TYPE_LOCAL) {
327
         // The sender is probably aware of any private messages as already sent
327
         // The sender is probably aware of any private messages as already sent
328
         // a message since then. Doesn't make sense to display the notice now.
328
         // a message since then. Doesn't make sense to display the notice now.
329
         return undefined;
329
         return undefined;
339
     const now = Date.now();
339
     const now = Date.now();
340
     const recentPrivateMessages = messages.filter(
340
     const recentPrivateMessages = messages.filter(
341
         message =>
341
         message =>
342
-            message.messageType !== 'local'
342
+            message.messageType !== MESSAGE_TYPE_LOCAL
343
             && message.privateMessage
343
             && message.privateMessage
344
             && message.timestamp + PRIVACY_NOTICE_TIMEOUT > now);
344
             && message.timestamp + PRIVACY_NOTICE_TIMEOUT > now);
345
     const recentPrivateMessage = navigator.product === 'ReactNative'
345
     const recentPrivateMessage = navigator.product === 'ReactNative'

正在加载...
取消
保存