Organise elements in fieldboxes

This commit is contained in:
Franck Royer 2021-06-29 15:32:29 +10:00
parent 5661c7d1ec
commit 31d0efc8d2
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
8 changed files with 232 additions and 129 deletions

View File

@ -8,6 +8,7 @@
"version": "0.1.0",
"dependencies": {
"@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
@ -3451,6 +3452,28 @@
}
}
},
"node_modules/@material-ui/icons": {
"version": "4.11.2",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz",
"integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==",
"dependencies": {
"@babel/runtime": "^7.4.4"
},
"engines": {
"node": ">=8.0.0"
},
"peerDependencies": {
"@material-ui/core": "^4.0.0",
"@types/react": "^16.8.6 || ^17.0.0",
"react": "^16.8.0 || ^17.0.0",
"react-dom": "^16.8.0 || ^17.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@material-ui/styles": {
"version": "4.11.4",
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
@ -26510,6 +26533,14 @@
"react-transition-group": "^4.4.0"
}
},
"@material-ui/icons": {
"version": "4.11.2",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz",
"integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==",
"requires": {
"@babel/runtime": "^7.4.4"
}
},
"@material-ui/styles": {
"version": "4.11.4",
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",

View File

@ -5,6 +5,7 @@
"homepage": "/js-waku/eth-dm",
"dependencies": {
"@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",

View File

@ -9,16 +9,61 @@ import { createPublicKeyMessage, KeyPair } from './crypto';
import { encode, PublicKeyMessage } from './messages';
import Messages, { Message } from './Messages';
import 'fontsource-roboto';
import { Button } from '@material-ui/core';
import {
AppBar,
Button,
IconButton,
Toolbar,
Typography,
} from '@material-ui/core';
import SendMessage from './SendMessage';
import KeyPairHandling from './key_pair_handling/KeyPairHandling';
import InitWaku from './InitWaku';
import {
createMuiTheme,
ThemeProvider,
makeStyles,
} from '@material-ui/core/styles';
import { teal, purple, green } from '@material-ui/core/colors';
import WifiIcon from '@material-ui/icons/Wifi';
export const PublicKeyContentTopic = '/eth-dm/1/public-key/json';
export const DirectMessageContentTopic = '/eth-dm/1/direct-message/json';
declare let window: any;
const theme = createMuiTheme({
palette: {
primary: {
main: purple[500],
},
secondary: {
main: teal[600],
},
},
});
const useStyles = makeStyles({
root: {
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
},
appBar: {
// height: '200p',
},
container: {
display: 'flex',
flex: 1,
},
main: {
flex: 1,
margin: '10px',
},
wakuStatus: {},
});
function App() {
const [waku, setWaku] = useState<Waku>();
const [provider, setProvider] = useState<Web3Provider>();
@ -28,6 +73,8 @@ function App() {
const [messages, setMessages] = useState<Message[]>([]);
const [address, setAddress] = useState<string>();
const classes = useStyles();
useEffect(() => {
if (provider) return;
try {
@ -72,34 +119,58 @@ function App() {
};
return (
<div className="App">
<header className="App-header">
<InitWaku
ethDmKeyPair={ethDmKeyPair}
setMessages={setMessages}
setPublicKeys={setPublicKeys}
setWaku={setWaku}
waku={waku}
address={address}
/>
<KeyPairHandling
ethDmKeyPair={ethDmKeyPair}
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
/>
<div>
<Button
variant="contained"
color="primary"
onClick={broadcastPublicKey}
disabled={!ethDmKeyPair || !waku}
>
Broadcast Eth-DM Public Key
</Button>
<ThemeProvider theme={theme}>
<div className={classes.root}>
<AppBar className={classes.appBar} position="static">
<Toolbar>
<Typography>Ethereum Direct Message</Typography>
<IconButton
edge="end"
className={classes.wakuStatus}
aria-label="waku-status"
>
<WifiIcon
color={waku ? undefined : 'disabled'}
style={waku ? { color: green[500] } : {}}
/>
</IconButton>
</Toolbar>
</AppBar>
<div className={classes.container}>
<main className={classes.main}>
<InitWaku
ethDmKeyPair={ethDmKeyPair}
setMessages={setMessages}
setPublicKeys={setPublicKeys}
setWaku={setWaku}
waku={waku}
address={address}
/>
<fieldset>
<legend>Eth-DM Key Pair</legend>
<KeyPairHandling
ethDmKeyPair={ethDmKeyPair}
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
/>
<Button
variant="contained"
color="primary"
onClick={broadcastPublicKey}
disabled={!ethDmKeyPair || !waku}
>
Broadcast Eth-DM Public Key
</Button>
</fieldset>
<fieldset>
<legend>Messaging</legend>
<SendMessage recipients={publicKeys} waku={waku} />
<Messages messages={messages} />
</fieldset>
</main>
</div>
<SendMessage recipients={publicKeys} waku={waku} />
<Messages messages={messages} />
</header>
</div>
</div>
</ThemeProvider>
);
}

View File

@ -79,7 +79,7 @@ export default function InitWaku({
};
});
return <p>{!!waku ? 'Waku is ready' : 'Waku is loading'}</p>;
return <div />;
}
async function initWaku(): Promise<Waku> {

View File

@ -1,8 +1,32 @@
import { Button } from '@material-ui/core';
import { LoadKeyPair } from './LoadKeyPair';
import { SaveKeyPair } from './SaveKeyPair';
import React from 'react';
import React, { useState } from 'react';
import { generateEthDmKeyPair, KeyPair } from '../crypto';
import { makeStyles } from '@material-ui/core/styles';
import PasswordInput from './PasswordInput';
const useStyles = makeStyles({
root: {
textAlign: 'center',
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
margin: '5px',
},
generate: { margin: '5px' },
storage: {
margin: '5px',
},
loadSave: {
display: 'flex',
flexDirection: 'row',
margin: '5px',
},
loadSaveButton: {
margin: '5px',
},
});
export interface Props {
ethDmKeyPair: KeyPair | undefined;
@ -13,6 +37,10 @@ export default function KeyPairHandling({
ethDmKeyPair,
setEthDmKeyPair,
}: Props) {
const classes = useStyles();
const [password, setPassword] = useState<string>();
const generateKeyPair = () => {
if (ethDmKeyPair) return;
@ -26,43 +54,33 @@ export default function KeyPairHandling({
};
return (
<div>
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
}}
<div className={classes.root}>
<Button
className={classes.generate}
variant="contained"
color="primary"
onClick={generateKeyPair}
disabled={!!ethDmKeyPair}
>
<Button
variant="contained"
color="primary"
onClick={generateKeyPair}
disabled={!!ethDmKeyPair}
>
Generate Eth-DM Key Pair
</Button>
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
}}
>
<LoadKeyPair
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
disabled={!!ethDmKeyPair}
Generate Eth-DM Key Pair
</Button>
<div className={classes.storage}>
<PasswordInput
password={password}
setPassword={(p) => setPassword(p)}
/>
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
}}
>
<SaveKeyPair ethDmKeyPair={ethDmKeyPair} />
<div className={classes.loadSave}>
<div className={classes.loadSaveButton}>
<LoadKeyPair
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
disabled={!!ethDmKeyPair}
password={password}
/>
</div>
<div className={classes.loadSaveButton}>
<SaveKeyPair ethDmKeyPair={ethDmKeyPair} password={password} />
</div>
</div>
</div>
</div>
);

View File

@ -1,20 +1,15 @@
import { Button, TextField } from '@material-ui/core';
import React, { ChangeEvent, useState } from 'react';
import { Button } from '@material-ui/core';
import React from 'react';
import { loadKeyPairFromStorage } from './key_pair_storage';
import { KeyPair } from '../crypto';
export interface Props {
setEthDmKeyPair: (keyPair: KeyPair) => void;
disabled: boolean;
password: string | undefined;
}
export function LoadKeyPair({ disabled, setEthDmKeyPair }: Props) {
const [password, setPassword] = useState<string>();
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value);
};
export function LoadKeyPair({ password, disabled, setEthDmKeyPair }: Props) {
const loadKeyPair = () => {
if (disabled) return;
if (!password) return;
@ -26,29 +21,13 @@ export function LoadKeyPair({ disabled, setEthDmKeyPair }: Props) {
};
return (
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
}}
<Button
variant="contained"
color="primary"
onClick={loadKeyPair}
disabled={!password || disabled}
>
<TextField
id="password-input"
label="Password"
variant="filled"
type="password"
onChange={handlePasswordChange}
value={password}
/>
<Button
variant="contained"
color="primary"
onClick={loadKeyPair}
disabled={!password || disabled}
>
Load Eth-DM Key Pair from storage
</Button>
</div>
Load Eth-DM Key Pair from storage
</Button>
);
}

View File

@ -0,0 +1,24 @@
import { TextField } from '@material-ui/core';
import React, { ChangeEvent } from 'react';
interface Props {
password: string | undefined;
setPassword: (password: string) => void;
}
export default function PasswordInput({ password, setPassword }: Props) {
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value);
};
return (
<TextField
id="password-input"
label="Password"
variant="filled"
type="password"
onChange={handlePasswordChange}
value={password}
/>
);
}

