Browse Source

[RN] Add branded dialog component

j8
Bettenbuk Zoltan 7 years ago
parent
commit
22a602768c
27 changed files with 760 additions and 88 deletions
  1. 2
    0
      lang/main.json
  2. 0
    0
      react/features/base/dialog/components/BottomSheet.web.js
  3. 1
    1
      react/features/base/dialog/components/DialogContent.js
  4. 0
    0
      react/features/base/dialog/components/DialogWithTabs.native.js
  5. 0
    0
      react/features/base/dialog/components/StatelessDialog.native.js
  6. 3
    0
      react/features/base/dialog/components/_.native.js
  7. 3
    0
      react/features/base/dialog/components/_.web.js
  8. 2
    6
      react/features/base/dialog/components/index.js
  9. 139
    0
      react/features/base/dialog/components/native/BaseDialog.js
  10. 93
    0
      react/features/base/dialog/components/native/BaseSubmitDialog.js
  11. 0
    0
      react/features/base/dialog/components/native/BottomSheet.js
  12. 91
    0
      react/features/base/dialog/components/native/ConfirmDialog.js
  13. 22
    0
      react/features/base/dialog/components/native/CustomDialog.js
  14. 30
    0
      react/features/base/dialog/components/native/CustomSubmitDialog.js
  15. 10
    5
      react/features/base/dialog/components/native/Dialog.js
  16. 133
    0
      react/features/base/dialog/components/native/InputDialog.js
  17. 12
    0
      react/features/base/dialog/components/native/index.js
  18. 183
    0
      react/features/base/dialog/components/native/styles.js
  19. 2
    63
      react/features/base/dialog/components/styles.native.js
  20. 1
    1
      react/features/base/dialog/components/styles.web.js
  21. 0
    0
      react/features/base/dialog/components/web/AbstractDialogTab.js
  22. 2
    2
      react/features/base/dialog/components/web/Dialog.js
  23. 2
    2
      react/features/base/dialog/components/web/DialogWithTabs.js
  24. 7
    2
      react/features/base/dialog/components/web/StatelessDialog.js
  25. 7
    0
      react/features/base/dialog/components/web/index.js
  26. 14
    2
      react/features/base/dialog/constants.js
  27. 1
    4
      react/features/settings/DeviceSelectionPopup.js

+ 2
- 0
lang/main.json View File

@@ -266,6 +266,8 @@
266 266
         },
267 267
         "allow": "Allow",
268 268
         "confirm": "Confirm",
269
+        "confirmNo": "No",
270
+        "confirmYes": "Yes",
269 271
         "kickMessage": "Ouch! You have been kicked out of the meet!",
270 272
         "kickTitle": "Kicked from meeting",
271 273
         "popupErrorTitle": "Pop-up blocked",

+ 0
- 0
react/features/base/dialog/components/BottomSheet.web.js View File


+ 1
- 1
react/features/base/dialog/components/DialogContent.js View File

@@ -4,7 +4,7 @@ import React, { Component } from 'react';
4 4
 
5 5
 import { Container, Text } from '../../react';
6 6
 
7
-import { dialog as styles } from './styles';
7
+import styles from './styles';
8 8
 
