ソースを参照

Introduce unsupported browser page

j8
Ilya Daynatovich 8年前
コミット
2e81b8493e

+ 0
- 3
Makefile ファイルの表示

@@ -8,7 +8,6 @@ OUTPUT_DIR = .
8 8
 STYLES_BUNDLE = css/all.bundle.css
9 9
 STYLES_DESTINATION = css/all.css
10 10
 STYLES_MAIN = css/main.scss
11
-STYLES_UNSUPPORTED_BROWSER = css/unsupported_browser.scss
12 11
 WEBPACK = ./node_modules/.bin/webpack
13 12
 
14 13
 all: update-deps compile deploy clean
@@ -47,7 +46,6 @@ deploy-lib-jitsi-meet:
47 46
 		$(DEPLOY_DIR)
48 47
 
49 48
 deploy-css:
50
-	$(NODE_SASS) css/unsupported_browser.scss css/unsupported_browser.css ; \
51 49
 	$(NODE_SASS) $(STYLES_MAIN) $(STYLES_BUNDLE) && \
52 50
 	$(CLEANCSS) $(STYLES_BUNDLE) > $(STYLES_DESTINATION) ; \
53 51
 	rm $(STYLES_BUNDLE)
@@ -59,6 +57,5 @@ source-package:
59 57
 	mkdir -p source_package/jitsi-meet/css && \
60 58
 	cp -r *.js *.html connection_optimization favicon.ico fonts images libs sounds LICENSE lang source_package/jitsi-meet && \
61 59
 	cp css/all.css source_package/jitsi-meet/css && \
62
-	cp css/unsupported_browser.css source_package/jitsi-meet/css && \
63 60
 	(cd source_package ; tar cjf ../jitsi-meet.tar.bz2 jitsi-meet) && \
64 61
 	rm -rf source_package

+ 3
- 3
css/_variables.scss ファイルの表示

@@ -131,6 +131,6 @@ $linkHoverFontColor: #287ade;
131 131
 /**
132 132
  * Landing
133 133
  */
134
-$landingButtonBgColor: #ff9a00;
135
-$landingTextColor: #4a4a4a;
136
-$primaryLandingButtonBgColor: #17a0db;
134
+$unsupportedBrowserButtonBgColor: #ff9a00;
135
+$unsupportedBrowserTextColor: #4a4a4a;
136
+$primaryUnsupportedBrowserButtonBgColor: #17a0db;

+ 2
- 1
css/main.scss ファイルの表示

@@ -67,6 +67,7 @@
67 67
 @import '404';
68 68
 @import 'policy';
69 69
 @import 'filmstrip';
70
-@import 'landing';
70
+@import 'unsupported-browser/mobile-browser-page';
71
+@import 'unsupported-browser/unsupported_browser';
71 72
 
72 73
 /* Modules END */

css/_landing.scss → css/unsupported-browser/_mobile-browser-page.scss ファイルの表示

