This commit is contained in:
2020-08-19 22:55:44 +02:00
parent 312c8754bc
commit b84aa3db45
18 changed files with 1184 additions and 146 deletions

View File

@@ -1,49 +1,49 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import { Theme } from '../theme';
import React, { Fragment, useState } from 'react';
import { Menu, Dropdown, Form } from 'antd';
import { DownOutlined, FileOutlined, FileTextOutlined } from '@ant-design/icons';
import AddText from './AddText';
import AddFile from './AddFile';
const Wrapper = styled.div`
`;
const Top = styled.div`
display: flex;
`;
const Button = styled.button<{
active: boolean;
theme: Theme;
}>`
background: ${({ active }) => active ? '#2c3e50' : 'transparent'};
padding: ${({ theme }) => theme.margin.medium}px;
border: none;
font: inherit;
color: inherit;
`;
const Panel = styled.div<{
theme: Theme;
}>`
background: #2c3e50;
color: #fff;
padding: ${({ theme }) => theme.margin.medium}px;
`;
const layout = {
labelCol: { span: 2 },
};
const Add: React.FC = () => {
const [type, setType] = useState<'file' | 'text'>('text');
const menu = (
<Menu>
<Menu.Item
onClick={() => setType('file')}
active={type === 'file'}
icon={<FileOutlined />}
>
File
</Menu.Item>
<Menu.Item
onClick={() => setType('text')}
active={type === 'text'}
icon={<FileTextOutlined />}
>
Text
</Menu.Item>
</Menu>
);
return (
<Wrapper>
<Top>
<Button active={type==='text'} onClick={() => setType('text')}>Text</Button>
<Button active={type==='file'} onClick={() => setType('file')}>File</Button>
</Top>
<Panel>
{type === 'file' && <AddFile />}
{type === 'text' && <AddText />}
</Panel>
</Wrapper>
<>
<Form {...layout}>
<Form.Item
label="I want to encrypt a"
>
<Dropdown overlay={menu}>
<a>{type} <DownOutlined /></a>
</Dropdown>
</Form.Item>
</Form>
{type === 'text' && <AddText />}
{type === 'file' && <AddFile />}
</>
);
};

View File

@@ -1,10 +1,15 @@
import React, { useContext, useCallback } from 'react';
import styled from 'styled-components';
import { Layout } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { useDropzone } from 'react-dropzone';
import EncryptionContext from '../contexts/Encryption';
import { Upload } from 'react-feather';
const DropWrapper = styled.div`
const Icon = styled(UploadOutlined)`
font-size: 100px;
`;
const DropWrapper = styled(Layout)`
display: flex;
justify-content: center;
align-items: center;
@@ -19,13 +24,11 @@ const AddFile: React.FC = () => {
}, [])
const {getRootProps, getInputProps} = useDropzone({ onDrop });
return (
<div>
<DropWrapper {...getRootProps()}>
<input {...getInputProps()} />
<Upload size={200} />
<Icon />
<p>Drag 'n' drop some files here, or click to select files</p>
</DropWrapper>
</div>
);
};

View File