9 9
 type Props = {
10 10
 

+ 0
- 0
react/features/base/dialog/components/DialogWithTabs.native.js View File


+ 0
- 0
react/features/base/dialog/components/StatelessDialog.native.js View File


+ 3
- 0
react/features/base/dialog/components/_.native.js View File

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

+ 3
- 0
react/features/base/dialog/components/_.web.js View File

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

+ 2
- 6
react/features/base/dialog/components/index.js View File

@@ -1,10 +1,6 @@
1 1
 // @flow
2 2
 
3
-export { default as BottomSheet } from './BottomSheet';
4
-export { default as Dialog } from './Dialog';
3
+export * from './_';
4
+
5 5
 export { default as DialogContainer } from './DialogContainer';
6 6
 export { default as DialogContent } from './DialogContent';
7
-export { default as StatelessDialog } from './StatelessDialog';
8
-export { default as DialogWithTabs } from './DialogWithTabs';
9
-export { default as AbstractDialogTab } from './AbstractDialogTab';
10
-export type { Props as AbstractDialogTabProps } from './AbstractDialogTab';

+ 139
- 0
react/features/base/dialog/components/native/BaseDialog.js View File

@@ -0,0 +1,139 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+import {
5
+    Text,
6
+    TouchableOpacity,
7
+    View
8
+} from 'react-native';
9
+
10
+import { Icon } from '../../../font-icons';
11
+
12
+import AbstractDialog, {
13
+    type Props as AbstractProps,
14
+    type State
15
+} from '../AbstractDialog';
16
+import { brandedDialog as styles } from './styles';
17
+
18
+export type Props = {
19
+    ...AbstractProps,
20
+
21
+    t: Function
22
+}
23
+
24
+/**
25
+ * Component to render a custom dialog.
26
+ */
27
+class BaseDialog<P: Props, S: State> extends AbstractDialog<P, S> {
28
+    /**
29
+     * Initializes a new {@code FeedbackDialog} instance.
30
+     *
31
+     * @inheritdoc
32
+     */
33
+    constructor(props: P) {
34
+        super(props);
35
+
36
+        this._onSubmit = this._onSubmit.bind(this);
37
+    }
38
+
39
+    /**
40
+     * Implements React's {@link Component#render()}.
41
+     *
42
+     * @inheritdoc
43
+     * @returns {ReactElement}
44
+     */
45
+    render() {
46
+        const { style } = this.props;
47
+
48
+        return (
49
+            <View
50
+                pointerEvents = 'box-none'
51
+                style = { [
52
+                    styles.overlay,
53
+                    style
54
+                ] }>
55
+                <View
56
+                    pointerEvents = 'box-none'
57
+                    style = { [
58
+                        styles.dialog,
59
+                        this.props.style
60
+                    ] }>
61
+                    <TouchableOpacity
62
+                        onPress = { this._onCancel }
63
+                        style = { styles.closeWrapper }>
64
+                        <Icon
65
+                            name = 'close'
66
+                            style = { styles.closeStyle } />
67
+                    </TouchableOpacity>
68
+                    { this._renderContent() }
69
+                </View>
70
+            </View>
71
+        );
72
+    }
73
+
74
+    _onCancel: () => void;
75
+
76
+    _onSubmit: () => boolean;
77
+
78
+    /**
79
+     * Renders the content of the dialog.
80
+     *
81
+     * @returns {ReactElement}
82
+     */
83
+    _renderContent: () => Object
84
+
85
+    /**
86
+     * Renders a specific {@code string} which may contain HTML.
87
+     *
88
+     * @param {string|undefined} html - The {@code string} which may
89
+     * contain HTML to render.
90
+     * @returns {ReactElement[]|string}
91
+     */
92
+    _renderHTML(html: ?string) {
93
+        if (typeof html === 'string') {
94
+            // At the time of this writing, the specified HTML contains a couple
95
+            // of spaces one after the other. They do not cause a visible
96
+            // problem on Web, because the specified HTML is rendered as, well,
97
+            // HTML. However, we're not rendering HTML here.
98
+
99
+            // eslint-disable-next-line no-param-reassign
100
+            html = html.replace(/\s{2,}/gi, ' ');
101
+
102
+            // Render text in <b>text</b> in bold.
103
+            const opening = /<\s*b\s*>/gi;
104
+            const closing = /<\s*\/\s*b\s*>/gi;
105
+            let o;
106
+            let c;
107
+            let prevClosingLastIndex = 0;
108
+            const r = [];
109
+
110
+            // eslint-disable-next-line no-cond-assign
111
+            while (o = opening.exec(html)) {
112
+                closing.lastIndex = opening.lastIndex;
113
+
114
+                // eslint-disable-next-line no-cond-assign
115
+                if (c = closing.exec(html)) {
116
+                    r.push(html.substring(prevClosingLastIndex, o.index));
117
+                    r.push(
118
+                        <Text style = { styles.boldDialogText }>
119
+                            { html.substring(opening.lastIndex, c.index) }
120
+                        </Text>);
121
+                    opening.lastIndex
122
+                        = prevClosingLastIndex
123
+                        = closing.lastIndex;
124
+                } else {
125
+                    break;
126
+                }
127
+            }
128
+            if (prevClosingLastIndex < html.length) {
129
+                r.push(html.substring(prevClosingLastIndex));
130
+            }
131
+
132
+            return r;
133
+        }
134
+
135
+        return html;
136
+    }
137
+}
138
+
139
+export default BaseDialog;

+ 93
- 0
react/features/base/dialog/components/native/BaseSubmitDialog.js View File

@@ -0,0 +1,93 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+import { View, Text, TouchableOpacity } from 'react-native';
5
+
6
+import BaseDialog, { type Props as BaseProps } from './BaseDialog';
7
+import {
8
+    brandedDialog
9
+} from './styles';
10
+
11
+type Props = {
12
+    ...BaseProps,
13
+
14
+    t: Function
15
+}
16
+
17
+/**
18
+ * Abstract dialog to submit something. E.g. a confirmation or a form.
19
+ */
20
+class BaseSubmitDialog<P: Props, S: *> extends BaseDialog<P, S> {
21
+    /**
22
+     * Returns the title key of the submit button.
23
+     *
24
+     * NOTE: Please do not change this, this should be consistent accross the
25
+     * application. This method is here to be able to be overriden ONLY by the
26
+     * {@code ConfirmDialog}.
27
+     *
28
+     * @returns {string}
29
+     */
30
+    _getSubmitButtonKey() {
31
+        return 'dialog.Ok';
32
+    }
33
+
34
+    /**
35
+     * Renders additional buttons, if any - may be overwritten by children.
36
+     *
37
+     * @returns {?ReactElement}
38
+     */
39
+    _renderAdditionalButtons() {
40
+        return null;
41
+    }
42
+
43
+    /**
44
+     * Implements {@code BaseDialog._renderContent}.
45
+     *
46
+     * @inheritdoc
47
+     */
48
+    _renderContent() {
49
+        const { t } = this.props;
50
+        const additionalButtons = this._renderAdditionalButtons();
51
+
52
+        return (
53
+            <View>
54
+                <View style = { brandedDialog.mainWrapper }>
55
+                    { this._renderSubmittable() }
56
+                </View>
57
+                <View style = { brandedDialog.buttonWrapper }>
58
+                    { additionalButtons }
59
+                    <TouchableOpacity
60
+                        disabled = { this.props.okDisabled }
61
+                        onPress = { this._onSubmit }
62
+                        style = { [
63
+                            brandedDialog.button,
64
+                            additionalButtons
65
+                                ? null : brandedDialog.buttonFarLeft,
66
+                            brandedDialog.buttonFarRight
67
+                        ] }>
68
+                        <Text style = { brandedDialog.text }>
69
+                            { t(this._getSubmitButtonKey()) }
70
+                        </Text>
71
+                    </TouchableOpacity>
72
+                </View>
73
+            </View>
74
+        );
75
+    }
76
+
77
+    _onCancel: () => void;
78
+
79
+    _onSubmit: ?string => boolean;
80
+
81
+    _renderHTML: string => Object | string
82
+
83
+    /**
84
+     * Renders the actual content of the dialog defining what is about to be
85
+     * submitted. E.g. a simple confirmation (text, properly wrapped) or a
86
+     * complex form.
87
+     *
88
+     * @returns {Object}
89
+     */
90
+    _renderSubmittable: () => Object
91
+}
92
+
93
+export default BaseSubmitDialog;

react/features/base/dialog/components/BottomSheet.native.js → react/features/base/dialog/components/native/BottomSheet.js View File


+ 91
- 0
react/features/base/dialog/components/native/ConfirmDialog.js View File

@@ -0,0 +1,91 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+import { Text, TouchableOpacity } from 'react-native';
5
+import { connect } from 'react-redux';
6
+
7
+import { translate } from '../../../i18n';
8
+
9
+import { type Props as BaseProps } from './BaseDialog';
10
+import BaseSubmitDialog from './BaseSubmitDialog';
11
+import { brandedDialog } from './styles';
12
+
13
+type Props = {
14
+    ...BaseProps,
15
+
16
+    /**
17
+     * Untranslated i18n key of the content to be displayed.
18
+     *
19
+     * NOTE: This dialog also adds support to Object type keys that will be
20
+     * translated using the provided params. See i18n function
21
+     * {@code translate(string, Object)} for more details.
22
+     */
23
+    contentKey: string | { key: string, params: Object},
24
+
25
+    t: Function
26
+}
27
+
28
+/**
29
+ * Implements a confirm dialog component.
30
+ */
31
+class ConfirmDialog extends BaseSubmitDialog<Props, *> {
32
+    /**
33
+     * Returns the title key of the submit button.
34
+     *
35
+     * @returns {string}
36
+     */
37
+    _getSubmitButtonKey() {
38
+        return 'dialog.confirmYes';
39
+    }
40
+
41
+    _onCancel: () => void;
42
+
43
+    /**
44
+     * Renders the 'No' button.
45
+     *
46
+     * NOTE: The {@code ConfirmDialog} is the only dialog right now that
47
+     * renders 2 buttons, mainly for clarity.
48
+     *
49
+     * @inheritdoc
50
+     */
51
+    _renderAdditionalButtons() {
52
+        const { t } = this.props;
53
+
54
+        return (
55
+            <TouchableOpacity
56
+                onPress = { this._onCancel }
57
+                style = { [
58
+                    brandedDialog.button,
59
+                    brandedDialog.buttonFarLeft,
60
+                    brandedDialog.buttonSeparator
61
+                ] }>
62
+                <Text style = { brandedDialog.text }>
63
+                    { t('dialog.confirmNo') }
64
+                </Text>
65
+            </TouchableOpacity>
66
+        );
67
+    }
68
+
69
+    /**
70
+     * Implements {@code BaseSubmitDialog._renderSubmittable}.
71
+     *
72
+     * @inheritdoc
73
+     */
74
+    _renderSubmittable() {
75
+        const { contentKey, t } = this.props;
76
+        const content
77
+            = typeof contentKey === 'string'
78
+                ? t(contentKey)
79
+                : this._renderHTML(t(contentKey.key, contentKey.params));
80
+
81
+        return (
82
+            <Text style = { brandedDialog.text }>
83
+                { content }
84
+            </Text>
85
+        );
86
+    }
87
+
88
+    _renderHTML: string => Object | string
89
+}
90
+
91
+export default translate(connect()(ConfirmDialog));

+ 22
- 0
react/features/base/dialog/components/native/CustomDialog.js View File

@@ -0,0 +1,22 @@
1
+// @flow
2
+
3
+import { connect } from 'react-redux';
4
+
5
+import BaseDialog, { type Props } from './BaseDialog';
6
+
7
+/**
8
+ * Implements a custom dialog component, where the content can freely be
9
+ * rendered.
10
+ */
11
+class CustomDialog extends BaseDialog<Props, *> {
12
+    /**
13
+     * Implements {@code BaseDialog._renderContent}.
14
+     *
15
+     * @inheritdoc
16
+     */
17
+    _renderContent() {
18
+        return this.props.children;
19
+    }
20
+}
21
+
22
+export default connect()(CustomDialog);

+ 30
- 0
react/features/base/dialog/components/native/CustomSubmitDialog.js View File

@@ -0,0 +1,30 @@
1
+// @flow
2
+
3
+import { connect } from 'react-redux';
4
+
5
+import { translate } from '../../../i18n';
6
+
7
+import { type Props as BaseProps } from './BaseDialog';
8
+import BaseSubmitDialog from './BaseSubmitDialog';
9
+
10
+type Props = {
11
+    ...BaseProps,
12
+
13
+    t: Function
14
+}
15
+
16
+/**
17
+ * Implements a submit dialog component that can have free content.
18
+ */
19
+class CustomSubmitDialog extends BaseSubmitDialog<Props, *> {
20
+    /**
21
+     * Implements {@code BaseSubmitDialog._renderSubmittable}.
22
+     *
23
+     * @inheritdoc
24
+     */
25
+    _renderSubmittable() {
26
+        return this.props.children;
27
+    }
28
+}
29
+
30
+export default translate(connect()(CustomSubmitDialog));

react/features/base/dialog/components/Dialog.native.js → react/features/base/dialog/components/native/Dialog.js View File

@@ -6,15 +6,15 @@ import { Modal, StyleSheet, TextInput } from 'react-native';
6 6
 import Prompt from 'react-native-prompt';
7 7
 import { connect } from 'react-redux';
8 8
 
9
-import { translate } from '../../i18n';
10
-import { LoadingIndicator } from '../../react';
11
-import { set } from '../../redux';
9
+import { translate } from '../../../i18n';
10
+import { LoadingIndicator } from '../../../react';
11
+import { set } from '../../../redux';
12 12
 
13
-import AbstractDialog from './AbstractDialog';
13
+import AbstractDialog from '../AbstractDialog';
14 14
 import type {
15 15
     Props as AbstractDialogProps,
16 16
     State as AbstractDialogState
17
-} from './AbstractDialog';
17
+} from '../AbstractDialog';
18 18
 import { dialog as styles } from './styles';