@@ -1,11 +1,11 @@
1
-.landing {
1
+.mobile-browser-page {
2 2
     background-color: #fff;
3 3
     height: 100vh;
4 4
     padding: 35px 0;
5 5
     width: 100vw;
6 6
 
7 7
     &__body {
8
-        color: $landingTextColor;
8
+        color: $unsupportedBrowserTextColor;
9 9
         margin: auto;
10 10
         max-width: 40em;
11 11
         text-align: center;
@@ -44,25 +44,25 @@
44 44
         max-width: 300px;
45 45
         width: 98%;
46 46
         @include border-radius(8px);
47
-        background-color: $landingButtonBgColor;
47
+        background-color: $unsupportedBrowserButtonBgColor;
48 48
         font-size: 1.5em;
49 49
         font-weight: 300;
50 50
         letter-spacing: 0.5px;
51
-        text-shadow: 0px 1px 2px $landingTextColor;
51
+        text-shadow: 0px 1px 2px $unsupportedBrowserTextColor;
52 52
 
53 53
         // Disable standard button effects.
54 54
         box-shadow: none;
55 55
         outline: none;
56 56
 
57 57
         &:active {
58
-            background-color: $landingButtonBgColor;
58
+            background-color: $unsupportedBrowserButtonBgColor;
59 59
         }
60 60
 
61 61
         &_primary {
62
-            background-color: $primaryLandingButtonBgColor;
62
+            background-color: $primaryUnsupportedBrowserButtonBgColor;
63 63
 
64 64
             &:active {
65
-                background-color: $primaryLandingButtonBgColor;
65
+                background-color: $primaryUnsupportedBrowserButtonBgColor;
66 66
             }
67 67
         }
68 68
     }

+ 132
- 0
css/unsupported-browser/_unsupported_browser.scss ファイルの表示

@@ -0,0 +1,132 @@
1
+.browser {
2
+    display: inline-block;
3
+    margin: 1em 7px;
4
+    width: 138px;
5
+    vertical-align: middle;
6
+    color: #929391;
7
+    font-size: 20px;
8
+
9
+    &__button {
10
+        background-color: #62c82a;
11
+        border: 1px solid #3c8117;
12
+        border-radius: 10px;
13
+        color: #FFFFFF;
14
+        font-size: 12px;
15
+        text-align: center;
16
+        width: 115px;
17
+        height: 26px;
18
+        padding-top: 13px;
19
+        margin: 15px auto 0px auto;
20
+    }
21
+
22
+    &__link {
23
+        color: #087dba;
24
+        text-decoration: none;
25
+
26
+        &:hover {
27
+            text-decoration: none;
28
+        }
29
+
30
+        &:active {
31
+            text-decoration: none;
32
+        }
33
+
34
+        &:focus {
35
+            text-decoration: none;
36
+        }
37
+    }
38
+
39
+    &-list
40
+    {
41
+        margin: 0 auto;
42
+    }
43
+
44
+    &__logo {
45
+        margin: 20px auto 0px auto;
46
+
47
+        &_chrome {
48
+            width: 78px;
49
+            height: 78px;
50
+            background-image: url('../../images/chrome.png');
51
+        }
52
+
53
+        &_chromium {
54
+            width: 77px;
55
+            height: 78px;
56
+            background-image: url('../../images/chromium.png');
57
+        }
58
+
59
+        &_firefox {
60
+            width: 86px;
61
+            height: 80px;
62
+            background-image: url('../../images/firefox.png');
63
+        }
64
+
65
+        &_opera {
66
+            width: 73px;
67
+            height: 78px;
68
+            background-image: url('../../images/opera.png');
69
+        }
70
+
71
+        &_ie {
72
+            width: 80px;
73
+            height: 78px;
74
+            background-image: url('../../images/ie.png');
75
+        }
76
+
77
+        &_safari {
78
+            width: 78px;
79
+            height: 79px;
80
+            background-image: url('../../images/safari.png');
81
+        }
82
+    }
83
+
84
+    &__text
85
+    {
86
+        line-height: 1.2em;
87
+
88
+        &_small {
89
+            font-size: small;
90
+        }
91
+    }
92
+
93
+    &__tile {
94
+        width: 138px;
95
+        height: 163px;
96
+        margin-top: 5px;
97
+        background-color: #e8e8e8;
98
+        border: 1px solid #cfcfcf;
99
+        border-radius: 10px;
100
+    }
101
+}
102
+
103
+.unsupported-browser {
104
+    display: block;
105
+    position: absolute;
106
+    width:500px;
107
+    height: 565px;
108
+    overflow:hidden;
109
+    text-align: center;
110
+    margin: auto;
111
+    top: 0; left: 0; bottom: 0; right: 0;
112
+
113
+    &__page {
114
+        display:inline-block;
115
+        font-size: 28px;
116
+        vertical-align:middle;
117
+        padding-top: 25px;
118
+    }
119
+
120
+    &__title {
121
+        margin: 0 auto;
122
+        width: 20em;
123
+    }
124
+
125
+    &-wrapper {
126
+        display: block;
127
+        position: absolute;
128
+        width: 100%;
129
+        height: 100%;
130
+        background: #fff;
131
+    }
132
+}

+ 0
- 138
css/unsupported_browser.scss ファイルの表示

@@ -1,138 +0,0 @@
1
-@import 'variables';
2
-
3
-body {
4
-    width:100%;
5
-    height:100%;
6
-    background-color: white;
7
-    color: #424242;
8
-    font-family: $baseFontFamily;
9
-    font-size: 28px;
10
-    margin:0;
11
-    padding:0;
12
-}
13
-#wrap{
14
-    display: block;
15
-    position: absolute;
16
-    width:500px;
17
-    height: 565px;
18
-    overflow:hidden;
19
-    text-align: center;
20
-    margin: auto;
21
-    top: 0; left: 0; bottom: 0; right: 0;
22
-}
23
-.firefox{
24
-    font-size: 11pt;
25
-    color: #c8c8c8;
26
-    width: 468px;
27
-    text-align: center;
28
-    margin: 30px auto 0px auto;
29
-    padding-left: 15px;
30
-}
31
-#text{
32
-    display:inline-block;
33
-    font-size: 28px;
34
-    /* width: 568px; */
35
-    vertical-align:middle;
36
-    padding-top: 25px;
37
-}
38
-
39
-a {
40
-    color: #087dba;
41
-    text-decoration:none;
42
-}
43
-
44
-.browser {
45
-    width: 138px;
46
-    height: 163px;
47
-    margin-top: 5px;
48
-    background-color: #e8e8e8;
49
-    border: 1px solid #cfcfcf;
50
-    border-radius: 10px;
51
-}
52
-
53
-.browser_wrapper
54
-{
55
-    width: 138px;
56
-    /* height: 188px; */
57
-    vertical-align: middle;
58
-    color: #929391;
59
-    font-size: 20px;
60
-    float: left;
61
-    margin-left: 15px;
62
-    margin-top: 5px;
63
-}
64
-
65
-.browser_text
66
-{
67
-    height: 2em;
68
-}
69
-.supported_browsers
70
-{
71
-    margin: 0px auto 0px auto;
72
-    /* width: 660px; */
73
-}
74
-
75
-.clear
76
-{
77
-    clear: both;
78
-}
79
-
80
-.button
81
-{
82
-    background-color: #62c82a;
83
-    border: 1px solid #3c8117;
84
-    border-radius: 10px;
85
-    color: #FFFFFF;
86
-    font-size: 12px;
87
-    text-align: center;
88
-    width: 115px;
89
-    height: 26px;
90
-    padding-top: 13px;
91
-    margin: 15px auto 0px auto;
92
-}
93
-
94
-.logo
95
-{
96
-    margin: 20px auto 0px auto;
97
-}
98
-
99
-#chrome_logo
100
-{
101
-    width: 78px;
102
-    height: 78px;
103
-    background-image: url('../images/chrome.png');
104
-}
105
-#chromium_logo
106
-{
107
-    width: 77px;
108
-    height: 78px;
109
-    background-image: url('../images/chromium.png');
110
-}
111
-#firefox_logo
112
-{
113
-    width: 86px;
114
-    height: 80px;
115
-    background-image: url('../images/firefox.png');
116
-}
117
-
118
-#opera_logo
119
-{
120
-    width: 73px;
121
-    height: 78px;
122
-    background-image: url('../images/opera.png');
123
-}
124
-
125
-#safari_logo
126
-{
127
-    width: 78px;
128
-    height: 79px;
129
-    background-image: url('../images/safari.png');
130
-}
131
-
132
-#ie_logo
133
-{
134
-    width: 80px;
135
-    height: 78px;
136
-    background-image: url('../images/ie.png');
137
-}
138
-

