Преглед на файлове

rn,recent-list: replace swipe options with long-press sheet

This change serves 2 purposes:

- (Hopefully) make the recent list entry options easier to discover
- Remove the (now unmaintained) swipeout dependency
j8
Saúl Ibarra Corretgé преди 4 години
родител
ревизия
63fe1de789

+ 3
- 3
lang/main.json Целия файл

366
         "password": "$t(lockRoomPasswordUppercase):",
366
         "password": "$t(lockRoomPasswordUppercase):",
367
         "title": "Share",
367
         "title": "Share",
368
         "tooltip": "Share link and dial-in info for this meeting",
368
         "tooltip": "Share link and dial-in info for this meeting",
369
-        "label": "Meeting info"
369
+        "label": "Dial-in info"
370
     },
370
     },
371
     "inviteDialog": {
371
     "inviteDialog": {
372
         "alertText": "Failed to invite some participants.",
372
         "alertText": "Failed to invite some participants.",
876
         "getHelp": "Get help",
876
         "getHelp": "Get help",
877
         "go": "GO",
877
         "go": "GO",
878
         "goSmall": "GO",
878
         "goSmall": "GO",
879
-        "info": "Info",
879
+        "info": "Dial-in info",
880
         "join": "CREATE / JOIN",
880
         "join": "CREATE / JOIN",
881
         "moderatedMessage": "Or <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">book a meeting URL</a> in advance where you are the only moderator.",
881
         "moderatedMessage": "Or <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">book a meeting URL</a> in advance where you are the only moderator.",
882
         "privacy": "Privacy",
882
         "privacy": "Privacy",
883
         "recentList": "Recent",
883
         "recentList": "Recent",
884
-        "recentListDelete": "Delete",
884
+        "recentListDelete": "Delete entry",
885
         "recentListEmpty": "Your recent list is currently empty. Chat with your team and you will find all your recent meetings here.",
885
         "recentListEmpty": "Your recent list is currently empty. Chat with your team and you will find all your recent meetings here.",
886
         "reducedUIText": "Welcome to {{app}}!",
886
         "reducedUIText": "Welcome to {{app}}!",
887
         "roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
887
         "roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",

+ 0
- 1
package.json Целия файл

81
     "react-native-sound": "github:jitsi/react-native-sound#3fe5480fce935e888d5089d94a191c7c7e3aa190",
81
     "react-native-sound": "github:jitsi/react-native-sound#3fe5480fce935e888d5089d94a191c7c7e3aa190",
82
     "react-native-svg": "9.7.1",
82
     "react-native-svg": "9.7.1",
83
     "react-native-svg-transformer": "0.13.0",
83
     "react-native-svg-transformer": "0.13.0",
84
-    "react-native-swipeout": "2.3.6",
85
     "react-native-watch-connectivity": "0.4.3",
84
     "react-native-watch-connectivity": "0.4.3",
86
     "react-native-webrtc": "1.84.0",
85
     "react-native-webrtc": "1.84.0",
87
     "react-native-webview": "10.9.0",
86
     "react-native-webview": "10.9.0",

+ 1
- 0
react/features/base/icons/svg/index.js Целия файл

91
 export { default as IconSwitchCamera } from './switch-camera.svg';
91
 export { default as IconSwitchCamera } from './switch-camera.svg';
92
 export { default as IconTileView } from './tiles-many.svg';
92
 export { default as IconTileView } from './tiles-many.svg';
93
 export { default as IconToggleRecording } from './camera-take-picture.svg';
93
 export { default as IconToggleRecording } from './camera-take-picture.svg';
94
+export { default as IconTrash } from './trash.svg';
94
 export { default as IconVideoQualityAudioOnly } from './AUD.svg';
95
 export { default as IconVideoQualityAudioOnly } from './AUD.svg';
95
 export { default as IconVideoQualityHD } from './HD.svg';
96
 export { default as IconVideoQualityHD } from './HD.svg';
96
 export { default as IconVideoQualityLD } from './LD.svg';
97
 export { default as IconVideoQualityLD } from './LD.svg';

+ 1
- 0
react/features/base/icons/svg/trash.svg Целия файл

1
+<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="trash-alt" class="svg-inline--fa fa-trash-alt fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M32 464a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128H32zm272-256a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zM432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z"></path></svg>

+ 29
- 11
react/features/base/react/components/NavigateSectionList.js Целия файл

20
      */
20
      */
21
     disabled: boolean,
21
     disabled: boolean,
22
 
22
 
23
+    /**
24
+     * Function to be invoked when an item is long pressed. The item is passed.
25
+     */
26
+    onLongPress: Function,
27
+
23
     /**
28
     /**
24
      * Function to be invoked when an item is pressed. The item's URL is passed.
29
      * Function to be invoked when an item is pressed. The item's URL is passed.
25
      */
30
      */
44
     /**
49
     /**
45
      * An array of sections
50
      * An array of sections
46
      */
51
      */
47
-    sections: Array<Section>,
48
-
49
-    /**
50
-     * Optional array of on-slide actions this list should support. For details
51
-     * see https://github.com/dancormier/react-native-swipeout.
52
-     */
53
-    slideActions?: Array<Object>
52
+    sections: Array<Section>
54
 };
53
 };