19 19
 
20 20
 /**
@@ -44,6 +44,11 @@ type Props = {
44 44
      */
45 45
     bodyKey: string,
46 46
 
47
+    /**
48
+     * Function to be used to retreive translated i18n labels.
49
+     */
50
+    t: Function,
51
+
47 52
     textInputProps: Object
48 53
 };
49 54
 

+ 133
- 0
react/features/base/dialog/components/native/InputDialog.js View File

@@ -0,0 +1,133 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+import { View, Text, TextInput, TouchableOpacity } from 'react-native';
5
+import { connect } from 'react-redux';
6
+
7
+import { translate } from '../../../i18n';
8
+
9
+import { type State as AbstractState } from '../AbstractDialog';
10
+
11
+import BaseDialog, { type Props as BaseProps } from './BaseDialog';
12
+import {
13
+    FIELD_UNDERLINE,
14
+    brandedDialog,
15
+    inputDialog as styles
16
+} from './styles';
17
+
18
+type Props = {
19
+    ...BaseProps,
20
+
21
+    /**
22
+     * The untranslated i18n key for the field label on the dialog.
23
+     */
24
+    contentKey: string,
25
+
26
+    t: Function,
27
+
28
+    textInputProps: ?Object
29
+}
30
+
31
+type State = {
32
+    ...AbstractState,
33
+
34
+    /**
35
+     * The current value of the field.
36
+     */
37
+    fieldValue: ?string
38
+};
39
+
40
+/**
41
+ * Implements a single field input dialog component.
42
+ */
43
+class InputDialog extends BaseDialog<Props, State> {
44
+    /**
45
+     * Instantiates a new {@code InputDialog}.
46
+     *
47
+     * @inheritdoc
48
+     */
49
+    constructor(props: Props) {
50
+        super(props);
51
+
52
+        this.state = {
53
+            fieldValue: undefined
54
+        };
55
+
56
+        this._onChangeText = this._onChangeText.bind(this);
57
+        this._onSubmitValue = this._onSubmitValue.bind(this);
58
+    }
59
+
60
+    /**
61
+     * Implements {@code BaseDialog._renderContent}.
62
+     *
63
+     * @inheritdoc
64
+     */
65
+    _renderContent() {
66
+        const { okDisabled, t } = this.props;
67
+
68
+        return (
69
+            <View>
70
+                <View
71
+                    style = { [
72
+                        brandedDialog.mainWrapper,
73
+                        styles.fieldWrapper
74
+                    ] }>
75
+                    <Text style = { styles.fieldLabel }>
76
+                        { t(this.props.contentKey) }
77
+                    </Text>
78
+                    <TextInput
79
+                        onChangeText = { this._onChangeText }
80
+                        style = { styles.field }
81
+                        underlineColorAndroid = { FIELD_UNDERLINE }
82
+                        value = { this.state.fieldValue }
83
+                        { ...this.props.textInputProps } />
84
+                </View>
85
+                <View style = { brandedDialog.buttonWrapper }>
86
+                    <TouchableOpacity
87
+                        disabled = { okDisabled }
88
+                        onPress = { this._onSubmit }
89
+                        style = { [
90
+                            brandedDialog.button,
91
+                            brandedDialog.buttonFarLeft,
92
+                            brandedDialog.buttonFarRight
93
+                        ] }>
94
+                        <Text style = { brandedDialog.text }>
95
+                            { t('dialog.Ok') }
96
+                        </Text>
97
+                    </TouchableOpacity>
98
+                </View>
99
+            </View>
100
+        );
101
+    }
102
+
103
+    _onCancel: () => void;
104
+
105
+    _onChangeText: string => void;
106
+
107
+    /**
108
+     * Callback to be invoked when the text in the field changes.
109
+     *
110
+     * @param {string} fieldValue - The updated field value.
111
+     * @returns {void}
112
+     */
113
+    _onChangeText(fieldValue) {
114
+        this.setState({
115
+            fieldValue
116
+        });
117
+    }
118
+
119
+    _onSubmit: ?string => boolean;
120
+
121
+    _onSubmitValue: () => boolean;
122
+
123
+    /**
124
+     * Callback to be invoked when the value of this dialog is submitted.
125
+     *
126
+     * @returns {boolean}
127
+     */
128
+    _onSubmitValue() {
129
+        return this._onSubmit(this.state.fieldValue);
130
+    }
131
+}
132
+
133
+export default translate(connect()(InputDialog));

