瀏覽代碼

Implement Landing component

j8
Ilya Daynatovich 8 年之前
父節點
當前提交
58a4f59fd8

+ 5
- 1
css/_landing.scss 查看文件

@@ -10,6 +10,10 @@
10 10
         max-width: 40em;
11 11
         text-align: center;
12 12
         color: $landingTextColor;
13
+
14
+        a:active {
15
+            text-decoration: none;
16
+        }
13 17
     }
14 18
 
15 19
     &__text {
@@ -31,7 +35,7 @@
31 35
 
32 36
     &__logo {
33 37
         width: 77px;
34
-        height: auto;
38
+        height: 108px;
35 39
     }
36 40
 
37 41
     &__button {

+ 1
- 0
index.html 查看文件

@@ -2,6 +2,7 @@
2 2
   <head>
3 3
     <meta charset="utf-8">
4 4
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
5 6
     <!--#include virtual="base.html" -->
6 7
     <script>
7 8
         window.indexLoadedTime = window.performance.now();

+ 3
- 2
react/features/app/functions.native.js 查看文件

@@ -1,5 +1,6 @@
1 1
 import { isRoomValid } from '../base/conference';
2 2
 import { RouteRegistry } from '../base/navigator';
3
+
3 4
 import { Conference } from '../conference';
4 5
 import { WelcomePage } from '../welcome';
5 6
 
@@ -85,8 +86,8 @@ export function _getRoomAndDomainFromUrlString(url) {
85 86
 export function _getRouteToRender(stateOrGetState) {
86 87
     const state
87 88
         = typeof stateOrGetState === 'function'
88
-            ? stateOrGetState()
89
-            : stateOrGetState;
89
+        ? stateOrGetState()
90
+        : stateOrGetState;
90 91
     const room = state['features/base/conference'].room;
91 92
     const component = isRoomValid(room) ? Conference : WelcomePage;
92 93
 

+ 43
- 0
react/features/base/util/detectDevices.js 查看文件

@@ -0,0 +1,43 @@
1
+/**
2
+ * Returns true if user agent is run on Android.
3
+ *
4
+ * @returns {boolean}
5
+ */
6
+export function detectAndroid() {
7
+    return Boolean(navigator.userAgent.match(/Android/i));
8
+}
9
+
10
+/**
11
+ * Returns true if user agent is run on iOS.
12
+ *
13
+ * @returns {boolean}
14
+ */
15
+export function detectIOS() {
16
+    if (navigator.userAgent.match(/iPhone/i)
17
+        || navigator.userAgent.match(/iPad/i)
18
+        || navigator.userAgent.match(/iPod/i)) {
19
+        return true;
20
+    }
21
+
22
+    return false;
23
+}
24
+
25
+/**
26
+ * Transforms hash map with parameters to query string.
27
+ *
28
+ * @param {Object} params - Hash map to be processed into query string.
29
+ * @returns {string}
30
+ */
31
+export function serializeQuery(params) {
32
+    return Object.keys(params).reduce((str, key, index) => {
33
+        const encodedKey = encodeURIComponent(key);
34
+        const encodedValue = encodeURIComponent(params[key]);
35
+        let separator = '&';
36
+
37
+        if (index === 0) {
38
+            separator = '?';
39
+        }
40
+
41
+        return `${str}${separator}${encodedKey}=${encodedValue}`;
42
+    }, '');
43
+}

+ 1
- 0
react/features/base/util/index.js 查看文件

@@ -1,2 +1,3 @@
1 1
 export * from './loadScript';
2 2
 export * from './roomnameGenerator';
3
+export * from './detectDevices';

+ 1
- 1
react/features/conference/route.js 查看文件

@@ -5,7 +5,7 @@ import HttpConfigFetch from '../../../modules/config/HttpConfigFetch';
5 5
 import ConferenceUrl from '../../../modules/URL/ConferenceUrl';
6 6
 
7 7
 import { RouteRegistry } from '../base/navigator';
8
-
8
+import { detectIOS, detectAndroid, serializeQuery } from '../base/util';
9 9
 import { Conference } from './components';
10 10
 
11 11
 const logger = require('jitsi-meet-logger').getLogger(__filename);

+ 11
- 0
react/features/landing/actionTypes.js 查看文件

@@ -0,0 +1,11 @@
1
+import { Symbol } from '../base/react';
2
+
3
+/**
4
+ * The type of the actions which signals that a mobile landing is shown.
5
+ *
6
+ * {
7
+ *     type: LANDING_IS_SHOWN
8
+ * }
9
+ */
10
+export const LANDING_IS_SHOWN = Symbol('LANDING_IS_SHOWN');
11
+

+ 16
- 0
react/features/landing/actions.js 查看文件

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

+ 97
- 0
react/features/landing/components/Landing.js 查看文件

@@ -0,0 +1,97 @@
1
+import React, { Component } from 'react';
2
+import { Link } from 'react-router';
3
+import { connect } from 'react-redux';
4
+import { landingIsShown } from '../actions';
5
+
6
+const links = {
7
+    'android': 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
8
+    'ios': ''
9
+};
10
+
11
+/**
12
+ * React component representing mobile landing page.
13
+ *
14
+ * @class Landing
15
+ */
16
+class Landing extends Component {
17
+    /**
18
+     * React lifecycle method triggered after
19
+     * component is mount.
20
+     *
21
+     * @returns {void}
22
+     */
23
+    componentDidMount() {
24
+        this.props.dispatch(landingIsShown());
25
+    }
26
+
27
+    static propTypes = {
28
+        dispatch: React.PropTypes.func,
29
+        location: React.PropTypes.object
30
+    };
31
+
32
+    /**
33
+     * React lifecycle method triggered before
34
+     * component will mount.
35
+     *
36
+     * @returns {void}
37
+     */
38
+    componentWillMount() {
39
+        const { query } = this.props.location;
40
+        const { conferenceName, platform } = query;
41
+        let btnText;
42
+        let link = '/';
43
+
44
+        if (conferenceName) {
45
+            btnText = 'Join the conversation';
46
+            link += conferenceName;
47
+        } else {
48
+            btnText = 'Start a conference';
49
+        }
50
+
51
+        this.setState({
52
+            btnText,
53
+            link,
54
+            platform
55
+        });
56
+    }
57
+
58
+    /**
59
+     * Renders landing component.
60
+     *
61
+     * @returns {ReactElement}
62
+     */
63
+    render() {
64
+        const { btnText, link, platform } = this.state;
65
+        const primaryButtonClasses = 'landing__button landing__button_primary';
66
+
67
+        return (
68
+            <div className = 'landing'>
69
+                <div className = 'landing__body'>
70
+                    <img
71
+                        className = 'landing__logo'
72
+                        src = '/images/logo-blue.svg' />
73
+                    <p className = 'landing__text'>
74
+                       You need <strong>Meet Jitsi</strong>
75
+                       to join a conversation on your mobile
76
+                    </p>
77
+                    <a href = { links[platform] }>
78
+                        <button
79
+                            className = { primaryButtonClasses }>
80
+                            Download the App
81
+                        </button>
82
+                    </a>
83
+                    <p className = 'landing__text landing__text_small'>
84
+                       or if you already have it
85
+                       <br /><strong>then</strong>
86
+                    </p>
87
+                    <Link to = { link }>
88
+                        <button
89
+                            className = 'landing__button'>{ btnText }</button>
90
+                    </Link>
91
+                </div>
92
+            </div>
93
+        );
94
+    }
95
+}
96
+
97
+export default connect()(Landing);

+ 1
- 0
react/features/landing/components/index.js 查看文件

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

+ 4
- 0
react/features/landing/index.js 查看文件

@@ -0,0 +1,4 @@
1
+import './route';
2
+
3
+export * from './actions';
4
+export * from './components';

+ 21
- 0
react/features/landing/reducer.js 查看文件

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

+ 15
- 0
react/features/landing/route.js 查看文件

@@ -0,0 +1,15 @@
1
+import { RouteRegistry } from '../base/navigator';
2
+import { Landing } from './components';
3
+
4
+RouteRegistry.register({
5
+    component: Landing,
6
+    path: '/mobile-app',
7
+    onEnter: store => () => {
8
+        const state = store.getState();
9
+        const { landingIsShown } = state;
10
+
11
+        if (landingIsShown) {
12
+            return;
13
+        }
14
+    }
15
+});

Loading…
取消
儲存