55
 
54
 
56
 /**
55
 /**
83
     constructor(props: Props) {
82
     constructor(props: Props) {
84
         super(props);
83
         super(props);
85
         this._getItemKey = this._getItemKey.bind(this);
84
         this._getItemKey = this._getItemKey.bind(this);
85
+        this._onLongPress = this._onLongPress.bind(this);
86
         this._onPress = this._onPress.bind(this);
86
         this._onPress = this._onPress.bind(this);
87
         this._onRefresh = this._onRefresh.bind(this);
87
         this._onRefresh = this._onRefresh.bind(this);
88
         this._renderItem = this._renderItem.bind(this);
88
         this._renderItem = this._renderItem.bind(this);
89
-        this._renderListEmptyComponent
90
-            = this._renderListEmptyComponent.bind(this);
89
+        this._renderListEmptyComponent = this._renderListEmptyComponent.bind(this);
91
         this._renderSectionHeader = this._renderSectionHeader.bind(this);
90
         this._renderSectionHeader = this._renderSectionHeader.bind(this);
92
     }
91
     }
93
 
92
 
131
         return `${index}-${item.key}`;
130
         return `${index}-${item.key}`;
132
     }
131
     }
133
 
132
 
133
+    _onLongPress: string => Function;
134
+
135
+    /**
136
+     * Returns a function that is used in the onLongPress callback of the items.
137
+     *
138
+     * @param {Object} item - The item that was long-pressed.
139
+     * @private
140
+     * @returns {Function}
141
+     */
142
+    _onLongPress(item) {
143
+        const { disabled, onLongPress } = this.props;
144
+
145
+        if (!disabled && typeof onLongPress === 'function') {
146
+            return () => onLongPress(item);
147
+        }
148
+
149
+        return null;
150
+    }
151
+
134
     _onPress: string => Function;
152
     _onPress: string => Function;
135
 
153
 
136
     /**
154
     /**
210
             <NavigateSectionListItem
228
             <NavigateSectionListItem
211
                 item = { item }
229
                 item = { item }
212
                 key = { key }
230
                 key = { key }
231
+                onLongPress = { url ? this._onLongPress(item) : undefined }
213
                 onPress = { url ? this._onPress(url) : undefined }
232
                 onPress = { url ? this._onPress(url) : undefined }
214
                 secondaryAction = {
233
                 secondaryAction = {
215
-                    url ? undefined : this._onSecondaryAction(id) }
216
-                slideActions = { this.props.slideActions } />
234
+                    url ? undefined : this._onSecondaryAction(id) } />
217
         );
235
         );
218
     }
236
     }
219
 
237
 

+ 10
- 2
react/features/base/react/components/native/AvatarListItem.js Целия файл

52
      */