+ 12
- 0
react/features/base/dialog/components/native/index.js View File

@@ -0,0 +1,12 @@
1
+// @flow
2
+
3
+export { default as BottomSheet } from './BottomSheet';
4
+export { default as ConfirmDialog } from './ConfirmDialog';
5
+export { default as CustomDialog } from './CustomDialog';
6
+export { default as Dialog } from './Dialog';
7
+export { default as InputDialog } from './InputDialog';
8
+export { default as CustomSubmitDialog } from './CustomSubmitDialog';
9
+
10
+// NOTE: Some dialogs reuse the style of these base classes for consistency
11
+// and as we're in a /native namespace, it's safe to export the styles.
12
+export * from './styles';

+ 183
- 0
react/features/base/dialog/components/native/styles.js View File

@@ -0,0 +1,183 @@
1
+// @flow
2
+
3
+import { StyleSheet } from 'react-native';
4
+
5
+import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles';
6
+
7
+import { PREFERRED_DIALOG_SIZE } from '../../constants';
8
+
9
+const BORDER_RADIUS = 5;
10
+const DIALOG_BORDER_COLOR = 'rgba(255, 255, 255, 0.2)';
11
+
12
+export const FIELD_UNDERLINE = ColorPalette.transparent;
13
+export const PLACEHOLDER_COLOR = ColorPalette.lightGrey;
14
+
15
+/**
16
+ * The React {@code Component} styles of {@code BottomSheet}. These have
17
+ * been implemented as per the Material Design guidelines:
18
+ * {@link https://material.io/guidelines/components/bottom-sheets.html}.
19
+ */
20
+export const bottomSheetStyles = createStyleSheet({
21
+    /**
22
+     * Style for a backdrop which dims the view in the background. This view
23
+     * will also be clickable. The backgroundColor is applied to the overlay
24
+     * view instead, so the modal animation doesn't affect the backdrop.
25
+     */
26
+    backdrop: {
27
+        ...StyleSheet.absoluteFillObject
28
+    },
29
+
30
+    /**
31
+     * Style for the container of the sheet.
32
+     */
33
+    container: {
34
+        alignItems: 'flex-end',
35
+        flex: 1,
36
+        flexDirection: 'row',
37
+        justifyContent: 'center'
38
+    },
39
+
40
+    /**
41
+     * Style for an overlay on top of which the sheet will be displayed.
42
+     */
43
+    overlay: {
44
+        ...StyleSheet.absoluteFillObject,
45
+        backgroundColor: 'rgba(0, 0, 0, 0.8)'
46
+    },
47
+
48
+    /**
49
+     * Bottom sheet's base style.
50
+     */
51
+    sheet: {
52
+        backgroundColor: ColorPalette.white,
53
+        flex: 1,
54
+        paddingHorizontal: 16,
55
+        paddingVertical: 8
56
+    }
57
+});
58
+
59
+export const brandedDialog = createStyleSheet({
60
+
61
+    /**
62
+     * The style of bold {@code Text} rendered by the {@code Dialog}s of the
63
+     * feature authentication.
64
+     */
65
+    boldDialogText: {
66
+        fontWeight: 'bold'
67
+    },
68
+
69
+    button: {
70
+        backgroundColor: ColorPalette.blue,
71
+        flex: 1,
72
+        padding: BoxModel.padding * 1.5
73
+    },
74
+
75
+    buttonFarLeft: {
76
+        borderBottomLeftRadius: BORDER_RADIUS
77
+    },
78
+
79
+    buttonFarRight: {
80
+        borderBottomRightRadius: BORDER_RADIUS
81
+    },
82
+
83
+    buttonSeparator: {
84
+        borderRightColor: DIALOG_BORDER_COLOR,
85
+        borderRightWidth: 1
86
+    },
87
+
88
+    buttonWrapper: {
89
+        alignItems: 'stretch',
90
+        borderRadius: BORDER_RADIUS,
91
+        flexDirection: 'row'
92
+    },
93
+
94
+    closeStyle: {
95
+        color: ColorPalette.white,
96
+        fontSize: 16
97
+    },
98
+
99
+    closeWrapper: {
100
+        alignSelf: 'flex-end',
101
+        padding: BoxModel.padding
102
+    },
103
+
104
+    dialog: {
105
+        alignItems: 'stretch',
106
+        backgroundColor: 'rgb(0, 3, 6)',
107
+        borderColor: DIALOG_BORDER_COLOR,
108
+        borderRadius: BORDER_RADIUS,
109
+        borderWidth: 1,
110
+        flex: 1,
111
+        flexDirection: 'column',
112
+        maxWidth: PREFERRED_DIALOG_SIZE
113
+    },
114
+
115
+    mainWrapper: {
116
+        alignSelf: 'stretch',
117
+        padding: BoxModel.padding * 2,
118
+
119
+        // The added bottom padding is to compensate the empty space around the
120
+        // close icon.
121
+        paddingBottom: BoxModel.padding * 3
122
+    },
123
+
124
+    overlay: {
125
+        ...StyleSheet.absoluteFillObject,
126
+        alignItems: 'center',
127
+        backgroundColor: 'rgba(127, 127, 127, 0.6)',
128
+        flexDirection: 'row',
129
+        justifyContent: 'center',
130
+        padding: 30
131
+    },
132
+
133
+    text: {
134
+        color: ColorPalette.white,
135
+        fontSize: 16,
136
+        textAlign: 'center'
137
+    }
138
+});
139
+
140
+/**
141
+ * The React {@code Component} styles of {@code Dialog}.
142
+ */
143
+export const dialog = createStyleSheet({
144
+    /**
145
+     * The style of the {@code Text} in a {@code Dialog} button.
146
+     */
147
+    buttonText: {
148
+        color: ColorPalette.blue
149
+    },
150
+
151
+    /**
152
+     * The style of the {@code Text} in a {@code Dialog} button which is
153
+     * disabled.
154
+     */
155
+    disabledButtonText: {
156
+        color: ColorPalette.darkGrey
157
+    }
158
+});
159
+
160
+export const inputDialog = createStyleSheet({
161
+    bottomField: {
162
+        marginBottom: 0
163
+    },
164
+
165
+    field: {
166
+        ...brandedDialog.text,
167
+        borderBottomWidth: 1,
168
+        borderColor: DIALOG_BORDER_COLOR,
169
+        margin: BoxModel.margin,
170
+        textAlign: 'left'
171
+    },
172
+
173
+    fieldLabel: {
174
+        ...brandedDialog.text,
175
+        margin: BoxModel.margin,
176
+        textAlign: 'left'
177
+    },
178
+
179
+    fieldWrapper: {
180
+        ...brandedDialog.mainWrapper,
181
+        paddingBottom: BoxModel.padding * 2
182
+    }
183
+});