+ 3
- 15
react/features/app/actions.js ファイルの表示

@@ -6,19 +6,10 @@ import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
6 6
 import {
7 7
     _getRoomAndDomainFromUrlString,
8 8
     _getRouteToRender,
9
-    areRoutesEqual,
10 9
     init
11 10
 } from './functions';
12 11
 import './reducer';
13 12
 
14
-/**
15
- * Variable saving current route of the app. Later it will be extracted as
16
- * a property of the class with Router specific logic.
17
- *
18
- * @type {Object}
19
- */
20
-let currentRoute = {};
21
-
22 13
 /**
23 14
  * Temporary solution. Should dispatch actions related to initial settings of
24 15
  * the app like setting log levels, reading the config parameters from query
@@ -73,8 +64,8 @@ export function appNavigate(urlOrRoom) {
73 64
                 .then(() => {
74 65
                     const link = typeof room === 'undefined'
75 66
                     && typeof domain === 'undefined'
76
-                        ? urlOrRoom
77
-                        : room;
67
+                    ? urlOrRoom
68
+                    : room;
78 69
 
79 70
                     dispatch(_setRoomAndNavigate(link));
80 71
                 });
@@ -153,9 +144,6 @@ function _setRoomAndNavigate(newRoom) {
153 144
         const { app } = state['features/app'];
154 145
         const newRoute = _getRouteToRender(state);
155 146
 
156
-        if (!areRoutesEqual(newRoute, currentRoute)) {
157
-            currentRoute = newRoute;
158
-            app._navigate(newRoute);
159
-        }
147
+        app._navigate(newRoute);
160 148
     };
161 149
 }

+ 34
- 28
react/features/app/components/AbstractApp.js ファイルの表示

@@ -5,6 +5,7 @@ import {
5 5
     localParticipantJoined,
6 6
     localParticipantLeft
7 7
 } from '../../base/participants';
8
+import { RouteRegistry } from '../../base/navigator';
8 9
 
9 10
 import {
10 11
     appNavigate,
@@ -31,7 +32,7 @@ export class AbstractApp extends Component {
31 32
          * The URL, if any, with which the app was launched.
32 33
          */