52
      */
53
     linesStyle?: StyleType,
53
     linesStyle?: StyleType,
54
 
54
 
55
+    /**
56
+     * Function to invoke on long press.
57
+     */
58
+    onLongPress: ?Function,
59
+
55
     /**
60
     /**
56
      * Function to invoke on press.
61
      * Function to invoke on press.
57
      */
62
      */
88
             avatarOnly,
93
             avatarOnly,
89
             avatarSize = AVATAR_SIZE,
94
             avatarSize = AVATAR_SIZE,
90
             avatarStatus,
95
             avatarStatus,
91
-            avatarStyle
96
+            avatarStyle,
97
+            onLongPress,
98
+            onPress
92
         } = this.props;
99
         } = this.props;
93
         const { avatar, colorBase, lines, title } = this.props.item;
100
         const { avatar, colorBase, lines, title } = this.props.item;
94
 
101
 
95
         return (
102
         return (
96
             <Container
103
             <Container
97
-                onClick = { this.props.onPress }
104
+                onClick = { onPress }
105
+                onLongPress = { onLongPress }
98
                 style = { styles.listItem }
106
                 style = { styles.listItem }
99
                 underlayColor = { UNDERLAY_COLOR }>
107
                 underlayColor = { UNDERLAY_COLOR }>
100
                 <Avatar
108
                 <Avatar

+ 13
- 38
react/features/base/react/components/native/NavigateSectionListItem.js Целия файл

1
 // @flow
1
 // @flow
2
 
2
 
3
 import React, { Component } from 'react';
3
 import React, { Component } from 'react';
4
-import Swipeout from 'react-native-swipeout';
5
 
4
 
6
-import { ColorPalette } from '../../../styles';
7
 import type { Item } from '../../Types';
5
 import type { Item } from '../../Types';
8
 
6
 
9
 import AvatarListItem from './AvatarListItem';
7
 import AvatarListItem from './AvatarListItem';
19
     item: Item,
17
     item: Item,
20
 
18
 
21
     /**
19
     /**
22
-     * Function to be invoked when an Item is pressed. The Item's URL is passed.
20
+     * Function to be invoked when an item is long pressed. The item is passed.
23
      */
21
      */
24
-    onPress: ?Function,
22
+    onLongPress: ?Function,
25
 
23
 
26
     /**
24
     /**
27
-     * Function to be invoked when secondary action was performed on an Item.
25
+     * Function to be invoked when an Item is pressed. The Item's URL is passed.
28
      */
26
      */
29
-    secondaryAction: ?Function,
27
+    onPress: ?Function,
30
 
28
 
31
     /**
29
     /**
32
-     * Optional array of on-slide actions this list should support. For details
33
-     * see https://github.com/dancormier/react-native-swipeout.
30
+     * Function to be invoked when secondary action was performed on an Item.
34
      */
31
      */
35
-    slideActions?: Array<Object>
32
+    secondaryAction: ?Function
36
 }
33
 }
37
 
34
 
38
 /**
35
 /**
116
      * @returns {ReactElement}
113
      * @returns {ReactElement}
117
      */
114
      */
118
     render() {
115
     render() {
119
-        const { item, slideActions } = this.props;
120
-        const { id } = item;
121
-        let right;
122
-
123
-        // NOTE: The {@code Swipeout} component has an onPress prop encapsulated
124
-        // in the {@code right} array, but we need to bind it to the ID of the
125
-        // item too.
126
-
127
-        if (slideActions) {
128
-            right = [];
129
-            for (const slideAction of slideActions) {
130
-                right.push({
131
-                    backgroundColor: slideAction.backgroundColor,
132
-                    onPress: slideAction.onPress.bind(undefined, id),
133
-                    text: slideAction.text
134
-                });
135
-            }
136
-        }
116
+        const { item, onLongPress, onPress, secondaryAction } = this.props;
137
 
117
 
138
         return (
118
         return (
139
-            <Swipeout
140
-                autoClose = { true }
141
-                backgroundColor = { ColorPalette.transparent }
142
-                right = { right }>
143
-                <AvatarListItem
144
-                    item = { item }
145
-                    onPress = { this.props.onPress } >
146
-                    { this.props.secondaryAction
147
-                            && this._renderSecondaryAction() }
148
-                </AvatarListItem>
149
-            </Swipeout>
119
+            <AvatarListItem
120
+                item = { item }
121
+                onLongPress = { onLongPress }
122
+                onPress = { onPress } >
123
+                { secondaryAction && this._renderSecondaryAction() }
124
+            </AvatarListItem>
150
         );
125
         );
151
     }
126
     }
