Przeglądaj źródła

feat: make links in chat clickable

master
Bettenbuk Zoltan 6 lat temu
rodzic
commit
bed3f62536

+ 10
- 11
package-lock.json Wyświetl plik

9109
       "from": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d"
9109
       "from": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d"
9110
     },
9110
     },
9111
     "linkify-it": {
9111
     "linkify-it": {
9112
-      "version": "2.0.3",
9113
-      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz",
9114
-      "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=",
9112
+      "version": "2.2.0",
9113
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
9114
+      "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
9115
       "requires": {
9115
       "requires": {
9116
         "uc.micro": "^1.0.1"
9116
         "uc.micro": "^1.0.1"
9117
       }
9117
       }
12203
       "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
12203
       "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
12204
     },
12204
     },
12205
     "react-linkify": {
12205
     "react-linkify": {
12206
-      "version": "0.2.2",
12207
-      "resolved": "https://registry.npmjs.org/react-linkify/-/react-linkify-0.2.2.tgz",
12208
-      "integrity": "sha512-0S8cvUNtEgfJpIGDPKklyrnrTffJ63WuJAc4KaYLBihl5TjgH5cHUmYD+AXLpsV+CVmfoo/56SUNfrZcY4zYMQ==",
12206
+      "version": "1.0.0-alpha",
12207
+      "resolved": "https://registry.npmjs.org/react-linkify/-/react-linkify-1.0.0-alpha.tgz",
12208
+      "integrity": "sha512-7gcIUvJkAXXttt1fmBK9cwn+1jTa4hbKLGCZ9J1U6EOkyb2/+LKL1Z28d9rtDLMnpvImlNlLPdTPooorl5cpmg==",
12209
       "requires": {
12209
       "requires": {
12210
         "linkify-it": "^2.0.3",
12210
         "linkify-it": "^2.0.3",
12211
-        "prop-types": "^15.5.8",
12212
-        "tlds": "^1.57.0"
12211
+        "tlds": "^1.199.0"
12213
       }
12212
       }
12214
     },
12213
     },
12215
     "react-native": {
12214
     "react-native": {
15553
       "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
15552
       "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
15554
     },
15553
     },
15555
     "uc.micro": {
15554
     "uc.micro": {
15556
-      "version": "1.0.5",
15557
-      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz",
15558
-      "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg=="
15555
+      "version": "1.0.6",
15556
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
15557
+      "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
15559
     },
15558
     },
