瀏覽代碼

feat: make links in chat clickable

master
Bettenbuk Zoltan 6 年之前
父節點
當前提交
bed3f62536

+ 10
- 11
package-lock.json 查看文件

@@ -9109,9 +9109,9 @@
9109 9109
       "from": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d"
9110 9110
     },
9111 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 9115
       "requires": {
9116 9116
         "uc.micro": "^1.0.1"
9117 9117
       }
@@ -12203,13 +12203,12 @@
12203 12203
       "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
12204 12204
     },
12205 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 12209
       "requires": {
12210 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 12214
     "react-native": {
@@ -15553,9 +15552,9 @@
15553 15552
       "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
15554 15553
     },
15555 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 15559
     "uglify-es": {
15561 15560
       "version": "3.3.9",

+ 1
- 1
package.json 查看文件

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

+ 2
- 2
react/features/base/react/components/native/Link.js 查看文件

@@ -18,12 +18,12 @@ type Props = {
18 18
     /**
19 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 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 29
      * The URL to be opened when this Link is clicked/pressed.

+ 75
- 0
react/features/base/react/components/native/Linkify.js 查看文件

@@ -0,0 +1,75 @@
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 查看文件

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

+ 51
- 0
react/features/base/react/components/web/Linkify.js 查看文件

@@ -0,0 +1,51 @@
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 查看文件

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

+ 11
- 8
react/features/chat/components/native/ChatMessage.js 查看文件

@@ -5,6 +5,7 @@ import { Text, View } from 'react-native';
5 5
 
6 6
 import { Avatar } from '../../../base/avatar';
7 7
 import { translate } from '../../../base/i18n';
8
+import { Linkify } from '../../../base/react';
8 9
 
9 10
 import AbstractChatMessage, { type Props } from '../AbstractChatMessage';
10 11
 import styles from './styles';
@@ -42,6 +43,13 @@ class ChatMessage extends AbstractChatMessage<Props> {
42 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 53
         return (
46 54
             <View style = { styles.messageWrapper } >
47 55
                 { this._renderAvatar() }
@@ -51,14 +59,9 @@ class ChatMessage extends AbstractChatMessage<Props> {
51 59
                             this.props.showDisplayName
52 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 65
                     </View>
63 66
                     { this.props.showTimestamp && this._renderTimestamp() }
64 67
                 </View>

+ 1
- 0
react/features/chat/components/native/MessageContainer.js 查看文件

@@ -36,6 +36,7 @@ export default class MessageContainer extends AbstractMessageContainer {
36 36
                 data = { this._getMessagesGroupedBySender() }
37 37
                 inverted = { true }
38 38
                 keyExtractor = { this._keyExtractor }
39
+                keyboardShouldPersistTaps = 'always'
39 40
                 renderItem = { this._renderMessageGroup }
40 41
                 style = { styles.messageContainer } />
41 42
         );

+ 4
- 0
react/features/chat/components/native/styles.js 查看文件

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

+ 2
- 8
react/features/chat/components/web/ChatMessage.js 查看文件

@@ -2,10 +2,10 @@
2 2
 
3 3
 import React from 'react';
4 4
 import { toArray } from 'react-emoji-render';
5
-import Linkify from 'react-linkify';
6 5
 
7 6
 
8 7
 import { translate } from '../../../base/i18n';
8
+import { Linkify } from '../../../base/react';
9 9
 
10 10
 import AbstractChatMessage, {
11 11
     type Props
@@ -43,13 +43,7 @@ class ChatMessage extends AbstractChatMessage<Props> {
43 43
 
44 44
         content.forEach(i => {
45 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 47
             } else {
54 48
                 processedMessage.push(i);
55 49
             }

Loading…
取消
儲存