View File

@ -1,19 +1,14 @@
import { Button, TextField } from '@material-ui/core';
import React, { ChangeEvent, useState } from 'react';
import { Button } from '@material-ui/core';
import React from 'react';
import { KeyPair } from '../crypto';
import { saveKeyPairToStorage } from './key_pair_storage';
export interface Props {
ethDmKeyPair: KeyPair | undefined;
password: string | undefined;
}
export function SaveKeyPair({ ethDmKeyPair }: Props) {
const [password, setPassword] = useState<string>();
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value);
};
export function SaveKeyPair({ password, ethDmKeyPair }: Props) {
const saveKeyPair = () => {
if (!ethDmKeyPair) return;
if (!password) return;
@ -23,29 +18,13 @@ export function SaveKeyPair({ ethDmKeyPair }: Props) {
};
return (
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
}}
<Button
variant="contained"
color="primary"
onClick={saveKeyPair}
disabled={!password || !ethDmKeyPair}
>
<TextField
id="password-input"
label="Password"
variant="filled"
type="password"
onChange={handlePasswordChange}
value={password}
/>
<Button
variant="contained"
color="primary"
onClick={saveKeyPair}
disabled={!password || !ethDmKeyPair}
>
Save Eth-DM Key Pair to storage
</Button>
</div>
Save Eth-DM Key Pair to storage
</Button>
);
}