@@ -1,39 +1,57 @@
import React, { useState, useCallback, useContext } from 'react';
import styled from 'styled-components';
import { Input, Form, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import EncryptionContext from '../contexts/Encryption';
import { Theme } from '../theme';
const Wrapper = styled.div`
display: flex;
flex-direction: column;
flex: 1;
`;
const layout = {
labelCol: { span: 2 },
};
const Text = styled.textarea<{
theme: Theme;
}>`
border: none;
height: 200px;
background: transparent;
color: inherit;
padding: ${({ theme }) => theme.margin.medium}px;
font: inherit;
`;
const tailLayout = {
wrapperCol: { offset: 2 },
};
const AddText : React.FC = () => {
const { addText } = useContext(EncryptionContext);
const [name, setName] = useState('');
const [text, setText] = useState('');
const add = useCallback(() => {
addText(text);
addText(text, name || 'untitled');
setText('');
setName('');
}, [text, addText]);
return (
<Wrapper>
<Text placeholder="Enter you message..." value={text} onChange={evt => setText(evt.target.value)} />
<button onClick={add}>Save</button>
</Wrapper>
<Form {...layout}>
<Form.Item
label="Name"
>
<Input
value={name}
onChange={evt => setName(evt.target.value)}
/>
</Form.Item>
<Form.Item
label="Message"
>
<Input.TextArea
value={text}
rows={10}
onChange={evt => setText(evt.target.value)}
/>
</Form.Item>
<Form.Item {...tailLayout}>
<Button
onClick={add}
type="primary"
icon={<PlusOutlined />}
disabled={!text}
>
Add
</Button>
</Form.Item>
</Form>
);
};

View File

@@ -1,12 +1,20 @@
import React from 'react';
import styled from 'styled-components';
import { File } from '../contexts/Encryption';
import {
List,
Button,
} from 'antd';
import {
DeleteOutlined,
SyncOutlined,
IssuesCloseOutlined,
LockOutlined,
} from '@ant-design/icons';
import { FileType } from '../contexts/Encryption';
import { CheckCircle, XCircle, Download, Trash, Loader } from 'react-feather';
import Row, { Cell } from './Row';
interface Props {
remove: () => void;
file: File;
file: FileType;
}
const downloadLink = (name: string, url: string) => {
@@ -18,42 +26,51 @@ const downloadLink = (name: string, url: string) => {
document.body.removeChild(downloadLink);
};
const Button = styled.button`
background: none;
border: none;
color: green;
`;
const icons: {[name: string]: typeof CheckCircle} = {
encrypting: Loader,
failed: XCircle,
encrypted: CheckCircle,
const icons: {[name: string]: any} = {
encrypting: <SyncOutlined spin />,
failed: <IssuesCloseOutlined />,
encrypted: <LockOutlined />,
};
const IconText = ({ icon, text, ...props }) => (
<Button
{...props}
icon={React.createElement(icon)}
>
{text}
</Button>
);
const FileView: React.FC<Props> = ({
file,
remove,
}) => {
const Icon = icons[file.status];
const icon = icons[file.status];
return (
<Row
left={(
<Cell><Icon /></Cell>
)}
title={file.name}
body={`encrypted for ${file.reciever}`}
right={!!file.link && (
<>
<Cell>
<Button onClick={() => downloadLink(file.name, file.link)}><Download /></Button>
</Cell>
<Cell>
<Button onClick={remove}><Trash /></Button>
</Cell>
</>
)}
/>
<List.Item
actions={file.link ? [(
<IconText
icon={DeleteOutlined}
danger
text="Delete"
onClick={remove}
/>
), (
<IconText
icon={DeleteOutlined}
type="primary"
text="Download"
onClick={() => downloadLink(file.name, file.link!)}
/>
)]: []}
>
<List.Item.Meta
avatar={icon}
title={file.name}
description={`Encrypted for ${file.reciever}`}
/>
</List.Item>
);
};

View File

@@ -1,12 +1,17 @@
import React, { useContext } from 'react';
import { List, Empty } from 'antd';
import EncryptionContext from '../contexts/Encryption';
import File from './File';
const Encrypt: React.FC = () => {
const { files, deleteFile } = useContext(EncryptionContext);
if (Object.keys(files).length === 0) {
return <Empty />
}
return (
<div>
<List>
{Object.entries(files).map(([id, file]) => (
<File
key={id}
@@ -14,7 +19,7 @@ const Encrypt: React.FC = () => {
remove={() => deleteFile(id)}
/>
))}
</div>
</List>
);
};

View File

@@ -0,0 +1,71 @@
import React, { useContext, useState } from 'react';
import {
Card,
Avatar,
Button,
Modal,
} from 'antd';
import { KeyOutlined, GithubOutlined } from '@ant-design/icons'
import GithubContext from '../contexts/Github';
const IconText = ({ icon, text, ...props }) => (
<Button
{...props}
icon={React.createElement(icon)}
>
{text}
</Button>
);
const Profile: React.FC = () => {
const { user, keys } = useContext(GithubContext);
const [showKeys, setShowKeys] = useState(false);
if (!user) {
return null;
}
return (
<>
<Modal
visible={showKeys}
onOk={() => setShowKeys(false)}
onCancel={() => setShowKeys(false)}
title="Keys"
>
<pre>
{keys!.join('\n\n')}
</pre>
</Modal>
<Card
style={{ width: 300, marginTop: 16, alignSelf: 'center' }}
actions={[(
<IconText
key="showkeys"
text="Show keys"
icon={KeyOutlined}
onClick={() => setShowKeys(true)}
/>
), (
<a target="_blank" href={`https://github.com/${user.login}`}>
<IconText
key="gotogithub"
text="Go to Github"
icon={GithubOutlined}
/>
</a>
)]}
>
<Card.Meta
title={user.name}
avatar={(
<Avatar src={user.avatar_url} size={80} />
)}
description={user.location}
/>
</Card>
</>
);
};
export default Profile;