added UI component for importing e2e keys

This commit is contained in:
unknown 2021-08-01 19:29:15 +05:30
parent 0745f964c1
commit 9f6047aebd
2 changed files with 171 additions and 0 deletions

View file

@ -0,0 +1,108 @@
import React, { useState, useEffect, useRef } from 'react';
import './ImportE2ERoomKeys.scss';
import EventEmitter from 'events';
import initMatrix from '../../../client/initMatrix';
import decryptMegolmKeyFile from '../../../util/decryptE2ERoomKeys';
import Text from '../../atoms/text/Text';
import IconButton from '../../atoms/button/IconButton';
import Button from '../../atoms/button/Button';
import Input from '../../atoms/input/Input';
import Spinner from '../../atoms/spinner/Spinner';
import CirclePlusIC from '../../../../public/res/ic/outlined/circle-plus.svg';
const viewEvent = new EventEmitter();
async function tryDecrypt(file, password) {
try {
const arrayBuffer = await file.arrayBuffer();
viewEvent.emit('importing', true);
viewEvent.emit('status', 'Decrypting file...');
const keys = await decryptMegolmKeyFile(arrayBuffer, password);
viewEvent.emit('status', 'Decrypting messages...');
await initMatrix.matrixClient.importRoomKeys(JSON.parse(keys));
viewEvent.emit('status', null);
viewEvent.emit('importing', false);
} catch (e) {
viewEvent.emit('status', e.friendlyText || 'Something went wrong!');
viewEvent.emit('importing', false);
}
}
function ImportE2ERoomKeys() {
const [keyFile, setKeyFile] = useState(null);
const [status, setStatus] = useState(null);
const [isImporting, setIsImporting] = useState(false);
const inputRef = useRef(null);
const passwordRef = useRef(null);
useEffect(() => {
const handleIsImporting = (isImp) => setIsImporting(isImp);
const handleStatus = (msg) => setStatus(msg);
viewEvent.on('importing', handleIsImporting);
viewEvent.on('status', handleStatus);
return () => {
viewEvent.removeListener('importing', handleIsImporting);
viewEvent.removeListener('status', handleStatus);
}
}, []);
function importE2ERoomKeys() {
const password = passwordRef.current.value;
if (password === '' || keyFile === null) return;
if (isImporting) return;
tryDecrypt(keyFile, password);
}
function handleFileChange(e) {
const file = e.target.files.item(0);
passwordRef.current.value = '';
setKeyFile(file);
setStatus(null);
}
function removeImportKeysFile() {
inputRef.current.value = null;
passwordRef.current.value = null;
setKeyFile(null);
setStatus(null);
}
useEffect(() => {
if (!isImporting && status === null) {
removeImportKeysFile();
}
}, [isImporting, status]);
return (
<div className="import-e2e-room-keys">
<input ref={inputRef} onChange={handleFileChange} style={{ display: 'none' }} type="file" />
<form className="import-e2e-room-keys__form" onSubmit={(e) => { e.preventDefault(); importE2ERoomKeys(); }}>
{ keyFile !== null && (
<div className="import-e2e-room-keys__file">
<IconButton onClick={removeImportKeysFile} src={CirclePlusIC} tooltip="Remove file" />
<Text>{keyFile.name}</Text>
</div>
)}
{keyFile === null && <Button onClick={() => inputRef.current.click()}>Import keys</Button>}
<Input forwardRef={passwordRef} type="password" placeholder="password" required />
<Button disabled={isImporting} variant="primary" type="submit">Decrypt</Button>
</form>
{ isImporting && status !== null && (
<div className="import-e2e-room-keys__process">
<Spinner size="small" />
<Text variant="b2">{status}</Text>
</div>
)}
{!isImporting && status !== null && <Text className="import-e2e-room-keys__error" variant="b2">{status}</Text>}
</div>
);
}
export default ImportE2ERoomKeys;

View file

@ -0,0 +1,63 @@
.import-e2e-room-keys {
&__file {
display: inline-flex;
align-items: center;
background: var(--bg-surface-low);
border-radius: var(--bo-radius);
box-shadow: var(--bs-surface-border);
& button {
--parent-height: 46px;
width: var(--parent-height);
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
& .ic-raw {
background-color: var(--bg-caution);
transform: rotate(45deg);
}
& .text {
margin-left: var(--sp-tight);
margin-right: var(--sp-loose);
max-width: 86px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
[dir=rtl] {
margin-right: var(--sp-tight);
margin-left: var(--sp-loose);
}
}
}
&__form {
display: flex;
margin-top: var(--sp-extra-tight);
& .input-container {
flex: 1;
margin: 0 var(--sp-tight);
}
}
&__process {
margin-top: var(--sp-tight);
display: flex;
justify-content: center;
align-items: center;
& .text {
margin: 0 var(--sp-tight);
}
}
&__error {
margin-top: var(--sp-tight);
color: var(--bg-danger);
}
}