33 34
         url: React.PropTypes.string
34
-    }
35
+    };
35 36
 
36 37
     /**
37 38
      * Initializes a new App instance.
@@ -210,33 +211,38 @@ export class AbstractApp extends Component {
210 211
      * @returns {void}
211 212
      */
212 213
     _navigate(route) {
213
-        let nextState = {
214
-            ...this.state,
215
-            route
216
-        };
217
-
218
-        // The Web App was using react-router so it utilized react-router's
219
-        // onEnter. During the removal of react-router, modifications were
220
-        // minimized by preserving the onEnter interface:
221
-        // (1) Router would provide its nextState to the Route's onEnter. As the
222
-        // role of Router is now this AbstractApp, provide its nextState.
223
-        // (2) A replace function would be provided to the Route in case it
224
-        // chose to redirect to another path.
225
-        this._onRouteEnter(route, nextState, pathname => {
226
-            // FIXME In order to minimize the modifications related to the
227
-            // removal of react-router, the Web implementation is provided
228
-            // bellow because the replace function is used on Web only at the
229
-            // time of this writing. Provide a platform-agnostic implementation.
230
-            // It should likely find the best Route matching the specified
231
-            // pathname and navigate to it.
232
-            window.location.pathname = pathname;
233
-
234
-            // Do not proceed with the route because it chose to redirect to
235
-            // another path.
236
-            nextState = undefined;
237
-        });
238
-
239
-        nextState && this.setState(nextState);
214
+        const currentRoute = this.state.route || {};
215
+
216
+        if (!RouteRegistry.areRoutesEqual(route, currentRoute)) {
217
+            let nextState = {
218
+                ...this.state,
219
+                route
220
+            };
221
+
222
+            // The Web App was using react-router so it utilized react-router's
223
+            // onEnter. During the removal of react-router, modifications were
224
+            // minimized by preserving the onEnter interface:
225
+            // (1) Router would provide its nextState to the Route's onEnter.
226
+            // As the role of Router is now this AbstractApp, provide its
227
+            // nextState.
228
+            // (2) A replace function would be provided to the Route in case it
229
+            // chose to redirect to another path.
230
+            this._onRouteEnter(route, nextState, pathname => {
231
+                // FIXME In order to minimize the modifications related to the
232
+                // removal of react-router, the Web implementation is provided
233
+                // bellow because the replace function is used on Web only at
234
+                // the time of this writing. Provide a platform-agnostic
235
+                // implementation. It should likely find the best Route matching
236
+                // the specified pathname and navigate to it.
237
+                window.location.pathname = pathname;
238
+
239
+                // Do not proceed with the route because it chose to redirect to
240
+                // another path.
241
+                nextState = undefined;
242
+            });
243
+
244
+            nextState && this.setState(nextState);
245
+        }
240 246
     }
241 247
 