+ 2
- 63
react/features/base/dialog/components/styles.native.js View File

@@ -1,75 +1,14 @@
1
-import { StyleSheet } from 'react-native';
2
-
3
-import { BoxModel, ColorPalette, createStyleSheet } from '../../styles';
1
+import { BoxModel, createStyleSheet } from '../../styles';
4 2
 
5 3
 /**
6 4
  * The React {@code Component} styles of {@code Dialog}.
7 5
  */
8
-export const dialog = createStyleSheet({
9
-    /**
10
-     * The style of the {@code Text} in a {@code Dialog} button.
11
-     */
12
-    buttonText: {
13
-        color: ColorPalette.blue
14
-    },
15
-
6
+export default createStyleSheet({
16 7
     /**
17 8
      * Unified container for a consistent Dialog style.
18 9
      */
19 10
     dialogContainer: {
20 11
         paddingHorizontal: BoxModel.padding,
21 12
         paddingVertical: 1.5 * BoxModel.padding
22
-    },
23
-
24
-    /**
25
-     * The style of the {@code Text} in a {@code Dialog} button which is
26
-     * disabled.
27
-     */
28
-    disabledButtonText: {
29
-        color: ColorPalette.darkGrey
30
-    }
31
-});
32
-
33
-/**
34
- * The React {@code Component} styles of {@code BottomSheet}. These have
35
- * been implemented as per the Material Design guidelines:
36
- * {@link https://material.io/guidelines/components/bottom-sheets.html}.
37
- */
38
-export const bottomSheetStyles = createStyleSheet({
39
-    /**
40
-     * Style for a backdrop which dims the view in the background. This view
41
-     * will also be clickable. The backgroundColor is applied to the overlay
42
-     * view instead, so the modal animation doesn't affect the backdrop.
43
-     */
44
-    backdrop: {
45
-        ...StyleSheet.absoluteFillObject
46
-    },
47
-
48
-    /**
49
-     * Style for the container of the sheet.
50
-     */
51
-    container: {
52
-        alignItems: 'flex-end',
53
-        flex: 1,
54
-        flexDirection: 'row',
55
-        justifyContent: 'center'
56
-    },
57
-
58
-    /**
59
-     * Style for an overlay on top of which the sheet will be displayed.
60
-     */
61
-    overlay: {
62
-        ...StyleSheet.absoluteFillObject,
63
-        backgroundColor: 'rgba(0, 0, 0, 0.8)'
64
-    },
65
-
66
-    /**
67
-     * Bottom sheet's base style.
68
-     */
69
-    sheet: {
70
-        flex: 1,
71
-        backgroundColor: ColorPalette.white,
72
-        paddingHorizontal: 16,
73
-        paddingVertical: 8
74 13
     }
75 14
 });

+ 1
- 1
react/features/base/dialog/components/styles.web.js View File

@@ -2,4 +2,4 @@
2 2
  * Placeholder styles for web to be able to use cross platform components
3 3
  * unmodified such as {@code DialogContent}.
4 4
  */
5
-export const dialog = {};
5
+export default {};

react/features/base/dialog/components/AbstractDialogTab.js → react/features/base/dialog/components/web/AbstractDialogTab.js View File


react/features/base/dialog/components/Dialog.web.js → react/features/base/dialog/components/web/Dialog.js View File

@@ -3,8 +3,8 @@
3 3
 import React from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
-import AbstractDialog from './AbstractDialog';
7
-import type { Props as AbstractDialogProps, State } from './AbstractDialog';
6
+import AbstractDialog from '../AbstractDialog';
7
+import type { Props as AbstractDialogProps, State } from '../AbstractDialog';
8 8
 import StatelessDialog from './StatelessDialog';
9 9
 
10 10
 /**

react/features/base/dialog/components/DialogWithTabs.web.js → react/features/base/dialog/components/web/DialogWithTabs.js View File

@@ -3,8 +3,8 @@
3 3
 import Tabs from '@atlaskit/tabs';
4 4
 import React, { Component } from 'react';
5 5
 
6
-import { StatelessDialog } from '../../../base/dialog';
7
-import { translate } from '../../../base/i18n';
6
+import { StatelessDialog } from '../../../dialog';
7
+import { translate } from '../../../i18n';
8 8
 
9 9
 const logger = require('jitsi-meet-logger').getLogger(__filename);
10 10
 

react/features/base/dialog/components/StatelessDialog.web.js → react/features/base/dialog/components/web/StatelessDialog.js View File

@@ -7,9 +7,9 @@ import _ from 'lodash';
7 7
 import PropTypes from 'prop-types';
8 8
 import React, { Component } from 'react';
9 9
 
10
-import { translate } from '../../i18n';
10
+import { translate } from '../../../i18n';
11 11
 
12
-import type { DialogProps } from '../constants';
12
+import type { DialogProps } from '../../constants';
13 13
 
14 14
 /**
15 15
  * The ID to be used for the cancel button if enabled.
@@ -56,6 +56,11 @@ type Props = {
56 56
      */
57 57
     submitDisabled: boolean,
58 58
 
59
+    /**
60
+     * Function to be used to retreive translated i18n labels.
61
+     */
62
+    t: Function,
63
+
59 64
     /**
60 65
      * Width of the dialog, can be:
61 66
      * - 'small' (400px), 'medium' (600px), 'large' (800px),

+ 7
- 0
react/features/base/dialog/components/web/index.js View File

@@ -0,0 +1,7 @@
1
+// @flow
2
+
3
+export { default as AbstractDialogTab } from './AbstractDialogTab';
4
+export type { Props as AbstractDialogTabProps } from './AbstractDialogTab';
5
+export { default as Dialog } from './Dialog';
6
+export { default as DialogWithTabs } from './DialogWithTabs';
7
+export { default as StatelessDialog } from './StatelessDialog';

+ 14
- 2
react/features/base/dialog/constants.js View File

@@ -38,9 +38,11 @@ export type DialogProps = {
38 38
     onSubmit: Function,
39 39
 
40 40
     /**
41
-     * Used to obtain translations in children classes.
41
+     * Additional style to be applied on the dialog.
42
+     *
43
+     * NOTE: Not all dialog types support this!
42 44
      */
43
-    t: Function,
45
+    style?: Object,
44 46
 
45 47
     /**
46 48
      * Key to use for showing a title.
@@ -54,3 +56,13 @@ export type DialogProps = {
54 56
      */
55 57
     titleString: string
56 58
 };
59
+
60
+/**
61
+ * A preferred (or optimal) dialog size. This constant is reused in many
62
+ * components, where dialog size optimization is suggested.
63
+ *
64
+ * NOTE: Even though we support valious devices, including tablets, we don't
65
+ * want the dialogs to be oversized even on larger devices. This number seems
66
+ * to be a good compromise, but also easy to update.
67
+ */
68
+export const PREFERRED_DIALOG_SIZE = 300;

+ 1
- 4
react/features/settings/DeviceSelectionPopup.js View File

@@ -12,10 +12,7 @@ import {
12 12
 } from '../../../modules/transport';
13 13
 import { parseURLParams } from '../base/config';
14 14
 import { DeviceSelection } from '../device-selection';
15
-
16
-// Using the full path to the file to prevent adding unnecessary code into the
17
-// dialog popup bundle.
18
-import DialogWithTabs from '../base/dialog/components/DialogWithTabs';
15
+import { DialogWithTabs } from '../base/dialog';
19 16
 
20 17
 const logger = Logger.getLogger(__filename);
21 18
 

Loading…
Cancel
Save