15560
     "uglify-es": {
15559
     "uglify-es": {
15561
       "version": "3.3.9",
15560
       "version": "3.3.9",

+ 1
- 1
package.json Wyświetl plik

64
     "react-dom": "16.8.3",
64
     "react-dom": "16.8.3",
65
     "react-emoji-render": "0.4.6",
65
     "react-emoji-render": "0.4.6",
66
     "react-i18next": "10.11.4",
66
     "react-i18next": "10.11.4",
67
-    "react-linkify": "0.2.2",
67
+    "react-linkify": "1.0.0-alpha",
68
     "react-native": "0.59.8",
68
     "react-native": "0.59.8",
69
     "react-native-background-timer": "2.1.1",
69
     "react-native-background-timer": "2.1.1",
70
     "react-native-calendar-events": "1.6.4",
70
     "react-native-calendar-events": "1.6.4",

+ 2
- 2
react/features/base/react/components/native/Link.js Wyświetl plik

18
     /**
18
     /**
19
      * Notifies that this Link failed to open the URL associated with it.
19
      * Notifies that this Link failed to open the URL associated with it.
20
      */
20
      */
21
-    onLinkingOpenURLRejected: Function,
21
+    onLinkingOpenURLRejected?: Function,
22
 
22
 
23
     /**
23
     /**
24
      * The CSS style to be applied to this Link for the purposes of display.
24
      * The CSS style to be applied to this Link for the purposes of display.
25
      */
25
      */
26
-    style: Object,
26
+    style?: Object,
27
 
27
 
28
     /**
28
     /**
29
      * The URL to be opened when this Link is clicked/pressed.
29
      * The URL to be opened when this Link is clicked/pressed.

+ 75
- 0
react/features/base/react/components/native/Linkify.js Wyświetl plik

1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import { Text } from 'react-native';
5
+import ReactLinkify from 'react-linkify';
6
+
7
+import { type StyleType } from '../../../styles';
8
+
9
+import Link from './Link';
10
+
11
+type Props = {
12
+
13
+    /**
14
+     * The children of the component.
15
+     */
16
+    children: React$Node,
17
+
18
+    /**
19
+     * The extra styles to be applied to links.
20
+     */
21
+    linkStyle: StyleType
22
+};
23
+
24
+/**
25
+ * Implements a react native wrapper for the react-linkify component.
26
+ */
27
+export default class Linkify extends Component<Props> {
28
+    /**
29
+     * Initiates a new {@code Component}.
30
+     *
31
+     * @inheritdoc
32
+     */
33
+    constructor(props: Props) {
34
+        super(props);
35
+
36
+        this._componentDecorator = this._componentDecorator.bind(this);
37
+    }
38
+
39
+    /**
40
+     * Implements {@code Component#render}.
41
+     *
42
+     * @inheritdoc
43
+     */
44
+    render() {
45
+        return (
46
+            <ReactLinkify
47
+                componentDecorator = { this._componentDecorator }>
48
+                <Text>
49
+                    { this.props.children }
50
+                </Text>
51
+            </ReactLinkify>
52
+        );
53
+    }
54
+
55
+    _componentDecorator: (string, string, number) => React$Node;
56
+
57
+    /**
58
+     * Implements a component decorator for react-linkify.
59
+     *
60
+     * @param {string} decoratedHref - The href src.
61
+     * @param {string} decoratedText - The link text.
62
+     * @param {string} key - The component key.
63
+     * @returns {React$Node}
64
+     */
65
+    _componentDecorator(decoratedHref: string, decoratedText: string, key: number) {
66
+        return (
67
+            <Link
68
+                key = { key }
69
+                style = { this.props.linkStyle }
70
+                url = { decoratedHref }>
71
+                {decoratedText}
72
+            </Link>
73
+        );
74
+    }
75
+}

+ 1
- 0
react/features/base/react/components/native/index.js Wyświetl plik

11
 export { default as HeaderWithNavigation } from './HeaderWithNavigation';
11
 export { default as HeaderWithNavigation } from './HeaderWithNavigation';
12
 export { default as Image } from './Image';
12
 export { default as Image } from './Image';
13
 export { default as Link } from './Link';
13
 export { default as Link } from './Link';
14
+export { default as Linkify } from './Linkify';
14
 export { default as LoadingIndicator } from './LoadingIndicator';
15
 export { default as LoadingIndicator } from './LoadingIndicator';
15
 export { default as Modal } from './Modal';
16
 export { default as Modal } from './Modal';
16
 export { default as NavigateSectionListEmptyComponent } from
17
 export { default as NavigateSectionListEmptyComponent } from

+ 51
- 0
react/features/base/react/components/web/Linkify.js Wyświetl plik

1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import ReactLinkify from 'react-linkify';
5
+
6
+type Props = {
7
+
8
+    /**
9
+     * The children of the component.
10
+     */
11
+    children: React$Node
12
+};
13
+
14
+/**
15
+ * Implements a react wrapper for the react-linkify component.
16
+ */
17
+export default class Linkify extends Component<Props> {
18
+    /**
19
+     * Implements {@Component#render}.
20
+     *
21
+     * @inheritdoc
22
+     */
23
+    render() {
24
+        return (
25
+            <ReactLinkify
26
+                componentDecorator = { this._componentDecorator }>
27
+                { this.props.children }
28
+            </ReactLinkify>
29
+        );
30
+    }
31
+
32
+    /**
33
+     * Implements a component decorator for react-linkify.
34
+     *
35
+     * @param {string} decoratedHref - The href src.
36
+     * @param {string} decoratedText - The link text.
37
+     * @param {string} key - The component key.
38
+     * @returns {React$Node}
39
+     */
40
+    _componentDecorator(decoratedHref: string, decoratedText: string, key: number) {
41
+        return (
42
+            <a
43
+                href = { decoratedHref }
44
+                key = { key }
45
+                rel = 'noopener noreferrer'
46
+                target = '_blank'>
47
+                {decoratedText}
48
+            </a>
49
+        );
50
+    }
51
+}

+ 1
- 0
react/features/base/react/components/web/index.js Wyświetl plik

4
 export { default as Button } from './Button';
4
 export { default as Button } from './Button';
5
 export { default as Container } from './Container';
5
 export { default as Container } from './Container';
6
 export { default as Image } from './Image';
6
 export { default as Image } from './Image';
7
+export { default as Linkify } from './Linkify';
7
 export { default as LoadingIndicator } from './LoadingIndicator';
8
 export { default as LoadingIndicator } from './LoadingIndicator';
8
 export { default as MeetingsList } from './MeetingsList';
9
 export { default as MeetingsList } from './MeetingsList';
9
 export { default as MultiSelectAutocomplete } from './MultiSelectAutocomplete';
10
 export { default as MultiSelectAutocomplete } from './MultiSelectAutocomplete';

+ 11
- 8
react/features/chat/components/native/ChatMessage.js Wyświetl plik

5
 
5
 
6
 import { Avatar } from '../../../base/avatar';
6
 import { Avatar } from '../../../base/avatar';
7
 import { translate } from '../../../base/i18n';
7
 import { translate } from '../../../base/i18n';
8
+import { Linkify } from '../../../base/react';
8
 
9
 
9
 import AbstractChatMessage, { type Props } from '../AbstractChatMessage';
10
 import AbstractChatMessage, { type Props } from '../AbstractChatMessage';
10
 import styles from './styles';
11
 import styles from './styles';
42
             textWrapperStyle.push(styles.systemTextWrapper);
43
             textWrapperStyle.push(styles.systemTextWrapper);
43
         }
