diff options
Diffstat (limited to 'src/components/auth/Locked.tsx')
-rw-r--r-- | src/components/auth/Locked.tsx | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/components/auth/Locked.tsx b/src/components/auth/Locked.tsx new file mode 100644 index 000000000..8b4e26878 --- /dev/null +++ b/src/components/auth/Locked.tsx | |||
@@ -0,0 +1,147 @@ | |||
1 | import { systemPreferences } from '@electron/remote'; | ||
2 | import { Component } from 'react'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; | ||
5 | import { noop } from 'lodash'; | ||
6 | import Form from '../../lib/Form'; | ||
7 | import Input from '../ui/input/index'; | ||
8 | import Button from '../ui/button'; | ||
9 | import { H1 } from '../ui/headline'; | ||
10 | import { isMac } from '../../environment'; | ||
11 | |||
12 | const messages = defineMessages({ | ||
13 | headline: { | ||
14 | id: 'locked.headline', | ||
15 | defaultMessage: 'Locked', | ||
16 | }, | ||
17 | touchId: { | ||
18 | id: 'locked.touchId', | ||
19 | defaultMessage: 'Unlock with Touch ID', | ||
20 | }, | ||
21 | touchIdPrompt: { | ||
22 | id: 'locked.touchIdPrompt', | ||
23 | defaultMessage: 'Unlock with Touch ID', | ||
24 | }, | ||
25 | passwordLabel: { | ||
26 | id: 'locked.password.label', | ||
27 | defaultMessage: 'Password', | ||
28 | }, | ||
29 | submitButtonLabel: { | ||
30 | id: 'locked.submit.label', | ||
31 | defaultMessage: 'Unlock', | ||
32 | }, | ||
33 | unlockWithPassword: { | ||
34 | id: 'locked.unlockWithPassword', | ||
35 | defaultMessage: 'Unlock with Password', | ||
36 | }, | ||
37 | invalidCredentials: { | ||
38 | id: 'locked.invalidCredentials', | ||
39 | defaultMessage: 'Password invalid', | ||
40 | }, | ||
41 | }); | ||
42 | |||
43 | interface IProps extends WrappedComponentProps { | ||
44 | onSubmit: (...args: any[]) => void; | ||
45 | unlock: () => void; | ||
46 | isSubmitting: boolean; | ||
47 | useTouchIdToUnlock: boolean; | ||
48 | error: boolean; | ||
49 | } | ||
50 | |||
51 | @observer | ||
52 | class Locked extends Component<IProps> { | ||
53 | form: Form; | ||
54 | |||
55 | constructor(props: IProps) { | ||
56 | super(props); | ||
57 | |||
58 | this.form = new Form({ | ||
59 | fields: { | ||
60 | password: { | ||
61 | label: this.props.intl.formatMessage(messages.passwordLabel), | ||
62 | value: '', | ||
63 | type: 'password', | ||
64 | }, | ||
65 | }, | ||
66 | }); | ||
67 | } | ||
68 | |||
69 | submit(e) { | ||
70 | e.preventDefault(); | ||
71 | this.form.submit({ | ||
72 | onSuccess: form => { | ||
73 | this.props.onSubmit(form.values()); | ||
74 | }, | ||
75 | onError: () => {}, | ||
76 | }); | ||
77 | } | ||
78 | |||
79 | touchIdUnlock() { | ||
80 | const { intl } = this.props; | ||
81 | |||
82 | systemPreferences | ||
83 | .promptTouchID(intl.formatMessage(messages.touchIdPrompt)) | ||
84 | .then(() => { | ||
85 | this.props.unlock(); | ||
86 | }); | ||
87 | } | ||
88 | |||
89 | render() { | ||
90 | const { form } = this; | ||
91 | const { isSubmitting, error, useTouchIdToUnlock, intl } = this.props; | ||
92 | |||
93 | const touchIdEnabled = isMac | ||
94 | ? useTouchIdToUnlock && systemPreferences.canPromptTouchID() | ||
95 | : false; | ||
96 | const submitButtonLabel = touchIdEnabled | ||
97 | ? intl.formatMessage(messages.unlockWithPassword) | ||
98 | : intl.formatMessage(messages.submitButtonLabel); | ||
99 | |||
100 | return ( | ||
101 | <div className="auth__container"> | ||
102 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> | ||
103 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> | ||
104 | <H1>{intl.formatMessage(messages.headline)}</H1> | ||
105 | |||
106 | {touchIdEnabled && ( | ||
107 | <> | ||
108 | <Button | ||
109 | className="auth__button touchid__button" | ||
110 | label={intl.formatMessage(messages.touchId)} | ||
111 | onClick={() => this.touchIdUnlock()} | ||
112 | type="button" | ||
113 | /> | ||
114 | <hr className="locked__or_line" /> | ||
115 | </> | ||
116 | )} | ||
117 | |||
118 | <Input {...form.$('password').bind()} showPasswordToggle focus /> | ||
119 | {error && ( | ||
120 | <p className="error-message center"> | ||
121 | {intl.formatMessage(messages.invalidCredentials)} | ||
122 | </p> | ||
123 | )} | ||
124 | {isSubmitting ? ( | ||
125 | <Button | ||
126 | className="auth__button is-loading" | ||
127 | buttonType="secondary" | ||
128 | label={`${submitButtonLabel} ...`} | ||
129 | loaded={false} | ||
130 | onClick={noop} | ||
131 | disabled | ||
132 | /> | ||
133 | ) : ( | ||
134 | <Button | ||
135 | type="submit" | ||
136 | className="auth__button" | ||
137 | label={submitButtonLabel} | ||
138 | onClick={noop} | ||
139 | /> | ||
140 | )} | ||
141 | </form> | ||
142 | </div> | ||
143 | ); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | export default injectIntl(Locked); | ||