152
 }
127
 }

+ 2
- 4
react/features/calendar-sync/components/CalendarListContent.native.js Целия файл

106
         );
106
         );
107
     }
107
     }
108
 
108
 
109
-    _onPress: (string, ?string) => Function;
109
+    _onPress: (string, ?string) => void;
110
 
110
 
111
     /**
111
     /**
112
      * Handles the list's navigate action.
112
      * Handles the list's navigate action.
259
  * Maps redux state to component props.
259
  * Maps redux state to component props.
260
  *
260
  *
261
  * @param {Object} state - The redux state.
261
  * @param {Object} state - The redux state.
262
- * @returns {{
263
- *     _eventList: Array<Object>
264
- * }}
262
+ * @returns {Props}
265
  */
263
  */
266
 function _mapStateToProps(state: Object) {
264
 function _mapStateToProps(state: Object) {
267
     return {
265
     return {

+ 48
- 0
react/features/recent-list/components/DeleteItemButton.native.js Целия файл

1
+// @flow
2
+
3
+import { translate } from '../../base/i18n';
4
+import { IconTrash } from '../../base/icons';
5
+import { connect } from '../../base/redux';
6
+import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
7
+import { deleteRecentListEntry } from '../actions';
8
+
9
+export type Props = AbstractButtonProps & {
10
+
11
+    /**
12
+     * The redux {@code dispatch} function.
13
+     */
14
+    dispatch: Function,
15
+
16
+    /**
17
+     * The ID of the entry to be deleted.
18
+     */
19
+    itemId: Object,
20
+
21
+    /**
22
+     * The function to be used to translate i18n labels.
23
+     */
24
+    t: Function
25
+};
26
+
27
+/**
28
+ * A recent list menu button which deletes the selected entry.
29
+ */
30
+class DeleteItemButton extends AbstractButton<Props, *> {
31
+    accessibilityLabel = 'welcomepage.recentListDelete';
32
+    icon = IconTrash;
33
+    label = 'welcomepage.recentListDelete';
34
+
35
+    /**
36
+     * Handles clicking / pressing the button.
37
+     *
38
+     * @private
39
+     * @returns {void}
40
+     */
41
+    _handleClick() {
42
+        const { dispatch, itemId } = this.props;
43
+
44
+        dispatch(deleteRecentListEntry(itemId));
45
+    }
46
+}
47
+
48
+export default translate(connect()(DeleteItemButton));

+ 13
- 39
react/features/recent-list/components/RecentList.native.js Целия файл

4
 import type { Dispatch } from 'redux';
4
 import type { Dispatch } from 'redux';
5
 
5
 
6
 import { getDefaultURL } from '../../app/functions';
6
 import { getDefaultURL } from '../../app/functions';
7
+import { openDialog } from '../../base/dialog/actions';
7
 import { translate } from '../../base/i18n';
8
 import { translate } from '../../base/i18n';
8
-import { setActiveModalId } from '../../base/modal';
9
 import { NavigateSectionList, type Section } from '../../base/react';
9
 import { NavigateSectionList, type Section } from '../../base/react';
10
 import { connect } from '../../base/redux';
10
 import { connect } from '../../base/redux';
11
-import { ColorPalette } from '../../base/styles';
12
-import { DIAL_IN_SUMMARY_VIEW_ID } from '../../invite/constants';
13
-import { deleteRecentListEntry } from '../actions';
14
 import { isRecentListEnabled, toDisplayableList } from '../functions';
11
 import { isRecentListEnabled, toDisplayableList } from '../functions';
15
 
12
 
16
 import AbstractRecentList from './AbstractRecentList';
13
 import AbstractRecentList from './AbstractRecentList';
14
+import RecentListItemMenu from './RecentListItemMenu.native';
17
 
15
 
18
 /**
16
 /**
19
  * The type of the React {@code Component} props of {@link RecentList}
17
  * The type of the React {@code Component} props of {@link RecentList}
62
     constructor(props: Props) {
60
     constructor(props: Props) {
63
         super(props);
61
         super(props);
64
 
62
 
65
-        this._onDelete = this._onDelete.bind(this);
66
-        this._onShowDialInInfo = this._onShowDialInInfo.bind(this);
63
+        // Bind event handlers so they are only bound once per instance.
64
+        this._onLongPress = this._onLongPress.bind(this);
67
     }
65
     }
68
 
66
 
69
     /**
67
     /**
82
             _recentList
80
             _recentList
83
         } = this.props;
81
         } = this.props;
84
         const recentList = toDisplayableList(_recentList, t, _defaultServerURL);
82
         const recentList = toDisplayableList(_recentList, t, _defaultServerURL);
85
-        const slideActions = [ {
86
-            backgroundColor: ColorPalette.blue,
87
-            onPress: this._onShowDialInInfo,
88
-            text: t('welcomepage.info')
89
-        }, {
90
-            backgroundColor: 'red',
91
-            onPress: this._onDelete,
92
-            text: t('welcomepage.recentListDelete')
93
-        } ];
94
 
83
 
95
         return (
84
         return (
96
             <NavigateSectionList
85
             <NavigateSectionList
97
                 disabled = { disabled }
86
                 disabled = { disabled }
87
+                onLongPress = { this._onLongPress }
98
                 onPress = { this._onPress }
88
                 onPress = { this._onPress }
99
                 renderListEmptyComponent
89
                 renderListEmptyComponent
100
                     = { this._getRenderListEmptyComponent() }
90
                     = { this._getRenderListEmptyComponent() }
101
-                sections = { recentList }
102
-                slideActions = { slideActions } />
91
+                sections = { recentList } />
103
         );
92
         );
104
     }
93
     }
105
 
94
 
106
-    _onDelete: Object => void
95
+    _onLongPress: (Object) => void;
107
 
96
 
108
     /**
97
     /**
109
-     * Callback for the delete action of the list.
98
+     * Handles the list's navigate action.
110
      *
99
      *
111
-     * @param {Object} itemId - The ID of the entry thats deletion is
112
-     * requested.
100
+     * @private
101
+     * @param {Object} item - The item which was long pressed.
113
      * @returns {void}
102
      * @returns {void}
114
      */
103
      */
115
-    _onDelete(itemId) {
116
-        this.props.dispatch(deleteRecentListEntry(itemId));
117
-    }
118
-
119
-    _onShowDialInInfo: Object => void
120
-
121
-    /**
122
-     * Callback for the dial-in info action of the list.
123
-     *
124
-     * @param {Object} itemId - The ID of the entry for which we'd like to show the dial in numbers.
125
-     * @returns {void}
126
-     */
127
-    _onShowDialInInfo(itemId) {
128
-        this.props.dispatch(setActiveModalId(DIAL_IN_SUMMARY_VIEW_ID, { summaryUrl: itemId.url }));
104
+    _onLongPress(item) {
105
+        this.props.dispatch(openDialog(RecentListItemMenu, { item }));
129
     }
106
     }
130
 }
107
 }
131
 
108
 
133
  * Maps redux state to component props.
110
  * Maps redux state to component props.
134
  *
111
  *
135
  * @param {Object} state - The redux state.
112
  * @param {Object} state - The redux state.
136
- * @returns {{
137
- *     _defaultServerURL: string,
138
- *     _recentList: Array
139
- * }}
113
+ * @returns {Props}
140
  */
114
  */
141
 export function _mapStateToProps(state: Object) {
115
 export function _mapStateToProps(state: Object) {
142
     return {
116
     return {

+ 143
- 0
react/features/recent-list/components/RecentListItemMenu.native.js Целия файл

1
+// @flow
2
+
3
+import React, { PureComponent } from 'react';
4
+import { Text, View } from 'react-native';
5
+
6
+import { ColorSchemeRegistry } from '../../base/color-scheme';
7
+import { BottomSheet, hideDialog, isDialogOpen } from '../../base/dialog';
8
+import { type Item } from '../../base/react/Types';
9
+import { connect } from '../../base/redux';
10
+import { StyleType } from '../../base/styles';
11
+
12
+import DeleteItemButton from './DeleteItemButton.native';
13
+import ShowDialInInfoButton from './ShowDialInInfoButton.native';
14
+import styles from './styles';
15
+
16
+type Props = {
17
+
18
+    /**
19
+     * The Redux dispatch function.
20
+     */
21
+    dispatch: Function,
22
+
23
+    /**
24
+     * Item being rendered in this menu.
25
+     */
26
+    item: Item,
27
+
28
+    /**
29
+     * The color-schemed stylesheet of the BottomSheet.
30
+     */
31
+    _bottomSheetStyles: StyleType,
32
+
33
+    /**
34
+     * True if the menu is currently open, false otherwise.
35
+     */
36
+    _isOpen: boolean
37
+}
38
+
39
+// eslint-disable-next-line prefer-const
40
+let RecentListItemMenu_;
41
+
42
+/**
43
+ * Class to implement a popup menu that opens upon long pressing a recent list item.
44
+ */
45
+class RecentListItemMenu extends PureComponent<Props> {
46
+    /**
47
+     * Constructor of the component.
48
+     *
49
+     * @inheritdoc
50
+     */
51
+    constructor(props: Props) {
52
+        super(props);
53
+
54
+        this._onCancel = this._onCancel.bind(this);
55
+        this._renderMenuHeader = this._renderMenuHeader.bind(this);
56
+    }
57
+
58
+    /**
59
+     * Implements {@code Component#render}.
60
+     *
61
+     * @inheritdoc
62
+     */
63
+    render() {
64
+        const { _bottomSheetStyles, item } = this.props;
65
+        const buttonProps = {
66
+            afterClick: this._onCancel,
67
+            itemId: item.id,
68
+            showLabel: true,
69
+            styles: _bottomSheetStyles.buttons
70
+        };
71
+
72
+        return (
73
+            <BottomSheet
74
+                onCancel = { this._onCancel }
75
+                renderHeader = { this._renderMenuHeader }>
76
+                <DeleteItemButton { ...buttonProps } />
77
+                <ShowDialInInfoButton { ...buttonProps } />
78
+            </BottomSheet>
79
+        );
80
+    }
81
+
82
+    _onCancel: () => boolean;
83
+
84
+    /**
85
+     * Callback to hide this menu.
86
+     *
87
+     * @private
88
+     * @returns {boolean}
89
+     */
90
+    _onCancel() {
91
+        if (this.props._isOpen) {
92
+            this.props.dispatch(hideDialog(RecentListItemMenu_));
93
+
94
+            return true;
95
+        }
96
+
97
+        return false;
98
+    }
99
+
100
+    _renderMenuHeader: () => React$Element<any>;
101
+
102
+    /**
103
+     * Function to render the menu's header.
104
+     *
105
+     * @returns {React$Element}
106
+     */
107
+    _renderMenuHeader() {
108
+        const { _bottomSheetStyles, item } = this.props;
109
+
110
+        return (
111
+            <View
112
+                style = { [
113
+                    _bottomSheetStyles.sheet,
114
+                    styles.entryNameContainer
115
+                ] }>
116
+                <Text
117
+                    ellipsizeMode = { 'middle' }
118
+                    numberOfLines = { 1 }
119
+                    style = { styles.entryNameLabel }>
120
+                    { item.title }
121
+                </Text>
122
+            </View>
123
+        );
124
+    }
125
+}
126
+
127
+/**
128
+ * Function that maps parts of Redux state tree into component props.
129
+ *
130
+ * @param {Object} state - Redux state.
131
+ * @private
132
+ * @returns {Props}
133
+ */
134
+function _mapStateToProps(state) {
135
+    return {
136
+        _bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'),
137
+        _isOpen: isDialogOpen(state, RecentListItemMenu_)
138
+    };
139
+}
140
+
141
+RecentListItemMenu_ = connect(_mapStateToProps)(RecentListItemMenu);
142
+
143
+export default RecentListItemMenu_;

+ 49
- 0
react/features/recent-list/components/ShowDialInInfoButton.native.js Целия файл

1
+// @flow
2
+
3
+import { translate } from '../../base/i18n';
4
+import { IconInfo } from '../../base/icons';
5
+import { setActiveModalId } from '../../base/modal';
6
+import { connect } from '../../base/redux';
7
+import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
8
+import { DIAL_IN_SUMMARY_VIEW_ID } from '../../invite/constants';
9
+
10
+export type Props = AbstractButtonProps & {
11
+
12
+    /**
13
+     * The redux {@code dispatch} function.
14
+     */
15
+    dispatch: Function,
16
+
17
+    /**
18
+     * The ID of the entry to be deleted.
19
+     */
20
+    itemId: Object,
21
+
22
+    /**
23
+     * The function to be used to translate i18n labels.
24
+     */
25
+    t: Function
26
+};
27
+
28
+/**
29
+ * A recent list menu button which opens the dial-in info dialog.
30
+ */
31
+class ShowDialInInfoButton extends AbstractButton<Props, *> {
32
+    accessibilityLabel = 'welcomepage.info';
33
+    icon = IconInfo;
34
+    label = 'welcomepage.info';
35
+
36
+    /**
37
+     * Handles clicking / pressing the button.
38
+     *
39
+     * @private
40
+     * @returns {void}
41
+     */
42
+    _handleClick() {
43
+        const { dispatch, itemId } = this.props;
44
+
45
+        dispatch(setActiveModalId(DIAL_IN_SUMMARY_VIEW_ID, { summaryUrl: itemId.url }));
46
+    }
47
+}
48
+
49
+export default translate(connect()(ShowDialInInfoButton));

+ 19
- 1
react/features/recent-list/components/styles.native.js Целия файл

1
-import { createStyleSheet } from '../../base/styles';
1
+import { ColorPalette, createStyleSheet } from '../../base/styles';
2
 
2
 
3
 /**
3
 /**
4
  * The styles of the React {@code Component}s of the feature recent-list i.e.
4
  * The styles of the React {@code Component}s of the feature recent-list i.e.
22
         alignItems: 'center',
22
         alignItems: 'center',
23
         justifyContent: 'center',
23
         justifyContent: 'center',
24
         padding: 20
24
         padding: 20
25
+    },
26
+
27
+    entryNameContainer: {
28
+        alignItems: 'center',
29
+        borderBottomColor: ColorPalette.lightGrey,
30
+        borderBottomWidth: 1,
31
+        borderTopLeftRadius: 16,
32
+        borderTopRightRadius: 16,
33
+        flexDirection: 'row',
34
+        justifyContent: 'center',
35
+        height: 48
36
+    },
37
+
38
+    entryNameLabel: {
39
+        color: ColorPalette.lightGrey,
40
+        flexShrink: 1,
41
+        fontSize: 16,
42
+        opacity: 0.90
25
     }
43
     }
26
 });
44
 });

Loading…
Отказ
Запис