Skip to content

Commit

Permalink
Merge pull request #47 from jhaals/typescript
Browse files Browse the repository at this point in the history
Website rewrite in Typescript
  • Loading branch information
jhaals committed Nov 28, 2018
2 parents 5c5bd3e + bc150c1 commit ec62793
Show file tree
Hide file tree
Showing 24 changed files with 3,665 additions and 4,829 deletions.
7 changes: 7 additions & 0 deletions website/images.d.ts
@@ -0,0 +1,7 @@
declare module '*.svg';
declare module '*.png';
declare module '*.jpg';
declare module '*.jpeg';
declare module '*.gif';
declare module '*.bmp';
declare module '*.tiff';
42 changes: 25 additions & 17 deletions website/package.json
@@ -1,30 +1,38 @@
{
"name": "website",
"name": "yopass",
"version": "0.1.0",
"private": true,
"dependencies": {
"bootstrap": "^4.0.0",
"bootstrap": "^4.1.3",
"clipboard": "^2.0.4",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-router-dom": "^4.2.2",
"react-scripts": "2.1.1",
"react": "^16.7.0-alpha",
"react-dom": "^16.7.0-alpha",
"react-router-dom": "^4.3.1",
"react-scripts-ts": "3.1.0",
"reactstrap": "^6.5.0",
"sjcl": "^1.0.8"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"puppeteer": "^1.10.0"
"@types/clipboard": "^2.0.1",
"@types/jest": "^23.3.9",
"@types/node": "^10.12.2",
"@types/puppeteer": "^1.10.0",
"@types/react": "^16.4.18",
"@types/react-dom": "^16.0.9",
"@types/react-router-dom": "^4.3.1",
"@types/reactstrap": "^6.4.2",
"@types/sjcl": "^1.0.28",
"puppeteer": "^1.10.0",
"typescript": "^3.1.5"
},
"prettier": {
"singleQuote": true,
"trailingComma": "all"
}
}
27 changes: 27 additions & 0 deletions website/react-hooks.d.ts
@@ -0,0 +1,27 @@
import * as React from 'react';

declare module 'react' {
function useState<T>(initialState: T | (() => T)): [T, (newState: T) => void];
function useEffect(
create: () => void | (() => void),
inputs?: ReadonlyArray<unknown>,
): void;
function useContext<T>(foo: React.Context<T>): T;
function useReducer<S, A>(
reducer: (state: S, action: A) => S,
initialState: S,
): [S, (action: A) => void];
function useCallback<F extends (...args: never[]) => unknown>(
callback: F,
inputs?: ReadonlyArray<unknown>,
): F;
function useMemo<T>(create: () => T, inputs?: ReadonlyArray<unknown>): T;
function useRef<T extends unknown>(initialValue?: T): React.RefObject<T>;
function useImperativeMethods<T>(
ref: React.Ref<T>,
createInstance: () => T,
inputs?: ReadonlyArray<unknown>,
): void;
const useMutationEffect: typeof useEffect;
const useLayoutEffect: typeof useEffect;
}
32 changes: 32 additions & 0 deletions website/src/App.css
@@ -0,0 +1,32 @@
.App {
text-align: center;
}

.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}

.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}

.App-title {
font-size: 1.5em;
}

.App-intro {
font-size: large;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
74 changes: 0 additions & 74 deletions website/src/App.js

This file was deleted.

44 changes: 0 additions & 44 deletions website/src/App.test.js

This file was deleted.

43 changes: 43 additions & 0 deletions website/src/App.test.tsx
@@ -0,0 +1,43 @@
import * as Puppeteer from 'puppeteer';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

// This requires the dev server to be running on port 3000
it('passes in browser encryption/decryption', async () => {
const secretMessage = 'Hello World!';
const browser = await Puppeteer.launch();
const page = await browser.newPage();

await page.goto('http://localhost:3000');
await page.keyboard.type(secretMessage);
await page.click('button');
// wait while uploading
await sleep(1500);
// @ts-ignore
const url = await page.$eval('#full-i', el => el.value);

await page.goto(url);
await sleep(250); // decrypting
// Ensure that secret can be viewed
const result = await page.$eval('pre', el => el.innerHTML);
expect(result).toBe(secretMessage);

// Page should not be visible twice
await page.reload({ waitUntil: 'networkidle0' });
expect(await page.$eval('h2', el => el.innerHTML)).toBe(
'Secret does not exist',
);

await browser.close();
}, 10000);
84 changes: 84 additions & 0 deletions website/src/App.tsx
@@ -0,0 +1,84 @@
import * as React from 'react';
import { HashRouter as Router, Route } from 'react-router-dom';
import { Col, Container, Navbar, NavbarBrand, Row } from 'reactstrap';

import './App.css';
import Create from './Create';
import DisplaySecret from './DisplaySecret';

class App extends React.Component {
public render() {
return (
<Router>
<div>
<div className="App">
<Navbar color="dark" dark={true} expand="md">
<NavbarBrand href="/">Yopass</NavbarBrand>
</Navbar>
</div>
<Container className="margin">
<Row>
<Col ml="auto">
<Route path="/" exact={true} component={Create} />
<Route
exact={true}
path="/s/:key/:password"
component={DisplaySecret}
/>
<Route exact={true} path="/s/:key" component={DisplaySecret} />
</Col>
</Row>
</Container>
<Features />
<Attribution />
</div>
</Router>
);
}
}

const Features = () => {
return (
<Container className="features">
<hr />
<p className="lead">
{' '}
Yopass is created to reduce the amount of clear text passwords stored in
email and chat conversations by encrypting and generating a short lived
link which can only be viewed once.
</p>
<p />
<h6>End-to-End encryption</h6>
<p>
Both encryption and decryption are being made locally in the browser,
the decryption key is not stored with yopass.
</p>
<h6>Self destruction</h6>
<p>
All messages have a fixed time to live and will be deleted automatically
after expiration.
</p>
<h6>No accounts needed</h6>
<p>
No additional information except the encrypted secret is stored in the
database.
</p>
<h6>Open source software</h6>
<p>
Yopass fully open source meaning full transparency and the possibility
to submit features, fix bugs or run the software yourself.
</p>
</Container>
);
};

const Attribution = () => {
return (
<Container className="text-center">
<div className="text-muted small">
Created by <a href="https://github.com/jhaals/yopass">Johan Haals</a>
</div>
</Container>
);
};
export default App;

0 comments on commit ec62793

Please sign in to comment.