Просмотр исходного кода

[RN] Extract AvatarListItem

j8
Bettenbuk Zoltan 6 лет назад
Родитель
Сommit
38b1be1291

+ 2
- 0
react/features/base/react/components/_.native.js Просмотреть файл

@@ -1 +1,3 @@
1
+// @flow
2
+
1 3
 export * from './native';

+ 2
- 0
react/features/base/react/components/index.js Просмотреть файл

@@ -1,3 +1,5 @@
1
+// @flow
2
+
1 3
 export * from './_';
2 4
 export { default as AbstractPage } from './AbstractPage';
3 5
 export { default as NavigateSectionList } from './NavigateSectionList';

+ 203
- 0
react/features/base/react/components/native/AvatarListItem.js Просмотреть файл

@@ -0,0 +1,203 @@
1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import { Text } from 'react-native';
5
+
6
+import { Icon } from '../../../font-icons';
7
+import { Avatar } from '../../../participants';
8
+import { StyleType } from '../../../styles';
9
+
10
+import { type Item } from '../../Types';
11
+
12
+import Container from './Container';
13
+import styles, { AVATAR_SIZE, UNDERLAY_COLOR } from './styles';
14
+
15
+type Props = {
16
+
17
+    /**
18
+     * Preferred size of the avatar.
19
+     */
20
+    avatarSize?: number,
21
+
22
+    /**
23
+     * External style to be applied to the avatar (icon).
24
+     */
25
+    avatarStyle?: StyleType,
26
+
27
+    /**
28
+     * External style to be applied to the avatar (text).
29
+     */
30
+    avatarTextStyle?: StyleType,
31
+
32
+    /**
33
+     * Children of the component.
34
+     */
35
+    children?: ?React$Element<*>,
36
+
37
+    /**
38
+     * item containing data to be rendered
39
+     */
40
+    item: Item,
41
+
42
+    /**
43
+     * External style prop to be applied to the extra lines.
44
+     */
45
+    linesStyle?: StyleType,
46
+
47
+    /**
48
+     * Function to invoke on press.
49
+     */
50
+    onPress: ?Function,
51
+
52
+    /**
53
+     * External style prop to be applied to the title.
54
+     */
55
+    titleStyle?: StyleType
56
+};
57
+
58
+/**
59
+ * Implements a list item with an avatar rendered for it.
60
+ */
61
+export default class AvatarListItem extends Component<Props> {
62
+    /**
63
+     * Constructor of the component.
64
+     *
65
+     * @inheritdoc
66
+     */
67
+    constructor(props: Props) {
68
+        super(props);
69
+
70
+        this._renderItemLine = this._renderItemLine.bind(this);
71
+    }
72
+
73
+    /**
74
+     * Implements {@code Component#render}.
75
+     *
76
+     * @inheritdoc
77
+     */
78
+    render() {
79
+        const {
80
+            avatarSize = AVATAR_SIZE,
81
+            avatarStyle,
82
+            avatarTextStyle
83
+        } = this.props;
84
+        const { avatar, colorBase, lines, title } = this.props.item;
85
+        const avatarStyles = {
86
+            ...styles.avatar,
87
+            ...this._getAvatarColor(colorBase),
88
+            ...avatarStyle,
89
+            borderRadius: avatarSize / 2,
90
+            height: avatarSize,
91
+            width: avatarSize
92
+        };
93
+
94
+        const isAvatarURL = Boolean(avatar && avatar.match(/^http[s]*:\/\//i));
95
+
96
+        return (
97
+            <Container
98
+                onClick = { this.props.onPress }
99
+                style = { styles.listItem }
100
+                underlayColor = { UNDERLAY_COLOR }>
101
+                <Container style = { styles.avatarContainer }>
102
+                    <Container style = { avatarStyles }>
103
+                        {
104
+                            isAvatarURL && <Avatar
105
+                                size = { avatarSize }
106
+                                uri = { avatar } />
107
+                        }
108
+
109
+                        {
110
+                            Boolean(avatar && !isAvatarURL) && <Icon
111
+                                name = { avatar } />
112
+                        }
113
+
114
+                        {
115
+                            !avatar && <Text
116
+                                style = { [
117
+                                    styles.avatarContent,
118
+                                    avatarTextStyle
119
+                                ] }>
120
+                                { title.substr(0, 1).toUpperCase() }
121
+                            </Text>
122
+                        }
123
+                    </Container>
124
+                </Container>
125
+                <Container style = { styles.listItemDetails }>
126
+                    <Text
127
+                        numberOfLines = { 1 }
128
+                        style = { [
129
+                            styles.listItemText,
130
+                            styles.listItemTitle,
131
+                            this.props.titleStyle
132
+                        ] }>
133
+                        { title }
134
+                    </Text>
135
+                    {this._renderItemLines(lines)}
136
+                </Container>
137
+                { this.props.children }
138
+            </Container>
139
+        );
140
+    }
141
+
142
+    /**
143
+     * Returns a style (color) based on the string that determines the color of
144
+     * the avatar.
145
+     *
146
+     * @param {string} colorBase - The string that is the base of the color.
147
+     * @private
148
+     * @returns {Object}
149
+     */
150
+    _getAvatarColor(colorBase) {
151
+        if (!colorBase) {
152
+            return null;
153
+        }
154
+        let nameHash = 0;
155
+
156
+        for (let i = 0; i < colorBase.length; i++) {
157
+            nameHash += colorBase.codePointAt(i);
158
+        }
159
+
160
+        return styles[`avatarColor${(nameHash % 5) + 1}`];
161
+    }
162
+
163
+    _renderItemLine: (string, number) => React$Node;
164
+
165
+    /**
166
+     * Renders a single line from the additional lines.
167
+     *
168
+     * @param {string} line - The line text.
169
+     * @param {number} index - The index of the line.
170
+     * @private
171
+     * @returns {React$Node}
172
+     */
173
+    _renderItemLine(line, index) {
174
+        if (!line) {
175
+            return null;
176
+        }
177
+
178
+        return (
179
+            <Text
180
+                key = { index }
181
+                numberOfLines = { 1 }
182
+                style = { [
183
+                    styles.listItemText,
184
+                    this.props.linesStyle
185
+                ] }>
186
+                {line}
187
+            </Text>
188
+        );
189
+    }
190
+
191
+    _renderItemLines: Array<string> => Array<React$Node>;
192
+
193
+    /**
194
+     * Renders the additional item lines, if any.
195
+     *
196
+     * @param {Array<string>} lines - The lines to render.
197
+     * @private
198
+     * @returns {Array<React$Node>}
199
+     */
200
+    _renderItemLines(lines) {
201
+        return lines && lines.length ? lines.map(this._renderItemLine) : null;
202
+    }
203
+}

+ 10
- 54
react/features/base/react/components/native/NavigateSectionListItem.js Просмотреть файл

@@ -7,9 +7,11 @@ import { ColorPalette } from '../../../styles';
7 7
 
8 8
 import Container from './Container';
9 9
 import Text from './Text';
10
-import styles, { UNDERLAY_COLOR } from './styles';
10
+import styles from './styles';
11 11
 import type { Item } from '../../Types';
12 12
 
13
+import AvatarListItem from './AvatarListItem';
14
+
13 15
 type Props = {
14 16
 
15 17
     /**
@@ -48,34 +50,11 @@ export default class NavigateSectionListItem extends Component<Props> {
48 50
      */
49 51
     constructor(props: Props) {
50 52
         super(props);
51
-        this._getAvatarColor = this._getAvatarColor.bind(this);
53
+
52 54
         this._renderItemLine = this._renderItemLine.bind(this);
53 55
         this._renderItemLines = this._renderItemLines.bind(this);
54 56
     }
55 57
 
56
-    _getAvatarColor: string => Object;
57
-
58
-    /**
59
-     * Returns a style (color) based on the string that determines the color of
60
-     * the avatar.
61
-     *
62
-     * @param {string} colorBase - The string that is the base of the color.
63
-     * @private
64
-     * @returns {Object}
65
-     */
66
-    _getAvatarColor(colorBase) {
67
-        if (!colorBase) {
68
-            return null;
69
-        }
70
-        let nameHash = 0;
71
-
72
-        for (let i = 0; i < colorBase.length; i++) {
73
-            nameHash += colorBase.codePointAt(i);
74
-        }
75
-
76
-        return styles[`avatarColor${(nameHash % 5) + 1}`];
77
-    }
78
-
79 58
     _renderItemLine: (string, number) => React$Node;
80 59
 
81 60
     /**
@@ -138,12 +117,8 @@ export default class NavigateSectionListItem extends Component<Props> {
138 117
      * @returns {ReactElement}
139 118
      */
140 119
     render() {
141
-        const { slideActions } = this.props;
142
-        const { id, colorBase, lines, title } = this.props.item;
143
-        const avatarStyles = {
144
-            ...styles.avatar,
145
-            ...this._getAvatarColor(colorBase)
146
-        };
120
+        const { item, slideActions } = this.props;
121
+        const { id } = item;
147 122
         let right;
148 123
 
149 124
         // NOTE: The {@code Swipeout} component has an onPress prop encapsulated
@@ -165,31 +140,12 @@ export default class NavigateSectionListItem extends Component<Props> {
165 140
             <Swipeout
166 141
                 backgroundColor = { ColorPalette.transparent }
167 142
                 right = { right }>
168
-                <Container
169
-                    onClick = { this.props.onPress }
170
-                    style = { styles.listItem }
171
-                    underlayColor = { UNDERLAY_COLOR }>
172
-                    <Container style = { styles.avatarContainer }>
173
-                        <Container style = { avatarStyles }>
174
-                            <Text style = { styles.avatarContent }>
175
-                                {title.substr(0, 1).toUpperCase()}
176
-                            </Text>
177
-                        </Container>
178
-                    </Container>
179
-                    <Container style = { styles.listItemDetails }>
180
-                        <Text
181
-                            numberOfLines = { 1 }
182
-                            style = { [
183
-                                styles.listItemText,
184
-                                styles.listItemTitle
185
-                            ] }>
186
-                            {title}
187
-                        </Text>
188
-                        {this._renderItemLines(lines)}
189
-                    </Container>
143
+                <AvatarListItem
144
+                    item = { item }
145
+                    onPress = { this.props.onPress }>
190 146
                     { this.props.secondaryAction
191 147
                         && this._renderSecondaryAction() }
192
-                </Container>
148
+                </AvatarListItem>
193 149
             </Swipeout>
194 150
         );
195 151
     }

+ 3
- 0
react/features/base/react/components/native/index.js Просмотреть файл

@@ -1,3 +1,6 @@
1
+// @flow
2
+
3
+export { default as AvatarListItem } from './AvatarListItem';
1 4
 export { default as BackButton } from './BackButton';
2 5
 export { default as Container } from './Container';
3 6
 export { default as Header } from './Header';

+ 3
- 6
react/features/base/react/components/native/styles.js Просмотреть файл

@@ -5,7 +5,6 @@ import { StyleSheet } from 'react-native';
5 5
 import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles';
6 6
 
7 7
 const AVATAR_OPACITY = 0.4;
8
-const AVATAR_SIZE = 65;
9 8
 const HEADER_COLOR = ColorPalette.blue;
10 9
 
11 10
 // Header height is from Android guidelines. Also, this looks good.
@@ -13,6 +12,7 @@ const HEADER_HEIGHT = 56;
13 12
 const OVERLAY_FONT_COLOR = 'rgba(255, 255, 255, 0.6)';
14 13
 const SECONDARY_ACTION_BUTTON_SIZE = 30;
15 14
 
15
+export const AVATAR_SIZE = 65;
16 16
 export const HEADER_PADDING = BoxModel.padding;
17 17
 export const STATUSBAR_COLOR = ColorPalette.blueHighlight;
18 18
 export const SIDEBAR_WIDTH = 250;
@@ -153,10 +153,7 @@ const SECTION_LIST_STYLES = {
153 153
     avatar: {
154 154
         alignItems: 'center',
155 155
         backgroundColor: `rgba(23, 160, 219, ${AVATAR_OPACITY})`,
156
-        borderRadius: AVATAR_SIZE,
157
-        height: AVATAR_SIZE,
158
-        justifyContent: 'center',
159
-        width: AVATAR_SIZE
156
+        justifyContent: 'center'
160 157
     },
161 158
 
162 159
     /**
@@ -200,7 +197,7 @@ const SECTION_LIST_STYLES = {
200 197
     avatarContent: {
201 198
         backgroundColor: 'rgba(0, 0, 0, 0)',
202 199
         color: OVERLAY_FONT_COLOR,
203
-        fontSize: 32,
200
+        fontSize: Math.floor(AVATAR_SIZE / 2),
204 201
         fontWeight: '100',
205 202
         textAlign: 'center'
206 203
     },

Загрузка…
Отмена
Сохранить