242 248
     /**

+ 6
- 24
react/features/app/functions.web.js ファイルの表示

@@ -4,7 +4,7 @@ import { isRoomValid } from '../base/conference';
4 4
 import { RouteRegistry } from '../base/navigator';
5 5
 import { Platform } from '../base/react';
6 6
 import { Conference } from '../conference';
7
-import { Landing } from '../unsupported-browser';
7
+import { MobileBrowserPage } from '../unsupported-browser';
8 8
 import { WelcomePage } from '../welcome';
9 9
 
10 10
 import URLProcessor from '../../../modules/config/URLProcessor';
@@ -33,37 +33,19 @@ export function _getRouteToRender(stateOrGetState) {
33 33
             ? stateOrGetState()
34 34
             : stateOrGetState;
35 35
 
36
-    // If landing was shown, there is no need to show it again.
37
-    const { landingIsShown } = state['features/unsupported-browser'];
36
+    // If mobile browser page was shown, there is no need to show it again.
37
+    const { mobileBrowserPageIsShown } = state['features/unsupported-browser'];
38 38
     const { room } = state['features/base/conference'];
39 39
     const component = isRoomValid(room) ? Conference : WelcomePage;
40
+    const route = RouteRegistry.getRouteByComponent(component);
40 41
 
41
-    // We're using spread operator here to create copy of the route registered
42
-    // in registry. If we overwrite some of its properties (like 'component')
43
-    // they will stay unchanged in the registry.
44
-    const route = { ...RouteRegistry.getRouteByComponent(component) };
45
-
46
-    if ((OS === 'android' || OS === 'ios') && !landingIsShown) {
47
-        route.component = Landing;
42
+    if ((OS === 'android' || OS === 'ios') && !mobileBrowserPageIsShown) {
43
+        route.component = MobileBrowserPage;
48 44
     }
49 45
 
50 46
     return route;
51 47
 }
52 48
 
53
-/**
54
- * Method checking whether route objects are equal by value. Returns true if
55
- * and only if key values of the first object are equal to key values of
56
- * the second one.
57
- *
58
- * @param {Object} newRoute - New route object to be compared.
59
- * @param {Object} oldRoute - Old route object to be compared.
60
- * @returns {boolean}
61
- */
62
-export function areRoutesEqual(newRoute, oldRoute) {
63
-    return Object.keys(newRoute)
64
-        .every(key => newRoute[key] === oldRoute[key]);
65
-}
66
-
67 49
 /**
68 50
  * Temporary solution. Later we'll get rid of global APP and set its properties
69 51
  * in redux store.

+ 14
- 0
react/features/base/navigator/RouteRegistry.js ファイルの表示

@@ -11,6 +11,20 @@
11 11
  * without needing to create additional inter-feature dependencies.
12 12
  */