44
         }
44
 
45
 
46
+        const messageText = message.messageType === 'error'
47
+            ? this.props.t('chat.error', {
48
+                error: message.error,
49
+                originalText: message.message
50
+            })
51
+            : message.message;
52
+
45
         return (
53
         return (
46
             <View style = { styles.messageWrapper } >
54
             <View style = { styles.messageWrapper } >
47
                 { this._renderAvatar() }
55
                 { this._renderAvatar() }
51
                             this.props.showDisplayName
59
                             this.props.showDisplayName
52
                                 && this._renderDisplayName()
60
                                 && this._renderDisplayName()
53
                         }
61
                         }
54
-                        <Text style = { styles.messageText }>
55
-                            { message.messageType === 'error'
56
-                                ? this.props.t('chat.error', {
57
-                                    error: message.error,
58
-                                    originalText: message.message
59
-                                })
60
-                                : message.message }
61
-                        </Text>
62
+                        <Linkify linkStyle = { styles.chatLink }>
63
+                            { messageText }
64
+                        </Linkify>
62
                     </View>
65
                     </View>
63
                     { this.props.showTimestamp && this._renderTimestamp() }
66
                     { this.props.showTimestamp && this._renderTimestamp() }
64
                 </View>
67
                 </View>

+ 1
- 0
react/features/chat/components/native/MessageContainer.js Wyświetl plik

36
                 data = { this._getMessagesGroupedBySender() }
36
                 data = { this._getMessagesGroupedBySender() }
37
                 inverted = { true }
37
                 inverted = { true }
38
                 keyExtractor = { this._keyExtractor }
38
                 keyExtractor = { this._keyExtractor }
39
+                keyboardShouldPersistTaps = 'always'
39
                 renderItem = { this._renderMessageGroup }
40
                 renderItem = { this._renderMessageGroup }
40
                 style = { styles.messageContainer } />
41
                 style = { styles.messageContainer } />
41
         );
42
         );

+ 4
- 0
react/features/chat/components/native/styles.js Wyświetl plik

34
         flexDirection: 'column'
34
         flexDirection: 'column'
35
     },
35
     },
36
 
36
 
37
+    chatLink: {
38
+        color: ColorPalette.blue
39
+    },
40
+
37
     /**
41
     /**
38
      * Wrapper for the details together, such as name, message and time.
42
      * Wrapper for the details together, such as name, message and time.
39
      */
43
      */

+ 2
- 8
react/features/chat/components/web/ChatMessage.js Wyświetl plik

2
 
2
 
3
 import React from 'react';
3
 import React from 'react';
4
 import { toArray } from 'react-emoji-render';
4
 import { toArray } from 'react-emoji-render';
5
-import Linkify from 'react-linkify';
6
 
5
 
7
 
6
 
8
 import { translate } from '../../../base/i18n';
7
 import { translate } from '../../../base/i18n';
8
+import { Linkify } from '../../../base/react';
9
 
9
 
10
 import AbstractChatMessage, {
10
 import AbstractChatMessage, {
11
     type Props
11
     type Props
43
 
43
 
44
         content.forEach(i => {
44
         content.forEach(i => {
45
             if (typeof i === 'string') {
45
             if (typeof i === 'string') {
46
-                processedMessage.push(
47
-                    <Linkify
48
-                        key = { i }
49
-                        properties = {{
50
-                            rel: 'noopener noreferrer',
51
-                            target: '_blank'
52
-                        }}>{ i }</Linkify>);
46
+                processedMessage.push(<Linkify key = { i }>{ i }</Linkify>);
53
             } else {
47
             } else {
54
                 processedMessage.push(i);
48
                 processedMessage.push(i);
55
             }
49
             }

Ładowanie…
Anuluj
Zapisz