diff options
Diffstat (limited to 'src/features')
-rw-r--r-- | src/features/basicAuth/Component.js | 102 | ||||
-rw-r--r-- | src/features/basicAuth/Form.js | 17 | ||||
-rw-r--r-- | src/features/basicAuth/index.js | 68 | ||||
-rw-r--r-- | src/features/basicAuth/mainIpcHandler.js | 9 | ||||
-rw-r--r-- | src/features/basicAuth/styles.js | 12 | ||||
-rw-r--r-- | src/features/delayApp/Component.js | 14 | ||||
-rw-r--r-- | src/features/delayApp/index.js | 23 |
7 files changed, 233 insertions, 12 deletions
diff --git a/src/features/basicAuth/Component.js b/src/features/basicAuth/Component.js new file mode 100644 index 000000000..13395fb40 --- /dev/null +++ b/src/features/basicAuth/Component.js | |||
@@ -0,0 +1,102 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import injectSheet from 'react-jss'; | ||
4 | import { observer } from 'mobx-react'; | ||
5 | import classnames from 'classnames'; | ||
6 | |||
7 | import Modal from '../../components/ui/Modal'; | ||
8 | import Input from '../../components/ui/Input'; | ||
9 | import Button from '../../components/ui/Button'; | ||
10 | |||
11 | import { | ||
12 | state, | ||
13 | resetState, | ||
14 | sendCredentials, | ||
15 | cancelLogin, | ||
16 | } from '.'; | ||
17 | import Form from './Form'; | ||
18 | |||
19 | import styles from './styles'; | ||
20 | |||
21 | export default @injectSheet(styles) @observer class BasicAuthModal extends Component { | ||
22 | static propTypes = { | ||
23 | classes: PropTypes.object.isRequired, | ||
24 | } | ||
25 | |||
26 | submit(e) { | ||
27 | e.preventDefault(); | ||
28 | |||
29 | const values = Form.values(); | ||
30 | console.log('form submit', values); | ||
31 | |||
32 | sendCredentials(values.user, values.password); | ||
33 | resetState(); | ||
34 | } | ||
35 | |||
36 | cancel() { | ||
37 | cancelLogin(); | ||
38 | this.close(); | ||
39 | } | ||
40 | |||
41 | close() { | ||
42 | resetState(); | ||
43 | state.isModalVisible = false; | ||
44 | } | ||
45 | |||
46 | render() { | ||
47 | const { | ||
48 | classes, | ||
49 | } = this.props; | ||
50 | |||
51 | const { | ||
52 | isModalVisible, | ||
53 | authInfo, | ||
54 | } = state; | ||
55 | |||
56 | if (!authInfo) { | ||
57 | return null; | ||
58 | } | ||
59 | |||
60 | return ( | ||
61 | <Modal | ||
62 | isOpen={isModalVisible} | ||
63 | className={classes.modal} | ||
64 | close={this.cancel.bind(this)} | ||
65 | > | ||
66 | <h1>Sign in</h1> | ||
67 | <p> | ||
68 | http | ||
69 | {authInfo.port === 443 && 's'} | ||
70 | :// | ||
71 | {authInfo.host} | ||
72 | </p> | ||
73 | <form | ||
74 | onSubmit={this.submit.bind(this)} | ||
75 | className={classnames('franz-form', classes.form)} | ||
76 | > | ||
77 | <Input | ||
78 | field={Form.$('user')} | ||
79 | showLabel={false} | ||
80 | /> | ||
81 | <Input | ||
82 | field={Form.$('password')} | ||
83 | showLabel={false} | ||
84 | showPasswordToggle | ||
85 | /> | ||
86 | <div className={classes.buttons}> | ||
87 | <Button | ||
88 | type="button" | ||
89 | label="Cancel" | ||
90 | buttonType="secondary" | ||
91 | onClick={this.cancel.bind(this)} | ||
92 | /> | ||
93 | <Button | ||
94 | type="submit" | ||
95 | label="Sign In" | ||
96 | /> | ||
97 | </div> | ||
98 | </form> | ||
99 | </Modal> | ||
100 | ); | ||
101 | } | ||
102 | } | ||
diff --git a/src/features/basicAuth/Form.js b/src/features/basicAuth/Form.js new file mode 100644 index 000000000..95721d0e9 --- /dev/null +++ b/src/features/basicAuth/Form.js | |||
@@ -0,0 +1,17 @@ | |||
1 | import Form from '../../lib/Form'; | ||
2 | |||
3 | export default new Form({ | ||
4 | fields: { | ||
5 | user: { | ||
6 | label: 'user', | ||
7 | placeholder: 'Username', | ||
8 | value: '', | ||
9 | }, | ||
10 | password: { | ||
11 | label: 'Password', | ||
12 | placeholder: 'Password', | ||
13 | value: '', | ||
14 | type: 'password', | ||
15 | }, | ||
16 | }, | ||
17 | }); | ||
diff --git a/src/features/basicAuth/index.js b/src/features/basicAuth/index.js new file mode 100644 index 000000000..03269582c --- /dev/null +++ b/src/features/basicAuth/index.js | |||
@@ -0,0 +1,68 @@ | |||
1 | import { ipcRenderer } from 'electron'; | ||
2 | import { observable } from 'mobx'; | ||
3 | |||
4 | import BasicAuthComponent from './Component'; | ||
5 | |||
6 | const debug = require('debug')('Franz:feature:basicAuth'); | ||
7 | |||
8 | const defaultState = { | ||
9 | isModalVisible: false, | ||
10 | service: null, | ||
11 | authInfo: null, | ||
12 | }; | ||
13 | |||
14 | export const state = observable(defaultState); | ||
15 | |||
16 | export function resetState() { | ||
17 | Object.assign(state, defaultState); | ||
18 | console.log('reset state', state); | ||
19 | } | ||
20 | |||
21 | export default function initialize() { | ||
22 | debug('Initialize basicAuth feature'); | ||
23 | |||
24 | window.franz.features.basicAuth = { | ||
25 | state, | ||
26 | }; | ||
27 | |||
28 | ipcRenderer.on('feature:basic-auth-request', (e, data) => { | ||
29 | debug(e, data); | ||
30 | // state.serviceId = data.serviceId; | ||
31 | state.authInfo = data.authInfo; | ||
32 | state.isModalVisible = true; | ||
33 | }); | ||
34 | |||
35 | // autorun(() => { | ||
36 | // // if (state.serviceId) { | ||
37 | // // const service = stores.services.one(state.serviceId); | ||
38 | // // if (service) { | ||
39 | // // state.service = service; | ||
40 | // // } | ||
41 | // // } | ||
42 | // }); | ||
43 | } | ||
44 | |||
45 | export function mainIpcHandler(mainWindow, authInfo) { | ||
46 | debug('Sending basic auth call', authInfo); | ||
47 | |||
48 | mainWindow.webContents.send('feature:basic-auth-request', { | ||
49 | authInfo, | ||
50 | }); | ||
51 | } | ||
52 | |||
53 | export function sendCredentials(user, password) { | ||
54 | debug('Sending credentials to main', user, password); | ||
55 | |||
56 | ipcRenderer.send('feature-basic-auth-credentials', { | ||
57 | user, | ||
58 | password, | ||
59 | }); | ||
60 | } | ||
61 | |||
62 | export function cancelLogin() { | ||
63 | debug('Cancel basic auth event'); | ||
64 | |||
65 | ipcRenderer.send('feature-basic-auth-cancel'); | ||
66 | } | ||
67 | |||
68 | export const Component = BasicAuthComponent; | ||
diff --git a/src/features/basicAuth/mainIpcHandler.js b/src/features/basicAuth/mainIpcHandler.js new file mode 100644 index 000000000..87ac0b6df --- /dev/null +++ b/src/features/basicAuth/mainIpcHandler.js | |||
@@ -0,0 +1,9 @@ | |||
1 | const debug = require('debug')('Franz:feature:basicAuth:main'); | ||
2 | |||
3 | export default function mainIpcHandler(mainWindow, authInfo) { | ||
4 | debug('Sending basic auth call', authInfo); | ||
5 | |||
6 | mainWindow.webContents.send('feature:basic-auth', { | ||
7 | authInfo, | ||
8 | }); | ||
9 | } | ||
diff --git a/src/features/basicAuth/styles.js b/src/features/basicAuth/styles.js new file mode 100644 index 000000000..6bdaf9a6e --- /dev/null +++ b/src/features/basicAuth/styles.js | |||
@@ -0,0 +1,12 @@ | |||
1 | export default { | ||
2 | modal: { | ||
3 | width: 300, | ||
4 | }, | ||
5 | buttons: { | ||
6 | display: 'flex', | ||
7 | justifyContent: 'space-between', | ||
8 | }, | ||
9 | form: { | ||
10 | marginTop: 15, | ||
11 | }, | ||
12 | }; | ||
diff --git a/src/features/delayApp/Component.js b/src/features/delayApp/Component.js index 6e0532c9a..ff84510e8 100644 --- a/src/features/delayApp/Component.js +++ b/src/features/delayApp/Component.js | |||
@@ -4,6 +4,8 @@ import { inject, observer } from 'mobx-react'; | |||
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import injectSheet from 'react-jss'; | 5 | import injectSheet from 'react-jss'; |
6 | 6 | ||
7 | import { gaEvent } from '../../lib/analytics'; | ||
8 | |||
7 | import Button from '../../components/ui/Button'; | 9 | import Button from '../../components/ui/Button'; |
8 | 10 | ||
9 | import { config } from '.'; | 11 | import { config } from '.'; |
@@ -59,8 +61,16 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp | |||
59 | clearInterval(this.countdownInterval); | 61 | clearInterval(this.countdownInterval); |
60 | } | 62 | } |
61 | 63 | ||
64 | handleCTAClick() { | ||
65 | const { actions } = this.props; | ||
66 | |||
67 | actions.ui.openSettings({ path: 'user' }); | ||
68 | |||
69 | gaEvent('DelayApp', 'subscribe_click', 'Delay App Feature'); | ||
70 | } | ||
71 | |||
62 | render() { | 72 | render() { |
63 | const { classes, actions } = this.props; | 73 | const { classes } = this.props; |
64 | const { intl } = this.context; | 74 | const { intl } = this.context; |
65 | 75 | ||
66 | return ( | 76 | return ( |
@@ -70,7 +80,7 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp | |||
70 | label={intl.formatMessage(messages.action)} | 80 | label={intl.formatMessage(messages.action)} |
71 | className={classes.button} | 81 | className={classes.button} |
72 | buttonType="inverted" | 82 | buttonType="inverted" |
73 | onClick={() => actions.ui.openSettings({ path: 'user' })} | 83 | onClick={this.handleCTAClick.bind(this)} |
74 | /> | 84 | /> |
75 | <p className="footnote"> | 85 | <p className="footnote"> |
76 | {intl.formatMessage(messages.text, { | 86 | {intl.formatMessage(messages.text, { |
diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js index d5c544b78..28aa50eb2 100644 --- a/src/features/delayApp/index.js +++ b/src/features/delayApp/index.js | |||
@@ -3,6 +3,7 @@ import moment from 'moment'; | |||
3 | import DelayAppComponent from './Component'; | 3 | import DelayAppComponent from './Component'; |
4 | 4 | ||
5 | import { DEFAULT_FEATURES_CONFIG } from '../../config'; | 5 | import { DEFAULT_FEATURES_CONFIG } from '../../config'; |
6 | import { gaEvent } from '../../lib/analytics'; | ||
6 | 7 | ||
7 | const debug = require('debug')('Franz:feature:delayApp'); | 8 | const debug = require('debug')('Franz:feature:delayApp'); |
8 | 9 | ||
@@ -22,19 +23,18 @@ function setVisibility(value) { | |||
22 | } | 23 | } |
23 | 24 | ||
24 | export default function init(stores) { | 25 | export default function init(stores) { |
25 | reaction( | 26 | debug('Initializing `delayApp` feature'); |
26 | () => stores.features.features.needToWaitToProceed, | ||
27 | (enabled, r) => { | ||
28 | if (enabled) { | ||
29 | debug('Initializing `delayApp` feature'); | ||
30 | 27 | ||
31 | // Dispose the reaction to run this only once | 28 | let shownAfterLaunch = false; |
32 | r.dispose(); | 29 | let timeLastDelay = moment(); |
33 | 30 | ||
34 | const { needToWaitToProceedConfig: globalConfig } = stores.features.features; | 31 | reaction( |
32 | () => stores.features.features.needToWaitToProceed && !stores.user.data.isPremium, | ||
33 | (isEnabled) => { | ||
34 | if (isEnabled) { | ||
35 | debug('Enabling `delayApp` feature'); | ||
35 | 36 | ||
36 | let shownAfterLaunch = false; | 37 | const { needToWaitToProceedConfig: globalConfig } = stores.features.features; |
37 | let timeLastDelay = moment(); | ||
38 | 38 | ||
39 | config.delayOffset = globalConfig.delayOffset !== undefined ? globalConfig.delayOffset : DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.delayOffset; | 39 | config.delayOffset = globalConfig.delayOffset !== undefined ? globalConfig.delayOffset : DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.delayOffset; |
40 | config.delayDuration = globalConfig.wait !== undefined ? globalConfig.wait : DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.wait; | 40 | config.delayDuration = globalConfig.wait !== undefined ? globalConfig.wait : DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.wait; |
@@ -50,6 +50,7 @@ export default function init(stores) { | |||
50 | debug(`App will be delayed for ${config.delayDuration / 1000}s`); | 50 | debug(`App will be delayed for ${config.delayDuration / 1000}s`); |
51 | 51 | ||
52 | setVisibility(true); | 52 | setVisibility(true); |
53 | gaEvent('delayApp', 'show', 'Delay App Feature'); | ||
53 | 54 | ||
54 | timeLastDelay = moment(); | 55 | timeLastDelay = moment(); |
55 | shownAfterLaunch = true; | 56 | shownAfterLaunch = true; |
@@ -61,6 +62,8 @@ export default function init(stores) { | |||
61 | }, DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.wait + 1000); // timer needs to be able to hit 0 | 62 | }, DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.wait + 1000); // timer needs to be able to hit 0 |
62 | } | 63 | } |
63 | }); | 64 | }); |
65 | } else { | ||
66 | setVisibility(false); | ||
64 | } | 67 | } |
65 | }, | 68 | }, |
66 | ); | 69 | ); |