Sfoglia il codice sorgente

feat(visitors) add info dialog (#14926)

factor2
Mihaela Dumitru 1 anno fa
parent
commit
94b6808ec6
Nessun account collegato all'indirizzo email del committer

+ 7
- 0
lang/main.json Vedi File

@@ -263,6 +263,7 @@
263 263
         "Remove": "Remove",
264 264
         "Share": "Share",
265 265
         "Submit": "Submit",
266
+        "Understood": "Understood",
266 267
         "WaitForHostMsg": "The conference has not yet started because no moderators have yet arrived. If you'd like to become a moderator please log-in. Otherwise, please wait.",
267 268
         "WaitForHostNoAuthMsg": "The conference has not yet started because no moderators have yet arrived. Please wait.",
268 269
         "WaitingForHostButton": "Wait for moderator",
@@ -1492,6 +1493,12 @@
1492 1493
     },
1493 1494
     "visitors": {
1494 1495
         "chatIndicator": "(visitor)",
1496
+        "joinMeeting": {
1497
+            "description": "You're currently an observer in this conference.",
1498
+            "raiseHand": "Raise your hand",
1499
+            "title": "Joining meeting",
1500
+            "wishToSpeak": "If you wish to speak, please raise your hand below and wait for the moderator's approval."
1501
+        },
1495 1502
         "labelTooltip": "Number of visitors: {{count}}",
1496 1503
         "notification": {
1497 1504
             "demoteDescription": "Sent here by {{actor}}, raise your hand to participate",

+ 2
- 5
react/features/base/ui/components/web/Dialog.tsx Vedi File

@@ -111,12 +111,9 @@ const Dialog = ({
111 111
     }, [ onCancel ]);
112 112
 
113 113
     const submit = useCallback(() => {
114
-        if (onSubmit && (
115
-            (document.activeElement && !operatesWithEnterKey(document.activeElement))
116
-            || !document.activeElement
117
-        )) {
114
+        if ((document.activeElement && !operatesWithEnterKey(document.activeElement)) || !document.activeElement) {
118 115
             !disableAutoHideOnSubmit && dispatch(hideDialog());
119
-            onSubmit();
116
+            onSubmit?.();
120 117
         }
121 118
     }, [ onSubmit ]);
122 119
 

+ 31
- 1
react/features/reactions/components/native/RaiseHandButton.tsx Vedi File

@@ -40,6 +40,11 @@ interface IProps extends AbstractButtonProps {
40 40
      */
41 41
     _raisedHand: boolean;
42 42
 
43
+    /**
44
+     * Whether or not the click is disabled.
45
+     */
46
+    disableClick?: boolean;
47
+
43 48
     /**
44 49
      * Used to close the overflow menu after raise hand is clicked.
45 50
      */
@@ -75,8 +80,14 @@ class RaiseHandButton extends Component<IProps> {
75 80
      * @returns {void}
76 81
      */
77 82
     _onClick() {
83
+        const { disableClick, onCancel } = this.props;
84
+
85
+        if (disableClick) {
86
+            return;
87
+        }
88
+
78 89
         this._toggleRaisedHand();
79
-        this.props.onCancel();
90
+        onCancel();
80 91
     }
81 92
 
82 93
     /**
@@ -159,4 +170,23 @@ function _mapStateToProps(state: IReduxState) {
159 170
     };
160 171
 }
161 172
 
173
+/**
174
+ * Maps part of the Redux state to the props of this component.
175
+ *
176
+ * @param {Object} state - The Redux state.
177
+ * @private
178
+ * @returns {IProps}
179
+ */
180
+function _standaloneMapStateToProps(state: IReduxState) {
181
+    const _enabled = getFeatureFlag(state, RAISE_HAND_ENABLED, true);
182
+
183
+    return {
184
+        _enabled
185
+    };
186
+}
187
+
188
+const StandaloneRaiseHandButton = translate(connect(_standaloneMapStateToProps)(RaiseHandButton));
189
+
190
+export { StandaloneRaiseHandButton };
191
+
162 192
 export default translate(connect(_mapStateToProps)(RaiseHandButton));

+ 18
- 2
react/features/reactions/components/web/RaiseHandButton.ts Vedi File

@@ -2,7 +2,7 @@ import { connect } from 'react-redux';
2 2
 
3 3
 import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
4 4
 import { sendAnalytics } from '../../../analytics/functions';
5
-import { IReduxState } from '../../../app/types';
5
+import { IReduxState, IStore } from '../../../app/types';
6 6
 import { translate } from '../../../base/i18n/functions';
7 7
 import { IconRaiseHand } from '../../../base/icons/svg';
8 8
 import { raiseHand } from '../../../base/participants/actions';
@@ -15,6 +15,16 @@ import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/too
15 15
  */
16 16
 interface IProps extends AbstractButtonProps {
17 17
 
18
+    /**
19
+     * Whether or not the click is disabled.
20
+     */
21
+    disableClick?: boolean;
22
+
23
+    /**
24
+     * Redux dispatch function.
25
+     */
26
+    dispatch: IStore['dispatch'];
27
+
18 28
     /**
19 29
      * Whether or not the hand is raised.
20 30
      */
@@ -51,7 +61,11 @@ class RaiseHandButton extends AbstractButton<IProps> {
51 61
      * @returns {void}
52 62
      */
53 63
     _handleClick() {
54
-        const { dispatch, raisedHand } = this.props;
64
+        const { disableClick, dispatch, raisedHand } = this.props;
65
+
66
+        if (disableClick) {
67
+            return;
68
+        }
55 69
 
56 70
         sendAnalytics(createToolbarEvent(
57 71
             'raise.hand',
@@ -76,4 +90,6 @@ const mapStateToProps = (state: IReduxState) => {
76 90
     };
77 91
 };
78 92
 
93
+export { RaiseHandButton };
94
+
79 95
 export default translate(connect(mapStateToProps)(RaiseHandButton));

+ 1
- 0
react/features/visitors/components/index.native.ts Vedi File

@@ -0,0 +1 @@
1
+export { default as JoinMeetingDialog } from './native/JoinMeetingDialog';

+ 1
- 0
react/features/visitors/components/index.web.ts Vedi File

@@ -0,0 +1 @@
1
+export { default as JoinMeetingDialog } from './web/JoinMeetingDialog';

+ 40
- 0
react/features/visitors/components/native/JoinMeetingDialog.tsx Vedi File

@@ -0,0 +1,40 @@
1
+import React, { useCallback, useState } from 'react';
2
+import { useTranslation } from 'react-i18next';
3
+import { View, ViewStyle } from 'react-native';
4
+import Dialog from 'react-native-dialog';
5
+
6
+import { StandaloneRaiseHandButton as RaiseHandButton } from '../../../reactions/components/native/RaiseHandButton';
7
+import styles from '../../components/native/styles';
8
+
9
+/**
10
+ * Component that renders the join meeting dialog for visitors.
11
+ *
12
+ * @returns {JSX.Element}
13
+ */
14
+export default function JoinMeetingDialog() {
15
+    const { t } = useTranslation();
16
+    const [ visible, setVisible ] = useState(true);
17
+
18
+    const closeDialog = useCallback(() => {
19
+        setVisible(false);
20
+    }, []);
21
+
22
+    return (
23
+        <Dialog.Container
24
+            coverScreen = { false }
25
+            visible = { visible }>
26
+            <Dialog.Title>{ t('visitors.joinMeeting.title') }</Dialog.Title>
27
+            <Dialog.Description>
28
+                { t('visitors.joinMeeting.description') }
29
+                <View style = { styles.raiseHandButton as ViewStyle }>
30
+                    {/* @ts-ignore */}
31
+                    <RaiseHandButton disableClick = { true } />
32
+                </View>
33
+            </Dialog.Description>
34
+            <Dialog.Description>{t('visitors.joinMeeting.wishToSpeak')}</Dialog.Description>
35
+            <Dialog.Button
36
+                label = { t('dialog.Understood') }
37
+                onPress = { closeDialog } />
38
+        </Dialog.Container>
39
+    );
40
+}

+ 12
- 0
react/features/visitors/components/native/styles.ts Vedi File

@@ -0,0 +1,12 @@
1
+/**
2
+ * The styles of the feature visitors.
3
+ */
4
+export default {
5
+
6
+    raiseHandButton: {
7
+        display: 'flex',
8
+        alignItems: 'center',
9
+        justifyContent: 'center',
10
+        width: '100%'
11
+    }
12
+};

+ 75
- 0
react/features/visitors/components/web/JoinMeetingDialog.tsx Vedi File

@@ -0,0 +1,75 @@
1
+import { noop } from 'lodash';
2
+import React from 'react';
3
+import { useTranslation } from 'react-i18next';
4
+import { makeStyles } from 'tss-react/mui';
5
+
6
+import { IconArrowUp } from '../../../base/icons/svg';
7
+import ToolboxButtonWithPopup from '../../../base/toolbox/components/web/ToolboxButtonWithPopup';
8
+import Dialog from '../../../base/ui/components/web/Dialog';
9
+import { RaiseHandButton } from '../../../reactions/components/web/RaiseHandButton';
10
+
11
+const useStyles = makeStyles()(theme => {
12
+    return {
13
+        raiseHand: {
14
+            alignItems: 'center',
15
+            display: 'flex',
16
+            flexDirection: 'column',
17
+            marginTop: theme.spacing(3),
18
+            marginBottom: theme.spacing(3),
19
+            pointerEvents: 'none'
20
+        },
21
+        raiseHandTooltip: {
22
+            border: '1px solid #444',
23
+            borderRadius: theme.shape.borderRadius,
24
+            paddingBottom: theme.spacing(1),
25
+            paddingTop: theme.spacing(1),
26
+            paddingLeft: theme.spacing(2),
27
+            paddingRight: theme.spacing(2)
28
+        },
29
+        raiseHandButton: {
30
+            display: 'inline-block',
31
+            marginTop: theme.spacing(2),
32
+            marginBottom: theme.spacing(2),
33
+            position: 'relative'
34
+        }
35
+    };
36
+});
37
+
38
+/**
39
+ * Component that renders the join meeting dialog for visitors.
40
+ *
41
+ * @returns {JSX.Element}
42
+ */
43
+export default function JoinMeetingDialog() {
44
+    const { t } = useTranslation();
45
+    const { classes } = useStyles();
46
+
47
+    return (
48
+        <Dialog
49
+            cancel = {{ hidden: true }}
50
+            ok = {{ translationKey: 'dialog.Understood' }}
51
+            titleKey = 'visitors.joinMeeting.title'>
52
+            <div className = 'join-meeting-dialog'>
53
+                <p>{t('visitors.joinMeeting.description')}</p>
54
+                <div className = { classes.raiseHand }>
55
+                    <p className = { classes.raiseHandTooltip }>{t('visitors.joinMeeting.raiseHand')}</p>
56
+                    <div className = { classes.raiseHandButton }>
57
+                        <ToolboxButtonWithPopup
58
+                            icon = { IconArrowUp }
59
+                            iconDisabled = { false }
60
+                            onPopoverClose = { noop }
61
+                            onPopoverOpen = { noop }
62
+                            popoverContent = { null }
63
+                            visible = { false }>
64
+                            {/* @ts-ignore */}
65
+                            <RaiseHandButton
66
+                                disableClick = { true }
67
+                                raisedHand = { true } />
68
+                        </ToolboxButtonWithPopup>
69
+                    </div>
70
+                </div>
71
+                <p>{t('visitors.joinMeeting.wishToSpeak')}</p>
72
+            </div>
73
+        </Dialog>
74
+    );
75
+}

+ 4
- 0
react/features/visitors/middleware.ts Vedi File

@@ -13,6 +13,7 @@ import { SET_CONFIG } from '../base/config/actionTypes';
13 13
 import { CONNECTION_FAILED } from '../base/connection/actionTypes';
14 14
 import { connect, setPreferVisitor } from '../base/connection/actions';
15 15
 import { disconnect } from '../base/connection/actions.any';
16
+import { openDialog } from '../base/dialog/actions';
16 17
 import { JitsiConferenceEvents, JitsiConnectionErrors } from '../base/lib-jitsi-meet';
17 18
 import { PARTICIPANT_UPDATED } from '../base/participants/actionTypes';
18 19
 import { raiseHand } from '../base/participants/actions';
@@ -48,6 +49,7 @@ import {
48 49
     updateVisitorsCount,
49 50
     updateVisitorsInQueueCount
50 51
 } from './actions';
52
+import { JoinMeetingDialog } from './components';
51 53
 import { getPromotionRequests, getVisitorsCount, getVisitorsInQueueCount } from './functions';
52 54
 import logger from './logger';
53 55
 import { WebsocketClient } from './websocket-client';
@@ -70,6 +72,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
70 72
         const { conference } = action;
71 73
 
72 74
         if (getState()['features/visitors'].iAmVisitor) {
75
+            dispatch(openDialog(JoinMeetingDialog));
76
+
73 77
             const { demoteActorDisplayName } = getState()['features/visitors'];
74 78
 
75 79
             dispatch(setVisitorDemoteActor(undefined));

Loading…
Annulla
Salva