Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 92ee1ad

Browse files
committed
Convert AccessSecretStorageDialog to TypeScript
This is to make upcoming changes a bit easier to do.
1 parent 318db15 commit 92ee1ad

File tree

1 file changed

+65
-58
lines changed

1 file changed

+65
-58
lines changed

src/components/views/dialogs/security/AccessSecretStorageDialog.js renamed to src/components/views/dialogs/security/AccessSecretStorageDialog.tsx

Lines changed: 65 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/*
2-
Copyright 2018, 2019 New Vector Ltd
3-
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
2+
Copyright 2018-2021 The Matrix.org Foundation C.I.C.
43
54
Licensed under the Apache License, Version 2.0 (the "License");
65
you may not use this file except in compliance with the License.
@@ -17,14 +16,16 @@ limitations under the License.
1716

1817
import {debounce} from "lodash";
1918
import classNames from 'classnames';
20-
import React from 'react';
21-
import PropTypes from "prop-types";
19+
import React, {ChangeEvent, FormEvent} from 'react';
20+
import {ISecretStorageKeyInfo} from "matrix-js-sdk/src";
21+
2222
import * as sdk from '../../../../index';
2323
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
2424
import Field from '../../elements/Field';
2525
import AccessibleButton from '../../elements/AccessibleButton';
26-
27-
import { _t } from '../../../../languageHandler';
26+
import {_t} from '../../../../languageHandler';
27+
import {IDialogProps} from "../IDialogProps";
28+
import BaseDialog from "../BaseDialog";
2829

2930
// Maximum acceptable size of a key file. It's 59 characters including the spaces we encode,
3031
// so this should be plenty and allow for people putting extra whitespace in the file because
@@ -34,22 +35,30 @@ const KEY_FILE_MAX_SIZE = 128;
3435
// Don't shout at the user that their key is invalid every time they type a key: wait a short time
3536
const VALIDATION_THROTTLE_MS = 200;
3637

38+
interface IProps extends IDialogProps {
39+
keyInfo: ISecretStorageKeyInfo;
40+
checkPrivateKey: (k: {passphrase?: string, recoveryKey?: string}) => boolean;
41+
}
42+
43+
interface IState {
44+
recoveryKey: string;
45+
recoveryKeyValid: boolean | null;
46+
recoveryKeyCorrect: boolean | null;
47+
recoveryKeyFileError: boolean | null;
48+
forceRecoveryKey: boolean;
49+
passPhrase: string;
50+
keyMatches: boolean | null;
51+
}
52+
3753
/*
3854
* Access Secure Secret Storage by requesting the user's passphrase.
3955
*/
40-
export default class AccessSecretStorageDialog extends React.PureComponent {
41-
static propTypes = {
42-
// { passphrase, pubkey }
43-
keyInfo: PropTypes.object.isRequired,
44-
// Function from one of { passphrase, recoveryKey } -> boolean
45-
checkPrivateKey: PropTypes.func.isRequired,
46-
}
56+
export default class AccessSecretStorageDialog extends React.PureComponent<IProps, IState> {
57+
private fileUpload = React.createRef<HTMLInputElement>();
4758

4859
constructor(props) {
4960
super(props);
5061

51-
this._fileUpload = React.createRef();
52-
5362
this.state = {
5463
recoveryKey: "",
5564
recoveryKeyValid: null,
@@ -61,21 +70,21 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
6170
};
6271
}
6372

64-
_onCancel = () => {
73+
private onCancel = () => {
6574
this.props.onFinished(false);
66-
}
75+
};
6776

68-
_onUseRecoveryKeyClick = () => {
77+
private onUseRecoveryKeyClick = () => {
6978
this.setState({
7079
forceRecoveryKey: true,
7180
});
72-
}
81+
};
7382

74-
_validateRecoveryKeyOnChange = debounce(() => {
75-
this._validateRecoveryKey();
83+
private validateRecoveryKeyOnChange = debounce(async () => {
84+
await this.validateRecoveryKey();
7685
}, VALIDATION_THROTTLE_MS);
7786

78-
async _validateRecoveryKey() {
87+
private async validateRecoveryKey() {
7988
if (this.state.recoveryKey === '') {
8089
this.setState({
8190
recoveryKeyValid: null,
@@ -102,27 +111,27 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
102111
}
103112
}
104113

105-
_onRecoveryKeyChange = (e) => {
114+
private onRecoveryKeyChange = (ev: ChangeEvent<HTMLInputElement>) => {
106115
this.setState({
107-
recoveryKey: e.target.value,
116+
recoveryKey: ev.target.value,
108117
recoveryKeyFileError: null,
109118
});
110119

111120
// also clear the file upload control so that the user can upload the same file
112121
// the did before (otherwise the onchange wouldn't fire)
113-
if (this._fileUpload.current) this._fileUpload.current.value = null;
122+
if (this.fileUpload.current) this.fileUpload.current.value = null;
114123

115124
// We don't use Field's validation here because a) we want it in a separate place rather
116125
// than in a tooltip and b) we want it to display feedback based on the uploaded file
117126
// as well as the text box. Ideally we would refactor Field's validation logic so we could
118127
// re-use some of it.
119-
this._validateRecoveryKeyOnChange();
120-
}
128+
this.validateRecoveryKeyOnChange();
129+
};
121130

122-
_onRecoveryKeyFileChange = async e => {
123-
if (e.target.files.length === 0) return;
131+
private onRecoveryKeyFileChange = async (ev: ChangeEvent<HTMLInputElement>) => {
132+
if (ev.target.files.length === 0) return;
124133

125-
const f = e.target.files[0];
134+
const f = ev.target.files[0];
126135

127136
if (f.size > KEY_FILE_MAX_SIZE) {
128137
this.setState({
@@ -140,7 +149,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
140149
recoveryKeyFileError: null,
141150
recoveryKey: contents.trim(),
142151
});
143-
this._validateRecoveryKey();
152+
await this.validateRecoveryKey();
144153
} else {
145154
this.setState({
146155
recoveryKeyFileError: true,
@@ -150,14 +159,14 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
150159
});
151160
}
152161
}
153-
}
162+
};
154163

155-
_onRecoveryKeyFileUploadClick = () => {
156-
this._fileUpload.current.click();
164+
private onRecoveryKeyFileUploadClick = () => {
165+
this.fileUpload.current.click();
157166
}
158167

159-
_onPassPhraseNext = async (e) => {
160-
e.preventDefault();
168+
private onPassPhraseNext = async (ev: FormEvent<HTMLFormElement>) => {
169+
ev.preventDefault();
161170

162171
if (this.state.passPhrase.length <= 0) return;
163172

@@ -169,10 +178,10 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
169178
} else {
170179
this.setState({ keyMatches });
171180
}
172-
}
181+
};
173182

174-
_onRecoveryKeyNext = async (e) => {
175-
e.preventDefault();
183+
private onRecoveryKeyNext = async (ev: FormEvent<HTMLFormElement>) => {
184+
ev.preventDefault();
176185

177186
if (!this.state.recoveryKeyValid) return;
178187

@@ -184,16 +193,16 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
184193
} else {
185194
this.setState({ keyMatches });
186195
}
187-
}
196+
};
188197

189-
_onPassPhraseChange = (e) => {
198+
private onPassPhraseChange = (ev: ChangeEvent<HTMLInputElement>) => {
190199
this.setState({
191-
passPhrase: e.target.value,
200+
passPhrase: ev.target.value,
192201
keyMatches: null,
193202
});
194-
}
203+
};
195204

196-
getKeyValidationText() {
205+
private getKeyValidationText(): string {
197206
if (this.state.recoveryKeyFileError) {
198207
return _t("Wrong file type");
199208
} else if (this.state.recoveryKeyCorrect) {
@@ -208,8 +217,6 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
208217
}
209218

210219
render() {
211-
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
212-
213220
const hasPassphrase = (
214221
this.props.keyInfo &&
215222
this.props.keyInfo.passphrase &&
@@ -244,18 +251,18 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
244251
{
245252
button: s => <AccessibleButton className="mx_linkButton"
246253
element="span"
247-
onClick={this._onUseRecoveryKeyClick}
254+
onClick={this.onUseRecoveryKeyClick}
248255
>
249256
{s}
250257
</AccessibleButton>,
251258
},
252259
)}</p>
253260

254-
<form className="mx_AccessSecretStorageDialog_primaryContainer" onSubmit={this._onPassPhraseNext}>
261+
<form className="mx_AccessSecretStorageDialog_primaryContainer" onSubmit={this.onPassPhraseNext}>
255262
<input
256263
type="password"
257264
className="mx_AccessSecretStorageDialog_passPhraseInput"
258-
onChange={this._onPassPhraseChange}
265+
onChange={this.onPassPhraseChange}
259266
value={this.state.passPhrase}
260267
autoFocus={true}
261268
autoComplete="new-password"
@@ -264,9 +271,9 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
264271
{keyStatus}
265272
<DialogButtons
266273
primaryButton={_t('Continue')}
267-
onPrimaryButtonClick={this._onPassPhraseNext}
274+
onPrimaryButtonClick={this.onPassPhraseNext}
268275
hasCancel={true}
269-
onCancel={this._onCancel}
276+
onCancel={this.onCancel}
270277
focus={false}
271278
primaryDisabled={this.state.passPhrase.length === 0}
272279
/>
@@ -291,7 +298,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
291298

292299
<form
293300
className="mx_AccessSecretStorageDialog_primaryContainer"
294-
onSubmit={this._onRecoveryKeyNext}
301+
onSubmit={this.onRecoveryKeyNext}
295302
spellCheck={false}
296303
autoComplete="off"
297304
>
@@ -301,7 +308,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
301308
type="password"
302309
label={_t('Security Key')}
303310
value={this.state.recoveryKey}
304-
onChange={this._onRecoveryKeyChange}
311+
onChange={this.onRecoveryKeyChange}
305312
forceValidity={this.state.recoveryKeyCorrect}
306313
autoComplete="off"
307314
/>
@@ -312,22 +319,22 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
312319
<div>
313320
<input type="file"
314321
className="mx_AccessSecretStorageDialog_recoveryKeyEntry_fileInput"
315-
ref={this._fileUpload}
316-
onChange={this._onRecoveryKeyFileChange}
322+
ref={this.fileUpload}
323+
onChange={this.onRecoveryKeyFileChange}
317324
/>
318-
<AccessibleButton kind="primary" onClick={this._onRecoveryKeyFileUploadClick}>
325+
<AccessibleButton kind="primary" onClick={this.onRecoveryKeyFileUploadClick}>
319326
{_t("Upload")}
320327
</AccessibleButton>
321328
</div>
322329
</div>
323330
{recoveryKeyFeedback}
324331
<DialogButtons
325332
primaryButton={_t('Continue')}
326-
onPrimaryButtonClick={this._onRecoveryKeyNext}
333+
onPrimaryButtonClick={this.onRecoveryKeyNext}
327334
hasCancel={true}
328335
cancelButton={_t("Go Back")}
329336
cancelButtonClass='danger'
330-
onCancel={this._onCancel}
337+
onCancel={this.onCancel}
331338
focus={false}
332339
primaryDisabled={!this.state.recoveryKeyValid}
333340
/>

0 commit comments

Comments
 (0)