13 13
 class RouteRegistry {
14
+    /**
15
+     * Method checking whether route objects are equal by value. Returns true if
16
+     * and only if key values of the first object are equal to key values of
17
+     * the second one.
18
+     *
19
+     * @param {Object} newRoute - New route object to be compared.
20
+     * @param {Object} oldRoute - Old route object to be compared.
21
+     * @returns {boolean}
22
+     */
23
+    areRoutesEqual(newRoute, oldRoute) {
24
+        return Object.keys(newRoute)
25
+            .every(key => newRoute[key] === oldRoute[key]);
26
+    }
27
+
14 28
     /**
15 29
      * Initializes a new RouteRegistry instance.
16 30
      */

+ 5
- 3
react/features/unsupported-browser/actionTypes.js ファイルの表示

@@ -1,10 +1,12 @@
1 1
 import { Symbol } from '../base/react';
2 2
 
3 3
 /**
4
- * The type of the Redux action which signals that a mobile landing is shown.
4
+ * The type of the Redux action which signals that a mobile browser page
5
+ * is shown.
5 6
  *
6 7
  * {
7
- *     type: LANDING_IS_SHOWN
8
+ *     type: MOBILE_BROWSER_PAGE_IS_SHOWN
8 9
  * }
9 10
  */
10
-export const LANDING_IS_SHOWN = Symbol('LANDING_IS_SHOWN');
11
+// eslint-disable-next-line max-len
12
+export const MOBILE_BROWSER_PAGE_IS_SHOWN = Symbol('MOBILE_BROWSER_PAGE_IS_SHOWN');

+ 6
- 6
react/features/unsupported-browser/actions.js ファイルの表示

@@ -1,16 +1,16 @@
1
-import { LANDING_IS_SHOWN } from './actionTypes';
1
+import { MOBILE_BROWSER_PAGE_IS_SHOWN } from './actionTypes';
2 2
 import './reducer';
3 3
 
4 4
 /**
5
- * Returns an action that mobile landing is shown
6
- * and there is no need to show it on other pages.
5
+ * Returns an action that mobile browser page is shown and there is no need
6
+ * to show it on other pages.
7 7
  *
8 8
  * @returns {{
9
- *     type: LANDING_IS_SHOWN
9
+ *     type: MOBILE_BROWSER_PAGE_IS_SHOWN
10 10
  * }}
11 11
  */
12
-export function landingIsShown() {
12
+export function mobileBrowserPageIsShown() {
13 13
     return {
14
-        type: LANDING_IS_SHOWN
14
+        type: MOBILE_BROWSER_PAGE_IS_SHOWN
15 15
     };
16 16
 }

react/features/unsupported-browser/components/Landing.js → react/features/unsupported-browser/components/MobileBrowserPage.js ファイルの表示

@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
4 4
 import { Platform } from '../../base/react';
5 5
 
6 6
 import { appNavigate } from '../../app';
7
-import { landingIsShown } from '../actions';
7
+import { mobileBrowserPageIsShown } from '../actions';
8 8
 
9 9
 /**
10 10
  * The map of platforms to URLs at which the mobile app for the associated
@@ -16,14 +16,14 @@ const URLS = {
16 16
 };
17 17
 
18 18
 /**
19
- * React component representing mobile landing page.
19
+ * React component representing mobile browser page.
20 20
  *
21
- * @class Landing
21
+ * @class MobileBrowserPage
22 22
  */
23
-class Landing extends Component {
23
+class MobileBrowserPage extends Component {
24 24
 
25 25
     /**
26
-     * Constructor of Landing component.
26
+     * Constructor of MobileBrowserPage component.
27 27
      *
28 28
      * @param {Object} props - The read-only React Component props with which
29 29
      * the new instance is to be initialized.
@@ -36,14 +36,14 @@ class Landing extends Component {
36 36
     }
37 37
 
38 38
     /**
39
-     * Landing component's property types.
39
+     * Mobile browser page component's property types.
40 40
      *
41 41
      * @static
42 42
      */
43 43
     static propTypes = {
44 44
         dispatch: React.PropTypes.func,
45 45
         room: React.PropTypes.string
46
-    }
46
+    };
47 47
 
48 48
     /**
49 49
      * React lifecycle method triggered after component is mounted.
@@ -51,7 +51,7 @@ class Landing extends Component {
51 51
      * @returns {void}
52 52
      */
53 53
     componentDidMount() {
54
-        this.props.dispatch(landingIsShown());
54
+        this.props.dispatch(mobileBrowserPageIsShown());
55 55
     }
56 56
 
57 57
     /**
@@ -90,21 +90,25 @@ class Landing extends Component {
90 90
     }
91 91
 
92 92
     /**
93
-     * Renders landing component.
93
+     * Renders component.
94 94
      *
95 95
      * @returns {ReactElement}
96 96
      */
97 97
     render() {
98 98
         const { btnText } = this.state;
99
-        const primaryButtonClasses = 'landing__button landing__button_primary';
99
+        const blockPrefix = 'mobile-browser-page';
100
+        const textClasses = `${blockPrefix}__text ${blockPrefix}__text_small`;
101
+        let primaryButtonClasses = `${blockPrefix}__button`;
102
+
103
+        primaryButtonClasses += `${blockPrefix}__button_primary`;
100 104
 
101 105
         return (
102
-            <div className = 'landing'>
103
-                <div className = 'landing__body'>
106
+            <div className = { blockPrefix }>
107
+                <div className = { `${blockPrefix}__body` }>
104 108
                     <img
105
-                        className = 'landing__logo'
109
+                        className = { `${blockPrefix}__logo` }
106 110
                         src = '/images/logo-blue.svg' />
107
-                    <p className = 'landing__text'>
111
+                    <p className = { `${blockPrefix}__text` }>
108 112
                         You need <strong>Jitsi Meet</strong> to join a
109 113
                         conversation on your mobile
110 114
                     </p>
@@ -113,13 +117,13 @@ class Landing extends Component {
113 117
                             Download the App
114 118
                         </button>
115 119
                     </a>
116
-                    <p className = 'landing__text landing__text_small'>
120
+                    <p className = { textClasses }>
117 121
                         or if you already have it
118 122
                         <br />
119 123
                         <strong>then</strong>
120 124
                     </p>
121 125
                     <button
122
-                        className = 'landing__button'
126
+                        className = 'mobile-browser-page__button'
123 127
                         onClick = { this._onClickJoin }>
124 128
                         { btnText }
125 129
                     </button>
@@ -130,7 +134,7 @@ class Landing extends Component {
130 134
 }
131 135
 
132 136
 /**
133
- * Maps (parts of) the Redux state to the associated Landing's props.
137
+ * Maps (parts of) the Redux state to the associated MobileBrowserPage's props.
134 138
  *
135 139
  * @param {Object} state - Redux state.
136 140
  * @returns {{
@@ -143,4 +147,4 @@ function mapStateToProps(state) {
143 147
     };
144 148
 }
145 149
 
146
-export default connect(mapStateToProps)(Landing);
150
+export default connect(mapStateToProps)(MobileBrowserPage);

+ 117
- 0
react/features/unsupported-browser/components/UnsupportedBrowserPage.js ファイルの表示

@@ -0,0 +1,117 @@
1
+import React, { Component } from 'react';
2
+
3
+/**
4
+ * Array of all supported browsers.
5
+ */
6
+const SUPPORTED_BROWSERS = [
7
+    {
8
+        link: 'http://google.com/chrome',
9
+        name: 'chrome',
10
+        plugin: false,
11
+        title: 'Chrome 44+'
12
+    }, {
13
+        link: 'http://www.chromium.org/',
14
+        name: 'chromium',
15
+        plugin: false,
16
+        title: 'Chromium 44+'
17
+    }, {
18
+        link: 'http://www.opera.com',
19
+        name: 'opera',
20
+        plugin: false,
21
+        title: 'Opera 32+'
22
+    }, {
23
+        link: 'http://www.getfirefox.com/',
24
+        name: 'firefox',
25
+        plugin: false,
26
+        title: 'Firefox and Iceweasel 40+'
27
+    }, {
28
+        link: 'https://temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins',
29
+        name: 'ie',
30
+        plugin: 'Temasys 0.8.854+',
31
+        title: 'IE'
32
+    }, {
33
+        link: 'https://temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins',
34
+        name: 'safari',
35
+        plugin: 'Temasys 0.8.854+',
36
+        title: 'Safari'
37
+    }
38
+];
39
+
40
+/**
41
+ * React component representing unsupported browser page.
42
+ *
43
+ * @class UnsupportedBrowserPage
44
+ */
45
+export default class UnsupportedBrowserPage extends Component {
46
+    /**
47
+     * Renders the component.
48
+     *
49
+     * @returns {ReactElement}
50
+     */
51
+    render() {
52
+        return (
53
+            <div className = 'unsupported-browser-wrapper'>
54
+                <div className = 'unsupported-browser'>
55
+                    <div className = 'unsupported-browser__content'>
56
+                        <h2 className = 'unsupported-browser__title'>
57
+                            This application is currently only supported by
58
+                        </h2>
59
+                        { this._getSupportedBrowsersLayout() }
60
+                    </div>
61
+                </div>
62
+            </div>
63
+        );
64
+    }
65
+
66
+    /**
67
+     * Generates layout for the list of supported browsers.
68
+     *
69
+     * @returns {ReactElement}
70
+     * @private
71
+     */
72
+    _getSupportedBrowsersLayout() {
73
+        return (
74
+            <div className = 'browser-list'>
75
+                { SUPPORTED_BROWSERS.map(this._getSupportedBrowser) }
76
+            </div>
77
+        );
78
+    }
79
+
80
+    /**
81
+     * Method that generated layout for supported browser object.
82
+     *
83
+     * @param {Object} browser - Object containing information about supported
84
+     * browser.
85
+     * @returns {ReactElement}
86
+     * @private
87
+     */
88
+    _getSupportedBrowser(browser) {
89
+        let pluginHtml = null;
90
+        const logoClassName = `browser__logo browser__logo_${browser.name}`;
91
+
92
+        // Browsers not supporting WebRTC could support application
93
+        // with Temasys plugin installed.
94
+        if (browser.plugin) {
95
+            const className = 'browser__text_small';
96
+
97
+            pluginHtml = <p className = { className }>({ browser.plugin })</p>;
98
+        }
99
+
100
+        return (
101
+            <div className = 'browser'>
102
+                <div className = 'browser__text'>
103
+                    { browser.title }
104
+                    { pluginHtml }
105
+                </div>
106
+                <div className = 'browser__tile'>
107
+                    <div className = { logoClassName } />
108
+                    <a
109
+                        className = 'browser__link'
110
+                        href = { browser.link }>
111
+                        <div className = 'browser__button'>DOWNLOAD</div>
112
+                    </a>
113
+                </div>
114
+            </div>
115
+        );
116
+    }
117
+}

+ 2
- 1
react/features/unsupported-browser/components/index.js ファイルの表示

@@ -1 +1,2 @@
1
-export { default as Landing } from './Landing';
1
+export { default as MobileBrowserPage } from './MobileBrowserPage';
2
+export { default as UnsupportedBrowserPage } from './UnsupportedBrowserPage';

+ 4
- 4
react/features/unsupported-browser/reducer.js ファイルの表示

@@ -1,21 +1,21 @@
1 1
 import { ReducerRegistry } from '../base/redux';
2 2
 
3
-import { LANDING_IS_SHOWN } from './actionTypes';
3
+import { MOBILE_BROWSER_PAGE_IS_SHOWN } from './actionTypes';
4 4
 
5 5
 ReducerRegistry.register(
6 6
         'features/unsupported-browser',
7 7
         (state = {}, action) => {
8 8
             switch (action.type) {
9
-            case LANDING_IS_SHOWN:
9
+            case MOBILE_BROWSER_PAGE_IS_SHOWN:
10 10
                 return {
11 11
                     ...state,
12 12
 
13 13
                     /**
14
-                     * Flag that shows that mobile landing is shown.
14
+                     * Flag that shows that mobile browser page is shown.
15 15
                      *
16 16
                      * @type {boolean}
17 17
                      */
18
-                    landingIsShown: true
18
+                    mobileBrowserPageIsShown: true
19 19
                 };
20 20
             }
21 21
 

+ 0
- 65
unsupported_browser.html ファイルの表示

@@ -1,65 +0,0 @@
1
-<html>
2
-<head>
3
-<title>Jitsi Meet: Unsupported Browser</title>
4
-<link rel="stylesheet" type="text/css" media="screen" href="css/unsupported_browser.css" />
5
-</head>
6
-
7
-<body>
8
-<!-- wrap starts here -->
9
-<div id="wrap"> 
10
-<div id="text">
11
-    <p>This application is currently only supported by</p>
12
-
13
-    <div class="supported_browsers">
14
-        <div class="browser_wrapper">
15
-            Chrome 44+
16
-            <div class="browser">
17
-                <div class="logo" id="chrome_logo"></div>
18
-                <a href="http://google.com/chrome"><div class="button">DOWNLOAD</div></a>
19
-            </div>
20
-        </div>
21
-        <div class="browser_wrapper">
22
-            Chromium 44+
23
-            <div class="browser">
24
-                <div class="logo" id="chromium_logo"></div>
25
-                <a href="http://www.chromium.org/"><div class="button">DOWNLOAD</div></a>
26
-            </div>
27
-        </div>
28
-        <div class="browser_wrapper">
29
-            Opera 32+
30
-            <div class="browser">
31
-                <div class="logo" id="opera_logo"></div>
32
-                <a href="http://www.opera.com"><div class="button">DOWNLOAD</div></a>
33
-            </div>
34
-        </div>
35
-        <div class="browser_wrapper">
36
-            <div class="browser_text">
37
-                Firefox and Iceweasel 40+</div>
38
-            <div class="browser">
39
-                <div class="logo" id="firefox_logo"></div>
40
-                <a href="http://www.getfirefox.com/"><div class="button">DOWNLOAD</div></a>
41
-            </div>
42
-        </div>
43
-        <div class="browser_wrapper">
44
-            <div class="browser_text">
45
-                IE <br /> <span style="font-size: small">(Temasys 0.8.854+)</span></div>
46
-            <div class="browser">
47
-                <div class="logo" id="ie_logo"></div>
48
-                <a href="https://temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins"><div class="button">DOWNLOAD</div></a>
49
-            </div>
50
-        </div>
51
-        <div class="browser_wrapper">
52
-            <div class="browser_text">
53
-                Safari <br /> <span style="font-size: small">(Temasys 0.8.854+)</span></div>
54
-            <div class="browser">
55
-                <div class="logo" id="safari_logo"></div>
56
-                <a href="https://temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins"><div class="button">DOWNLOAD</div></a>
57
-            </div>
58
-        </div>
59
-    </div>
60
-    <div class="clear"></div>
61
-</div>
62
-<!-- wrap ends here -->
63
-</div>		
64
-</body>
65
-</html>

読み込み中…
キャンセル
保存